- 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:
parent
e5de30ab6d
commit
40cda51553
@ -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,
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user