Skip to content

Commit 497560b

Browse files
Christoph Hellwigcmaiolino
authored andcommitted
xfs: switch (back) to a per-buftarg buffer hash
The per-AG buffer hashes were added when all buffer lookups took a per-hash look. Since then we've made lookups entirely lockless and removed the need for a hash-wide lock for inserts and removals as well. With this there is no need to sharding the hash, so reduce the used resources by using a per-buftarg hash for all buftargs. Long after writing this initially, syzbot found a problem in the buffer cache teardown order, which this happens to fix as well by doing the entire buffer cache teardown in one places instead of splitting it between destroying the buftarg and the perag structures. Link: https://lore.kernel.org/linux-xfs/aLeUdemAZ5wmtZel@dread.disaster.area/ Reported-by: syzbot+0391d34e801643e2809b@syzkaller.appspotmail.com Reviewed-by: Darrick J. Wong <djwong@kernel.org> Tested-by: syzbot+0391d34e801643e2809b@syzkaller.appspotmail.com Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Brian Foster <bfoster@redhat.com> Signed-off-by: Carlos Maiolino <cem@kernel.org>
1 parent d02ee47 commit 497560b

5 files changed

Lines changed: 18 additions & 69 deletions

File tree

fs/xfs/libxfs/xfs_ag.c

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,7 @@ xfs_perag_uninit(
110110
struct xfs_group *xg)
111111
{
112112
#ifdef __KERNEL__
113-
struct xfs_perag *pag = to_perag(xg);
114-
115-
cancel_delayed_work_sync(&pag->pag_blockgc_work);
116-
xfs_buf_cache_destroy(&pag->pag_bcache);
113+
cancel_delayed_work_sync(&to_perag(xg)->pag_blockgc_work);
117114
#endif
118115
}
119116

@@ -235,10 +232,6 @@ xfs_perag_alloc(
235232
INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC);
236233
#endif /* __KERNEL__ */
237234

