Index: sbin/geom/class/label/geom_label.c =================================================================== --- sbin/geom/class/label/geom_label.c (revision 211037) +++ sbin/geom/class/label/geom_label.c (working copy) @@ -71,8 +71,12 @@ { "dump", 0, label_main, G_NULL_OPTS, NULL, "dev ..." }, - { "label", G_FLAG_VERBOSE | G_FLAG_LOADKLD, label_main, G_NULL_OPTS, - NULL, "[-v] name dev" + { "label", G_FLAG_VERBOSE | G_FLAG_LOADKLD, label_main, + { + { 's', "sectorsize", NULL, G_TYPE_NUMBER }, + G_OPT_SENTINEL + }, + NULL, "[-v] [-s sectorsize] name dev" }, { "stop", G_FLAG_VERBOSE, NULL, { @@ -144,7 +148,29 @@ strerror(errno)); return; } + md.md_sectorsize = gctl_has_param(req, "sectorsize") ? + gctl_get_intmax(req, "sectorsize") : 0; + if (md.md_sectorsize > 0) { + unsigned ssize; + ssize = g_get_sectorsize(name); + if (ssize == 0) { + gctl_error(req, "Can't get sectorsize of %s: %s", + name, strerror(errno)); + return; + } + if (md.md_sectorsize < ssize) { + gctl_error(req, "Cannot force sectorsize smaller " + "than original sectorsize on %s", name); + return; + } + if (md.md_sectorsize % ssize != 0) { + gctl_error(req, "Forced sectorsize must be a " + "multiple of original sectorsize on %s", name); + return; + } + } + /* * Ok, store metadata. */ @@ -189,9 +215,11 @@ label_metadata_dump(const struct g_label_metadata *md) { - printf(" Magic string: %s\n", md->md_magic); - printf("Metadata version: %u\n", (u_int)md->md_version); - printf(" Label: %s\n", md->md_label); + printf(" Magic string: %s\n", md->md_magic); + printf(" Metadata version: %u\n", (u_int)md->md_version); + printf(" Label: %s\n", md->md_label); + if (md->md_version > 2 && md->md_sectorsize > 0) + printf("Forced sector size: %u\n", md->md_sectorsize); } static void Index: sbin/geom/class/label/glabel.8 =================================================================== --- sbin/geom/class/label/glabel.8 (revision 211037) +++ sbin/geom/class/label/glabel.8 (working copy) @@ -43,6 +43,7 @@ .Nm .Cm label .Op Fl v +.Op Fl s Ar sectorsize .Ar name .Ar dev .Nm @@ -157,6 +158,11 @@ The kernel module .Pa geom_label.ko will be loaded if it is not loaded already. +In this mode +.Nm +can optionally force a sector size on the labeled device, which is intended +to be used with drives whose internal sector size (e.g. 4k) is different from +their advertised sector size (e.g. 512 bytes). .It Cm stop Turn off the given label by its .Ar name . Index: sbin/geom/misc/subr.c =================================================================== --- sbin/geom/misc/subr.c (revision 211037) +++ sbin/geom/misc/subr.c (working copy) @@ -436,7 +436,8 @@ abort(); } } else if ((int)len != argp->len) { - fprintf(stderr, "Wrong length %s argument.\n", param); + fprintf(stderr, "Wrong length %s argument. " + "Got %d, expecting %d.\n", param, argp->len, len); abort(); } return (p); Index: sys/geom/label/g_label.c =================================================================== --- sys/geom/label/g_label.c (revision 211037) +++ sys/geom/label/g_label.c (working copy) @@ -138,13 +138,18 @@ static struct g_geom * g_label_create(struct gctl_req *req, struct g_class *mp, struct g_provider *pp, - const char *label, const char *dir, off_t mediasize) + const char *label, const char *dir, off_t mediasize, unsigned sectorsize) { struct g_geom *gp; struct g_provider *pp2; struct g_consumer *cp; char name[64]; + KASSERT(sectorsize > 0, ("Passed 0 sectorsize to g_label_create")); + KASSERT(sectorsize >= pp->sectorsize, ("Forced sectorsize smaller than" + " physical sectorsize on %s", pp->name)); + KASSERT(sectorsize % pp->sectorsize == 0, ("Forced sectorsize not a" + " multiple of physical sectorsize on %s", pp->name)); g_topology_assert(); if (!g_label_is_name_ok(label)) { @@ -181,8 +186,11 @@ gp->spoiled = g_label_spoiled; g_access(cp, -1, 0, 0); g_slice_config(gp, 0, G_SLICE_CONFIG_SET, (off_t)0, mediasize, - pp->sectorsize, name); + sectorsize, name); G_LABEL_DEBUG(1, "Label for provider %s is %s.", pp->name, name); + if (sectorsize != pp->sectorsize) + G_LABEL_DEBUG(1, "Forcing sector size %u on %s", + sectorsize, pp->name); return (gp); } @@ -284,6 +292,8 @@ if (g_access(cp, 1, 0, 0) != 0) goto end; do { + unsigned forcedssize; + if (g_label_read_metadata(cp, &md) != 0) break; if (strcmp(md.md_magic, G_LABEL_MAGIC) != 0) @@ -307,8 +317,13 @@ if (md.md_provsize != pp->mediasize) break; + if (md.md_version > 2 && md.md_sectorsize > 0) + forcedssize = md.md_sectorsize; + else + forcedssize = pp->sectorsize; + g_label_create(NULL, mp, pp, md.md_label, G_LABEL_DIR, - pp->mediasize - pp->sectorsize); + pp->mediasize - forcedssize, forcedssize); } while (0); for (i = 0; g_labels[i] != NULL; i++) { char label[64]; @@ -321,7 +336,7 @@ if (label[0] == '\0') continue; g_label_create(NULL, mp, pp, label, g_labels[i]->ld_dir, - pp->mediasize); + pp->mediasize, pp->sectorsize); } g_access(cp, -1, 0, 0); end: @@ -373,7 +388,8 @@ gctl_error(req, "No 'arg%d' argument", 0); return; } - g_label_create(req, mp, pp, name, G_LABEL_DIR, pp->mediasize); + g_label_create(req, mp, pp, name, G_LABEL_DIR, pp->mediasize, + pp->sectorsize); } static const char * Index: sys/geom/label/g_label.h =================================================================== --- sys/geom/label/g_label.h (revision 211037) +++ sys/geom/label/g_label.h (working copy) @@ -41,8 +41,9 @@ * Version history: * 1 - Initial version number. * 2 - Added md_provsize field to metadata. + * 3 - Added forced sector size field to metadata. */ -#define G_LABEL_VERSION 2 +#define G_LABEL_VERSION 3 #define G_LABEL_DIR "label" #ifdef _KERNEL @@ -94,6 +95,7 @@ uint32_t md_version; /* Version number. */ char md_label[16]; /* Label. */ uint64_t md_provsize; /* Provider's size. */ + uint32_t md_sectorsize; /* Forced sector size (0=disabled). */ }; static __inline void label_metadata_encode(const struct g_label_metadata *md, u_char *data) @@ -103,6 +105,7 @@ le32enc(data + 16, md->md_version); bcopy(md->md_label, data + 20, sizeof(md->md_label)); le64enc(data + 36, md->md_provsize); + le32enc(data + 44, md->md_sectorsize); } static __inline void label_metadata_decode(const u_char *data, struct g_label_metadata *md) @@ -112,5 +115,6 @@ md->md_version = le32dec(data + 16); bcopy(data + 20, md->md_label, sizeof(md->md_label)); md->md_provsize = le64dec(data + 36); + md->md_sectorsize = le32dec(data + 44); } #endif /* _G_LABEL_H_ */