- 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.
*
* 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 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 secsize = 0;
static intmax_t size = 0;
@ -46,20 +48,25 @@ static intmax_t size = 0;
struct g_command class_commands[] = {
{ "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 },
{ 'r', "rfailprob", &rfailprob, G_TYPE_NUMBER },
{ 's', "size", &size, G_TYPE_NUMBER },
{ 'S', "secsize", &secsize, G_TYPE_NUMBER },
{ 'w', "wfailprob", &wfailprob, G_TYPE_NUMBER },
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,
{
{ '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
},
"[-v] [-f failprob] prov ..."
"[-v] [-e error] [-r rfailprob] [-w wfailprob] prov ..."
},
{ "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.
.\"
.\" Redistribution and use in source and binary forms, with or without
@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd May 21, 2004
.Dd September 8, 2006
.Dt GNOP 8
.Os
.Sh NAME
@ -34,15 +34,19 @@
.Nm
.Cm create
.Op Fl v
.Op Fl f Ar failprob
.Op Fl e Ar error
.Op Fl o Ar offset
.Op Fl r Ar rfailprob
.Op Fl s Ar size
.Op Fl S Ar secsize
.Op Fl w Ar wfailprob
.Ar dev ...
.Nm
.Cm configure
.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 ...
.Nm
.Cm destroy
@ -104,17 +108,21 @@ See
.El
.Pp
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
Force the removal of the specified provider.
.It Fl f Ar failprob
Specifies failure probability in percentage.
.It Fl o Ar offset
Where to begin on the original provider.
.It Fl r Ar rfailprob
Specifies read failure probability in percent.
.It Fl s Ar size
Size of the transparent provider.
.It Fl S Ar secsize
Sector size of the transparent provider.
.It Fl w Ar wfailprob
Specifies write failure probability in percent.
.It Fl v
Be more verbose.
.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.
*
* 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_provider *pp;
struct bio *cbp;
u_int failprob = 0;
gp = bp->bio_to->geom;
sc = gp->softc;
@ -85,19 +86,21 @@ g_nop_start(struct bio *bp)
case BIO_READ:
sc->sc_reads++;
sc->sc_readbytes += bp->bio_length;
failprob = sc->sc_rfailprob;
break;
case BIO_WRITE:
sc->sc_writes++;
sc->sc_wrotebytes += bp->bio_length;
failprob = sc->sc_wfailprob;
break;
}
if (sc->sc_failprob > 0) {
if (failprob > 0) {
u_int rval;
rval = arc4random() % 100;
if (rval < sc->sc_failprob) {
G_NOP_LOGREQ(bp, "Returning EIO.");
g_io_deliver(bp, EIO);
if (rval < failprob) {
G_NOP_LOGREQ(bp, "Returning error=%d.", sc->sc_error);
g_io_deliver(bp, sc->sc_error);
return;
}
}
@ -133,7 +136,8 @@ 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,
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_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->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_writes = 0;
sc->sc_readbytes = 0;
@ -276,7 +282,7 @@ static void
g_nop_ctl_create(struct gctl_req *req, struct g_class *mp)
{
struct g_provider *pp;
intmax_t *failprob, *offset, *secsize, *size;
intmax_t *error, *rfailprob, *wfailprob, *offset, *secsize, *size;
const char *name;
char param[16];
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).");
return;
}
failprob = gctl_get_paraml(req, "failprob", sizeof(*failprob));
if (failprob == NULL) {
gctl_error(req, "No '%s' argument", "failprob");
error = gctl_get_paraml(req, "error", sizeof(*error));
if (error == NULL) {
gctl_error(req, "No '%s' argument", "error");
return;
}
if (*failprob < 0 || *failprob > 100) {
gctl_error(req, "Invalid '%s' argument", "failprob");
rfailprob = gctl_get_paraml(req, "rfailprob", sizeof(*rfailprob));
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;
}
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);
return;
}
if (g_nop_create(req, mp, pp, (u_int)*failprob, (off_t)*offset,
(off_t)*size, (u_int)*secsize) != 0) {
if (g_nop_create(req, mp, pp,
*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;
}
}
@ -356,7 +379,7 @@ g_nop_ctl_configure(struct gctl_req *req, struct g_class *mp)
{
struct g_nop_softc *sc;
struct g_provider *pp;
intmax_t *failprob;
intmax_t *error, *rfailprob, *wfailprob;
const char *name;
char param[16];
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).");
return;
}
failprob = gctl_get_paraml(req, "failprob", sizeof(*failprob));
if (failprob == NULL) {
gctl_error(req, "No '%s' argument", "failprob");
error = gctl_get_paraml(req, "error", sizeof(*error));
if (error == NULL) {
gctl_error(req, "No '%s' argument", "error");
return;
}
if (*failprob < 0 || *failprob > 100) {
gctl_error(req, "Invalid '%s' argument", "failprob");
rfailprob = gctl_get_paraml(req, "rfailprob", sizeof(*rfailprob));
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;
}
@ -398,7 +435,12 @@ g_nop_ctl_configure(struct gctl_req *req, struct g_class *mp)
return;
}
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;
sbuf_printf(sb, "%s<Offset>%jd</Offset>\n", indent,
(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<Writes>%ju</Writes>\n", indent, sc->sc_writes);
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.
*
* Redistribution and use in source and binary forms, with or without
@ -30,7 +30,7 @@
#define _G_NOP_H_
#define G_NOP_CLASS_NAME "NOP"
#define G_NOP_VERSION 3
#define G_NOP_VERSION 4
#define G_NOP_SUFFIX ".nop"
#ifdef _KERNEL
@ -55,8 +55,10 @@
} while (0)
struct g_nop_softc {
int sc_error;
off_t sc_offset;
u_int sc_failprob;
u_int sc_rfailprob;
u_int sc_wfailprob;
uintmax_t sc_reads;
uintmax_t sc_writes;
uintmax_t sc_readbytes;