Re: patch for fs/buffer.c get_unused_buffer_head

Colin Plumb (
Sat, 26 Jul 97 00:18:18 MDT

Bill - close, but it's not quite deadlock-free.

The problem is that create_buffers is called for a page worth of
buffers (up to 16, if the file system has a 512 byte block and this
is an Alpha with 8K pages), and if two processes each grab half of
the reserved list and hen block waiting for more to become available
so they can satisfy their quota, we have deadlock.

With your 12-head example, a 4K page example:

- The unused list is empty
- Process 1 grabs 4 buffer heads for something on a 1K-block system
(e.g. ext2fs)
- Process 2 grabs 2 for a 2K-block system (e.g. CDROM)
- Process 3 tries for 8 for something, gets 6, and blocks pending two more.
- Process 4 starts trying some async I/O, and is about to ask for buffers
- Process 1 and 2's I/O completes (and wake up 3, but 4 is in the kernel)
- Process 4 tries for 8 for something on a 512-byte-block system (e.g. HFS),
gets 6, and blocks pending two more.

Yeah, it's involved, but it's deadlock.

There are two possible fixes:
- Have the async I/O be able to work with fewer buffer_heads if necessary,
doing as much of the page as it can and then reusing the buffer_heads
for the rest, or
- Have create_buffers try for all the buffers it needs, and if it doesn't
get them all, put them all back and go to sleep on &buffer_wait until
more come available.

The latter is probably easier. It takes the sleep out of
get_unused_buffer_head and moves it into create_buffers.
(You also might want to up the reserved list to 16 entries,
to cope with the Alpha worst case.)

(I'm a little unclear on the locking here - is there any risk that
the lists will get refreshed before the sleep_on?)

Oh, if I'm confused and wrong about anything I'm saying here, please
consider it another step in my learning the page & buffer cache and
explain where I'm mistaken.