From fb8c784670716035ec37a2572c1750be4c1b3d3c Mon Sep 17 00:00:00 2001 From: Michel Machado Date: Tue, 16 Dec 2014 12:01:52 -0500 Subject: [PATCH] f3probe: make it more uniform to add reset methods --- f3probe.c | 19 +++++++---- libdevs.c | 98 ++++++++++++++++++++++++++++--------------------------- libdevs.h | 12 +++++-- 3 files changed, 72 insertions(+), 57 deletions(-) diff --git a/f3probe.c b/f3probe.c index ae7a474..70d5dd3 100644 --- a/f3probe.c +++ b/f3probe.c @@ -45,8 +45,8 @@ static struct argp_option options[] = { "Do not restore blocks of the device after probing it", 2}, {"min-memory", 'l', NULL, 0, "Trade speed for less use of memory", 0}, - {"manual-reset", 'm', NULL, 0, - "Ask user to manually reset the drive", 0}, + {"reset-type", 's', "TYPE", 0, + "Reset method to use during the probe", 0}, {"time-ops", 't', NULL, 0, "Time reads, writes, and resets", 0}, { 0 } @@ -63,7 +63,7 @@ struct args { /* Behavior options. */ bool save; bool min_mem; - bool manual_reset; + enum reset_type reset_type; bool time_ops; /* 1 free bytes. */ @@ -182,8 +182,13 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) args->min_mem = true; break; - case 'm': - args->manual_reset = true; + case 's': + ll = arg_to_long_long(state, arg); + if (ll < 0 || ll >= RT_MAX) + argp_error(state, + "Reset type must be in the interval [0, %i]", + RT_MAX - 1); + args->reset_type = ll; break; case 't': @@ -357,7 +362,7 @@ static int test_device(struct args *args) ? create_file_device(args->filename, args->real_size_byte, args->fake_size_byte, args->wrap, args->block_order, args->keep_file) - : create_block_device(args->filename, args->manual_reset); + : create_block_device(args->filename, args->reset_type); if (!dev) { fprintf(stderr, "\nApplication cannot continue, finishing...\n"); exit(1); @@ -456,7 +461,7 @@ int main(int argc, char **argv) .keep_file = false, .save = true, .min_mem = false, - .manual_reset = false, + .reset_type = RT_DEFAULT, .time_ops = false, .real_size_byte = 1ULL << 31, .fake_size_byte = 1ULL << 34, diff --git a/libdevs.c b/libdevs.c index 45eb6a1..0b6037d 100644 --- a/libdevs.c +++ b/libdevs.c @@ -275,7 +275,6 @@ struct block_device { const char *filename; int fd; - int hw_fd; /* Underlying hardware of the block device. */ }; static inline struct block_device *dev_bdev(struct device *dev) @@ -337,34 +336,6 @@ static int bdev_manual_reset(struct device *dev) return 0; } -static int bdev_reset(struct device *dev) -{ - struct block_device *bdev = dev_bdev(dev); - assert(!close(bdev->fd)); - assert(!ioctl(bdev->hw_fd, USBDEVFS_RESET)); - bdev->fd = bdev_open(bdev->filename); - if (bdev->fd < 0) - err(errno, "Can't REopen device `%s'", bdev->filename); - return 0; -} - -static void bdev_free(struct device *dev) -{ - struct block_device *bdev = dev_bdev(dev); - if (bdev->hw_fd >= 0) - assert(!close(bdev->hw_fd)); - if (bdev->fd >= 0) - assert(!close(bdev->fd)); - free((void *)bdev->filename); -} - -static bool is_block_dev(int fd) -{ - struct stat stat; - assert(!fstat(fd, &stat)); - return S_ISBLK(stat.st_mode); -} - static char *map_block_to_usb_dev(const char *block_dev) { struct udev *udev; @@ -433,6 +404,47 @@ static char *map_block_to_usb_dev(const char *block_dev) return usb_dev_path; } +static int bdev_usb_reset(struct device *dev) +{ + const char *usb_filename; + int hw_fd; /* Underlying hardware of the block device. */ + struct block_device *bdev = dev_bdev(dev); + + usb_filename = map_block_to_usb_dev(bdev->filename); + if (!usb_filename) + err(EINVAL, "Block device `%s' is not backed by a USB device", + bdev->filename); + + hw_fd = open(usb_filename, O_WRONLY | O_NONBLOCK); + free((void *)usb_filename); + usb_filename = NULL; + if (hw_fd < 0) + err(errno, "Can't open device `%s'", usb_filename); + + assert(!close(bdev->fd)); + assert(!ioctl(hw_fd, USBDEVFS_RESET)); + assert(!close(hw_fd)); + bdev->fd = bdev_open(bdev->filename); + if (bdev->fd < 0) + err(errno, "Can't REopen device `%s'", bdev->filename); + return 0; +} + +static void bdev_free(struct device *dev) +{ + struct block_device *bdev = dev_bdev(dev); + if (bdev->fd >= 0) + assert(!close(bdev->fd)); + free((void *)bdev->filename); +} + +static bool is_block_dev(int fd) +{ + struct stat stat; + assert(!fstat(fd, &stat)); + return S_ISBLK(stat.st_mode); +} + /* XXX Test if it's a device, or a partition. * If a partition, warn user, and ask for confirmation before * going ahead. @@ -441,7 +453,7 @@ static char *map_block_to_usb_dev(const char *block_dev) * Use udev to do these tests. * Make sure that no partition of the drive is mounted. */ -struct device *create_block_device(const char *filename, int manual_reset) +struct device *create_block_device(const char *filename, enum reset_type rt) { struct block_device *bdev; int block_size; @@ -472,25 +484,15 @@ struct device *create_block_device(const char *filename, int manual_reset) goto fd; } - if (manual_reset) { - bdev->hw_fd = -1; + switch (rt) { + case RT_MANUAL: bdev->dev.reset = bdev_manual_reset; - } else { - /* XXX Add support for block devices backed by SCSI and ATA. */ - const char *usb_filename = map_block_to_usb_dev(filename); - if (!usb_filename) { - err(EINVAL, "Block device `%s' is not backed by a USB device", - filename); - goto fd; - } - - bdev->hw_fd = open(usb_filename, O_WRONLY | O_NONBLOCK); - free((void *)usb_filename); - if (bdev->hw_fd < 0) { - err(errno, "Can't open device `%s'", usb_filename); - goto fd; - } - bdev->dev.reset = bdev_reset; + break; + case RT_USB_RESET: + bdev->dev.reset = bdev_usb_reset; + break; + default: + assert(0); } assert(!ioctl(bdev->fd, BLKGETSIZE64, &bdev->dev.size_byte)); diff --git a/libdevs.h b/libdevs.h index b68577c..e67a3d7 100644 --- a/libdevs.h +++ b/libdevs.h @@ -23,7 +23,7 @@ enum fake_type { /* Device is a sequence of wraparound and limbo regions. */ FKTY_CHAIN, - FKTY_MAX, + FKTY_MAX }; const char *fake_type_to_name(enum fake_type fake_type); @@ -66,7 +66,15 @@ struct device *create_file_device(const char *filename, uint64_t real_size_byte, uint64_t fake_size_byte, int wrap, int block_order, int keep_file); -struct device *create_block_device(const char *filename, int manual_reset); +/* XXX Add support for block devices backed by SCSI and ATA. */ +enum reset_type { + RT_MANUAL = 0, + RT_USB_RESET, + RT_MAX +}; +#define RT_DEFAULT RT_MANUAL + +struct device *create_block_device(const char *filename, enum reset_type rt); struct device *create_perf_device(struct device *dev); void perf_device_sample(struct device *dev,