diff options
| author | Andreas Gruenbacher <agruen@suse.de> | 2005-01-14 23:35:57 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-01-14 23:35:57 -0800 |
| commit | fd1ea9abe35beaa2402b90b83a4c47135b086613 (patch) | |
| tree | fae65165516b9faed78100cd3e9bb532a01c43d4 /include/linux | |
| parent | 401494b1615efb1922a380226b0bea3eccb22ff3 (diff) | |
[PATCH] ext3/EA: Race in ext[23] xattr sharing code
Andrew Tridgell and Stephen C. Tweedie have reported two different Oopses
caused by a race condition in the mbcache, which is responsible for
extended attribute sharing in ext2 and ext3. Stephen tracked down the bug;
I did the fix.
Explanation:
The mbcache caches the locations and content hashes of xattr blocks. There
are two access strategies: [1] xattr block disposal via
mb_cache_entry_get(), [2] xattr block reuse (sharing) via
mb_cache_entry_find_{first,next}(). There is no locking between the two
methods, so between one mb_cache_entry_find_x and the next, a
mb_cache_entry_get might come in, unhash the cache entry, and change the
journaling state of the xattr buffer. Subsequently, two things can happen:
[a] the next mb_cache_entry_find_x may try to follow the mbcache hash chain
starting from the entry that has become unhashed, which now is a stale
pointer, [b] the block may have become deallocated, and then we try to
reuse it.
Fix this by converting the mbcache into a readers-writer style lock, and
protect all block accesses in ext2/ext3 by the mbcache entry lock. This
ensures that destroying blocks is an exclusive operation that may not
overlap xattr block reuse, while allowing multiple "re-users". Write
access to the xattr block's buffer is protected by the buffer lock.
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/mbcache.h | 3 |
1 files changed, 2 insertions, 1 deletions
diff --git a/include/linux/mbcache.h b/include/linux/mbcache.h index 4c941af6225c..8e5a10410a30 100644 --- a/include/linux/mbcache.h +++ b/include/linux/mbcache.h @@ -10,7 +10,8 @@ struct mb_cache_entry { struct list_head e_lru_list; struct mb_cache *e_cache; - atomic_t e_used; + unsigned short e_used; + unsigned short e_queued; struct block_device *e_bdev; sector_t e_block; struct list_head e_block_list; |
