diff options
author | Omar Sandoval <osandov@osandov.com> | 2015-02-24 02:47:05 -0800 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2015-04-26 06:27:00 -0700 |
commit | 5ca64f45e92dc52bd3bc1ad93f4f9e5a57955f28 (patch) | |
tree | 3e197015904be5b68c3ed94314c4ca2ef0c06051 /fs/btrfs/free-space-cache.c | |
parent | 67b7859e9bfa0dcee5a8256932e393e98739be1b (diff) | |
download | blackbird-op-linux-5ca64f45e92dc52bd3bc1ad93f4f9e5a57955f28.tar.gz blackbird-op-linux-5ca64f45e92dc52bd3bc1ad93f4f9e5a57955f28.zip |
btrfs: fix race on ENOMEM in alloc_extent_buffer
Consider the following interleaving of overlapping calls to
alloc_extent_buffer:
Call 1:
- Successfully allocates a few pages with find_or_create_page
- find_or_create_page fails, goto free_eb
- Unlocks the allocated pages
Call 2:
- Calls find_or_create_page and gets a page in call 1's extent_buffer
- Finds that the page is already associated with an extent_buffer
- Grabs a reference to the half-written extent_buffer and calls
mark_extent_buffer_accessed on it
mark_extent_buffer_accessed will then try to call mark_page_accessed on
a null page and panic.
The fix is to decrement the reference count on the half-written
extent_buffer before unlocking the pages so call 2 won't use it. We
should also set exists = NULL in the case that we don't use exists to
avoid accidentally returning a freed extent_buffer in an error case.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
Reviewed-by: David Sterba <dsterba@suse.cz>
Reviewed-by: Liu Bo <bo.li.liu@oracle.com>
Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/free-space-cache.c')
0 files changed, 0 insertions, 0 deletions