mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Merge tag 'xfs-fixes-7.1-rc5' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
Pull xfs fix from Carlos Maiolino: "A single fix for a race in xfs buffer cache which may lead to filesystem shutdown due to inconsistent metadata if the buffer lookup happens to find an old dead buffer still in the cache" * tag 'xfs-fixes-7.1-rc5' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: xfs: fix a buffer lookup against removal race
This commit is contained in:
+24
-10
@@ -472,6 +472,7 @@ xfs_buf_find_insert(
|
||||
/* The new buffer keeps the perag reference until it is freed. */
|
||||
new_bp->b_pag = pag;
|
||||
|
||||
retry:
|
||||
rcu_read_lock();
|
||||
bp = rhashtable_lookup_get_insert_fast(&btp->bt_hash,
|
||||
&new_bp->b_rhash_head, xfs_buf_hash_params);
|
||||
@@ -480,8 +481,16 @@ xfs_buf_find_insert(
|
||||
error = PTR_ERR(bp);
|
||||
goto out_free_buf;
|
||||
}
|
||||
if (bp && lockref_get_not_dead(&bp->b_lockref)) {
|
||||
/* found an existing buffer */
|
||||
if (bp) {
|
||||
/*
|
||||
* If there is an existing buffer with a dead lockref, retry
|
||||
* until the new buffer is added, or a usable buffer is found.
|
||||
*/
|
||||
if (!lockref_get_not_dead(&bp->b_lockref)) {
|
||||
rcu_read_unlock();
|
||||
cpu_relax();
|
||||
goto retry;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
error = xfs_buf_find_lock(bp, flags);
|
||||
if (error)
|
||||
@@ -820,15 +829,20 @@ xfs_buf_destroy(
|
||||
ASSERT(__lockref_is_dead(&bp->b_lockref));
|
||||
ASSERT(!(bp->b_flags & _XBF_DELWRI_Q));
|
||||
|
||||
if (bp->b_pag)
|
||||
xfs_perag_put(bp->b_pag);
|
||||
xfs_buf_free(bp);
|
||||
}
|
||||
|
||||
static inline void
|
||||
xfs_buf_kill(
|
||||
struct xfs_buf *bp)
|
||||
{
|
||||
lockref_mark_dead(&bp->b_lockref);
|
||||
if (!xfs_buf_is_uncached(bp)) {
|
||||
rhashtable_remove_fast(&bp->b_target->bt_hash,
|
||||
&bp->b_rhash_head, xfs_buf_hash_params);
|
||||
|
||||
if (bp->b_pag)
|
||||
xfs_perag_put(bp->b_pag);
|
||||
}
|
||||
|
||||
xfs_buf_free(bp);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -851,7 +865,7 @@ xfs_buf_rele(
|
||||
return;
|
||||
|
||||
kill:
|
||||
lockref_mark_dead(&bp->b_lockref);
|
||||
xfs_buf_kill(bp);
|
||||
list_lru_del_obj(&bp->b_target->bt_lru, &bp->b_lru);
|
||||
spin_unlock(&bp->b_lockref.lock);
|
||||
|
||||
@@ -1433,7 +1447,7 @@ xfs_buftarg_drain_rele(
|
||||
return LRU_SKIP;
|
||||
}
|
||||
|
||||
lockref_mark_dead(&bp->b_lockref);
|
||||
xfs_buf_kill(bp);
|
||||
list_lru_isolate_move(lru, item, dispose);
|
||||
spin_unlock(&bp->b_lockref.lock);
|
||||
return LRU_REMOVED;
|
||||
@@ -1545,7 +1559,7 @@ xfs_buftarg_isolate(
|
||||
return LRU_ROTATE;
|
||||
}
|
||||
|
||||
lockref_mark_dead(&bp->b_lockref);
|
||||
xfs_buf_kill(bp);
|
||||
list_lru_isolate_move(lru, item, dispose);
|
||||
spin_unlock(&bp->b_lockref.lock);
|
||||
return LRU_REMOVED;
|
||||
|
||||
Reference in New Issue
Block a user