Inject zinject(8) a percentage amount of dev errs

In the original form of device error injection, it was an all or nothing
situation.  To help simulate intermittent error conditions, you can now
specify a real number percentage value. This is also very useful for our
ZFS fault diagnosis testing and for injecting intermittent errors during
load testing.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Don Brady <don.brady@intel.com>
Closes #6227
This commit is contained in:
Don Brady
2017-06-16 18:21:11 -06:00
committed by Brian Behlendorf
parent 05a5357a6c
commit 0241e491a0
4 changed files with 76 additions and 20 deletions
+30 -7
View File
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2015 by Delphix. All rights reserved.
* Copyright (c) 2017, Intel Corporation.
*/
/*
@@ -98,6 +99,26 @@ static kmutex_t inject_delay_mtx;
*/
static int inject_next_id = 1;
/*
* Test if the requested frequency was triggered
*/
static boolean_t
freq_triggered(uint32_t frequency)
{
/*
* zero implies always (100%)
*/
if (frequency == 0)
return (B_TRUE);
/*
* Note: we still handle legacy (unscaled) frequecy values
*/
uint32_t maximum = (frequency <= 100) ? 100 : ZI_PERCENTAGE_MAX;
return (spa_get_random(maximum) < frequency);
}
/*
* Returns true if the given record matches the I/O in progress.
*/
@@ -113,8 +134,7 @@ zio_match_handler(zbookmark_phys_t *zb, uint64_t type,
record->zi_object == DMU_META_DNODE_OBJECT) {
if (record->zi_type == DMU_OT_NONE ||
type == record->zi_type)
return (record->zi_freq == 0 ||
spa_get_random(100) < record->zi_freq);
return (freq_triggered(record->zi_freq));
else
return (B_FALSE);
}
@@ -128,8 +148,7 @@ zio_match_handler(zbookmark_phys_t *zb, uint64_t type,
zb->zb_blkid >= record->zi_start &&
zb->zb_blkid <= record->zi_end &&
error == record->zi_error)
return (record->zi_freq == 0 ||
spa_get_random(100) < record->zi_freq);
return (freq_triggered(record->zi_freq));
return (B_FALSE);
}
@@ -293,6 +312,12 @@ zio_handle_device_injection(vdev_t *vd, zio_t *zio, int error)
continue;
if (handler->zi_record.zi_error == error) {
/*
* limit error injection if requested
*/
if (!freq_triggered(handler->zi_record.zi_freq))
continue;
/*
* For a failed open, pretend like the device
* has gone away.
@@ -466,10 +491,8 @@ zio_handle_io_delay(zio_t *zio)
if (handler->zi_record.zi_cmd != ZINJECT_DELAY_IO)
continue;
if (handler->zi_record.zi_freq != 0 &&
spa_get_random(100) >= handler->zi_record.zi_freq) {
if (!freq_triggered(handler->zi_record.zi_freq))
continue;
}
if (vd->vdev_guid != handler->zi_record.zi_guid)
continue;