diff options
author | Carlos Maiolino <cmaiolino@redhat.com> | 2012-08-10 15:01:51 -0300 |
---|---|---|
committer | Ben Myers <bpm@sgi.com> | 2012-08-24 13:46:10 -0500 |
commit | e599b3253c5e49f7a2a579eef2fc2aa066989ef5 (patch) | |
tree | b54f738a2ab484b0d86a78e6cf8edf7cec4c9530 /lib/fault-inject.c | |
parent | 643bfc061c47e9c7661324a09fb0a0bc6601e5d6 (diff) | |
download | op-kernel-dev-e599b3253c5e49f7a2a579eef2fc2aa066989ef5.zip op-kernel-dev-e599b3253c5e49f7a2a579eef2fc2aa066989ef5.tar.gz |
xfs: fix race while discarding buffers [V4]
While xfs_buftarg_shrink() is freeing buffers from the dispose list (filled with
buffers from lru list), there is a possibility to have xfs_buf_stale() racing
with it, and removing buffers from dispose list before xfs_buftarg_shrink() does
it.
This happens because xfs_buftarg_shrink() handle the dispose list without
locking and the test condition in xfs_buf_stale() checks for the buffer being in
*any* list:
if (!list_empty(&bp->b_lru))
If the buffer happens to be on dispose list, this causes the buffer counter of
lru list (btp->bt_lru_nr) to be decremented twice (once in xfs_buftarg_shrink()
and another in xfs_buf_stale()) causing a wrong account usage of the lru list.
This may cause xfs_buftarg_shrink() to return a wrong value to the memory
shrinker shrink_slab(), and such account error may also cause an underflowed
value to be returned; since the counter is lower than the current number of
items in the lru list, a decrement may happen when the counter is 0, causing
an underflow on the counter.
The fix uses a new flag field (and a new buffer flag) to serialize buffer
handling during the shrink process. The new flag field has been designed to use
btp->bt_lru_lock/unlock instead of xfs_buf_lock/unlock mechanism.
dchinner, sandeen, aquini and aris also deserve credits for this.
Signed-off-by: Carlos Maiolino <cmaiolino@redhat.com>
Reviewed-by: Ben Myers <bpm@sgi.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'lib/fault-inject.c')
0 files changed, 0 insertions, 0 deletions