238-
error = xfs_buf_cache_init(&pag->pag_bcache);
239-
if (error)
240-
goto out_free_perag;
241-
242235
/*
243236
* Pre-calculated geometry
244237
*/
@@ -250,12 +243,10 @@ xfs_perag_alloc(
250243

251244
error = xfs_group_insert(mp, pag_group(pag), index, XG_TYPE_AG);
252245
if (error)
253-
goto out_buf_cache_destroy;
246+
goto out_free_perag;
254247

255248
return 0;
256249

257-
out_buf_cache_destroy:
258-
xfs_buf_cache_destroy(&pag->pag_bcache);
259250
out_free_perag:
260251
kfree(pag);
261252
return error;

fs/xfs/libxfs/xfs_ag.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,6 @@ struct xfs_perag {
8585
int pag_ici_reclaimable; /* reclaimable inodes */
8686
unsigned long pag_ici_reclaim_cursor; /* reclaim restart point */
8787

88-
struct xfs_buf_cache pag_bcache;
89-
9088
/* background prealloc block trimming */
9189
struct delayed_work pag_blockgc_work;
9290
#endif /* __KERNEL__ */

fs/xfs/xfs_buf.c

Lines changed: 13 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -363,20 +363,6 @@ static const struct rhashtable_params xfs_buf_hash_params = {
363363
.obj_cmpfn = _xfs_buf_obj_cmp,
364364
};
365365

366-
int
367-
xfs_buf_cache_init(
368-
struct xfs_buf_cache *bch)
369-
{
370-
return rhashtable_init(&bch->bc_hash, &xfs_buf_hash_params);
371-
}
372-
373-
void
374-
xfs_buf_cache_destroy(
375-
struct xfs_buf_cache *bch)
376-
{
377-
rhashtable_destroy(&bch->bc_hash);
378-
}
379-
380366
static int
381367
xfs_buf_map_verify(
382368
struct xfs_buftarg *btp,
@@ -434,7 +420,7 @@ xfs_buf_find_lock(
434420

435421
static inline int
436422
xfs_buf_lookup(
437-
struct xfs_buf_cache *bch,
423+
struct xfs_buftarg *btp,
438424
struct xfs_buf_map *map,
439425
xfs_buf_flags_t flags,
440426
struct xfs_buf **bpp)
@@ -443,7 +429,7 @@ xfs_buf_lookup(
443429
int error;
444430

445431
rcu_read_lock();
446-
bp = rhashtable_lookup(&bch->bc_hash, map, xfs_buf_hash_params);
432+
bp = rhashtable_lookup(&btp->bt_hash, map, xfs_buf_hash_params);
447433
if (!bp || !lockref_get_not_dead(&bp->b_lockref)) {
448434
rcu_read_unlock();
449435
return -ENOENT;
@@ -468,7 +454,6 @@ xfs_buf_lookup(
468454
static int
469455
xfs_buf_find_insert(
470456
struct xfs_buftarg *btp,
471-
struct xfs_buf_cache *bch,
472457
struct xfs_perag *pag,
473458
struct xfs_buf_map *cmap,
474459
struct xfs_buf_map *map,
@@ -488,7 +473,7 @@ xfs_buf_find_insert(
488473
new_bp->b_pag = pag;
489474

490475
rcu_read_lock();
491-
bp = rhashtable_lookup_get_insert_fast(&bch->bc_hash,
476+
bp = rhashtable_lookup_get_insert_fast(&btp->bt_hash,
492477
&new_bp->b_rhash_head, xfs_buf_hash_params);
493478
if (IS_ERR(bp)) {
494479
rcu_read_unlock();
@@ -530,16 +515,6 @@ xfs_buftarg_get_pag(
530515
return xfs_perag_get(mp, xfs_daddr_to_agno(mp, map->bm_bn));
531516
}
532517

533-
static inline struct xfs_buf_cache *
534-
xfs_buftarg_buf_cache(
535-
struct xfs_buftarg *btp,
536-
struct xfs_perag *pag)
537-
{
538-
if (pag)
539-
return &pag->pag_bcache;
540-
return btp->bt_cache;
541-
}
542-
543518
/*
544519
* Assembles a buffer covering the specified range. The code is optimised for
545520
* cache hits, as metadata intensive workloads will see 3 orders of magnitude
@@ -553,7 +528,6 @@ xfs_buf_get_map(
553528
xfs_buf_flags_t flags,
554529
struct xfs_buf **bpp)
555530
{
556-
struct xfs_buf_cache *bch;
557531
struct xfs_perag *pag;
558532
struct xfs_buf *bp = NULL;
559533
struct xfs_buf_map cmap = { .bm_bn = map[0].bm_bn };
@@ -570,9 +544,8 @@ xfs_buf_get_map(
570544
return error;
571545

572546
pag = xfs_buftarg_get_pag(btp, &cmap);
573-
bch = xfs_buftarg_buf_cache(btp, pag);
574547

575-
error = xfs_buf_lookup(bch, &cmap, flags, &bp);
548+
error = xfs_buf_lookup(btp, &cmap, flags, &bp);
576549
if (error && error != -ENOENT)
577550
goto out_put_perag;
578551

@@ -584,7 +557,7 @@ xfs_buf_get_map(
584557
goto out_put_perag;
585558

586559
/* xfs_buf_find_insert() consumes the perag reference. */
587-
error = xfs_buf_find_insert(btp, bch, pag, &cmap, map, nmaps,
560+
error = xfs_buf_find_insert(btp, pag, &cmap, map, nmaps,
588561
flags, &bp);
589562
if (error)
590563
return error;
@@ -848,11 +821,8 @@ xfs_buf_destroy(
848821
ASSERT(!(bp->b_flags & _XBF_DELWRI_Q));
849822

850823
if (!xfs_buf_is_uncached(bp)) {
851-
struct xfs_buf_cache *bch =
852-
xfs_buftarg_buf_cache(bp->b_target, bp->b_pag);
853-
854-
rhashtable_remove_fast(&bch->bc_hash, &bp->b_rhash_head,
855-
xfs_buf_hash_params);
824+
rhashtable_remove_fast(&bp->b_target->bt_hash,
825+
&bp->b_rhash_head, xfs_buf_hash_params);
856826

857827
if (bp->b_pag)
858828
xfs_perag_put(bp->b_pag);
@@ -1618,6 +1588,7 @@ xfs_destroy_buftarg(
16181588
ASSERT(percpu_counter_sum(&btp->bt_readahead_count) == 0);
16191589
percpu_counter_destroy(&btp->bt_readahead_count);
16201590
list_lru_destroy(&btp->bt_lru);
1591+
rhashtable_destroy(&btp->bt_hash);
16211592
}
16221593

16231594
void
@@ -1712,8 +1683,10 @@ xfs_init_buftarg(
17121683
ratelimit_state_init(&btp->bt_ioerror_rl, 30 * HZ,
17131684
DEFAULT_RATELIMIT_BURST);
17141685

1715-
if (list_lru_init(&btp->bt_lru))
1686+
if (rhashtable_init(&btp->bt_hash, &xfs_buf_hash_params))
17161687
return -ENOMEM;
1688+
if (list_lru_init(&btp->bt_lru))
1689+
goto out_destroy_hash;
17171690
if (percpu_counter_init(&btp->bt_readahead_count, 0, GFP_KERNEL))
17181691
goto out_destroy_lru;
17191692

@@ -1731,6 +1704,8 @@ xfs_init_buftarg(
17311704
percpu_counter_destroy(&btp->bt_readahead_count);
17321705
out_destroy_lru:
17331706
list_lru_destroy(&btp->bt_lru);
1707+
out_destroy_hash:
1708+
rhashtable_destroy(&btp->bt_hash);
17341709
return -ENOMEM;
17351710
}
17361711

fs/xfs/xfs_buf.h

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,6 @@ typedef unsigned int xfs_buf_flags_t;
6969
{ XBF_INCORE, "INCORE" }, \
7070
{ XBF_TRYLOCK, "TRYLOCK" }
7171

72-
struct xfs_buf_cache {
73-
struct rhashtable bc_hash;
74-
};
75-
76-
int xfs_buf_cache_init(struct xfs_buf_cache *bch);
77-
void xfs_buf_cache_destroy(struct xfs_buf_cache *bch);
78-
7972
/*
8073
* The xfs_buftarg contains 2 notions of "sector size" -
8174
*
@@ -113,8 +106,7 @@ struct xfs_buftarg {
113106
unsigned int bt_awu_min;
114107
unsigned int bt_awu_max;
115108

116-
/* built-in cache, if we're not using the perag one */
117-
struct xfs_buf_cache bt_cache[];
109+
struct rhashtable bt_hash;
118110
};
119111

120112
struct xfs_buf_map {

fs/xfs/xfs_buf_mem.c

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ xmbuf_alloc(
5858
struct xfs_buftarg *btp;
5959
int error;
6060

61-
btp = kzalloc_flex(*btp, bt_cache, 1);
61+
btp = kzalloc_obj(*btp);
6262
if (!btp)
6363
return -ENOMEM;
6464

@@ -81,10 +81,6 @@ xmbuf_alloc(
8181
/* ensure all writes are below EOF to avoid pagecache zeroing */
8282
i_size_write(inode, inode->i_sb->s_maxbytes);
8383

84-
error = xfs_buf_cache_init(btp->bt_cache);
85-
if (error)
86-
goto out_file;
87-
8884
/* Initialize buffer target */
8985
btp->bt_mount = mp;
9086
btp->bt_dev = (dev_t)-1U;
@@ -95,15 +91,13 @@ xmbuf_alloc(
9591

9692
error = xfs_init_buftarg(btp, XMBUF_BLOCKSIZE, descr);
9793
if (error)
98-
goto out_bcache;
94+
goto out_file;
9995

10096
trace_xmbuf_create(btp);
10197

10298
*btpp = btp;
10399
return 0;
104100

105-
out_bcache:
106-
xfs_buf_cache_destroy(btp->bt_cache);
107101
out_file:
108102
fput(file);
109103
out_free_btp:
@@ -122,7 +116,6 @@ xmbuf_free(
122116
trace_xmbuf_free(btp);
123117

124118
xfs_destroy_buftarg(btp);
125-
xfs_buf_cache_destroy(btp->bt_cache);
126119
fput(btp->bt_file);
127120
kfree(btp);
128121
}

0 commit comments

Comments
 (0)