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;
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);
}

View File

@ -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

View File

@ -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);

View File

@ -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_ */