Skip to content

Commit 32fa405

Browse files
Christoph HellwigChandan Babu R
authored andcommitted
xfs: convert perag lookup to xarray
Convert the perag lookup from the legacy radix tree to the xarray, which allows for much nicer iteration and bulk lookup semantics. Signed-off-by: Christoph Hellwig <[email protected]> Reviewed-by: Darrick J. Wong <[email protected]> Signed-off-by: Chandan Babu R <[email protected]>
1 parent f9ffd09 commit 32fa405

File tree

4 files changed

+35
-52
lines changed

4 files changed

+35
-52
lines changed

fs/xfs/libxfs/xfs_ag.c

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ xfs_perag_get(
4646
struct xfs_perag *pag;
4747

4848
rcu_read_lock();
49-
pag = radix_tree_lookup(&mp->m_perag_tree, agno);
49+
pag = xa_load(&mp->m_perags, agno);
5050
if (pag) {
5151
trace_xfs_perag_get(pag, _RET_IP_);
5252
ASSERT(atomic_read(&pag->pag_ref) >= 0);
@@ -92,7 +92,7 @@ xfs_perag_grab(
9292
struct xfs_perag *pag;
9393

9494
rcu_read_lock();
95-
pag = radix_tree_lookup(&mp->m_perag_tree, agno);
95+
pag = xa_load(&mp->m_perags, agno);
9696
if (pag) {
9797
trace_xfs_perag_grab(pag, _RET_IP_);
9898
if (!atomic_inc_not_zero(&pag->pag_active_ref))
@@ -195,9 +195,7 @@ xfs_free_perag(
195195
xfs_agnumber_t agno;
196196

197197
for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
198-
spin_lock(&mp->m_perag_lock);
199-
pag = radix_tree_delete(&mp->m_perag_tree, agno);
200-
spin_unlock(&mp->m_perag_lock);
198+
pag = xa_erase(&mp->m_perags, agno);
201199
ASSERT(pag);
202200
XFS_IS_CORRUPT(pag->pag_mount, atomic_read(&pag->pag_ref) != 0);
203201
xfs_defer_drain_free(&pag->pag_intents_drain);
@@ -286,9 +284,7 @@ xfs_free_unused_perag_range(
286284
xfs_agnumber_t index;
287285

288286
for (index = agstart; index < agend; index++) {
289-
spin_lock(&mp->m_perag_lock);
290-
pag = radix_tree_delete(&mp->m_perag_tree, index);
291-
spin_unlock(&mp->m_perag_lock);
287+
pag = xa_erase(&mp->m_perags, index);
292288
if (!pag)
293289
break;
294290
xfs_buf_cache_destroy(&pag->pag_bcache);
@@ -329,20 +325,11 @@ xfs_initialize_perag(
329325
pag->pag_agno = index;
330326
pag->pag_mount = mp;
331327

332-
error = radix_tree_preload(GFP_KERNEL | __GFP_RETRY_MAYFAIL);
333-
if (error)
334-
goto out_free_pag;
335-
336-
spin_lock(&mp->m_perag_lock);
337-
if (radix_tree_insert(&mp->m_perag_tree, index, pag)) {
338-
WARN_ON_ONCE(1);
339-
spin_unlock(&mp->m_perag_lock);
340-
radix_tree_preload_end();
341-
error = -EEXIST;
328+
error = xa_insert(&mp->m_perags, index, pag, GFP_KERNEL);
329+
if (error) {
330+
WARN_ON_ONCE(error == -EBUSY);
342331
goto out_free_pag;
343332
}
344-
spin_unlock(&mp->m_perag_lock);
345-
radix_tree_preload_end();
346333

347334
#ifdef __KERNEL__
348335
/* Place kernel structure only init below this point. */
@@ -390,9 +377,7 @@ xfs_initialize_perag(
390377

391378
out_remove_pag:
392379
xfs_defer_drain_free(&pag->pag_intents_drain);
393-
spin_lock(&mp->m_perag_lock);
394-
radix_tree_delete(&mp->m_perag_tree, index);
395-
spin_unlock(&mp->m_perag_lock);
380+
pag = xa_erase(&mp->m_perags, index);
396381
out_free_pag:
397382
kfree(pag);
398383
out_unwind_new_pags:

fs/xfs/xfs_icache.c

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,18 @@ static int xfs_icwalk_ag(struct xfs_perag *pag,
6565
XFS_ICWALK_FLAG_RECLAIM_SICK | \
6666
XFS_ICWALK_FLAG_UNION)
6767

68+
/* Marks for the perag xarray */
69+
#define XFS_PERAG_RECLAIM_MARK XA_MARK_0
70+
#define XFS_PERAG_BLOCKGC_MARK XA_MARK_1
71+
72+
static inline xa_mark_t ici_tag_to_mark(unsigned int tag)
73+
{
74+
if (tag == XFS_ICI_RECLAIM_TAG)
75+
return XFS_PERAG_RECLAIM_MARK;
76+
ASSERT(tag == XFS_ICI_BLOCKGC_TAG);
77+
return XFS_PERAG_BLOCKGC_MARK;
78+
}
79+
6880
/*
6981
* Allocate and initialise an xfs_inode.
7082
*/
@@ -191,7 +203,7 @@ xfs_reclaim_work_queue(
191203
{
192204

193205
rcu_read_lock();
194-
if (radix_tree_tagged(&mp->m_perag_tree, XFS_ICI_RECLAIM_TAG)) {
206+
if (xa_marked(&mp->m_perags, XFS_PERAG_RECLAIM_MARK)) {
195207
queue_delayed_work(mp->m_reclaim_workqueue, &mp->m_reclaim_work,
196208
msecs_to_jiffies(xfs_syncd_centisecs / 6 * 10));
197209
}
@@ -241,9 +253,7 @@ xfs_perag_set_inode_tag(
241253
return;
242254

243255
/* propagate the tag up into the perag radix tree */
244-
spin_lock(&mp->m_perag_lock);
245-
radix_tree_tag_set(&mp->m_perag_tree, pag->pag_agno, tag);
246-
spin_unlock(&mp->m_perag_lock);
256+
xa_set_mark(&mp->m_perags, pag->pag_agno, ici_tag_to_mark(tag));
247257

248258
/* start background work */
249259
switch (tag) {
@@ -285,9 +295,7 @@ xfs_perag_clear_inode_tag(
285295
return;
286296

287297
/* clear the tag from the perag radix tree */
288-
spin_lock(&mp->m_perag_lock);
289-
radix_tree_tag_clear(&mp->m_perag_tree, pag->pag_agno, tag);
290-
spin_unlock(&mp->m_perag_lock);
298+
xa_clear_mark(&mp->m_perags, pag->pag_agno, ici_tag_to_mark(tag));
291299

292300
trace_xfs_perag_clear_inode_tag(pag, _RET_IP_);
293301
}
@@ -302,22 +310,18 @@ xfs_perag_get_next_tag(
302310
unsigned int tag)
303311
{
304312
unsigned long index = 0;
305-
int found;
306313

307314
if (pag) {
308315
index = pag->pag_agno + 1;
309316
xfs_perag_rele(pag);
310317
}
311318

312319
rcu_read_lock();
313-
found = radix_tree_gang_lookup_tag(&mp->m_perag_tree,
314-
(void **)&pag, index, 1, tag);
315-
if (found <= 0) {
316-
rcu_read_unlock();
317-
return NULL;
320+
pag = xa_find(&mp->m_perags, &index, ULONG_MAX, ici_tag_to_mark(tag));
321+
if (pag) {
322+
trace_xfs_perag_get_next_tag(pag, _RET_IP_);
323+
atomic_inc(&pag->pag_ref);
318324
}
319-
trace_xfs_perag_get_next_tag(pag, _RET_IP_);
320-
atomic_inc(&pag->pag_ref);
321325
rcu_read_unlock();
322326
return pag;
323327
}
@@ -332,23 +336,19 @@ xfs_perag_grab_next_tag(
332336
int tag)
333337
{
334338
unsigned long index = 0;
335-
int found;
336339

337340
if (pag) {
338341
index = pag->pag_agno + 1;
339342
xfs_perag_rele(pag);
340343
}
341344

342345
rcu_read_lock();
343-
found = radix_tree_gang_lookup_tag(&mp->m_perag_tree,
344-
(void **)&pag, index, 1, tag);
345-
if (found <= 0) {
346-
rcu_read_unlock();
347-
return NULL;
346+
pag = xa_find(&mp->m_perags, &index, ULONG_MAX, ici_tag_to_mark(tag));
347+
if (pag) {
348+
trace_xfs_perag_grab_next_tag(pag, _RET_IP_);
349+
if (!atomic_inc_not_zero(&pag->pag_active_ref))
350+
pag = NULL;
348351
}
349-
trace_xfs_perag_grab_next_tag(pag, _RET_IP_);
350-
if (!atomic_inc_not_zero(&pag->pag_active_ref))
351-
pag = NULL;
352352
rcu_read_unlock();
353353
return pag;
354354
}
@@ -1038,7 +1038,7 @@ xfs_reclaim_inodes(
10381038
if (xfs_want_reclaim_sick(mp))
10391039
icw.icw_flags |= XFS_ICWALK_FLAG_RECLAIM_SICK;
10401040

1041-
while (radix_tree_tagged(&mp->m_perag_tree, XFS_ICI_RECLAIM_TAG)) {
1041+
while (xa_marked(&mp->m_perags, XFS_PERAG_RECLAIM_MARK)) {
10421042
xfs_ail_push_all_sync(mp->m_ail);
10431043
xfs_icwalk(mp, XFS_ICWALK_RECLAIM, &icw);
10441044
}

fs/xfs/xfs_mount.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,8 +208,7 @@ typedef struct xfs_mount {
208208
*/
209209
atomic64_t m_allocbt_blks;
210210

211-
struct radix_tree_root m_perag_tree; /* per-ag accounting info */
212-
spinlock_t m_perag_lock; /* lock for m_perag_tree */
211+
struct xarray m_perags; /* per-ag accounting info */
213212
uint64_t m_resblks; /* total reserved blocks */
214213
uint64_t m_resblks_avail;/* available reserved blocks */
215214
uint64_t m_resblks_save; /* reserved blks @ remount,ro */

fs/xfs/xfs_super.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2009,8 +2009,7 @@ static int xfs_init_fs_context(
20092009
return -ENOMEM;
20102010

20112011
spin_lock_init(&mp->m_sb_lock);
2012-
INIT_RADIX_TREE(&mp->m_perag_tree, GFP_ATOMIC);
2013-
spin_lock_init(&mp->m_perag_lock);
2012+
xa_init(&mp->m_perags);
20142013
mutex_init(&mp->m_growlock);
20152014
INIT_WORK(&mp->m_flush_inodes_work, xfs_flush_inodes_worker);
20162015
INIT_DELAYED_WORK(&mp->m_reclaim_work, xfs_reclaim_worker);

0 commit comments

Comments
 (0)