From f2e3e9e07318ddf592e5f29fb5edce4ea8b697c8 Mon Sep 17 00:00:00 2001 From: trasz Date: Sat, 7 Jul 2012 20:13:40 +0000 Subject: [PATCH] Add a new GEOM method, resize(), which is called after provider size changes. Add a new routine, g_resize_provider(), to use to notify GEOM about provider change. Reviewed by: mav Sponsored by: FreeBSD Foundation --- sys/geom/geom.h | 6 ++-- sys/geom/geom_subr.c | 79 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 80 insertions(+), 5 deletions(-) diff --git a/sys/geom/geom.h b/sys/geom/geom.h index e85448c1b942..5d97f50fd717 100644 --- a/sys/geom/geom.h +++ b/sys/geom/geom.h @@ -79,6 +79,7 @@ typedef void g_attrchanged_t (struct g_consumer *, const char *attr); typedef void g_provgone_t (struct g_provider *); typedef void g_dumpconf_t (struct sbuf *, const char *indent, struct g_geom *, struct g_consumer *, struct g_provider *); +typedef void g_resize_t(struct g_consumer *cp); /* * The g_class structure describes a transformation class. In other words @@ -108,7 +109,7 @@ struct g_class { g_orphan_t *orphan; g_ioctl_t *ioctl; g_provgone_t *providergone; - void *spare2; + g_resize_t *resize; /* * The remaining elements are private */ @@ -139,7 +140,7 @@ struct g_geom { g_orphan_t *orphan; g_ioctl_t *ioctl; g_provgone_t *providergone; - void *spare1; + g_resize_t *resize; void *softc; unsigned flags; #define G_GEOM_WITHER 1 @@ -265,6 +266,7 @@ int g_handleattr_str(struct bio *bp, const char *attribute, const char *str); struct g_consumer * g_new_consumer(struct g_geom *gp); struct g_geom * g_new_geomf(struct g_class *mp, const char *fmt, ...); struct g_provider * g_new_providerf(struct g_geom *gp, const char *fmt, ...); +void g_resize_provider(struct g_provider *pp, off_t size); int g_retaste(struct g_class *mp); void g_spoil(struct g_provider *pp, struct g_consumer *cp); int g_std_access(struct g_provider *pp, int dr, int dw, int de); diff --git a/sys/geom/geom_subr.c b/sys/geom/geom_subr.c index 489de91cf3b8..37a9ce09c0f7 100644 --- a/sys/geom/geom_subr.c +++ b/sys/geom/geom_subr.c @@ -68,9 +68,11 @@ static struct g_tailq_head geoms = TAILQ_HEAD_INITIALIZER(geoms); char *g_wait_event, *g_wait_up, *g_wait_down, *g_wait_sim; struct g_hh00 { - struct g_class *mp; - int error; - int post; + struct g_class *mp; + struct g_provider *pp; + off_t size; + int error; + int post; }; /* @@ -356,6 +358,7 @@ g_new_geomf(struct g_class *mp, const char *fmt, ...) gp->access = mp->access; gp->orphan = mp->orphan; gp->ioctl = mp->ioctl; + gp->resize = mp->resize; return (gp); } @@ -601,6 +604,76 @@ g_error_provider(struct g_provider *pp, int error) pp->error = error; } +static void +g_resize_provider_event(void *arg, int flag) +{ + struct g_hh00 *hh; + struct g_class *mp; + struct g_geom *gp; + struct g_provider *pp; + struct g_consumer *cp, *cp2; + off_t size; + + g_topology_assert(); + if (flag == EV_CANCEL) + return; + if (g_shutdown) + return; + + hh = arg; + pp = hh->pp; + size = hh->size; + + G_VALID_PROVIDER(pp); + g_trace(G_T_TOPOLOGY, "g_resize_provider_event(%p)", pp); + + LIST_FOREACH_SAFE(cp, &pp->consumers, consumers, cp2) { + gp = cp->geom; + if (gp->resize == NULL && size < pp->mediasize) + cp->geom->orphan(cp); + } + + pp->mediasize = size; + + LIST_FOREACH_SAFE(cp, &pp->consumers, consumers, cp2) { + gp = cp->geom; + if (gp->resize != NULL) + gp->resize(cp); + } + + /* + * After resizing, the previously invalid GEOM class metadata + * might become valid. This means we should retaste. + */ + LIST_FOREACH(mp, &g_classes, class) { + if (mp->taste == NULL) + continue; + LIST_FOREACH(cp, &pp->consumers, consumers) + if (cp->geom->class == mp) + break; + if (cp != NULL) + continue; + mp->taste(mp, pp, 0); + g_topology_assert(); + } +} + +void +g_resize_provider(struct g_provider *pp, off_t size) +{ + struct g_hh00 *hh; + + G_VALID_PROVIDER(pp); + + if (size == pp->mediasize) + return; + + hh = g_malloc(sizeof *hh, M_WAITOK | M_ZERO); + hh->pp = pp; + hh->size = size; + g_post_event(g_resize_provider_event, hh, M_WAITOK, NULL); +} + struct g_provider * g_provider_by_name(char const *arg) {