MFp4: Add two options for gnop(8)'s 'create' command:
-o offset - specifies where to start on the original provider -s size - specifies size of the transparent provider
This commit is contained in:
parent
3a50c49cc8
commit
3d268c83c7
@ -39,11 +39,15 @@ uint32_t lib_version = G_LIB_VERSION;
|
||||
uint32_t version = G_NOP_VERSION;
|
||||
|
||||
static intmax_t failprob = 0;
|
||||
static intmax_t offset = 0;
|
||||
static intmax_t size = 0;
|
||||
|
||||
struct g_command class_commands[] = {
|
||||
{ "create", G_FLAG_VERBOSE | G_FLAG_LOADKLD, NULL,
|
||||
{
|
||||
{ 'f', "failprob", &failprob, G_TYPE_NUMBER },
|
||||
{ 'o', "offset", &offset, G_TYPE_NUMBER },
|
||||
{ 's', "size", &size, G_TYPE_NUMBER },
|
||||
G_OPT_SENTINEL
|
||||
}
|
||||
},
|
||||
@ -67,7 +71,7 @@ void
|
||||
usage(const char *name)
|
||||
{
|
||||
|
||||
fprintf(stderr, "usage: %s create [-v] [-f failprob] <dev1> [dev2 [...]]\n", name);
|
||||
fprintf(stderr, "usage: %s create [-v] [-f failprob] [-o offset] [-s size] <dev1> [dev2 [...]]\n", name);
|
||||
fprintf(stderr, " %s configure [-v] [-f failprob] <prov1> [prov2 [...]]\n", name);
|
||||
fprintf(stderr, " %s destroy [-fv] <prov1> [prov2 [...]]\n", name);
|
||||
}
|
||||
|
@ -35,6 +35,8 @@
|
||||
.Cm create
|
||||
.Op Fl v
|
||||
.Op Fl f Ar failprob
|
||||
.Op Fl o Ar offset
|
||||
.Op Fl s Ar size
|
||||
.Ar dev1
|
||||
.Op Ar dev2 Op Ar ...
|
||||
.Nm
|
||||
@ -103,6 +105,10 @@ Additional options:
|
||||
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 o Ar size
|
||||
Size of the transparent provider.
|
||||
.It Fl v
|
||||
Be more verbose.
|
||||
.El
|
||||
|
@ -72,11 +72,13 @@ g_nop_orphan(struct g_consumer *cp)
|
||||
static void
|
||||
g_nop_start(struct bio *bp)
|
||||
{
|
||||
struct g_nop_softc *sc;
|
||||
struct g_geom *gp;
|
||||
struct g_provider *pp;
|
||||
struct bio *cbp;
|
||||
|
||||
gp = bp->bio_to->geom;
|
||||
sc = gp->softc;
|
||||
G_NOP_LOGREQ(bp, "Request received.");
|
||||
cbp = g_clone_bio(bp);
|
||||
if (cbp == NULL) {
|
||||
@ -85,17 +87,17 @@ g_nop_start(struct bio *bp)
|
||||
}
|
||||
pp = LIST_FIRST(&gp->provider);
|
||||
KASSERT(pp != NULL, ("NULL pp"));
|
||||
if (pp->index > 0) {
|
||||
if (sc->sc_failprob > 0) {
|
||||
u_int rval;
|
||||
|
||||
rval = arc4random() % 100;
|
||||
if (rval < pp->index) {
|
||||
if (rval < sc->sc_failprob) {
|
||||
g_io_deliver(bp, EIO);
|
||||
return;
|
||||
}
|
||||
}
|
||||
cbp->bio_done = g_std_done;
|
||||
cbp->bio_offset = bp->bio_offset;
|
||||
cbp->bio_offset = bp->bio_offset + sc->sc_offset;
|
||||
cbp->bio_data = bp->bio_data;
|
||||
cbp->bio_length = bp->bio_length;
|
||||
cbp->bio_to = LIST_FIRST(&gp->provider);
|
||||
@ -119,8 +121,9 @@ 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)
|
||||
u_int failprob, off_t offset, off_t size)
|
||||
{
|
||||
struct g_nop_softc *sc;
|
||||
struct g_geom *gp;
|
||||
struct g_provider *newpp;
|
||||
struct g_consumer *cp;
|
||||
@ -133,6 +136,24 @@ g_nop_create(struct gctl_req *req, struct g_class *mp, struct g_provider *pp,
|
||||
newpp = NULL;
|
||||
cp = NULL;
|
||||
|
||||
if ((offset % pp->sectorsize) != 0) {
|
||||
gctl_error(req, "Invalid offset for provider %s.", pp->name);
|
||||
return (EINVAL);
|
||||
}
|
||||
if ((size % pp->sectorsize) != 0) {
|
||||
gctl_error(req, "Invalid size for provider %s.", pp->name);
|
||||
return (EINVAL);
|
||||
}
|
||||
if (offset >= pp->mediasize) {
|
||||
gctl_error(req, "Invalid offset for provider %s.", pp->name);
|
||||
return (EINVAL);
|
||||
}
|
||||
if (size == 0)
|
||||
size = pp->mediasize - offset;
|
||||
if (offset + size > pp->mediasize) {
|
||||
gctl_error(req, "Invalid size for provider %s.", pp->name);
|
||||
return (EINVAL);
|
||||
}
|
||||
snprintf(name, sizeof(name), "%s%s", pp->name, G_NOP_SUFFIX);
|
||||
LIST_FOREACH(gp, &mp->geom, geom) {
|
||||
if (strcmp(gp->name, name) == 0) {
|
||||
@ -145,7 +166,10 @@ g_nop_create(struct gctl_req *req, struct g_class *mp, struct g_provider *pp,
|
||||
gctl_error(req, "Cannot create geom %s.", name);
|
||||
return (ENOMEM);
|
||||
}
|
||||
gp->softc = NULL;
|
||||
sc = g_malloc(sizeof(*sc), M_WAITOK);
|
||||
sc->sc_offset = offset;
|
||||
sc->sc_failprob = failprob;
|
||||
gp->softc = sc;
|
||||
gp->start = g_nop_start;
|
||||
gp->spoiled = g_nop_orphan;
|
||||
gp->orphan = g_nop_orphan;
|
||||
@ -158,9 +182,8 @@ g_nop_create(struct gctl_req *req, struct g_class *mp, struct g_provider *pp,
|
||||
error = ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
newpp->mediasize = pp->mediasize;
|
||||
newpp->mediasize = size;
|
||||
newpp->sectorsize = pp->sectorsize;
|
||||
newpp->index = failprob;
|
||||
|
||||
cp = g_new_consumer(gp);
|
||||
if (cp == NULL) {
|
||||
@ -185,8 +208,11 @@ g_nop_create(struct gctl_req *req, struct g_class *mp, struct g_provider *pp,
|
||||
}
|
||||
if (newpp != NULL)
|
||||
g_destroy_provider(pp);
|
||||
if (gp != NULL)
|
||||
if (gp != NULL) {
|
||||
if (gp->softc != NULL)
|
||||
g_free(gp->softc);
|
||||
g_destroy_geom(gp);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -209,6 +235,8 @@ g_nop_destroy(struct g_geom *gp, boolean_t force)
|
||||
} else {
|
||||
G_NOP_DEBUG(0, "Device %s removed.", gp->name);
|
||||
}
|
||||
g_free(gp->softc);
|
||||
gp->softc = NULL;
|
||||
g_wither_geom(gp, ENXIO);
|
||||
|
||||
return (0);
|
||||
@ -225,7 +253,7 @@ static void
|
||||
g_nop_ctl_create(struct gctl_req *req, struct g_class *mp)
|
||||
{
|
||||
struct g_provider *pp;
|
||||
intmax_t *failprob;
|
||||
intmax_t *failprob, *offset, *size;
|
||||
const char *name;
|
||||
char param[16];
|
||||
int i, *nargs;
|
||||
@ -250,6 +278,24 @@ g_nop_ctl_create(struct gctl_req *req, struct g_class *mp)
|
||||
gctl_error(req, "Invalid '%s' argument", "failprob");
|
||||
return;
|
||||
}
|
||||
offset = gctl_get_paraml(req, "offset", sizeof(*offset));
|
||||
if (offset == NULL) {
|
||||
gctl_error(req, "No '%s' argument", "offset");
|
||||
return;
|
||||
}
|
||||
if (*offset < 0) {
|
||||
gctl_error(req, "Invalid '%s' argument", "offset");
|
||||
return;
|
||||
}
|
||||
size = gctl_get_paraml(req, "size", sizeof(*size));
|
||||
if (size == NULL) {
|
||||
gctl_error(req, "No '%s' argument", "size");
|
||||
return;
|
||||
}
|
||||
if (*size < 0) {
|
||||
gctl_error(req, "Invalid '%s' argument", "size");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < *nargs; i++) {
|
||||
snprintf(param, sizeof(param), "arg%d", i);
|
||||
@ -266,14 +312,17 @@ 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) != 0)
|
||||
if (g_nop_create(req, mp, pp, (u_int)*failprob, (off_t)*offset,
|
||||
(off_t)*size) != 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
g_nop_ctl_configure(struct gctl_req *req, struct g_class *mp)
|
||||
{
|
||||
struct g_nop_softc *sc;
|
||||
struct g_provider *pp;
|
||||
intmax_t *failprob;
|
||||
const char *name;
|
||||
@ -316,7 +365,8 @@ g_nop_ctl_configure(struct gctl_req *req, struct g_class *mp)
|
||||
gctl_error(req, "Provider %s is invalid.", name);
|
||||
return;
|
||||
}
|
||||
pp->index = (u_int)*failprob;
|
||||
sc = pp->geom->softc;
|
||||
sc->sc_failprob = (u_int)*failprob;
|
||||
}
|
||||
}
|
||||
|
||||
@ -416,11 +466,14 @@ static void
|
||||
g_nop_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp,
|
||||
struct g_consumer *cp, struct g_provider *pp)
|
||||
{
|
||||
struct g_nop_softc *sc;
|
||||
|
||||
if (pp != NULL) {
|
||||
sbuf_printf(sb, "%s<failprob>%u</failprob>\n", indent,
|
||||
pp->index);
|
||||
}
|
||||
if (pp == NULL)
|
||||
return;
|
||||
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);
|
||||
}
|
||||
|
||||
DECLARE_GEOM_CLASS(g_nop_class, g_nop);
|
||||
|
@ -30,7 +30,7 @@
|
||||
#define _G_NOP_H_
|
||||
|
||||
#define G_NOP_CLASS_NAME "NOP"
|
||||
#define G_NOP_VERSION 1
|
||||
#define G_NOP_VERSION 2
|
||||
#define G_NOP_SUFFIX ".nop"
|
||||
|
||||
#ifdef _KERNEL
|
||||
@ -53,6 +53,11 @@
|
||||
printf("\n"); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
struct g_nop_softc {
|
||||
off_t sc_offset;
|
||||
u_int sc_failprob;
|
||||
};
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* _G_NOP_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user