41 lines
1.8 KiB
Plaintext
Raw Normal View History

$FreeBSD$
For the lack of a better place to put them, this file will contain
notes on some of the more intricate details of geom.
-----------------------------------------------------------------------
Locking of bio_children and bio_inbed
bio_children is used by g_std_done() and g_clone_bio() to keep track
of children cloned off a request. g_clone_bio will increment the
bio_children counter for each time it is called and g_std_done will
increment bio_inbed for every call, and if the two counters are
equal, call g_io_deliver() on the parent bio.
The general assumption is that g_clone_bio() is called only in
the g_down thread, and g_std_done() only in the g_up thread and
therefore the two fields do not generally need locking. These
restrictions are not enforced by the code, but only with great
care should they be violated.
It is the responsibility of the class implementation to avoid the
following race condition: A class intend to split a bio in two
children. It clones the bio, and requests I/O on the child.
This I/O operation completes before the second child is cloned
and g_std_done() sees the counters both equal 1 and finishes off
the bio.
There is no race present in the common case where the bio is split
in multiple parts in the class start method and the I/O is requested
on another GEOM class below: There is only one g_down thread and
the class below will not get its start method run until we return
from our start method, and consequently the I/O cannot complete
prematurely.
In all other cases, this race needs to be mitigated, for instance
by cloning all children before I/O is request on any of them.
Notice that cloning an "extra" child and calling g_std_done() on
it directly opens another race since the assumption is that
g_std_done() only is called in the g_up thread.