mirror of
https://github.com/AltraMayor/f3.git
synced 2025-08-04 02:55:57 -04:00
f3probe: add option --manual-reset
The current reset method isn't supported for all USB drives, what leads to wrong conclusions about some fake drives. The option --manual-reset allows users to unplug and plug back the USB drive being tested to manually reset the drive.
This commit is contained in:
parent
73a657deec
commit
35a351ff39
12
f3probe.c
12
f3probe.c
@ -43,6 +43,8 @@ static struct argp_option options[] = {
|
|||||||
"Run a unit test; it ignores all other debug options", 0},
|
"Run a unit test; it ignores all other debug options", 0},
|
||||||
{"destructive", 'n', NULL, 0,
|
{"destructive", 'n', NULL, 0,
|
||||||
"Do not restore blocks of the device after probing it", 2},
|
"Do not restore blocks of the device after probing it", 2},
|
||||||
|
{"manual-reset", 'm', NULL, 0,
|
||||||
|
"Ask user to manually reset the drive", 0},
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -59,6 +61,9 @@ struct args {
|
|||||||
uint64_t fake_size_byte;
|
uint64_t fake_size_byte;
|
||||||
int wrap;
|
int wrap;
|
||||||
int block_order;
|
int block_order;
|
||||||
|
|
||||||
|
bool manual_reset;
|
||||||
|
/* 3 free bytes. */
|
||||||
};
|
};
|
||||||
|
|
||||||
static long long arg_to_long_long(const struct argp_state *state,
|
static long long arg_to_long_long(const struct argp_state *state,
|
||||||
@ -132,6 +137,10 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state)
|
|||||||
args->save = false;
|
args->save = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'm':
|
||||||
|
args->manual_reset = true;
|
||||||
|
break;
|
||||||
|
|
||||||
case ARGP_KEY_INIT:
|
case ARGP_KEY_INIT:
|
||||||
args->filename = NULL;
|
args->filename = NULL;
|
||||||
break;
|
break;
|
||||||
@ -284,7 +293,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);
|
: create_block_device(args->filename, args->manual_reset);
|
||||||
assert(dev);
|
assert(dev);
|
||||||
|
|
||||||
if (args->save) {
|
if (args->save) {
|
||||||
@ -345,6 +354,7 @@ int main(int argc, char **argv)
|
|||||||
.fake_size_byte = 1ULL << 34,
|
.fake_size_byte = 1ULL << 34,
|
||||||
.wrap = 31,
|
.wrap = 31,
|
||||||
.block_order = 9,
|
.block_order = 9,
|
||||||
|
.manual_reset = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Read parameters. */
|
/* Read parameters. */
|
||||||
|
58
libprobe.c
58
libprobe.c
@ -324,6 +324,21 @@ static inline int bdev_open(const char *filename)
|
|||||||
return open(filename, O_RDWR | O_DIRECT | O_SYNC);
|
return open(filename, O_RDWR | O_DIRECT | O_SYNC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* XXX Monitor the USB subsytem to know when the drive was unplugged and
|
||||||
|
* plugged back to continue instead of waiting for a key.
|
||||||
|
*/
|
||||||
|
static int bdev_manual_reset(struct device *dev)
|
||||||
|
{
|
||||||
|
struct block_device *bdev = dev_bdev(dev);
|
||||||
|
assert(!close(bdev->fd));
|
||||||
|
printf("Please unplug and plug back the USB drive, and press a key to continue...\n");
|
||||||
|
getchar();
|
||||||
|
bdev->fd = bdev_open(bdev->filename);
|
||||||
|
if (bdev->fd < 0)
|
||||||
|
err(errno, "Can't REopen device `%s'", bdev->filename);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int bdev_reset(struct device *dev)
|
static int bdev_reset(struct device *dev)
|
||||||
{
|
{
|
||||||
struct block_device *bdev = dev_bdev(dev);
|
struct block_device *bdev = dev_bdev(dev);
|
||||||
@ -338,8 +353,10 @@ static int bdev_reset(struct device *dev)
|
|||||||
static void bdev_free(struct device *dev)
|
static void bdev_free(struct device *dev)
|
||||||
{
|
{
|
||||||
struct block_device *bdev = dev_bdev(dev);
|
struct block_device *bdev = dev_bdev(dev);
|
||||||
assert(!close(bdev->hw_fd));
|
if (bdev->hw_fd >= 0)
|
||||||
assert(!close(bdev->fd));
|
assert(!close(bdev->hw_fd));
|
||||||
|
if (bdev->fd >= 0)
|
||||||
|
assert(!close(bdev->fd));
|
||||||
free((void *)bdev->filename);
|
free((void *)bdev->filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,14 +463,14 @@ static int ilog2(uint64_t x)
|
|||||||
* Suggest how to call f3probe with the correct device name if
|
* Suggest how to call f3probe with the correct device name if
|
||||||
* the block device is a partition.
|
* the block device is a partition.
|
||||||
* Use udev to do these tests.
|
* Use udev to do these tests.
|
||||||
|
* Make sure that no partition of the drive is mounted.
|
||||||
*/
|
*/
|
||||||
/* XXX Test for write access of the block device to give
|
/* XXX Test for write access of the block device to give
|
||||||
* a nice error message.
|
* a nice error message.
|
||||||
* If it fails, suggest running f3probe as root.
|
* If it fails, suggest running f3probe as root.
|
||||||
*/
|
*/
|
||||||
struct device *create_block_device(const char *filename)
|
struct device *create_block_device(const char *filename, int manual_reset)
|
||||||
{
|
{
|
||||||
const char *usb_filename;
|
|
||||||
struct block_device *bdev;
|
struct block_device *bdev;
|
||||||
int block_size;
|
int block_size;
|
||||||
|
|
||||||
@ -476,18 +493,25 @@ struct device *create_block_device(const char *filename)
|
|||||||
goto fd;
|
goto fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX Add support for block devices backed by SCSI, SATA, and ATA. */
|
if (manual_reset) {
|
||||||
usb_filename = map_block_to_usb_dev(filename);
|
bdev->hw_fd = -1;
|
||||||
if (!usb_filename) {
|
bdev->dev.reset = bdev_manual_reset;
|
||||||
err(EINVAL, "Block device `%s' is not backed by a USB device",
|
} else {
|
||||||
filename);
|
/* XXX Add support for block devices backed by SCSI and ATA. */
|
||||||
goto fd;
|
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);
|
bdev->hw_fd = open(usb_filename, O_WRONLY | O_NONBLOCK);
|
||||||
if (bdev->hw_fd < 0) {
|
free((void *)usb_filename);
|
||||||
err(errno, "Can't open device `%s'", usb_filename);
|
if (bdev->hw_fd < 0) {
|
||||||
goto usb_filename;
|
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));
|
||||||
@ -498,14 +522,10 @@ struct device *create_block_device(const char *filename)
|
|||||||
|
|
||||||
bdev->dev.read_block = bdev_read_block;
|
bdev->dev.read_block = bdev_read_block;
|
||||||
bdev->dev.write_block = bdev_write_block;
|
bdev->dev.write_block = bdev_write_block;
|
||||||
bdev->dev.reset = bdev_reset;
|
|
||||||
bdev->dev.free = bdev_free;
|
bdev->dev.free = bdev_free;
|
||||||
|
|
||||||
free((void *)usb_filename);
|
|
||||||
return &bdev->dev;
|
return &bdev->dev;
|
||||||
|
|
||||||
usb_filename:
|
|
||||||
free((void *)usb_filename);
|
|
||||||
fd:
|
fd:
|
||||||
assert(!close(bdev->fd));
|
assert(!close(bdev->fd));
|
||||||
filename:
|
filename:
|
||||||
|
@ -36,7 +36,7 @@ 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);
|
struct device *create_block_device(const char *filename, int manual_reset);
|
||||||
|
|
||||||
struct device *create_safe_device(struct device *dev, int max_blocks);
|
struct device *create_safe_device(struct device *dev, int max_blocks);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user