diff --git a/sbin/geom/class/mirror/geom_mirror.c b/sbin/geom/class/mirror/geom_mirror.c index 04f035152a7b..e27c8acad33e 100644 --- a/sbin/geom/class/mirror/geom_mirror.c +++ b/sbin/geom/class/mirror/geom_mirror.c @@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -48,7 +49,7 @@ static char label_balance[] = "split", configure_balance[] = "none"; static intmax_t label_slice = 4096, configure_slice = -1; static intmax_t insert_priority = 0; -static void mirror_main(struct gctl_req *req, unsigned f); +static void mirror_main(struct gctl_req *req, unsigned flags); static void mirror_activate(struct gctl_req *req); static void mirror_clear(struct gctl_req *req); static void mirror_dump(struct gctl_req *req); @@ -61,6 +62,8 @@ struct g_command class_commands[] = { { { 'a', "autosync", NULL, G_TYPE_NONE }, { 'b', "balance", configure_balance, G_TYPE_STRING }, + { 'd', "dynamic", NULL, G_TYPE_NONE }, + { 'h', "hardcode", NULL, G_TYPE_NONE }, { 'n', "noautosync", NULL, G_TYPE_NONE }, { 's', "slice", &configure_slice, G_TYPE_NUMBER }, G_OPT_SENTINEL @@ -72,6 +75,7 @@ struct g_command class_commands[] = { { "label", G_FLAG_VERBOSE, mirror_main, { { 'b', "balance", label_balance, G_TYPE_STRING }, + { 'h', "hardcode", NULL, G_TYPE_NONE }, { 'n', "noautosync", NULL, G_TYPE_NONE }, { 's', "slice", &label_slice, G_TYPE_NUMBER }, G_OPT_SENTINEL @@ -79,6 +83,7 @@ struct g_command class_commands[] = { }, { "insert", G_FLAG_VERBOSE, NULL, { + { 'h', "hardcode", NULL, G_TYPE_NONE }, { 'i', "inactive", NULL, G_TYPE_NONE }, { 'p', "priority", &insert_priority, G_TYPE_NUMBER }, G_OPT_SENTINEL @@ -102,27 +107,27 @@ void usage(const char *comm) { fprintf(stderr, - "usage: %s label [-nv] [-b balance] [-s slice] name dev1 [dev2 [...]]\n" - " %s clear [-v] dev1 [dev2 [...]]\n" - " %s dump dev1 [dev2 [...]]\n" - " %s configure [-anv] [-b balance] [-s slice] name\n" - " %s rebuild [-v] name dev1 [dev2 [...]]\n" - " %s insert [-iv] [-p priority] name dev1 [dev2 [...]]\n" - " %s remove [-v] name dev1 [dev2 [...]]\n" - " %s activate [-v] name dev1 [dev2 [...]]\n" - " %s deactivate [-v] name dev1 [dev2 [...]]\n" - " %s forget dev1 [dev2 [...]]\n" + "usage: %s label [-hnv] [-b balance] [-s slice] name prov [prov [...]]\n" + " %s clear [-v] prov [prov [...]]\n" + " %s dump prov [prov [...]]\n" + " %s configure [-adhnv] [-b balance] [-s slice] name\n" + " %s rebuild [-v] name prov [prov [...]]\n" + " %s insert [-hiv] [-p priority] name prov [prov [...]]\n" + " %s remove [-v] name prov [prov [...]]\n" + " %s activate [-v] name prov [prov [...]]\n" + " %s deactivate [-v] name prov [prov [...]]\n" + " %s forget prov [prov [...]]\n" " %s stop [-fv] name\n", comm, comm, comm, comm, comm, comm, comm, comm, comm, comm, comm); exit(EXIT_FAILURE); } static void -mirror_main(struct gctl_req *req, unsigned f) +mirror_main(struct gctl_req *req, unsigned flags) { const char *name; - if ((f & G_FLAG_VERBOSE) != 0) + if ((flags & G_FLAG_VERBOSE) != 0) verbose = 1; name = gctl_get_asciiparam(req, "verb"); @@ -149,7 +154,7 @@ mirror_label(struct gctl_req *req) u_char sector[512]; const char *str; char param[16]; - int *nargs, *noautosync, bal, error, i; + int *hardcode, *nargs, *noautosync, bal, error, i; unsigned sectorsize; off_t mediasize; intmax_t *valp; @@ -202,6 +207,11 @@ mirror_label(struct gctl_req *req) } if (*noautosync) md.md_mflags |= G_MIRROR_DEVICE_FLAG_NOAUTOSYNC; + hardcode = gctl_get_paraml(req, "hardcode", sizeof(*hardcode)); + if (hardcode == NULL) { + gctl_error(req, "No '%s' argument.", "hardcode"); + return; + } /* * Calculate sectorsize by finding least common multiple from @@ -258,6 +268,13 @@ mirror_label(struct gctl_req *req) md.md_did = arc4random(); md.md_priority = i - 1; + if (!*hardcode) + bzero(md.md_provider, sizeof(md.md_provider)); + else { + if (strncmp(str, _PATH_DEV, strlen(_PATH_DEV)) == 0) + str += strlen(_PATH_DEV); + strlcpy(md.md_provider, str, sizeof(md.md_provider)); + } mirror_metadata_encode(&md, sector); error = g_metadata_store(str, sector, sizeof(sector)); if (error != 0) { diff --git a/sys/geom/mirror/g_mirror_ctl.c b/sys/geom/mirror/g_mirror_ctl.c index d69c44595ec8..0ec5401bb683 100644 --- a/sys/geom/mirror/g_mirror_ctl.c +++ b/sys/geom/mirror/g_mirror_ctl.c @@ -92,7 +92,7 @@ g_mirror_ctl_configure(struct gctl_req *req, struct g_class *mp) intmax_t *slicep; uint32_t slice; uint8_t balance; - int *nargs, *autosync, *noautosync, do_sync = 0; + int *nargs, *autosync, *noautosync, *hardcode, *dynamic, do_sync = 0; g_topology_assert(); nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); @@ -139,8 +139,18 @@ g_mirror_ctl_configure(struct gctl_req *req, struct g_class *mp) gctl_error(req, "No '%s' argument.", "noautosync"); return; } + hardcode = gctl_get_paraml(req, "hardcode", sizeof(*hardcode)); + if (hardcode == NULL) { + gctl_error(req, "No '%s' argument.", "hardcode"); + return; + } + dynamic = gctl_get_paraml(req, "dynamic", sizeof(*dynamic)); + if (dynamic == NULL) { + gctl_error(req, "No '%s' argument.", "dynamic"); + return; + } if (sc->sc_balance == balance && sc->sc_slice == slice && !*autosync && - !*noautosync) { + !*noautosync && !*hardcode && !*dynamic) { gctl_error(req, "Nothing has changed."); return; } @@ -149,6 +159,11 @@ g_mirror_ctl_configure(struct gctl_req *req, struct g_class *mp) "noautosync"); return; } + if (*hardcode && *dynamic) { + gctl_error(req, "'%s' and '%s' specified.", "hardcode", + "dynamic"); + return; + } sc->sc_balance = balance; sc->sc_slice = slice; if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_NOAUTOSYNC) != 0) { @@ -165,6 +180,10 @@ g_mirror_ctl_configure(struct gctl_req *req, struct g_class *mp) if (disk->d_state == G_MIRROR_DISK_STATE_SYNCHRONIZING) disk->d_flags &= ~G_MIRROR_DISK_FLAG_FORCE_SYNC; } + if (*hardcode) + disk->d_flags |= G_MIRROR_DISK_FLAG_HARDCODED; + else if (*dynamic) + disk->d_flags &= ~G_MIRROR_DISK_FLAG_HARDCODED; g_mirror_update_metadata(disk); if (do_sync) { if (disk->d_state == G_MIRROR_DISK_STATE_STALE) { @@ -257,7 +276,7 @@ g_mirror_ctl_insert(struct gctl_req *req, struct g_class *mp) char param[16]; u_char *sector; u_int i, n; - int error, *nargs, *inactive; + int error, *nargs, *hardcode, *inactive; struct { struct g_provider *provider; struct g_consumer *consumer; @@ -283,6 +302,11 @@ g_mirror_ctl_insert(struct gctl_req *req, struct g_class *mp) gctl_error(req, "No '%s' argument.", "inactive"); return; } + hardcode = gctl_get_paraml(req, "hardcode", sizeof(*hardcode)); + if (hardcode == NULL) { + gctl_error(req, "No '%s' argument.", "hardcode"); + return; + } name = gctl_get_asciiparam(req, "arg0"); if (name == NULL) { gctl_error(req, "No 'arg%u' argument.", 0); @@ -356,6 +380,12 @@ g_mirror_ctl_insert(struct gctl_req *req, struct g_class *mp) if (*inactive) md.md_dflags |= G_MIRROR_DISK_FLAG_INACTIVE; pp = disks[i].provider; + if (*hardcode) { + strlcpy(md.md_provider, pp->name, + sizeof(md.md_provider)); + } else { + bzero(md.md_provider, sizeof(md.md_provider)); + } sector = g_malloc(pp->sectorsize, M_WAITOK); mirror_metadata_encode(&md, sector); error = g_write_data(disks[i].consumer,