Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 23 Mar 2009 21:07:12 +0100
From:      Luigi Rizzo <rizzo@iet.unipi.it>
To:        Poul-Henning Kamp <phk@phk.freebsd.dk>
Cc:        luigi@FreeBSD.org, freebsd-geom@FreeBSD.org, Pawel Jakub Dawidek <pjd@FreeBSD.org>, fabio@gandalf.sssup.it, Ivan Voras <ivoras@FreeBSD.org>
Subject:   Re: RFC: adding 'proxy' nodes to provider ports (with patch)
Message-ID:  <20090323200712.GA28660@onelab2.iet.unipi.it>
In-Reply-To: <42618.1237791496@critter.freebsd.dk>
References:  <20090323060325.GN3102@garage.freebsd.pl> <42618.1237791496@critter.freebsd.dk>

next in thread | previous in thread | raw e-mail | index | archive | help
On Mon, Mar 23, 2009 at 06:58:16AM +0000, Poul-Henning Kamp wrote:
> In message <20090323060325.GN3102@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;
                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;
                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.

	cheers
	luigi



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