]> git.karo-electronics.de Git - karo-tx-linux.git/commit
buffer: memorder fix
authorNick Piggin <npiggin@suse.de>
Sat, 10 Feb 2007 09:46:22 +0000 (01:46 -0800)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 9 Mar 2007 18:50:30 +0000 (10:50 -0800)
commit54710f60049c613cd0ae4bb0d3180f8bfb8c323c
treea5b0ca8f6ed51afb56568f4fb2152346928e4f56
parent5556eaffcc2704d9dca81c80cf3e7cbcc869f680
buffer: memorder fix

unlock_buffer(), like unlock_page(), must not clear the lock without
ensuring that the critical section is closed.

Mingming later sent the same patch, saying:

We are running SDET benchmark and saw double free issue for ext3 extended
attributes block, which complains the same xattr block already being freed (in
ext3_xattr_release_block()).  The problem could also been triggered by
multiple threads loop untar/rm a kernel tree.

The race is caused by missing a memory barrier at unlock_buffer() before the
lock bit being cleared, resulting in possible concurrent h_refcounter update.
That causes a reference counter leak, then later leads to the double free that
we have seen.

Inside unlock_buffer(), there is a memory barrier is placed *after* the lock
bit is being cleared, however, there is no memory barrier *before* the bit is
cleared.  On some arch the h_refcount update instruction and the clear bit
instruction could be reordered, thus leave the critical section re-entered.

The race is like this: For example, if the h_refcount is initialized as 1,

cpu 0:                                   cpu1
fs/buffer.c