- Split failure probability configuration into read failure probability and

write failure probability.
- Allow to specify an error number to return of failure.

MFC after:	3 days
This commit is contained in:
pjd 2006-09-08 09:21:21 +00:00
parent e5de30ab6d
commit 40cda51553
4 changed files with 102 additions and 39 deletions

View File

@ -1,5 +1,5 @@
/*- /*-
* Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org> * Copyright (c) 2004-2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -38,7 +38,9 @@ __FBSDID("$FreeBSD$");
uint32_t lib_version = G_LIB_VERSION; uint32_t lib_version = G_LIB_VERSION;
uint32_t version = G_NOP_VERSION; uint32_t version = G_NOP_VERSION;
static intmax_t failprob = 0; static intmax_t error = -1;
static intmax_t rfailprob = -1;
static intmax_t wfailprob = -1;
static intmax_t offset = 0; static intmax_t offset = 0;
static intmax_t secsize = 0; static intmax_t secsize = 0;
static intmax_t size = 0; static intmax_t size = 0;
@ -46,20 +48,25 @@ static intmax_t size = 0;
struct g_command class_commands[] = { struct g_command class_commands[] = {
{ "create", G_FLAG_VERBOSE | G_FLAG_LOADKLD, NULL, { "create", G_FLAG_VERBOSE | G_FLAG_LOADKLD, NULL,
{ {
{ 'f', "failprob", &failprob, G_TYPE_NUMBER }, { 'e', "error", &error, G_TYPE_NUMBER },
{ 'o', "offset", &offset, G_TYPE_NUMBER }, { 'o', "offset", &offset, G_TYPE_NUMBER },
{ 'r', "rfailprob", &rfailprob, G_TYPE_NUMBER },
{ 's', "size", &size, G_TYPE_NUMBER }, { 's', "size", &size, G_TYPE_NUMBER },
{ 'S', "secsize", &secsize, G_TYPE_NUMBER }, { 'S', "secsize", &secsize, G_TYPE_NUMBER },
{ 'w', "wfailprob", &wfailprob, G_TYPE_NUMBER },
G_OPT_SENTINEL G_OPT_SENTINEL
}, },
"[-v] [-f failprob] [-o offset] [-s size] [-S secsize] dev ..." "[-v] [-e error] [-o offset] [-r rfailprob] [-s size] [-S secsize] "
"[-w wfailprob] dev ..."
}, },
{ "configure", G_FLAG_VERBOSE, NULL, { "configure", G_FLAG_VERBOSE, NULL,
{ {
{ 'f', "failprob", &failprob, G_TYPE_NUMBER }, { 'e', "error", &error, G_TYPE_NUMBER },
{ 'r', "rfailprob", &rfailprob, G_TYPE_NUMBER },
{ 'w', "wfailprob", &wfailprob, G_TYPE_NUMBER },
G_OPT_SENTINEL G_OPT_SENTINEL
}, },
"[-v] [-f failprob] prov ..." "[-v] [-e error] [-r rfailprob] [-w wfailprob] prov ..."
}, },
{ "destroy", G_FLAG_VERBOSE, NULL, { "destroy", G_FLAG_VERBOSE, NULL,
{ {

View File

@ -1,4 +1,4 @@
.\" Copyright (c) 2004-2005 Pawel Jakub Dawidek <pjd@FreeBSD.org> .\" Copyright (c) 2004-2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
.\" All rights reserved. .\" All rights reserved.
.\" .\"
.\" Redistribution and use in source and binary forms, with or without .\" Redistribution and use in source and binary forms, with or without
@ -24,7 +24,7 @@
.\" .\"
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd May 21, 2004 .Dd September 8, 2006
.Dt GNOP 8 .Dt GNOP 8
.Os .Os
.Sh NAME .Sh NAME
@ -34,15 +34,19 @@
.Nm .Nm
.Cm create .Cm create
.Op Fl v .Op Fl v
.Op Fl f Ar failprob .Op Fl e Ar error
.Op Fl o Ar offset .Op Fl o Ar offset
.Op Fl r Ar rfailprob
.Op Fl s Ar size .Op Fl s Ar size
.Op Fl S Ar secsize .Op Fl S Ar secsize
.Op Fl w Ar wfailprob
.Ar dev ... .Ar dev ...
.Nm .Nm
.Cm configure .Cm configure
.Op Fl v .Op Fl v
.Op Fl f Ar failprob .Op Fl e Ar error
.Op Fl r Ar rfailprob
.Op Fl w Ar wfailprob
.Ar prov ... .Ar prov ...
.Nm .Nm
.Cm destroy .Cm destroy
@ -104,17 +108,21 @@ See
.El .El
.Pp .Pp
Additional options: Additional options:
.Bl -tag -width ".Fl f Ar failprob" .Bl -tag -width ".Fl f Ar rfailprob"
.It Fl e Ar error
Specifies the error number to return on failure.
.It Fl f .It Fl f
Force the removal of the specified provider. Force the removal of the specified provider.
.It Fl f Ar failprob
Specifies failure probability in percentage.
.It Fl o Ar offset .It Fl o Ar offset
Where to begin on the original provider. Where to begin on the original provider.
.It Fl r Ar rfailprob
Specifies read failure probability in percent.
.It Fl s Ar size .It Fl s Ar size
Size of the transparent provider. Size of the transparent provider.
.It Fl S Ar secsize .It Fl S Ar secsize
Sector size of the transparent provider. Sector size of the transparent provider.
.It Fl w Ar wfailprob
Specifies write failure probability in percent.
.It Fl v .It Fl v
Be more verbose. Be more verbose.
.El .El

View File

@ -1,5 +1,5 @@
/*- /*-
* Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org> * Copyright (c) 2004-2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -77,6 +77,7 @@ g_nop_start(struct bio *bp)
struct g_geom *gp; struct g_geom *gp;
struct g_provider *pp; struct g_provider *pp;
struct bio *cbp; struct bio *cbp;
u_int failprob = 0;
gp = bp->bio_to->geom; gp = bp->bio_to->geom;
sc = gp->softc; sc = gp->softc;
@ -85,19 +86,21 @@ g_nop_start(struct bio *bp)
case BIO_READ: case BIO_READ:
sc->sc_reads++; sc->sc_reads++;
sc->sc_readbytes += bp->bio_length; sc->sc_readbytes += bp->bio_length;
failprob = sc->sc_rfailprob;
break; break;
case BIO_WRITE: case BIO_WRITE:
sc->sc_writes++; sc->sc_writes++;
sc->sc_wrotebytes += bp->bio_length; sc->sc_wrotebytes += bp->bio_length;
failprob = sc->sc_wfailprob;
break; break;
} }
if (sc->sc_failprob > 0) { if (failprob > 0) {
u_int rval; u_int rval;
rval = arc4random() % 100; rval = arc4random() % 100;
if (rval < sc->sc_failprob) { if (rval < failprob) {
G_NOP_LOGREQ(bp, "Returning EIO."); G_NOP_LOGREQ(bp, "Returning error=%d.", sc->sc_error);
g_io_deliver(bp, EIO); g_io_deliver(bp, sc->sc_error);
return; return;
} }
} }
@ -133,7 +136,8 @@ g_nop_access(struct g_provider *pp, int dr, int dw, int de)
static int static int
g_nop_create(struct gctl_req *req, struct g_class *mp, struct g_provider *pp, g_nop_create(struct gctl_req *req, struct g_class *mp, struct g_provider *pp,
u_int failprob, off_t offset, off_t size, u_int secsize) int ioerror, u_int rfailprob, u_int wfailprob, off_t offset, off_t size,
u_int secsize)
{ {
struct g_nop_softc *sc; struct g_nop_softc *sc;
struct g_geom *gp; struct g_geom *gp;
@ -186,7 +190,9 @@ g_nop_create(struct gctl_req *req, struct g_class *mp, struct g_provider *pp,
} }
sc = g_malloc(sizeof(*sc), M_WAITOK); sc = g_malloc(sizeof(*sc), M_WAITOK);
sc->sc_offset = offset; sc->sc_offset = offset;
sc->sc_failprob = failprob; sc->sc_error = ioerror;
sc->sc_rfailprob = rfailprob;
sc->sc_wfailprob = wfailprob;
sc->sc_reads = 0; sc->sc_reads = 0;
sc->sc_writes = 0; sc->sc_writes = 0;
sc->sc_readbytes = 0; sc->sc_readbytes = 0;
@ -276,7 +282,7 @@ static void
g_nop_ctl_create(struct gctl_req *req, struct g_class *mp) g_nop_ctl_create(struct gctl_req *req, struct g_class *mp)
{ {
struct g_provider *pp; struct g_provider *pp;
intmax_t *failprob, *offset, *secsize, *size; intmax_t *error, *rfailprob, *wfailprob, *offset, *secsize, *size;
const char *name; const char *name;
char param[16]; char param[16];
int i, *nargs; int i, *nargs;
@ -292,13 +298,27 @@ g_nop_ctl_create(struct gctl_req *req, struct g_class *mp)
gctl_error(req, "Missing device(s)."); gctl_error(req, "Missing device(s).");
return; return;
} }
failprob = gctl_get_paraml(req, "failprob", sizeof(*failprob)); error = gctl_get_paraml(req, "error", sizeof(*error));
if (failprob == NULL) { if (error == NULL) {
gctl_error(req, "No '%s' argument", "failprob"); gctl_error(req, "No '%s' argument", "error");
return; return;
} }
if (*failprob < 0 || *failprob > 100) { rfailprob = gctl_get_paraml(req, "rfailprob", sizeof(*rfailprob));
gctl_error(req, "Invalid '%s' argument", "failprob"); if (rfailprob == NULL) {
gctl_error(req, "No '%s' argument", "rfailprob");
return;
}
if (*rfailprob < -1 || *rfailprob > 100) {
gctl_error(req, "Invalid '%s' argument", "rfailprob");
return;
}
wfailprob = gctl_get_paraml(req, "wfailprob", sizeof(*wfailprob));
if (wfailprob == NULL) {
gctl_error(req, "No '%s' argument", "wfailprob");
return;
}
if (*wfailprob < -1 || *wfailprob > 100) {
gctl_error(req, "Invalid '%s' argument", "wfailprob");
return; return;
} }
offset = gctl_get_paraml(req, "offset", sizeof(*offset)); offset = gctl_get_paraml(req, "offset", sizeof(*offset));
@ -344,8 +364,11 @@ g_nop_ctl_create(struct gctl_req *req, struct g_class *mp)
gctl_error(req, "Provider %s is invalid.", name); gctl_error(req, "Provider %s is invalid.", name);
return; return;
} }
if (g_nop_create(req, mp, pp, (u_int)*failprob, (off_t)*offset, if (g_nop_create(req, mp, pp,
(off_t)*size, (u_int)*secsize) != 0) { *error == -1 ? EIO : (int)*error,
*rfailprob == -1 ? 0 : (u_int)*rfailprob,
*wfailprob == -1 ? 0 : (u_int)*wfailprob,
(off_t)*offset, (off_t)*size, (u_int)*secsize) != 0) {
return; return;
} }
} }
@ -356,7 +379,7 @@ g_nop_ctl_configure(struct gctl_req *req, struct g_class *mp)
{ {
struct g_nop_softc *sc; struct g_nop_softc *sc;
struct g_provider *pp; struct g_provider *pp;
intmax_t *failprob; intmax_t *error, *rfailprob, *wfailprob;
const char *name; const char *name;
char param[16]; char param[16];
int i, *nargs; int i, *nargs;
@ -372,13 +395,27 @@ g_nop_ctl_configure(struct gctl_req *req, struct g_class *mp)
gctl_error(req, "Missing device(s)."); gctl_error(req, "Missing device(s).");
return; return;
} }
failprob = gctl_get_paraml(req, "failprob", sizeof(*failprob)); error = gctl_get_paraml(req, "error", sizeof(*error));
if (failprob == NULL) { if (error == NULL) {
gctl_error(req, "No '%s' argument", "failprob"); gctl_error(req, "No '%s' argument", "error");
return; return;
} }
if (*failprob < 0 || *failprob > 100) { rfailprob = gctl_get_paraml(req, "rfailprob", sizeof(*rfailprob));
gctl_error(req, "Invalid '%s' argument", "failprob"); if (rfailprob == NULL) {
gctl_error(req, "No '%s' argument", "rfailprob");
return;
}
if (*rfailprob < -1 || *rfailprob > 100) {
gctl_error(req, "Invalid '%s' argument", "rfailprob");
return;
}
wfailprob = gctl_get_paraml(req, "wfailprob", sizeof(*wfailprob));
if (wfailprob == NULL) {
gctl_error(req, "No '%s' argument", "wfailprob");
return;
}
if (*wfailprob < -1 || *wfailprob > 100) {
gctl_error(req, "Invalid '%s' argument", "wfailprob");
return; return;
} }
@ -398,7 +435,12 @@ g_nop_ctl_configure(struct gctl_req *req, struct g_class *mp)
return; return;
} }
sc = pp->geom->softc; sc = pp->geom->softc;
sc->sc_failprob = (u_int)*failprob; if (*error != -1)
sc->sc_error = (int)*error;
if (*rfailprob != -1)
sc->sc_rfailprob = (u_int)*rfailprob;
if (*wfailprob != -1)
sc->sc_wfailprob = (u_int)*wfailprob;
} }
} }
@ -552,7 +594,11 @@ g_nop_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp,
sc = gp->softc; sc = gp->softc;
sbuf_printf(sb, "%s<Offset>%jd</Offset>\n", indent, sbuf_printf(sb, "%s<Offset>%jd</Offset>\n", indent,
(intmax_t)sc->sc_offset); (intmax_t)sc->sc_offset);
sbuf_printf(sb, "%s<FailProb>%u</FailProb>\n", indent, sc->sc_failprob); sbuf_printf(sb, "%s<ReadFailProb>%u</ReadFailProb>\n", indent,
sc->sc_rfailprob);
sbuf_printf(sb, "%s<WriteFailProb>%u</WriteFailProb>\n", indent,
sc->sc_wfailprob);
sbuf_printf(sb, "%s<Error>%ju</Error>\n", indent, sc->sc_error);
sbuf_printf(sb, "%s<Reads>%ju</Reads>\n", indent, sc->sc_reads); sbuf_printf(sb, "%s<Reads>%ju</Reads>\n", indent, sc->sc_reads);
sbuf_printf(sb, "%s<Writes>%ju</Writes>\n", indent, sc->sc_writes); sbuf_printf(sb, "%s<Writes>%ju</Writes>\n", indent, sc->sc_writes);
sbuf_printf(sb, "%s<ReadBytes>%ju</ReadBytes>\n", indent, sbuf_printf(sb, "%s<ReadBytes>%ju</ReadBytes>\n", indent,

View File

@ -1,5 +1,5 @@
/*- /*-
* Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org> * Copyright (c) 2004-2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -30,7 +30,7 @@
#define _G_NOP_H_ #define _G_NOP_H_
#define G_NOP_CLASS_NAME "NOP" #define G_NOP_CLASS_NAME "NOP"
#define G_NOP_VERSION 3 #define G_NOP_VERSION 4
#define G_NOP_SUFFIX ".nop" #define G_NOP_SUFFIX ".nop"
#ifdef _KERNEL #ifdef _KERNEL
@ -55,8 +55,10 @@
} while (0) } while (0)
struct g_nop_softc { struct g_nop_softc {
int sc_error;
off_t sc_offset; off_t sc_offset;
u_int sc_failprob; u_int sc_rfailprob;
u_int sc_wfailprob;
uintmax_t sc_reads; uintmax_t sc_reads;
uintmax_t sc_writes; uintmax_t sc_writes;
uintmax_t sc_readbytes; uintmax_t sc_readbytes;