Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 7 Jul 2012 20:13:41 +0000 (UTC)
From:      Edward Tomasz Napierala <trasz@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r238213 - head/sys/geom
Message-ID:  <201207072013.q67KDfHN082943@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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)
 {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201207072013.q67KDfHN082943>