Add a "count_until_fail" option to gnop, which says to start failing

I/O requests after the given number have been allowed though.

Approved by:    imp (mentor)
Reviewed by:    rpokala kib 0mp mckusick
Sponsored by:   Netflix
Differential Revision:  https://reviews.freebsd.org/D21593
This commit is contained in:
Chuck Silvers 2019-09-13 23:03:56 +00:00
parent f8b45306c6
commit 090a3ea3c2
4 changed files with 52 additions and 13 deletions

View File

@ -43,6 +43,7 @@ uint32_t version = G_NOP_VERSION;
struct g_command class_commands[] = {
{ "create", G_FLAG_VERBOSE | G_FLAG_LOADKLD, NULL,
{
{ 'c', "count_until_fail", "-1", G_TYPE_NUMBER },
{ 'd', "delaymsec", "-1", G_TYPE_NUMBER },
{ 'e', "error", "-1", G_TYPE_NUMBER },
{ 'o', "offset", "0", G_TYPE_NUMBER },
@ -57,12 +58,14 @@ struct g_command class_commands[] = {
{ 'z', "physpath", G_NOP_PHYSPATH_PASSTHROUGH, G_TYPE_STRING },
G_OPT_SENTINEL
},
"[-v] [-d delaymsec] [-e error] [-o offset] [-p stripesize] "
"[-P stripeoffset] [-q rdelayprob] [-r rfailprob] [-s size] "
"[-S secsize] [-w wfailprob] [-x wdelayprob] [-z physpath] dev ..."
"[-v] [-c count_until_fail] [-d delaymsec] [-e error] [-o offset] "
"[-p stripesize] [-P stripeoffset] [-q rdelayprob] [-r rfailprob] "
"[-s size] [-S secsize] [-w wfailprob] [-x wdelayprob] "
"[-z physpath] dev ..."
},
{ "configure", G_FLAG_VERBOSE, NULL,
{
{ 'c', "count_until_fail", "-1", G_TYPE_NUMBER },
{ 'd', "delaymsec", "-1", G_TYPE_NUMBER },
{ 'e', "error", "-1", G_TYPE_NUMBER },
{ 'q', "rdelayprob", "-1", G_TYPE_NUMBER },
@ -71,8 +74,9 @@ struct g_command class_commands[] = {
{ 'x', "wdelayprob", "-1", G_TYPE_NUMBER },
G_OPT_SENTINEL
},
"[-v] [-d delaymsec] [-e error] [-q rdelayprob] [-r rfailprob] "
"[-w wfailprob] [-x wdelayprob] prov ..."
"[-v] [-c count_until_fail] [-d delaymsec] [-e error] "
"[-q rdelayprob] [-r rfailprob] [-w wfailprob] [-x wdelayprob] "
"prov ..."
},
{ "destroy", G_FLAG_VERBOSE, NULL,
{

View File

@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd July 31, 2019
.Dd September 13, 2019
.Dt GNOP 8
.Os
.Sh NAME
@ -34,6 +34,7 @@
.Nm
.Cm create
.Op Fl v
.Op Fl c Ar count_until_fail
.Op Fl d Ar delaymsec
.Op Fl e Ar error
.Op Fl o Ar offset
@ -50,6 +51,7 @@
.Nm
.Cm configure
.Op Fl v
.Op Fl c Ar count_until_fail
.Op Fl d Ar delaymsec
.Op Fl e Ar error
.Op Fl q Ar rdelayprob
@ -118,7 +120,10 @@ See
.El
.Pp
Additional options:
.Bl -tag -width ".Fl r Ar rfailprob"
.Bl -tag -width "-c count_until_fail"
.It Fl c Ar count_until_fail
Specifies the number of I/O requests to allow before setting the read and write
failure probabilities to 100%.
.It Fl d Ar delaymsec
Specifies the delay of the requests in milliseconds.
Note that requests will be delayed before they are sent to the backing device.

View File

@ -195,6 +195,10 @@ g_nop_start(struct bio *bp)
G_NOP_LOGREQ(bp, "Request received.");
mtx_lock(&sc->sc_lock);
if (sc->sc_count_until_fail != 0 && --sc->sc_count_until_fail == 0) {
sc->sc_rfailprob = 100;
sc->sc_wfailprob = 100;
}
switch (bp->bio_cmd) {
case BIO_READ:
sc->sc_reads++;
@ -308,9 +312,10 @@ g_nop_access(struct g_provider *pp, int dr, int dw, int de)
static int
g_nop_create(struct gctl_req *req, struct g_class *mp, struct g_provider *pp,
int ioerror, u_int rfailprob, u_int wfailprob, u_int delaymsec, u_int rdelayprob,
u_int wdelayprob, off_t offset, off_t size, u_int secsize, off_t stripesize,
off_t stripeoffset, const char *physpath)
int ioerror, u_int count_until_fail, u_int rfailprob, u_int wfailprob,
u_int delaymsec, u_int rdelayprob, u_int wdelayprob, off_t offset,
off_t size, u_int secsize, off_t stripesize, off_t stripeoffset,
const char *physpath)
{
struct g_nop_softc *sc;
struct g_geom *gp;
@ -386,6 +391,7 @@ g_nop_create(struct gctl_req *req, struct g_class *mp, struct g_provider *pp,
} else
sc->sc_physpath = NULL;
sc->sc_error = ioerror;
sc->sc_count_until_fail = count_until_fail;
sc->sc_rfailprob = rfailprob;
sc->sc_wfailprob = wfailprob;
sc->sc_delaymsec = delaymsec;
@ -491,8 +497,9 @@ static void
g_nop_ctl_create(struct gctl_req *req, struct g_class *mp)
{
struct g_provider *pp;
intmax_t *error, *rfailprob, *wfailprob, *offset, *secsize, *size,
*stripesize, *stripeoffset, *delaymsec, *rdelayprob, *wdelayprob;
intmax_t *error, *rfailprob, *wfailprob, *count_until_fail, *offset,
*secsize, *size, *stripesize, *stripeoffset, *delaymsec,
*rdelayprob, *wdelayprob;
const char *name, *physpath;
char param[16];
int i, *nargs;
@ -558,6 +565,16 @@ g_nop_ctl_create(struct gctl_req *req, struct g_class *mp)
gctl_error(req, "Invalid '%s' argument", "wdelayprob");
return;
}
count_until_fail = gctl_get_paraml(req, "count_until_fail",
sizeof(*count_until_fail));
if (count_until_fail == NULL) {
gctl_error(req, "No '%s' argument", "count_until_fail");
return;
}
if (*count_until_fail < -1) {
gctl_error(req, "Invalid '%s' argument", "count_until_fail");
return;
}
offset = gctl_get_paraml(req, "offset", sizeof(*offset));
if (offset == NULL) {
gctl_error(req, "No '%s' argument", "offset");
@ -622,6 +639,7 @@ g_nop_ctl_create(struct gctl_req *req, struct g_class *mp)
}
if (g_nop_create(req, mp, pp,
*error == -1 ? EIO : (int)*error,
*count_until_fail == -1 ? 0 : (u_int)*count_until_fail,
*rfailprob == -1 ? 0 : (u_int)*rfailprob,
*wfailprob == -1 ? 0 : (u_int)*wfailprob,
*delaymsec == -1 ? 1 : (u_int)*delaymsec,
@ -640,7 +658,8 @@ g_nop_ctl_configure(struct gctl_req *req, struct g_class *mp)
{
struct g_nop_softc *sc;
struct g_provider *pp;
intmax_t *delaymsec, *error, *rdelayprob, *rfailprob, *wdelayprob, *wfailprob;
intmax_t *delaymsec, *error, *rdelayprob, *rfailprob, *wdelayprob,
*wfailprob, *count_until_fail;
const char *name;
char param[16];
int i, *nargs;
@ -661,6 +680,12 @@ g_nop_ctl_configure(struct gctl_req *req, struct g_class *mp)
gctl_error(req, "No '%s' argument", "error");
return;
}
count_until_fail = gctl_get_paraml(req, "count_until_fail",
sizeof(*count_until_fail));
if (count_until_fail == NULL) {
gctl_error(req, "No '%s' argument", "count_until_fail");
return;
}
rfailprob = gctl_get_paraml(req, "rfailprob", sizeof(*rfailprob));
if (rfailprob == NULL) {
gctl_error(req, "No '%s' argument", "rfailprob");
@ -736,6 +761,8 @@ g_nop_ctl_configure(struct gctl_req *req, struct g_class *mp)
sc->sc_wdelayprob = (u_int)*wdelayprob;
if (*delaymsec != -1)
sc->sc_delaymsec = (u_int)*delaymsec;
if (*count_until_fail != -1)
sc->sc_count_until_fail = (u_int)*count_until_fail;
}
}
@ -904,6 +931,8 @@ g_nop_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp,
sbuf_printf(sb, "%s<WriteDelayedProb>%u</WriteDelayedProb>\n", indent,
sc->sc_wdelayprob);
sbuf_printf(sb, "%s<Delay>%d</Delay>\n", indent, sc->sc_delaymsec);
sbuf_printf(sb, "%s<CountUntilFail>%u</CountUntilFail>\n", indent,
sc->sc_count_until_fail);
sbuf_printf(sb, "%s<Error>%d</Error>\n", indent, sc->sc_error);
sbuf_printf(sb, "%s<Reads>%ju</Reads>\n", indent, sc->sc_reads);
sbuf_printf(sb, "%s<Writes>%ju</Writes>\n", indent, sc->sc_writes);

View File

@ -62,6 +62,7 @@ struct g_nop_softc {
u_int sc_delaymsec;
u_int sc_rdelayprob;
u_int sc_wdelayprob;
u_int sc_count_until_fail;
uintmax_t sc_reads;
uintmax_t sc_writes;
uintmax_t sc_deletes;