FreeBSD Bugzilla – Attachment 201701 Details for
Bug 235473
geom: add feature: gconcat online append
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
Initial patch draft
file_235473.txt (text/plain), 8.24 KB, created by
noah.bergbauer
on 2019-02-03 22:49:52 UTC
(
hide
)
Description:
Initial patch draft
Filename:
MIME Type:
Creator:
noah.bergbauer
Created:
2019-02-03 22:49:52 UTC
Size:
8.24 KB
patch
obsolete
>Index: /root/svn/freebsd/sys/geom/concat/g_concat.c >=================================================================== >--- /root/svn/freebsd/sys/geom/concat/g_concat.c (.../head/sys/geom/concat/g_concat.c) (revision 343724) >+++ /root/svn/freebsd/sys/geom/concat/g_concat.c (.../releng/12.0/sys/geom/concat/g_concat.c) (working copy) >@@ -172,10 +172,12 @@ > struct g_consumer *cp1, *cp2, *tmp; > struct g_concat_disk *disk; > struct g_geom *gp; >+ struct g_concat_softc *sc; > int error; > > g_topology_assert(); > gp = pp->geom; >+ sc = gp->softc; > > /* On first open, grab an extra "exclusive" bit */ > if (pp->acr == 0 && pp->acw == 0 && pp->ace == 0) >@@ -184,6 +186,7 @@ > if ((pp->acr + dr) == 0 && (pp->acw + dw) == 0 && (pp->ace + de) == 0) > de--; > >+ mtx_lock(&sc->sc_lock_append); > LIST_FOREACH_SAFE(cp1, &gp->consumer, consumer, tmp) { > error = g_access(cp1, dr, dw, de); > if (error != 0) >@@ -194,9 +197,11 @@ > g_concat_remove_disk(disk); /* May destroy geom. */ > } > } >+ mtx_unlock(&sc->sc_lock_append); > return (0); > > fail: >+ mtx_unlock(&sc->sc_lock_append); > LIST_FOREACH(cp2, &gp->consumer, consumer) { > if (cp1 == cp2) > break; >@@ -623,6 +628,7 @@ > sc->sc_disks[no].d_consumer = NULL; > sc->sc_type = type; > mtx_init(&sc->sc_lock, "gconcat lock", NULL, MTX_DEF); >+ mtx_init(&sc->sc_lock_append, "gconcat append lock", NULL, MTX_DEF); > > gp->softc = sc; > sc->sc_geom = gp; >@@ -672,6 +678,7 @@ > gp->name)); > free(sc->sc_disks, M_CONCAT); > mtx_destroy(&sc->sc_lock); >+ mtx_destroy(&sc->sc_lock_append); > free(sc, M_CONCAT); > > G_CONCAT_DEBUG(0, "Device %s destroyed.", gp->name); >@@ -948,6 +955,169 @@ > } > > static void >+g_concat_ctl_append(struct gctl_req *req, struct g_class *mp) >+{ >+ u_int no, i; >+ struct g_concat_softc *sc; >+ struct g_provider *pp; >+ struct g_consumer *cp, *fcp; // no idea what fcp does >+ struct g_geom *gp; >+ const char *name, *cname; >+ //char param[16]; >+ struct g_concat_disk *disks_tmp, *disk; >+ int *nargs; >+ int error; >+ int disk_candelete; >+ struct g_concat_metadata md; >+ u_char *sector; >+ >+ g_topology_assert(); >+ >+ nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); >+ if (nargs == NULL) { >+ gctl_error(req, "No '%s' argument.", "nargs"); >+ return; >+ } >+ if (*nargs != 2) { >+ gctl_error(req, "Invalid number of arguments."); >+ return; >+ } >+ >+ cname = gctl_get_asciiparam(req, "arg0"); >+ if (cname == NULL) { >+ gctl_error(req, "No 'arg%u' argument.", 0); >+ return; >+ } >+ sc = g_concat_find_device(mp, cname); >+ if (sc == NULL) { >+ gctl_error(req, "No such device: %s.", name); >+ return; >+ } >+ G_CONCAT_DEBUG(1, "Appending to %s:", cname); >+ mtx_lock(&sc->sc_lock_append); >+ gp = sc->sc_geom; >+ fcp = LIST_FIRST(&gp->consumer); >+ >+ //for (no = 1; no < *nargs; no++) { >+ //snprintf(param, sizeof(param), "arg%u", no); >+ name = gctl_get_asciiparam(req, "arg1"); >+ if (name == NULL) { >+ gctl_error(req, "No 'arg%u' argument.", 1); >+ return; >+ } >+ if (strncmp(name, "/dev/", strlen("/dev/")) == 0) >+ name += strlen("/dev/"); >+ pp = g_provider_by_name(name); >+ if (pp == NULL) { >+ G_CONCAT_DEBUG(1, "Disk %s is invalid.", name); >+ gctl_error(req, "Disk %s is invalid.", name); >+ return; >+ } >+ G_CONCAT_DEBUG(1, "Appending %s to this", name); >+ >+ // TODO: already-there check? >+ >+ // make sure sector size matches >+ if ((sc->sc_provider->sectorsize % pp->sectorsize) != 0) { >+ gctl_error(req, "Providers sectorsize mismatch: %u vs %u", >+ sc->sc_provider->sectorsize, pp->sectorsize); >+ return; >+ } >+ >+ cp = g_new_consumer(gp); >+ cp->flags |= G_CF_DIRECT_SEND | G_CF_DIRECT_RECEIVE; >+ error = g_attach(cp, pp); >+ if (error != 0) { >+ g_destroy_consumer(cp); >+ gctl_error(req, "Cannot open device %s (error=%d).", >+ name, error); >+ return; >+ } >+ >+ error = g_access(cp, 1, 0, 0); >+ if (error == 0) { >+ error = g_getattr("GEOM::candelete", cp, &disk_candelete); >+ if (error != 0) >+ disk_candelete = 0; >+ (void)g_access(cp, -1, 0, 0); >+ } else >+ G_CONCAT_DEBUG(1, "Failed to access disk %s, error %d.", name, error); >+ >+ // invoke g_access exactly as deep as all the other members currently are >+ if (fcp != NULL && (fcp->acr > 0 || fcp->acw > 0 || fcp->ace > 0)) { >+ error = g_access(cp, fcp->acr, fcp->acw, fcp->ace); >+ if (error != 0) { >+ g_detach(cp); >+ g_destroy_consumer(cp); >+ gctl_error(req, "Failed to access disk %s (error=%d).", name, error); >+ return; >+ } >+ } >+ >+ disks_tmp = sc->sc_disks; >+ sc->sc_disks = malloc(sizeof(struct g_concat_disk) * (sc->sc_ndisks + 1), M_CONCAT, M_WAITOK | M_ZERO); >+ memcpy(sc->sc_disks, disks_tmp, sizeof(struct g_concat_disk) * sc->sc_ndisks); >+ // fix up disk ptrs of existing consumers >+ for (i = 0; i < sc->sc_ndisks; i++) { >+ sc->sc_disks[i].d_consumer->private = &sc->sc_disks[i]; >+ } >+ // now it is safe to free the old array >+ free(disks_tmp, M_CONCAT); >+ disks_tmp = NULL; >+ >+ disk = &sc->sc_disks[sc->sc_ndisks]; >+ cp->private = disk; >+ disk->d_consumer = cp; >+ disk->d_softc = sc; >+ disk->d_start = sc->sc_disks[sc->sc_ndisks - 1].d_end; >+ disk->d_end = disk->d_start + cp->provider->mediasize; >+ disk->d_candelete = disk_candelete; >+ disk->d_removed = 0; >+ >+ sc->sc_ndisks += 1; >+ >+ if (sc->sc_type == G_CONCAT_TYPE_AUTOMATIC) { >+ // last sector is for metadata >+ disk->d_end -= cp->provider->sectorsize; >+ >+ // update metadata on all parts >+ strlcpy(md.md_magic, G_CONCAT_MAGIC, sizeof(md.md_magic)); >+ md.md_version = G_CONCAT_VERSION; >+ strlcpy(md.md_name, cname, sizeof(md.md_name)); >+ md.md_id = sc->sc_id; >+ md.md_all = sc->sc_ndisks; >+ for (no = 0; no < sc->sc_ndisks; no++) { >+ disk = &sc->sc_disks[no]; >+ >+ md.md_no = no; >+ // TODO: implement hardcode? (not sure how, not sure why it even exists) >+ bzero(md.md_provider, sizeof(md.md_provider)); >+ md.md_provsize = disk->d_consumer->provider->mediasize; >+ >+ pp = disk->d_consumer->provider; >+ sector = g_malloc(pp->sectorsize, M_WAITOK); >+ >+ concat_metadata_encode(&md, sector); >+ error = g_access(disk->d_consumer, 0, 1, 0); >+ if (error == 0) { >+ error = g_write_data(disk->d_consumer, pp->mediasize - pp->sectorsize, >+ sector, pp->sectorsize); >+ } >+ (void)g_access(disk->d_consumer, 0, -1, 0); >+ g_free(sector); >+ if (error != 0) { >+ gctl_error(req, "Cannot store metadata on %s.", pp->name); >+ } >+ } >+ >+ } >+ >+ g_resize_provider(sc->sc_provider, disk->d_end); >+ >+ mtx_unlock(&sc->sc_lock_append); >+} >+ >+static void > g_concat_config(struct gctl_req *req, struct g_class *mp, const char *verb) > { > uint32_t *version; >@@ -971,6 +1141,9 @@ > strcmp(verb, "stop") == 0) { > g_concat_ctl_destroy(req, mp); > return; >+ } else if (strcmp(verb, "append") == 0) { >+ g_concat_ctl_append(req, mp); >+ return; > } > gctl_error(req, "Unknown verb."); > } >Index: /root/svn/freebsd/sys/geom/concat/g_concat.h >=================================================================== >--- /root/svn/freebsd/sys/geom/concat/g_concat.h (.../head/sys/geom/concat/g_concat.h) (revision 343724) >+++ /root/svn/freebsd/sys/geom/concat/g_concat.h (.../releng/12.0/sys/geom/concat/g_concat.h) (working copy) >@@ -42,8 +42,9 @@ > * 2 - Added 'stop' command to gconcat(8). > * 3 - Added md_provider field to metadata and '-h' option to gconcat(8). > * 4 - Added md_provsize field to metadata. >+ * 5 - Added online append functionality ('append' command). > */ >-#define G_CONCAT_VERSION 4 >+#define G_CONCAT_VERSION 4 // FIXME > > #ifdef _KERNEL > #define G_CONCAT_TYPE_MANUAL 0 >@@ -87,6 +88,7 @@ > struct g_concat_disk *sc_disks; > uint16_t sc_ndisks; > struct mtx sc_lock; >+ struct mtx sc_lock_append; > }; > #define sc_name sc_geom->name > #endif /* _KERNEL */ >Index: /root/svn/freebsd/lib/geom/concat/geom_concat.c >=================================================================== >--- /root/svn/freebsd/lib/geom/concat/geom_concat.c (revision 343718) >+++ /root/svn/freebsd/lib/geom/concat/geom_concat.c (working copy) >@@ -59,6 +59,9 @@ > { "create", G_FLAG_VERBOSE | G_FLAG_LOADKLD, NULL, G_NULL_OPTS, > "[-v] name prov ..." > }, >+ { "append", G_FLAG_VERBOSE, NULL, G_NULL_OPTS, >+ "[-v] name prov" >+ }, > { "destroy", G_FLAG_VERBOSE, NULL, > { > { 'f', "force", NULL, G_TYPE_BOOL },
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 235473
:
201701
|
202078