Author: trasz
Date: Sat Jul  7 20:13:40 2012
New Revision: 238213
URL: http://svn.freebsd.org/changeset/base/238213

Log:
  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

Modified:
  head/sys/geom/geom.h
  head/sys/geom/geom_subr.c

Modified: head/sys/geom/geom.h
==============================================================================
--- head/sys/geom/geom.h        Sat Jul  7 19:39:08 2012        (r238212)
+++ head/sys/geom/geom.h        Sat Jul  7 20:13:40 2012        (r238213)
@@ -79,6 +79,7 @@ typedef void g_attrchanged_t (struct g_c
 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, con
 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);

Modified: head/sys/geom/geom_subr.c
==============================================================================
--- head/sys/geom/geom_subr.c   Sat Jul  7 19:39:08 2012        (r238212)
+++ head/sys/geom/geom_subr.c   Sat Jul  7 20:13:40 2012        (r238213)
@@ -68,9 +68,11 @@ static struct g_tailq_head geoms = TAILQ
 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 ch
        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, 
        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)
 {
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to