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
472 /* The new buffer keeps the perag reference until it is freed. */472 /* The new buffer keeps the perag reference until it is freed. */
473 new_bp->b_pag = pag;473 new_bp->b_pag = pag;
474 474
475retry:
475 rcu_read_lock();476 rcu_read_lock();
476 bp = rhashtable_lookup_get_insert_fast(&btp->bt_hash,477 bp = rhashtable_lookup_get_insert_fast(&btp->bt_hash,
477 &new_bp->b_rhash_head, xfs_buf_hash_params);478 &new_bp->b_rhash_head, xfs_buf_hash_params);
@@ -480,8 +481,16 @@ xfs_buf_find_insert( · 2 unmodified lines
480 error = PTR_ERR(bp);481 error = PTR_ERR(bp);
481 goto out_free_buf;482 goto out_free_buf;
482 }483 }
483 if (bp && lockref_get_not_dead(&bp->b_lockref)) {484 if (bp) {
484 /* found an existing buffer */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 }
485 rcu_read_unlock();494 rcu_read_unlock();
486 error = xfs_buf_find_lock(bp, flags);495 error = xfs_buf_find_lock(bp, flags);
487 if (error)496 if (error)
@@ -820,15 +829,20 @@ xfs_buf_destroy( · 332 unmodified lines
820 ASSERT(__lockref_is_dead(&bp->b_lockref));829 ASSERT(__lockref_is_dead(&bp->b_lockref));
821 ASSERT(!(bp->b_flags & _XBF_DELWRI_Q));830 ASSERT(!(bp->b_flags & _XBF_DELWRI_Q));
822 831
832 if (bp->b_pag)
833 xfs_perag_put(bp->b_pag);
834 xfs_buf_free(bp);
835}
836
837static inline void
838xfs_buf_kill(
839 struct xfs_buf *bp)
840{
841 lockref_mark_dead(&bp->b_lockref);
823 if (!xfs_buf_is_uncached(bp)) {842 if (!xfs_buf_is_uncached(bp)) {
824 rhashtable_remove_fast(&bp->b_target->bt_hash,843 rhashtable_remove_fast(&bp->b_target->bt_hash,
825 &bp->b_rhash_head, xfs_buf_hash_params);844 &bp->b_rhash_head, xfs_buf_hash_params);
826
827 if (bp->b_pag)
828 xfs_perag_put(bp->b_pag);
829 }845 }
830
831 xfs_buf_free(bp);
832}846}
833 847
834/*848/*
@@ -851,7 +865,7 @@ xfs_buf_rele( · 16 unmodified lines
851 return;865 return;
852 866
853kill:867kill:
854 lockref_mark_dead(&bp->b_lockref);868 xfs_buf_kill(bp);
855 list_lru_del_obj(&bp->b_target->bt_lru, &bp->b_lru);869 list_lru_del_obj(&bp->b_target->bt_lru, &bp->b_lru);
856 spin_unlock(&bp->b_lockref.lock);870 spin_unlock(&bp->b_lockref.lock);
857 871
@@ -1433,7 +1447,7 @@ xfs_buftarg_drain_rele( · 575 unmodified lines
1433 return LRU_SKIP;1447 return LRU_SKIP;
1434 }1448 }
1435 1449
1436 lockref_mark_dead(&bp->b_lockref);1450 xfs_buf_kill(bp);
1437 list_lru_isolate_move(lru, item, dispose);1451 list_lru_isolate_move(lru, item, dispose);
1438 spin_unlock(&bp->b_lockref.lock);1452 spin_unlock(&bp->b_lockref.lock);
1439 return LRU_REMOVED;1453 return LRU_REMOVED;
@@ -1545,7 +1559,7 @@ xfs_buftarg_isolate( · 105 unmodified lines
1545 return LRU_ROTATE;1559 return LRU_ROTATE;
1546 }1560 }
1547 1561
1548 lockref_mark_dead(&bp->b_lockref);1562 xfs_buf_kill(bp);
1549 list_lru_isolate_move(lru, item, dispose);1563 list_lru_isolate_move(lru, item, dispose);
1550 spin_unlock(&bp->b_lockref.lock);1564 spin_unlock(&bp->b_lockref.lock);
1551 return LRU_REMOVED;1565 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