History

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

Linus Torvalds committed 5 months ago

Commit f83ef5b2 parents eed108e 8339dd01 file · +24 −10Browse files

Unified · Split

fs/xfs/xfs_buf.c+24−10
@@ -472,6 +472,7 @@ xfs_buf_find_insert( · 471 unmodified lines
472472 /* The new buffer keeps the perag reference until it is freed. */
473473 new_bp->b_pag = pag;
474474
475+retry:
475476 rcu_read_lock();
476477 bp = rhashtable_lookup_get_insert_fast(&btp->bt_hash,
477478 &new_bp->b_rhash_head, xfs_buf_hash_params);
@@ -480,8 +481,16 @@ xfs_buf_find_insert( · 2 unmodified lines
480481 error = PTR_ERR(bp);
481482 goto out_free_buf;
482483 }
483− if (bp && lockref_get_not_dead(&bp->b_lockref)) {
484− /* found an existing buffer */
484+ if (bp) {
485+ /*
486+ * If there is an existing buffer with a dead lockref, retry
487+ * until the new buffer is added, or a usable buffer is found.
488+ */
489+ if (!lockref_get_not_dead(&bp->b_lockref)) {
490+ rcu_read_unlock();
491+ cpu_relax();
492+ goto retry;
493+ }
485494 rcu_read_unlock();
486495 error = xfs_buf_find_lock(bp, flags);
487496 if (error)
@@ -820,15 +829,20 @@ xfs_buf_destroy( · 332 unmodified lines
820829 ASSERT(__lockref_is_dead(&bp->b_lockref));
821830 ASSERT(!(bp->b_flags & _XBF_DELWRI_Q));
822831
832+ if (bp->b_pag)
833+ xfs_perag_put(bp->b_pag);
834+ xfs_buf_free(bp);
835+}
836+
837+static inline void
838+xfs_buf_kill(
839+ struct xfs_buf *bp)
840+{
841+ lockref_mark_dead(&bp->b_lockref);
823842 if (!xfs_buf_is_uncached(bp)) {
824843 rhashtable_remove_fast(&bp->b_target->bt_hash,
825844 &bp->b_rhash_head, xfs_buf_hash_params);
826−
827− if (bp->b_pag)
828− xfs_perag_put(bp->b_pag);
829845 }
830−
831− xfs_buf_free(bp);
832846 }
833847
834848 /*
@@ -851,7 +865,7 @@ xfs_buf_rele( · 16 unmodified lines
851865 return;
852866
853867 kill:
854− lockref_mark_dead(&bp->b_lockref);
868+ xfs_buf_kill(bp);
855869 list_lru_del_obj(&bp->b_target->bt_lru, &bp->b_lru);
856870 spin_unlock(&bp->b_lockref.lock);
857871
@@ -1433,7 +1447,7 @@ xfs_buftarg_drain_rele( · 575 unmodified lines
14331447 return LRU_SKIP;
14341448 }
14351449
1436− lockref_mark_dead(&bp->b_lockref);
1450+ xfs_buf_kill(bp);
14371451 list_lru_isolate_move(lru, item, dispose);
14381452 spin_unlock(&bp->b_lockref.lock);
14391453 return LRU_REMOVED;
@@ -1545,7 +1559,7 @@ xfs_buftarg_isolate( · 105 unmodified lines
15451559 return LRU_ROTATE;
15461560 }
15471561
1548− lockref_mark_dead(&bp->b_lockref);
1562+ xfs_buf_kill(bp);
15491563 list_lru_isolate_move(lru, item, dispose);
15501564 spin_unlock(&bp->b_lockref.lock);
15511565 return LRU_REMOVED;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t