Changes since last update:
- Fix an unmount hang due to a race in io buffer accounting. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABCgAGBQJZMKVEAAoJEPh/dxk0SrTrBYcQAKSpzE8C9wDBw6cyxP3kwrTr FSQiSr7flnGBHwy2U0UC/SIFIwYxvW4BTnXJWADyqtnvLWP1+TC7UY1oNpkTsbkK KLsWgz3aOcT/8sb346PzFDAuxof2lkv3xFPRBFaoeSkybxWqLz6BWsbmaJNH/wqy W3k3H241mAftEiv1i9IUlAZMXE31qywIKzzUJvkOglXS8OdVFfMPQvUz6epU2LWA I2tBip936Sl45vLu6ubqoRpk8dWNuPPX+f4YXl8dVeqRKTYhviMwgYD4rlljb6Ti kIRG9HYg1GVZo5z/5unAjyEaKzYoRrXnO5Lg+i09NIhezlDhB2HJ+k71NljoeHoe YCwqumQIGgnxdFu+FP10tKh2EWvDp80SQxgzIvr+FCCKJdsdNYyftRh4CtsCPJSG xWHT1jgovygHsBEEmG2LS9mCXKkyWgMkHNMBu3Yy/F/4HGzrPjcU3F+x90OmOo7J S26kEwsAoo+Q5Is8QkmqrnD+CQ7jwXEv9Mw3UqRwQ7UagRdR2nI8CIGEC7W+42Mm Gd3TtAyJCbhZWXNq7pLeTnGu7JY3/dhR/8VSW+mIKtvFg7v9O1wZBYId8vTwZN1+ 8jgnW0h6myE10YKU5bc1TZeYYAkWA+JLRKxoexL3QD8jWeffyZgMNWPM2rb+4Jjp 2wwCHMPvHE8X7a2urTW3 =wRbJ -----END PGP SIGNATURE----- Merge tag 'xfs-4.12-fixes-3' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux Pull XFS fix from Darrick Wong: "I've one more bugfix for you for 4.12-rc4: Fix an unmount hang due to a race in io buffer accounting" * tag 'xfs-4.12-fixes-3' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: xfs: use ->b_state to fix buffer I/O accounting release race
This commit is contained in:
commit
e6e6d07436
|
@ -97,27 +97,41 @@ static inline void
|
||||||
xfs_buf_ioacct_inc(
|
xfs_buf_ioacct_inc(
|
||||||
struct xfs_buf *bp)
|
struct xfs_buf *bp)
|
||||||
{
|
{
|
||||||
if (bp->b_flags & (XBF_NO_IOACCT|_XBF_IN_FLIGHT))
|
if (bp->b_flags & XBF_NO_IOACCT)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ASSERT(bp->b_flags & XBF_ASYNC);
|
ASSERT(bp->b_flags & XBF_ASYNC);
|
||||||
bp->b_flags |= _XBF_IN_FLIGHT;
|
spin_lock(&bp->b_lock);
|
||||||
percpu_counter_inc(&bp->b_target->bt_io_count);
|
if (!(bp->b_state & XFS_BSTATE_IN_FLIGHT)) {
|
||||||
|
bp->b_state |= XFS_BSTATE_IN_FLIGHT;
|
||||||
|
percpu_counter_inc(&bp->b_target->bt_io_count);
|
||||||
|
}
|
||||||
|
spin_unlock(&bp->b_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clear the in-flight state on a buffer about to be released to the LRU or
|
* Clear the in-flight state on a buffer about to be released to the LRU or
|
||||||
* freed and unaccount from the buftarg.
|
* freed and unaccount from the buftarg.
|
||||||
*/
|
*/
|
||||||
|
static inline void
|
||||||
|
__xfs_buf_ioacct_dec(
|
||||||
|
struct xfs_buf *bp)
|
||||||
|
{
|
||||||
|
ASSERT(spin_is_locked(&bp->b_lock));
|
||||||
|
|
||||||
|
if (bp->b_state & XFS_BSTATE_IN_FLIGHT) {
|
||||||
|
bp->b_state &= ~XFS_BSTATE_IN_FLIGHT;
|
||||||
|
percpu_counter_dec(&bp->b_target->bt_io_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
xfs_buf_ioacct_dec(
|
xfs_buf_ioacct_dec(
|
||||||
struct xfs_buf *bp)
|
struct xfs_buf *bp)
|
||||||
{
|
{
|
||||||
if (!(bp->b_flags & _XBF_IN_FLIGHT))
|
spin_lock(&bp->b_lock);
|
||||||
return;
|
__xfs_buf_ioacct_dec(bp);
|
||||||
|
spin_unlock(&bp->b_lock);
|
||||||
bp->b_flags &= ~_XBF_IN_FLIGHT;
|
|
||||||
percpu_counter_dec(&bp->b_target->bt_io_count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -149,9 +163,9 @@ xfs_buf_stale(
|
||||||
* unaccounted (released to LRU) before that occurs. Drop in-flight
|
* unaccounted (released to LRU) before that occurs. Drop in-flight
|
||||||
* status now to preserve accounting consistency.
|
* status now to preserve accounting consistency.
|
||||||
*/
|
*/
|
||||||
xfs_buf_ioacct_dec(bp);
|
|
||||||
|
|
||||||
spin_lock(&bp->b_lock);
|
spin_lock(&bp->b_lock);
|
||||||
|
__xfs_buf_ioacct_dec(bp);
|
||||||
|
|
||||||
atomic_set(&bp->b_lru_ref, 0);
|
atomic_set(&bp->b_lru_ref, 0);
|
||||||
if (!(bp->b_state & XFS_BSTATE_DISPOSE) &&
|
if (!(bp->b_state & XFS_BSTATE_DISPOSE) &&
|
||||||
(list_lru_del(&bp->b_target->bt_lru, &bp->b_lru)))
|
(list_lru_del(&bp->b_target->bt_lru, &bp->b_lru)))
|
||||||
|
@ -979,12 +993,12 @@ xfs_buf_rele(
|
||||||
* ensures the decrement occurs only once per-buf.
|
* ensures the decrement occurs only once per-buf.
|
||||||
*/
|
*/
|
||||||
if ((atomic_read(&bp->b_hold) == 1) && !list_empty(&bp->b_lru))
|
if ((atomic_read(&bp->b_hold) == 1) && !list_empty(&bp->b_lru))
|
||||||
xfs_buf_ioacct_dec(bp);
|
__xfs_buf_ioacct_dec(bp);
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the last reference has been dropped ... */
|
/* the last reference has been dropped ... */
|
||||||
xfs_buf_ioacct_dec(bp);
|
__xfs_buf_ioacct_dec(bp);
|
||||||
if (!(bp->b_flags & XBF_STALE) && atomic_read(&bp->b_lru_ref)) {
|
if (!(bp->b_flags & XBF_STALE) && atomic_read(&bp->b_lru_ref)) {
|
||||||
/*
|
/*
|
||||||
* If the buffer is added to the LRU take a new reference to the
|
* If the buffer is added to the LRU take a new reference to the
|
||||||
|
|
|
@ -63,7 +63,6 @@ typedef enum {
|
||||||
#define _XBF_KMEM (1 << 21)/* backed by heap memory */
|
#define _XBF_KMEM (1 << 21)/* backed by heap memory */
|
||||||
#define _XBF_DELWRI_Q (1 << 22)/* buffer on a delwri queue */
|
#define _XBF_DELWRI_Q (1 << 22)/* buffer on a delwri queue */
|
||||||
#define _XBF_COMPOUND (1 << 23)/* compound buffer */
|
#define _XBF_COMPOUND (1 << 23)/* compound buffer */
|
||||||
#define _XBF_IN_FLIGHT (1 << 25) /* I/O in flight, for accounting purposes */
|
|
||||||
|
|
||||||
typedef unsigned int xfs_buf_flags_t;
|
typedef unsigned int xfs_buf_flags_t;
|
||||||
|
|
||||||
|
@ -84,14 +83,14 @@ typedef unsigned int xfs_buf_flags_t;
|
||||||
{ _XBF_PAGES, "PAGES" }, \
|
{ _XBF_PAGES, "PAGES" }, \
|
||||||
{ _XBF_KMEM, "KMEM" }, \
|
{ _XBF_KMEM, "KMEM" }, \
|
||||||
{ _XBF_DELWRI_Q, "DELWRI_Q" }, \
|
{ _XBF_DELWRI_Q, "DELWRI_Q" }, \
|
||||||
{ _XBF_COMPOUND, "COMPOUND" }, \
|
{ _XBF_COMPOUND, "COMPOUND" }
|
||||||
{ _XBF_IN_FLIGHT, "IN_FLIGHT" }
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Internal state flags.
|
* Internal state flags.
|
||||||
*/
|
*/
|
||||||
#define XFS_BSTATE_DISPOSE (1 << 0) /* buffer being discarded */
|
#define XFS_BSTATE_DISPOSE (1 << 0) /* buffer being discarded */
|
||||||
|
#define XFS_BSTATE_IN_FLIGHT (1 << 1) /* I/O in flight */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The xfs_buftarg contains 2 notions of "sector size" -
|
* The xfs_buftarg contains 2 notions of "sector size" -
|
||||||
|
|
Loading…
Reference in New Issue