Carlos Maiolino e599b3253c 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>
2012-08-24 13:46:10 -05:00
..
2011-08-12 16:21:35 -05:00
2011-08-12 16:21:35 -05:00
2011-08-12 16:21:35 -05:00
2011-08-12 16:21:35 -05:00
2011-07-25 15:03:13 -05:00
2012-05-14 16:21:00 -05:00
2011-07-13 13:43:48 +02:00
2011-08-12 16:21:35 -05:00
2011-08-12 16:21:35 -05:00
2011-03-07 10:09:35 +11:00
2012-05-29 23:28:33 -04:00
2011-08-12 16:21:35 -05:00
2011-08-12 16:21:35 -05:00
2012-07-29 16:23:51 -05:00
2012-07-29 16:23:51 -05:00
2012-05-14 16:20:54 -05:00
2011-08-12 16:21:35 -05:00
2012-07-31 09:45:48 +04:00
2011-08-12 16:21:35 -05:00
2010-12-16 16:05:51 -06:00
2012-07-30 13:37:53 -07:00
2011-08-12 16:21:35 -05:00
2012-06-21 14:22:27 -05:00
2012-06-21 14:22:27 -05:00
2012-05-14 16:21:00 -05:00
2012-07-29 16:23:51 -05:00
2012-03-13 17:01:15 -05:00
2011-08-12 16:21:35 -05:00
2011-08-12 16:21:35 -05:00
2012-05-14 16:21:00 -05:00
2012-07-31 09:45:48 +04:00
2012-01-03 22:55:00 -05:00
2011-08-12 16:21:35 -05:00