RFC: adding 'proxy' nodes to provider ports (with patch)
Pawel Jakub Dawidek
pjd at FreeBSD.org
Mon Mar 23 13:19:21 PDT 2009
On Mon, Mar 23, 2009 at 09:07:12PM +0100, Luigi Rizzo wrote:
> On Mon, Mar 23, 2009 at 06:58:16AM +0000, Poul-Henning Kamp wrote:
> > In message <20090323060325.GN3102 at garage.freebsd.pl>, Pawel Jakub Dawidek write
> > s:
> >
> > >There is still a naming problem. pp and new_pp will end up with the same
> > >name. I'd suggest instructing GEOM to expose only parent in /dev/.
> >
> > who said the new provider had to have same name ?
> >
> > >The taste is still going to be send on new class arrival and on the last
> > >pp write close.
> >
> > We decide that.
> >
> > Since we are inserting in an already open path, I think it makes very
> > good sense to supress tasting, at least until close.
>
> To summarize, here is how I have implemented a node that
> supports both regular "create" and the transparent "insert"
> we are discussing.
> Say we want to attach to an existing provider "pp" whose name is "ad0"
>
> BEFORE ---> [ pp --> old_gp ...]
>
> Then we can do either "geom xx create ad0" which results in
>
> AFTER create ---> [ newpp --> gp --> cp ] ---> [ pp --> old_gp ... ]
>
> or "geom xx insert ad0", which results in
>
> AFTER insert ---> [ pp --> gp --> cp ] ---> [ newpp --> old_gp ... ]
>
> The names of the various objects are the same in both cases so
>
> old_gp->name = "ad0"
> pp->name = "ad0"
> gp->name = "ad0.xx."
> newpp->name = "ad0.xx."
>
> This lets new clients connect to provider "ad0" without having to
> know about any insertion.
> Also, to remove the newly inserted pieces, in both cases you can
> run the same command "geom xx destroy ad0.xx." (remembering that
> in this case you are naming the geom, not the provider).
>
> In terms of code, no changes to the infrastructure, and the
> create/insert and destroy functions are the following (error checking
> removed for clarity)
>
> g_xx_create(struct g_provider *pp, struct g_class *mp, int insert ...)
> {
> snprintf(name, sizeof(name), "%s%s", pp->name, MY_SUFFIX);
> gp = g_new_geomf(mp, name);
> ... allocate and fill softc and geom...
> newpp = g_new_providerf(insert ? pp->geom : gp, gp->name);
> ... initialize mediasize and sectorsize
> cp = g_new_consumer(gp);
> g_attach(cp, insert ? newpp : pp);
> if (insert) {
> g_cancel_event(newpp); /* no taste() on this*/
> /* link pp to old_gp */
> LIST_REMOVE(pp, provider);
> pp->geom = gp;
newpp->private = pp->private;
pp->private = NULL;
newpp->index = pp->index;
pp->index = 0;
> LIST_INSERT_HEAD(&gp->provider, pp, provider);
> g_access(cp, 1, 1, 1); /* we can move data */
> sc->sc_insert = 1; /* remember for the destroy */
> }
> g_error_provider(newpp, 0);
> }
>
> Here it is a bit inefficient to have to call g_cancel_event()
> but short of changing g_new_providerf() there is no way to
> avoid the g_new_provider event.
>
> g_xx_destroy(struct g_geom *gp)
> {
> ...
> if (sc->sc_insert) {
> pp = LIST_FIRST(&gp->provider);
> cp = LIST_FIRST(&gp->consumer);
> newpp = cp->provider;
> /* Link provider to the original geom. */
> LIST_REMOVE(pp, provider);
> pp->geom = newpp->geom;
pp->private = newpp->private;
newpp->private = NULL;
pp->index = newpp->index;
newpp->index = 0;
> LIST_INSERT_HEAD(&pp->geom->provider, pp, provider);
> g_access(cp, -1, -1, -1);
> /* I am not sure if we need the following 3 */
> g_detach(cp);
> LIST_REMOVE(newpp, provider);
> g_destroy_provider(newpp);
> }
> ...
> /* regular destroy path */
> }
>
> Above, I am not totally sure if we need to explicitly call g_detach()
> and destroy the provider, or if it will come for free as a result of
> the regular destoy code.
>
> The block "if (sc->sc_insert) {..}" is reasonably generic
> (and large, when you put in the error checking) to possibly deserve
> a function in geom_subr.c -- but until there are no other clients,
> it makes no sense.
>
> As usual, feedback welcome.
I don't think this is good idea to try to squeeze creation and insertion
in one function. IMHO it would be better to have generic functions for
insert/remove functionality:
int g_insert(struct g_class *class, struct g_provider *oldpp);
int g_remove(struct g_provider *oldpp);
(In g_insert() class name can be attached to new provider's name for
example.)
--
Pawel Jakub Dawidek http://www.wheel.pl
pjd at FreeBSD.org http://www.FreeBSD.org
FreeBSD committer Am I Evil? Yes, I Am!
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 187 bytes
Desc: not available
Url : http://lists.freebsd.org/pipermail/freebsd-geom/attachments/20090323/83a8da72/attachment.pgp
More information about the freebsd-geom
mailing list