diff --git a/sbin/geom/class/concat/gconcat.8 b/sbin/geom/class/concat/gconcat.8 index eacccebcfa26..e7e06a7c8801 100644 --- a/sbin/geom/class/concat/gconcat.8 +++ b/sbin/geom/class/concat/gconcat.8 @@ -35,35 +35,35 @@ .Cm create .Op Fl v .Ar name -.Ar dev1 -.Ar dev2 -.Op Ar dev3 Op Ar ... +.Ar prov +.Ar prov +.Op Ar prov Op Ar ... .Nm .Cm destroy .Op Fl fv .Ar name -.Op Ar name2 Op Ar ... +.Op Ar name Op Ar ... .Nm .Cm label -.Op Fl v +.Op Fl hv .Ar name -.Ar dev1 -.Ar dev2 -.Op Ar dev3 Op Ar ... +.Ar prov +.Ar prov +.Op Ar prov Op Ar ... .Nm .Cm stop .Op Fl fv .Ar name -.Op Ar name2 Op Ar ... +.Op Ar name Op Ar ... .Nm .Cm clear .Op Fl v -.Ar dev1 -.Op Ar dev2 Op Ar ... +.Ar prov +.Op Ar prov Op Ar ... .Nm .Cm dump -.Ar dev1 -.Op Ar dev2 Op Ar ... +.Ar prov +.Op Ar prov Op Ar ... .Nm .Cm list .Op Ar name Op Ar ... @@ -140,6 +140,8 @@ Additional options: .Bl -tag -width indent .It Fl f Force the removal of the specified concatenated device. +.It Fl h +Hardcode providers' names in metadata. .It Fl v Be more verbose. .El diff --git a/sbin/geom/class/concat/geom_concat.c b/sbin/geom/class/concat/geom_concat.c index 49e6101916f4..c97027aa85fc 100644 --- a/sbin/geom/class/concat/geom_concat.c +++ b/sbin/geom/class/concat/geom_concat.c @@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -59,7 +60,12 @@ struct g_command class_commands[] = { } }, { "dump", 0, concat_main, G_NULL_OPTS }, - { "label", G_FLAG_VERBOSE | G_FLAG_LOADKLD, concat_main, G_NULL_OPTS }, + { "label", G_FLAG_VERBOSE | G_FLAG_LOADKLD, concat_main, + { + { 'h', "hardcode", NULL, G_TYPE_NONE }, + G_OPT_SENTINEL + } + }, { "stop", G_FLAG_VERBOSE, NULL, { { 'f', "force", NULL, G_TYPE_NONE }, @@ -77,12 +83,12 @@ void usage(const char *name) { - fprintf(stderr, "usage: %s create [-v] [dev3 [...]]\n", name); - fprintf(stderr, " %s destroy [-fv] [name2 [...]]\n", name); - fprintf(stderr, " %s label [-v] [dev3 [...]]\n", name); - fprintf(stderr, " %s stop [-fv] [name2 [...]]\n", name); - fprintf(stderr, " %s clear [-v] [dev2 [...]]\n", name); - fprintf(stderr, " %s dump [dev2 [...]]\n", name); + fprintf(stderr, "usage: %s create [-v] [prov [...]]\n", name); + fprintf(stderr, " %s destroy [-fv] [name [...]]\n", name); + fprintf(stderr, " %s label [-hv] [prov [...]]\n", name); + fprintf(stderr, " %s stop [-fv] [name [...]]\n", name); + fprintf(stderr, " %s clear [-v] [prov [...]]\n", name); + fprintf(stderr, " %s dump [prov [...]]\n", name); } static void @@ -116,7 +122,7 @@ concat_label(struct gctl_req *req) const char *name; char param[16]; unsigned i; - int *nargs, error; + int *hardcode, *nargs, error; nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); if (nargs == NULL) { @@ -127,6 +133,11 @@ concat_label(struct gctl_req *req) gctl_error(req, "Too few arguments."); return; } + hardcode = gctl_get_paraml(req, "hardcode", sizeof(*hardcode)); + if (hardcode == NULL) { + gctl_error(req, "No '%s' argument.", "hardcode"); + return; + } /* * Clear last sector first to spoil all components if device exists. @@ -162,6 +173,13 @@ concat_label(struct gctl_req *req) name = gctl_get_asciiparam(req, param); md.md_no = i - 1; + if (!*hardcode) + bzero(md.md_provider, sizeof(md.md_provider)); + else { + if (strncmp(name, _PATH_DEV, strlen(_PATH_DEV)) == 0) + name += strlen(_PATH_DEV); + strlcpy(md.md_provider, name, sizeof(md.md_provider)); + } concat_metadata_encode(&md, sector); error = g_metadata_store(name, sector, sizeof(sector)); if (error != 0) { @@ -219,6 +237,7 @@ concat_metadata_dump(const struct g_concat_metadata *md) printf(" Device ID: %u\n", (u_int)md->md_id); printf(" Disk number: %u\n", (u_int)md->md_no); printf("Total number of disks: %u\n", (u_int)md->md_all); + printf(" Hardcoded provider: %s\n", md->md_provider); } static void diff --git a/sbin/geom/class/stripe/geom_stripe.c b/sbin/geom/class/stripe/geom_stripe.c index 5b6a9a353a78..9c47ef4e1019 100644 --- a/sbin/geom/class/stripe/geom_stripe.c +++ b/sbin/geom/class/stripe/geom_stripe.c @@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -69,6 +70,7 @@ struct g_command class_commands[] = { { "dump", 0, stripe_main, G_NULL_OPTS }, { "label", G_FLAG_VERBOSE | G_FLAG_LOADKLD, stripe_main, { + { 'h', "hardcode", NULL, G_TYPE_NONE }, { 's', "stripesize", &stripesize, G_TYPE_NUMBER }, G_OPT_SENTINEL } @@ -89,12 +91,12 @@ void usage(const char *name) { - fprintf(stderr, "usage: %s create [-v] [-s stripesize] [dev3 [...]]\n", name); - fprintf(stderr, " %s destroy [-fv] [name2 [...]]\n", name); - fprintf(stderr, " %s label [-v] [-s stripesize] [dev3 [...]]\n", name); - fprintf(stderr, " %s stop [-fv] [name2 [...]]\n", name); - fprintf(stderr, " %s clear [-v] [dev2 [...]]\n", name); - fprintf(stderr, " %s dump [dev2 [...]]\n", name); + fprintf(stderr, "usage: %s create [-hv] [-s stripesize] [prov [...]]\n", name); + fprintf(stderr, " %s destroy [-fv] [name [...]]\n", name); + fprintf(stderr, " %s label [-hv] [-s stripesize] [prov [...]]\n", name); + fprintf(stderr, " %s stop [-fv] [name [...]]\n", name); + fprintf(stderr, " %s clear [-v] [prov [...]]\n", name); + fprintf(stderr, " %s dump [prov [...]]\n", name); } static void @@ -129,7 +131,7 @@ stripe_label(struct gctl_req *req) const char *name; char param[16]; unsigned i; - int *nargs, error; + int *hardcode, *nargs, error; nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); if (nargs == NULL) { @@ -140,6 +142,11 @@ stripe_label(struct gctl_req *req) gctl_error(req, "Too few arguments."); return; } + hardcode = gctl_get_paraml(req, "hardcode", sizeof(*hardcode)); + if (hardcode == NULL) { + gctl_error(req, "No '%s' argument.", "hardcode"); + return; + } /* * Clear last sector first to spoil all components if device exists. @@ -181,6 +188,13 @@ stripe_label(struct gctl_req *req) name = gctl_get_asciiparam(req, param); md.md_no = i - 1; + if (!*hardcode) + bzero(md.md_provider, sizeof(md.md_provider)); + else { + if (strncmp(name, _PATH_DEV, strlen(_PATH_DEV)) == 0) + name += strlen(_PATH_DEV); + strlcpy(md.md_provider, name, sizeof(md.md_provider)); + } stripe_metadata_encode(&md, sector); error = g_metadata_store(name, sector, sizeof(sector)); if (error != 0) { @@ -239,6 +253,7 @@ stripe_metadata_dump(const struct g_stripe_metadata *md) printf(" Disk number: %u\n", (u_int)md->md_no); printf("Total number of disks: %u\n", (u_int)md->md_all); printf(" Stripe size: %u\n", (u_int)md->md_stripesize); + printf(" Hardcoded provider: %s\n", md->md_provider); } static void diff --git a/sbin/geom/class/stripe/gstripe.8 b/sbin/geom/class/stripe/gstripe.8 index fbf4bf11c964..ddf7d9085333 100644 --- a/sbin/geom/class/stripe/gstripe.8 +++ b/sbin/geom/class/stripe/gstripe.8 @@ -36,36 +36,36 @@ .Op Fl v .Op Fl s Ar stripesize .Ar name -.Ar dev1 -.Ar dev2 -.Op Ar dev3 Op Ar ... +.Ar prov +.Ar prov +.Op Ar prov Op Ar ... .Nm .Cm destroy .Op Fl fv .Ar name -.Op Ar name2 Op Ar ... +.Op Ar name Op Ar ... .Nm .Cm label -.Op Fl v +.Op Fl hv .Op Fl s Ar stripesize .Ar name -.Ar dev1 -.Ar dev2 -.Op Ar dev3 Op Ar ... +.Ar prov +.Ar prov +.Op Ar prov Op Ar ... .Nm .Cm stop .Op Fl fv .Ar name -.Op Ar name2 Op Ar ... +.Op Ar name Op Ar ... .Nm .Cm clear .Op Fl v -.Ar dev1 -.Op Ar dev2 Op Ar ... +.Ar prov +.Op Ar prov Op Ar ... .Nm .Cm dump -.Ar dev1 -.Op Ar dev2 Op Ar ... +.Ar prov +.Op Ar prov Op Ar ... .Nm .Cm list .Op Ar name Op Ar ... @@ -142,6 +142,8 @@ Additional options: .Bl -tag -width ".Fl s Ar stripesize" .It Fl f Force the removal of the specified striped device. +.It Fl h +Hardcode providers' names in metadata. .It Fl s Ar stripesize Specifies size of stripe block. .It Fl v diff --git a/sys/geom/concat/g_concat.c b/sys/geom/concat/g_concat.c index 480b30d77342..8103ea6409b8 100644 --- a/sys/geom/concat/g_concat.c +++ b/sys/geom/concat/g_concat.c @@ -567,6 +567,15 @@ g_concat_taste(struct g_class *mp, struct g_provider *pp, int flags __unused) pp->name); return (NULL); } + /* + * Backward compatibility: + * There was no md_provider field in earlier versions of metadata. + */ + if (md.md_version < 3) + bzero(md.md_provider, sizeof(md.md_provider)); + + if (md.md_provider[0] != '\0' && strcmp(md.md_provider, pp->name) != 0) + return (NULL); /* * Let's check if device already exists. @@ -650,6 +659,7 @@ g_concat_ctl_create(struct gctl_req *req, struct g_class *mp) md.md_id = arc4random(); md.md_no = 0; md.md_all = *nargs - 1; + bzero(md.md_provider, sizeof(md.md_provider)); /* Check all providers are valid */ for (no = 1; no < *nargs; no++) { diff --git a/sys/geom/concat/g_concat.h b/sys/geom/concat/g_concat.h index 2c2296f67d1a..5cf8757bb169 100644 --- a/sys/geom/concat/g_concat.h +++ b/sys/geom/concat/g_concat.h @@ -34,7 +34,13 @@ #define G_CONCAT_CLASS_NAME "CONCAT" #define G_CONCAT_MAGIC "GEOM::CONCAT" -#define G_CONCAT_VERSION 2 +/* + * Version history: + * 1 - Initial version number. + * 2 - Added 'stop' command to gconcat(8). + * 3 - Added md_provider field to metadata and '-h' option to gconcat(8). + */ +#define G_CONCAT_VERSION 3 #ifdef _KERNEL #define G_CONCAT_TYPE_MANUAL 0 @@ -86,6 +92,7 @@ struct g_concat_metadata { uint32_t md_id; /* Unique ID. */ uint16_t md_no; /* Disk number. */ uint16_t md_all; /* Number of all disks. */ + char md_provider[16]; /* Hardcoded provider. */ }; static __inline void concat_metadata_encode(const struct g_concat_metadata *md, u_char *data) @@ -97,6 +104,7 @@ concat_metadata_encode(const struct g_concat_metadata *md, u_char *data) le32enc(data + 36, md->md_id); le16enc(data + 40, md->md_no); le16enc(data + 42, md->md_all); + bcopy(md->md_provider, data + 44, sizeof(md->md_provider)); } static __inline void concat_metadata_decode(const u_char *data, struct g_concat_metadata *md) @@ -108,5 +116,6 @@ concat_metadata_decode(const u_char *data, struct g_concat_metadata *md) md->md_id = le32dec(data + 36); md->md_no = le16dec(data + 40); md->md_all = le16dec(data + 42); + bcopy(data + 44, md->md_provider, sizeof(md->md_provider)); } #endif /* _G_CONCAT_H_ */ diff --git a/sys/geom/mirror/g_mirror.c b/sys/geom/mirror/g_mirror.c index 427bc449ee78..fed14a49153d 100644 --- a/sys/geom/mirror/g_mirror.c +++ b/sys/geom/mirror/g_mirror.c @@ -382,6 +382,8 @@ g_mirror_init_disk(struct g_mirror_softc *sc, struct g_provider *pp, disk->d_delay.frac = 0; binuptime(&disk->d_last_used); disk->d_flags = md->md_dflags; + if (md->md_provider[0] != '\0') + disk->d_flags |= G_MIRROR_DISK_FLAG_HARDCODED; disk->d_sync.ds_consumer = NULL; disk->d_sync.ds_offset = md->md_sync_offset; disk->d_sync.ds_offset_done = md->md_sync_offset; @@ -621,6 +623,7 @@ g_mirror_fill_metadata(struct g_mirror_softc *sc, struct g_mirror_disk *disk, md->md_mediasize = sc->sc_mediasize; md->md_sectorsize = sc->sc_sectorsize; md->md_mflags = (sc->sc_flags & G_MIRROR_DEVICE_FLAG_MASK); + bzero(md->md_provider, sizeof(md->md_provider)); if (disk == NULL) { md->md_did = arc4random(); md->md_priority = 0; @@ -636,6 +639,11 @@ g_mirror_fill_metadata(struct g_mirror_softc *sc, struct g_mirror_disk *disk, md->md_sync_offset = disk->d_sync.ds_offset_done; else md->md_sync_offset = 0; + if ((disk->d_flags & G_MIRROR_DISK_FLAG_HARDCODED) != 0) { + strlcpy(md->md_provider, + disk->d_consumer->provider->name, + sizeof(md->md_provider)); + } } } @@ -2491,6 +2499,8 @@ g_mirror_taste(struct g_class *mp, struct g_provider *pp, int flags __unused) pp->name); return (NULL); } + if (md.md_provider[0] != '\0' && strcmp(md.md_provider, pp->name) != 0) + return (NULL); if ((md.md_dflags & G_MIRROR_DISK_FLAG_INACTIVE) != 0) { G_MIRROR_DEBUG(0, "Device %s: provider %s marked as inactive, skipping.", diff --git a/sys/geom/mirror/g_mirror.h b/sys/geom/mirror/g_mirror.h index 5be5cdada810..77dc43359b03 100644 --- a/sys/geom/mirror/g_mirror.h +++ b/sys/geom/mirror/g_mirror.h @@ -49,6 +49,7 @@ #define G_MIRROR_DISK_FLAG_SYNCHRONIZING 0x0000000000000002ULL #define G_MIRROR_DISK_FLAG_FORCE_SYNC 0x0000000000000004ULL #define G_MIRROR_DISK_FLAG_INACTIVE 0x0000000000000008ULL +#define G_MIRROR_DISK_FLAG_HARDCODED 0x0000000000000010ULL #define G_MIRROR_DISK_FLAG_MASK (G_MIRROR_DISK_FLAG_DIRTY | \ G_MIRROR_DISK_FLAG_SYNCHRONIZING | \ G_MIRROR_DISK_FLAG_FORCE_SYNC | \ @@ -210,6 +211,7 @@ struct g_mirror_metadata { uint64_t md_sync_offset; /* Synchronized offset. */ uint64_t md_mflags; /* Additional mirror flags. */ uint64_t md_dflags; /* Additional disk flags. */ + char md_provider[16]; /* Hardcoded provider. */ u_char md_hash[16]; /* MD5 hash. */ }; static __inline void @@ -232,10 +234,11 @@ mirror_metadata_encode(struct g_mirror_metadata *md, u_char *data) le64enc(data + 67, md->md_sync_offset); le64enc(data + 75, md->md_mflags); le64enc(data + 83, md->md_dflags); + bcopy(md->md_provider, data + 91, 16); MD5Init(&ctx); - MD5Update(&ctx, data, 91); + MD5Update(&ctx, data, 107); MD5Final(md->md_hash, &ctx); - bcopy(md->md_hash, data + 91, 16); + bcopy(md->md_hash, data + 107, 16); } static __inline int mirror_metadata_decode(const u_char *data, struct g_mirror_metadata *md) @@ -257,11 +260,12 @@ mirror_metadata_decode(const u_char *data, struct g_mirror_metadata *md) md->md_sync_offset = le64dec(data + 67); md->md_mflags = le64dec(data + 75); md->md_dflags = le64dec(data + 83); - bcopy(data + 91, md->md_hash, 16); + bcopy(data + 91, md->md_provider, 16); + bcopy(data + 107, md->md_hash, 16); MD5Init(&ctx); - MD5Update(&ctx, data, 91); + MD5Update(&ctx, data, 107); MD5Final(md->md_hash, &ctx); - if (bcmp(md->md_hash, data + 91, 16) != 0) + if (bcmp(md->md_hash, data + 107, 16) != 0) return (EINVAL); return (0); } @@ -345,6 +349,7 @@ mirror_metadata_dump(const struct g_mirror_metadata *md) printf(" INACTIVE"); } printf("\n"); + printf("hcprovider: %s\n", md->md_provider); bzero(hash, sizeof(hash)); for (i = 0; i < 16; i++) { hash[i * 2] = hex[md->md_hash[i] >> 4]; diff --git a/sys/geom/stripe/g_stripe.c b/sys/geom/stripe/g_stripe.c index 017cf3ce4596..a661704caa92 100644 --- a/sys/geom/stripe/g_stripe.c +++ b/sys/geom/stripe/g_stripe.c @@ -898,6 +898,15 @@ g_stripe_taste(struct g_class *mp, struct g_provider *pp, int flags __unused) pp->name); return (NULL); } + /* + * Backward compatibility: + * There was no md_provider field in earlier versions of metadata. + */ + if (md.md_version < 2) + bzero(md.md_provider, sizeof(md.md_provider)); + + if (md.md_provider[0] != '\0' && strcmp(md.md_provider, pp->name) != 0) + return (NULL); /* * Let's check if device already exists. @@ -988,6 +997,7 @@ g_stripe_ctl_create(struct gctl_req *req, struct g_class *mp) return; } md.md_stripesize = *stripesize; + bzero(md.md_provider, sizeof(md.md_provider)); /* Check all providers are valid */ for (no = 1; no < *nargs; no++) { diff --git a/sys/geom/stripe/g_stripe.h b/sys/geom/stripe/g_stripe.h index 5f4edc9153d5..5a7825b0e818 100644 --- a/sys/geom/stripe/g_stripe.h +++ b/sys/geom/stripe/g_stripe.h @@ -34,7 +34,13 @@ #define G_STRIPE_CLASS_NAME "STRIPE" #define G_STRIPE_MAGIC "GEOM::STRIPE" -#define G_STRIPE_VERSION 1 +/* + * Version history: + * 0 - Initial version number. + * 1 - Added 'stop' command for gstripe(8). + * 2 - Added md_provider field to metadata and '-h' option for gstripe(8). + */ +#define G_STRIPE_VERSION 2 #ifdef _KERNEL #define G_STRIPE_TYPE_MANUAL 0 @@ -81,6 +87,7 @@ struct g_stripe_metadata { uint16_t md_no; /* Disk number. */ uint16_t md_all; /* Number of all disks. */ uint32_t md_stripesize; /* Stripe size. */ + char md_provider[16]; /* Hardcoded provider. */ }; static __inline void stripe_metadata_encode(const struct g_stripe_metadata *md, u_char *data) @@ -93,6 +100,7 @@ stripe_metadata_encode(const struct g_stripe_metadata *md, u_char *data) le16enc(data + 40, md->md_no); le16enc(data + 42, md->md_all); le32enc(data + 44, md->md_stripesize); + bcopy(md->md_provider, data + 48, sizeof(md->md_provider)); } static __inline void stripe_metadata_decode(const u_char *data, struct g_stripe_metadata *md) @@ -105,6 +113,7 @@ stripe_metadata_decode(const u_char *data, struct g_stripe_metadata *md) md->md_no = le16dec(data + 40); md->md_all = le16dec(data + 42); md->md_stripesize = le32dec(data + 44); + bcopy(data + 48, md->md_provider, sizeof(md->md_provider)); } #ifndef BITCOUNT