Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 9 Jan 2009 14:09:11 +0100
From:      Luigi Rizzo <rizzo@iet.unipi.it>
To:        arch@freebsd.org
Cc:        fabio@gandalf.sssup.it
Subject:   tagging disk requests (geom-related)
Message-ID:  <20090109130911.GA17017@onelab2.iet.unipi.it>

next in thread | raw e-mail | index | archive | help
Hi,
together with Fabio Checconi we are working on some disk schedulers
using a geom class.
One of the things we have is to do is tag requests (struct bio)
with the identity of the thread issuing the request (or some other
classification information, but which one is irrelevant here).
We cannot do the tagging when we reach our geom class because at this
point we have lost the thread information (curthread is "g_down"
at this point).

So there are two issues here: 1) where to store the tag, 2) who
does the tagging.

    (Background for non geom-aware people: each request is identified
    by a 'struct bio' (BIO); when moving from a GEOM class to the
    next one downstream, a BIO is cloned and possibly split (e.g.,
    to do slicing, RAID, or simply breaking up large requests) and
    each child BIO has a pointer to the parent BIO, so overall they
    are connected in a tree even though more frequently there is
    just a linear chain.)

For #1, to avoid adding a field to 'struct bio', we store the tag
in the bio_caller1 field (if available) of the root element of the
BIO tree, bio_caller1 is normally unused (except by ZFS), and we
say it is available if it contains NULL. For the reasons stated
above, we cannot store the mark in the BIO associated to our geom
class because it does not exist yet when we need to store the mark.

Re #2, we can put the code that does the marking either in the place
where the root BIO is created (but there may be many such places,
and especially they can be in external modules that we are not even
aware of), or hook into a central place, g_io_request(), and walk
up the BIO tree until we find the root:

        {
                struct bio *top = bp;

                while (top->bio_parent)
                        top = top->bio_parent;
                if (top->bio_caller1 == NULL)
                        top->bio_caller1 = (void *)curthread->td_tid;
        }

We opted for the latter.
The drawbacks of this approach are that we are writing in a BIO
that is not ours, also that bio_caller1 might be unavailable (e.g.
in the ZFS case).

The alternative approach is adding one field to the struct bio -- in this
case the marking could just be done on the current BIO in g_io_request,
and propagated down in g_clone_bio() (or just in the lookup, walk
up the tree to the topmost marked bio).

So, do you have any better ideas, e.g. other fields in the topmost
bio that we can use ?

	cheers
	luigi




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