mirror of
https://github.com/AltraMayor/f3.git
synced 2025-09-10 07:39:31 -04:00
f3probe: make it more uniform to add reset methods
This commit is contained in:
parent
f2ac688edd
commit
fb8c784670
19
f3probe.c
19
f3probe.c
@ -45,8 +45,8 @@ static struct argp_option options[] = {
|
|||||||
"Do not restore blocks of the device after probing it", 2},
|
"Do not restore blocks of the device after probing it", 2},
|
||||||
{"min-memory", 'l', NULL, 0,
|
{"min-memory", 'l', NULL, 0,
|
||||||
"Trade speed for less use of memory", 0},
|
"Trade speed for less use of memory", 0},
|
||||||
{"manual-reset", 'm', NULL, 0,
|
{"reset-type", 's', "TYPE", 0,
|
||||||
"Ask user to manually reset the drive", 0},
|
"Reset method to use during the probe", 0},
|
||||||
{"time-ops", 't', NULL, 0,
|
{"time-ops", 't', NULL, 0,
|
||||||
"Time reads, writes, and resets", 0},
|
"Time reads, writes, and resets", 0},
|
||||||
{ 0 }
|
{ 0 }
|
||||||
@ -63,7 +63,7 @@ struct args {
|
|||||||
/* Behavior options. */
|
/* Behavior options. */
|
||||||
bool save;
|
bool save;
|
||||||
bool min_mem;
|
bool min_mem;
|
||||||
bool manual_reset;
|
enum reset_type reset_type;
|
||||||
bool time_ops;
|
bool time_ops;
|
||||||
/* 1 free bytes. */
|
/* 1 free bytes. */
|
||||||
|
|
||||||
@ -182,8 +182,13 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state)
|
|||||||
args->min_mem = true;
|
args->min_mem = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'm':
|
case 's':
|
||||||
args->manual_reset = true;
|
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;
|
break;
|
||||||
|
|
||||||
case 't':
|
case 't':
|
||||||
@ -357,7 +362,7 @@ static int test_device(struct args *args)
|
|||||||
? create_file_device(args->filename, args->real_size_byte,
|
? create_file_device(args->filename, args->real_size_byte,
|
||||||
args->fake_size_byte, args->wrap, args->block_order,
|
args->fake_size_byte, args->wrap, args->block_order,
|
||||||
args->keep_file)
|
args->keep_file)
|
||||||
: create_block_device(args->filename, args->manual_reset);
|
: create_block_device(args->filename, args->reset_type);
|
||||||
if (!dev) {
|
if (!dev) {
|
||||||
fprintf(stderr, "\nApplication cannot continue, finishing...\n");
|
fprintf(stderr, "\nApplication cannot continue, finishing...\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -456,7 +461,7 @@ int main(int argc, char **argv)
|
|||||||
.keep_file = false,
|
.keep_file = false,
|
||||||
.save = true,
|
.save = true,
|
||||||
.min_mem = false,
|
.min_mem = false,
|
||||||
.manual_reset = false,
|
.reset_type = RT_DEFAULT,
|
||||||
.time_ops = false,
|
.time_ops = false,
|
||||||
.real_size_byte = 1ULL << 31,
|
.real_size_byte = 1ULL << 31,
|
||||||
.fake_size_byte = 1ULL << 34,
|
.fake_size_byte = 1ULL << 34,
|
||||||
|
98
libdevs.c
98
libdevs.c
@ -275,7 +275,6 @@ struct block_device {
|
|||||||
|
|
||||||
const char *filename;
|
const char *filename;
|
||||||
int fd;
|
int fd;
|
||||||
int hw_fd; /* Underlying hardware of the block device. */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct block_device *dev_bdev(struct device *dev)
|
static inline struct block_device *dev_bdev(struct device *dev)
|
||||||
@ -337,34 +336,6 @@ static int bdev_manual_reset(struct device *dev)
|
|||||||
return 0;
|
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)
|
static char *map_block_to_usb_dev(const char *block_dev)
|
||||||
{
|
{
|
||||||
struct udev *udev;
|
struct udev *udev;
|
||||||
@ -433,6 +404,47 @@ static char *map_block_to_usb_dev(const char *block_dev)
|
|||||||
return usb_dev_path;
|
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.
|
/* XXX Test if it's a device, or a partition.
|
||||||
* If a partition, warn user, and ask for confirmation before
|
* If a partition, warn user, and ask for confirmation before
|
||||||
* going ahead.
|
* going ahead.
|
||||||
@ -441,7 +453,7 @@ static char *map_block_to_usb_dev(const char *block_dev)
|
|||||||
* Use udev to do these tests.
|
* Use udev to do these tests.
|
||||||
* Make sure that no partition of the drive is mounted.
|
* 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;
|
struct block_device *bdev;
|
||||||
int block_size;
|
int block_size;
|
||||||
@ -472,25 +484,15 @@ struct device *create_block_device(const char *filename, int manual_reset)
|
|||||||
goto fd;
|
goto fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (manual_reset) {
|
switch (rt) {
|
||||||
bdev->hw_fd = -1;
|
case RT_MANUAL:
|
||||||
bdev->dev.reset = bdev_manual_reset;
|
bdev->dev.reset = bdev_manual_reset;
|
||||||
} else {
|
break;
|
||||||
/* XXX Add support for block devices backed by SCSI and ATA. */
|
case RT_USB_RESET:
|
||||||
const char *usb_filename = map_block_to_usb_dev(filename);
|
bdev->dev.reset = bdev_usb_reset;
|
||||||
if (!usb_filename) {
|
break;
|
||||||
err(EINVAL, "Block device `%s' is not backed by a USB device",
|
default:
|
||||||
filename);
|
assert(0);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(!ioctl(bdev->fd, BLKGETSIZE64, &bdev->dev.size_byte));
|
assert(!ioctl(bdev->fd, BLKGETSIZE64, &bdev->dev.size_byte));
|
||||||
|
12
libdevs.h
12
libdevs.h
@ -23,7 +23,7 @@ enum fake_type {
|
|||||||
/* Device is a sequence of wraparound and limbo regions. */
|
/* Device is a sequence of wraparound and limbo regions. */
|
||||||
FKTY_CHAIN,
|
FKTY_CHAIN,
|
||||||
|
|
||||||
FKTY_MAX,
|
FKTY_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *fake_type_to_name(enum fake_type fake_type);
|
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,
|
uint64_t real_size_byte, uint64_t fake_size_byte, int wrap,
|
||||||
int block_order, int keep_file);
|
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);
|
struct device *create_perf_device(struct device *dev);
|
||||||
void perf_device_sample(struct device *dev,
|
void perf_device_sample(struct device *dev,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user