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:
Pawel Jakub Dawidek 2004-07-19 07:52:56 +00:00
parent 3327cde241
commit e370e911b2
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=132381
4 changed files with 85 additions and 17 deletions

View File

@ -39,11 +39,15 @@ 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 failprob = 0;
static intmax_t offset = 0;
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 }, { 'f', "failprob", &failprob, G_TYPE_NUMBER },
{ 'o', "offset", &offset, G_TYPE_NUMBER },
{ 's', "size", &size, G_TYPE_NUMBER },
G_OPT_SENTINEL G_OPT_SENTINEL
} }
}, },
@ -67,7 +71,7 @@ void
usage(const char *name) 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 configure [-v] [-f failprob] <prov1> [prov2 [...]]\n", name);
fprintf(stderr, " %s destroy [-fv] <prov1> [prov2 [...]]\n", name); fprintf(stderr, " %s destroy [-fv] <prov1> [prov2 [...]]\n", name);
} }

View File

@ -35,6 +35,8 @@
.Cm create .Cm create
.Op Fl v .Op Fl v
.Op Fl f Ar failprob .Op Fl f Ar failprob
.Op Fl o Ar offset
.Op Fl s Ar size
.Ar dev1 .Ar dev1
.Op Ar dev2 Op Ar ... .Op Ar dev2 Op Ar ...
.Nm .Nm
@ -103,6 +105,10 @@ Additional options:
Force the removal of the specified provider. Force the removal of the specified provider.
.It Fl f Ar failprob .It Fl f Ar failprob
Specifies failure probability in percentage. 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 .It Fl v
Be more verbose. Be more verbose.
.El .El

View File

@ -72,11 +72,13 @@ g_nop_orphan(struct g_consumer *cp)
static void static void
g_nop_start(struct bio *bp) g_nop_start(struct bio *bp)
{ {
struct g_nop_softc *sc;
struct g_geom *gp; struct g_geom *gp;
struct g_provider *pp; struct g_provider *pp;
struct bio *cbp; struct bio *cbp;
gp = bp->bio_to->geom; gp = bp->bio_to->geom;
sc = gp->softc;
G_NOP_LOGREQ(bp, "Request received."); G_NOP_LOGREQ(bp, "Request received.");
cbp = g_clone_bio(bp); cbp = g_clone_bio(bp);
if (cbp == NULL) { if (cbp == NULL) {
@ -85,17 +87,17 @@ g_nop_start(struct bio *bp)
} }
pp = LIST_FIRST(&gp->provider); pp = LIST_FIRST(&gp->provider);
KASSERT(pp != NULL, ("NULL pp")); KASSERT(pp != NULL, ("NULL pp"));
if (pp->index > 0) { if (sc->sc_failprob > 0) {
u_int rval; u_int rval;
rval = arc4random() % 100; rval = arc4random() % 100;
if (rval < pp->index) { if (rval < sc->sc_failprob) {
g_io_deliver(bp, EIO); g_io_deliver(bp, EIO);
return; return;
} }
} }
cbp->bio_done = g_std_done; 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_data = bp->bio_data;
cbp->bio_length = bp->bio_length; cbp->bio_length = bp->bio_length;
cbp->bio_to = LIST_FIRST(&gp->provider); 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 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) u_int failprob, off_t offset, off_t size)
{ {
struct g_nop_softc *sc;
struct g_geom *gp; struct g_geom *gp;
struct g_provider *newpp; struct g_provider *newpp;
struct g_consumer *cp; 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; newpp = NULL;
cp = 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); snprintf(name, sizeof(name), "%s%s", pp->name, G_NOP_SUFFIX);
LIST_FOREACH(gp, &mp->geom, geom) { LIST_FOREACH(gp, &mp->geom, geom) {
if (strcmp(gp->name, name) == 0) { 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); gctl_error(req, "Cannot create geom %s.", name);
return (ENOMEM); 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->start = g_nop_start;
gp->spoiled = g_nop_orphan; gp->spoiled = g_nop_orphan;
gp->orphan = 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; error = ENOMEM;
goto fail; goto fail;
} }
newpp->mediasize = pp->mediasize; newpp->mediasize = size;
newpp->sectorsize = pp->sectorsize; newpp->sectorsize = pp->sectorsize;
newpp->index = failprob;
cp = g_new_consumer(gp); cp = g_new_consumer(gp);
if (cp == NULL) { 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) if (newpp != NULL)
g_destroy_provider(pp); g_destroy_provider(pp);
if (gp != NULL) if (gp != NULL) {
if (gp->softc != NULL)
g_free(gp->softc);
g_destroy_geom(gp); g_destroy_geom(gp);
}
return (error); return (error);
} }
@ -209,6 +235,8 @@ g_nop_destroy(struct g_geom *gp, boolean_t force)
} else { } else {
G_NOP_DEBUG(0, "Device %s removed.", gp->name); G_NOP_DEBUG(0, "Device %s removed.", gp->name);
} }
g_free(gp->softc);
gp->softc = NULL;
g_wither_geom(gp, ENXIO); g_wither_geom(gp, ENXIO);
return (0); return (0);
@ -225,7 +253,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; intmax_t *failprob, *offset, *size;
const char *name; const char *name;
char param[16]; char param[16];
int i, *nargs; 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"); gctl_error(req, "Invalid '%s' argument", "failprob");
return; 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++) { for (i = 0; i < *nargs; i++) {
snprintf(param, sizeof(param), "arg%d", 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); gctl_error(req, "Provider %s is invalid.", name);
return; 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; return;
}
} }
} }
static void static void
g_nop_ctl_configure(struct gctl_req *req, struct g_class *mp) g_nop_ctl_configure(struct gctl_req *req, struct g_class *mp)
{ {
struct g_nop_softc *sc;
struct g_provider *pp; struct g_provider *pp;
intmax_t *failprob; intmax_t *failprob;
const char *name; 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); gctl_error(req, "Provider %s is invalid.", name);
return; 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, g_nop_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp,
struct g_consumer *cp, struct g_provider *pp) struct g_consumer *cp, struct g_provider *pp)
{ {
struct g_nop_softc *sc;
if (pp != NULL) { if (pp == NULL)
sbuf_printf(sb, "%s<failprob>%u</failprob>\n", indent, return;
pp->index); 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); DECLARE_GEOM_CLASS(g_nop_class, g_nop);

View File

@ -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 1 #define G_NOP_VERSION 2
#define G_NOP_SUFFIX ".nop" #define G_NOP_SUFFIX ".nop"
#ifdef _KERNEL #ifdef _KERNEL
@ -53,6 +53,11 @@
printf("\n"); \ printf("\n"); \
} \ } \
} while (0) } while (0)
struct g_nop_softc {
off_t sc_offset;
u_int sc_failprob;
};
#endif /* _KERNEL */ #endif /* _KERNEL */
#endif /* _G_NOP_H_ */ #endif /* _G_NOP_H_ */