mirror of
https://git.proxmox.com/git/mirror_zfs
synced 2025-04-28 21:46:09 +00:00
zinject: make iotype extendable
I'm about to add a new "type", and I need somewhere to put it! Sponsored-by: Klara, Inc. Sponsored-by: Wasabi Technology, Inc. Reviewed-by: Alexander Motin <mav@FreeBSD.org> Reviewed-by: Tony Hutter <hutter2@llnl.gov> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Rob Norris <rob.norris@klarasystems.com> Closes #16947
This commit is contained in:
parent
cf55fdea24
commit
0dfcfe023e
@ -242,6 +242,35 @@ err_to_str(int err)
|
|||||||
return ("[unknown]");
|
return ("[unknown]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *const iotypestrtable[ZINJECT_IOTYPES] = {
|
||||||
|
[ZINJECT_IOTYPE_NULL] = "null",
|
||||||
|
[ZINJECT_IOTYPE_READ] = "read",
|
||||||
|
[ZINJECT_IOTYPE_WRITE] = "write",
|
||||||
|
[ZINJECT_IOTYPE_FREE] = "free",
|
||||||
|
[ZINJECT_IOTYPE_CLAIM] = "claim",
|
||||||
|
[ZINJECT_IOTYPE_FLUSH] = "flush",
|
||||||
|
[ZINJECT_IOTYPE_TRIM] = "trim",
|
||||||
|
[ZINJECT_IOTYPE_ALL] = "all",
|
||||||
|
};
|
||||||
|
|
||||||
|
static zinject_iotype_t
|
||||||
|
str_to_iotype(const char *arg)
|
||||||
|
{
|
||||||
|
for (uint_t iotype = 0; iotype < ZINJECT_IOTYPES; iotype++)
|
||||||
|
if (iotypestrtable[iotype] != NULL &&
|
||||||
|
strcasecmp(iotypestrtable[iotype], arg) == 0)
|
||||||
|
return (iotype);
|
||||||
|
return (ZINJECT_IOTYPES);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
iotype_to_str(zinject_iotype_t iotype)
|
||||||
|
{
|
||||||
|
if (iotype >= ZINJECT_IOTYPES || iotypestrtable[iotype] == NULL)
|
||||||
|
return ("[unknown]");
|
||||||
|
return (iotypestrtable[iotype]);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Print usage message.
|
* Print usage message.
|
||||||
*/
|
*/
|
||||||
@ -435,10 +464,6 @@ static int
|
|||||||
print_device_handler(int id, const char *pool, zinject_record_t *record,
|
print_device_handler(int id, const char *pool, zinject_record_t *record,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
static const char *iotypestr[] = {
|
|
||||||
"null", "read", "write", "free", "claim", "flush", "trim", "all",
|
|
||||||
};
|
|
||||||
|
|
||||||
int *count = data;
|
int *count = data;
|
||||||
|
|
||||||
if (record->zi_guid == 0 || record->zi_func[0] != '\0')
|
if (record->zi_guid == 0 || record->zi_func[0] != '\0')
|
||||||
@ -465,7 +490,7 @@ print_device_handler(int id, const char *pool, zinject_record_t *record,
|
|||||||
|
|
||||||
(void) printf("%3d %-15s %llx %-5s %-10s %8.4f%% "
|
(void) printf("%3d %-15s %llx %-5s %-10s %8.4f%% "
|
||||||
"%6lu %6lu\n", id, pool, (u_longlong_t)record->zi_guid,
|
"%6lu %6lu\n", id, pool, (u_longlong_t)record->zi_guid,
|
||||||
iotypestr[record->zi_iotype], err_to_str(record->zi_error),
|
iotype_to_str(record->zi_iotype), err_to_str(record->zi_error),
|
||||||
freq, record->zi_match_count, record->zi_inject_count);
|
freq, record->zi_match_count, record->zi_inject_count);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
@ -866,7 +891,7 @@ main(int argc, char **argv)
|
|||||||
int quiet = 0;
|
int quiet = 0;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
int domount = 0;
|
int domount = 0;
|
||||||
int io_type = ZIO_TYPES;
|
int io_type = ZINJECT_IOTYPE_ALL;
|
||||||
int action = VDEV_STATE_UNKNOWN;
|
int action = VDEV_STATE_UNKNOWN;
|
||||||
err_type_t type = TYPE_INVAL;
|
err_type_t type = TYPE_INVAL;
|
||||||
err_type_t label = TYPE_INVAL;
|
err_type_t label = TYPE_INVAL;
|
||||||
@ -1060,19 +1085,8 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'T':
|
case 'T':
|
||||||
if (strcasecmp(optarg, "read") == 0) {
|
io_type = str_to_iotype(optarg);
|
||||||
io_type = ZIO_TYPE_READ;
|
if (io_type == ZINJECT_IOTYPES) {
|
||||||
} else if (strcasecmp(optarg, "write") == 0) {
|
|
||||||
io_type = ZIO_TYPE_WRITE;
|
|
||||||
} else if (strcasecmp(optarg, "free") == 0) {
|
|
||||||
io_type = ZIO_TYPE_FREE;
|
|
||||||
} else if (strcasecmp(optarg, "claim") == 0) {
|
|
||||||
io_type = ZIO_TYPE_CLAIM;
|
|
||||||
} else if (strcasecmp(optarg, "flush") == 0) {
|
|
||||||
io_type = ZIO_TYPE_FLUSH;
|
|
||||||
} else if (strcasecmp(optarg, "all") == 0) {
|
|
||||||
io_type = ZIO_TYPES;
|
|
||||||
} else {
|
|
||||||
(void) fprintf(stderr, "invalid I/O type "
|
(void) fprintf(stderr, "invalid I/O type "
|
||||||
"'%s': must be 'read', 'write', 'free', "
|
"'%s': must be 'read', 'write', 'free', "
|
||||||
"'claim', 'flush' or 'all'\n", optarg);
|
"'claim', 'flush' or 'all'\n", optarg);
|
||||||
@ -1194,7 +1208,7 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (error == EILSEQ &&
|
if (error == EILSEQ &&
|
||||||
(record.zi_freq == 0 || io_type != ZIO_TYPE_READ)) {
|
(record.zi_freq == 0 || io_type != ZINJECT_IOTYPE_READ)) {
|
||||||
(void) fprintf(stderr, "device corrupt errors require "
|
(void) fprintf(stderr, "device corrupt errors require "
|
||||||
"io type read and a frequency value\n");
|
"io type read and a frequency value\n");
|
||||||
libzfs_fini(g_zfs);
|
libzfs_fini(g_zfs);
|
||||||
@ -1209,9 +1223,9 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
if (record.zi_nlanes) {
|
if (record.zi_nlanes) {
|
||||||
switch (io_type) {
|
switch (io_type) {
|
||||||
case ZIO_TYPE_READ:
|
case ZINJECT_IOTYPE_READ:
|
||||||
case ZIO_TYPE_WRITE:
|
case ZINJECT_IOTYPE_WRITE:
|
||||||
case ZIO_TYPES:
|
case ZINJECT_IOTYPE_ALL:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
(void) fprintf(stderr, "I/O type for a delay "
|
(void) fprintf(stderr, "I/O type for a delay "
|
||||||
|
@ -456,6 +456,24 @@ typedef enum zinject_type {
|
|||||||
ZINJECT_DELAY_EXPORT,
|
ZINJECT_DELAY_EXPORT,
|
||||||
} zinject_type_t;
|
} zinject_type_t;
|
||||||
|
|
||||||
|
typedef enum zinject_iotype {
|
||||||
|
/*
|
||||||
|
* Compatibility: zi_iotype used to be set to ZIO_TYPE_, so make sure
|
||||||
|
* the corresponding ZINJECT_IOTYPE_ matches. Note that existing here
|
||||||
|
* does not mean that injections are possible for all these types.
|
||||||
|
*/
|
||||||
|
ZINJECT_IOTYPE_NULL = ZIO_TYPE_NULL,
|
||||||
|
ZINJECT_IOTYPE_READ = ZIO_TYPE_READ,
|
||||||
|
ZINJECT_IOTYPE_WRITE = ZIO_TYPE_WRITE,
|
||||||
|
ZINJECT_IOTYPE_FREE = ZIO_TYPE_FREE,
|
||||||
|
ZINJECT_IOTYPE_CLAIM = ZIO_TYPE_CLAIM,
|
||||||
|
ZINJECT_IOTYPE_FLUSH = ZIO_TYPE_FLUSH,
|
||||||
|
ZINJECT_IOTYPE_TRIM = ZIO_TYPE_TRIM,
|
||||||
|
ZINJECT_IOTYPE_ALL = ZIO_TYPES,
|
||||||
|
/* Room for future expansion for ZIO_TYPE_* */
|
||||||
|
ZINJECT_IOTYPES = 16,
|
||||||
|
} zinject_iotype_t;
|
||||||
|
|
||||||
typedef struct zfs_share {
|
typedef struct zfs_share {
|
||||||
uint64_t z_exportdata;
|
uint64_t z_exportdata;
|
||||||
uint64_t z_sharedata;
|
uint64_t z_sharedata;
|
||||||
|
@ -376,6 +376,27 @@ zio_inject_bitflip_cb(void *data, size_t len, void *private)
|
|||||||
return (1); /* stop after first flip */
|
return (1); /* stop after first flip */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Test if this zio matches the iotype from the injection record. */
|
||||||
|
static boolean_t
|
||||||
|
zio_match_iotype(zio_t *zio, uint32_t iotype)
|
||||||
|
{
|
||||||
|
ASSERT3P(zio, !=, NULL);
|
||||||
|
|
||||||
|
/* Unknown iotype, maybe from a newer version of zinject. Reject it. */
|
||||||
|
if (iotype >= ZINJECT_IOTYPES)
|
||||||
|
return (B_FALSE);
|
||||||
|
|
||||||
|
/* Standard IO types, match against ZIO type. */
|
||||||
|
if (iotype < ZINJECT_IOTYPE_ALL)
|
||||||
|
return (iotype == zio->io_type);
|
||||||
|
|
||||||
|
/* Match any standard IO type. */
|
||||||
|
if (iotype == ZINJECT_IOTYPE_ALL)
|
||||||
|
return (B_TRUE);
|
||||||
|
|
||||||
|
return (B_FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
zio_handle_device_injection_impl(vdev_t *vd, zio_t *zio, int err1, int err2)
|
zio_handle_device_injection_impl(vdev_t *vd, zio_t *zio, int err1, int err2)
|
||||||
{
|
{
|
||||||
@ -410,9 +431,8 @@ zio_handle_device_injection_impl(vdev_t *vd, zio_t *zio, int err1, int err2)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Handle type specific I/O failures */
|
/* Handle type specific I/O failures */
|
||||||
if (zio != NULL &&
|
if (zio != NULL && !zio_match_iotype(zio,
|
||||||
handler->zi_record.zi_iotype != ZIO_TYPES &&
|
handler->zi_record.zi_iotype))
|
||||||
handler->zi_record.zi_iotype != zio->io_type)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (handler->zi_record.zi_error == err1 ||
|
if (handler->zi_record.zi_error == err1 ||
|
||||||
@ -635,10 +655,8 @@ zio_handle_io_delay(zio_t *zio)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* also match on I/O type (e.g., -T read) */
|
/* also match on I/O type (e.g., -T read) */
|
||||||
if (handler->zi_record.zi_iotype != ZIO_TYPES &&
|
if (!zio_match_iotype(zio, handler->zi_record.zi_iotype))
|
||||||
handler->zi_record.zi_iotype != zio->io_type) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Defensive; should never happen as the array allocation
|
* Defensive; should never happen as the array allocation
|
||||||
|
Loading…
Reference in New Issue
Block a user