]> git.hungrycats.org Git - linux/commit
[PATCH] raw.c refcounting fix
authorAndrew Morton <akpm@osdl.org>
Mon, 19 Jan 2004 02:07:34 +0000 (18:07 -0800)
committerLinus Torvalds <torvalds@home.osdl.org>
Mon, 19 Jan 2004 02:07:34 +0000 (18:07 -0800)
commita15092bd9efa40e0a4584e62efd69ecb66906ed0
treecbdb7a49c9155714f200dec842a665d202c8ffe3
parent5524f26f3c6f3ce54dd76bb8651fec4544199ae7
[PATCH] raw.c refcounting fix

From: viro@parcelfarce.linux.theplanet.co.uk

raw.c has a refcounting bug (patch attached).

As for the theory...  If you have a pathname - use filp_open() or
open_bdev_excl() and be done with that.  bdget() et.al.  are OK only if you
really have nothing better than device number and that's a situation that
should be avoided unless you really have no choice.

Said that, we have the following primitives:

* lookup_bdev(): takes a pathname, returns a reference to block_device.

* bdget(): takes a number, returns a reference to block_device.

* blkdev_get(): takes a reference to block_device and opens it.  If open
  fails - drops the reference to block_device passed to it.

* blkdev_put(): takes a reference to block_device and closes it.  The
  reference is dropped.

* bdput(): drops a reference to block_device.

Note that behaviour of blkdev_get() and blkdev_put() is such that it makes
for minimal cleanup code.

bd_claim()/bd_release() is the exclusion mechanism - that's what mount,
swapon, open with O_EXCL, etc.  are using to avoid stepping on each others
toes.  bd_claim() claims bdev for given owner; if it's already owned and
not by the same owner you'll get -EBUSY.  bd_release() reverts the effect
of bd_claim().  Note that if you claim the thing N times (with the same
owner, obviously), you'll need N bd_release() before it stops being owned.

raw.c grabbed a reference to bdev only after blkdev_get().  If blkdev_get()
failed (e.g.  media being absent), you've got an unbalanced bdput().
drivers/char/raw.c