mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 19:41:42 +00:00
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 <hch@lst.de> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Chandan Babu R <chandanbabu@kernel.org>
This commit is contained in:
parent
f9ffd095c8
commit
32fa4059fe
@ -46,7 +46,7 @@ xfs_perag_get(
|
||||
struct xfs_perag *pag;
|
||||
|
||||
rcu_read_lock();
|
||||
pag = radix_tree_lookup(&mp->m_perag_tree, agno);
|
||||
pag = xa_load(&mp->m_perags, agno);
|
||||
if (pag) {
|
||||
trace_xfs_perag_get(pag, _RET_IP_);
|
||||
ASSERT(atomic_read(&pag->pag_ref) >= 0);
|
||||
@ -92,7 +92,7 @@ xfs_perag_grab(
|
||||
struct xfs_perag *pag;
|
||||
|
||||
rcu_read_lock();
|
||||
pag = radix_tree_lookup(&mp->m_perag_tree, agno);
|
||||
pag = xa_load(&mp->m_perags, agno);
|
||||
if (pag) {
|
||||
trace_xfs_perag_grab(pag, _RET_IP_);
|
||||
if (!atomic_inc_not_zero(&pag->pag_active_ref))
|
||||
@ -195,9 +195,7 @@ xfs_free_perag(
|
||||
xfs_agnumber_t agno;
|
||||
|
||||
for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
|
||||
spin_lock(&mp->m_perag_lock);
|
||||
pag = radix_tree_delete(&mp->m_perag_tree, agno);
|
||||
spin_unlock(&mp->m_perag_lock);
|
||||
pag = xa_erase(&mp->m_perags, agno);
|
||||
ASSERT(pag);
|
||||
XFS_IS_CORRUPT(pag->pag_mount, atomic_read(&pag->pag_ref) != 0);
|
||||
xfs_defer_drain_free(&pag->pag_intents_drain);
|
||||
@ -286,9 +284,7 @@ xfs_free_unused_perag_range(
|
||||
xfs_agnumber_t index;
|
||||
|
||||
for (index = agstart; index < agend; index++) {
|
||||
spin_lock(&mp->m_perag_lock);
|
||||
pag = radix_tree_delete(&mp->m_perag_tree, index);
|
||||
spin_unlock(&mp->m_perag_lock);
|
||||
pag = xa_erase(&mp->m_perags, index);
|
||||
if (!pag)
|
||||
break;
|
||||
xfs_buf_cache_destroy(&pag->pag_bcache);
|
||||
@ -329,20 +325,11 @@ xfs_initialize_perag(
|
||||
pag->pag_agno = index;
|
||||
pag->pag_mount = mp;
|
||||
|
||||
error = radix_tree_preload(GFP_KERNEL | __GFP_RETRY_MAYFAIL);
|
||||
if (error)
|
||||
goto out_free_pag;
|
||||
|
||||
spin_lock(&mp->m_perag_lock);
|
||||
if (radix_tree_insert(&mp->m_perag_tree, index, pag)) {
|
||||
WARN_ON_ONCE(1);
|
||||
spin_unlock(&mp->m_perag_lock);
|
||||
radix_tree_preload_end();
|
||||
error = -EEXIST;
|
||||
error = xa_insert(&mp->m_perags, index, pag, GFP_KERNEL);
|
||||
if (error) {
|
||||
WARN_ON_ONCE(error == -EBUSY);
|
||||
goto out_free_pag;
|
||||
}
|
||||
spin_unlock(&mp->m_perag_lock);
|
||||
radix_tree_preload_end();
|
||||
|
||||
#ifdef __KERNEL__
|
||||
/* Place kernel structure only init below this point. */
|
||||
@ -390,9 +377,7 @@ xfs_initialize_perag(
|
||||
|
||||
out_remove_pag:
|
||||
xfs_defer_drain_free(&pag->pag_intents_drain);
|
||||
spin_lock(&mp->m_perag_lock);
|
||||
radix_tree_delete(&mp->m_perag_tree, index);
|
||||
spin_unlock(&mp->m_perag_lock);
|
||||
pag = xa_erase(&mp->m_perags, index);
|
||||
out_free_pag:
|
||||
kfree(pag);
|
||||
out_unwind_new_pags:
|
||||
|
@ -65,6 +65,18 @@ static int xfs_icwalk_ag(struct xfs_perag *pag,
|
||||
XFS_ICWALK_FLAG_RECLAIM_SICK | \
|
||||
XFS_ICWALK_FLAG_UNION)
|
||||
|
||||
/* Marks for the perag xarray */
|
||||
#define XFS_PERAG_RECLAIM_MARK XA_MARK_0
|
||||
#define XFS_PERAG_BLOCKGC_MARK XA_MARK_1
|
||||
|
||||
static inline xa_mark_t ici_tag_to_mark(unsigned int tag)
|
||||
{
|
||||
if (tag == XFS_ICI_RECLAIM_TAG)
|
||||
return XFS_PERAG_RECLAIM_MARK;
|
||||
ASSERT(tag == XFS_ICI_BLOCKGC_TAG);
|
||||
return XFS_PERAG_BLOCKGC_MARK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate and initialise an xfs_inode.
|
||||
*/
|
||||
@ -191,7 +203,7 @@ xfs_reclaim_work_queue(
|
||||
{
|
||||
|
||||
rcu_read_lock();
|
||||
if (radix_tree_tagged(&mp->m_perag_tree, XFS_ICI_RECLAIM_TAG)) {
|
||||
if (xa_marked(&mp->m_perags, XFS_PERAG_RECLAIM_MARK)) {
|
||||
queue_delayed_work(mp->m_reclaim_workqueue, &mp->m_reclaim_work,
|
||||
msecs_to_jiffies(xfs_syncd_centisecs / 6 * 10));
|
||||
}
|
||||
@ -241,9 +253,7 @@ xfs_perag_set_inode_tag(
|
||||
return;
|
||||
|
||||
/* propagate the tag up into the perag radix tree */
|
||||
spin_lock(&mp->m_perag_lock);
|
||||
radix_tree_tag_set(&mp->m_perag_tree, pag->pag_agno, tag);
|
||||
spin_unlock(&mp->m_perag_lock);
|
||||
xa_set_mark(&mp->m_perags, pag->pag_agno, ici_tag_to_mark(tag));
|
||||
|
||||
/* start background work */
|
||||
switch (tag) {
|
||||
@ -285,9 +295,7 @@ xfs_perag_clear_inode_tag(
|
||||
return;
|
||||
|
||||
/* clear the tag from the perag radix tree */
|
||||
spin_lock(&mp->m_perag_lock);
|
||||
radix_tree_tag_clear(&mp->m_perag_tree, pag->pag_agno, tag);
|
||||
spin_unlock(&mp->m_perag_lock);
|
||||
xa_clear_mark(&mp->m_perags, pag->pag_agno, ici_tag_to_mark(tag));
|
||||
|
||||
trace_xfs_perag_clear_inode_tag(pag, _RET_IP_);
|
||||
}
|
||||
@ -302,7 +310,6 @@ xfs_perag_get_next_tag(
|
||||
unsigned int tag)
|
||||
{
|
||||
unsigned long index = 0;
|
||||
int found;
|
||||
|
||||
if (pag) {
|
||||
index = pag->pag_agno + 1;
|
||||
@ -310,14 +317,11 @@ xfs_perag_get_next_tag(
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
found = radix_tree_gang_lookup_tag(&mp->m_perag_tree,
|
||||
(void **)&pag, index, 1, tag);
|
||||
if (found <= 0) {
|
||||
rcu_read_unlock();
|
||||
return NULL;
|
||||
}
|
||||
pag = xa_find(&mp->m_perags, &index, ULONG_MAX, ici_tag_to_mark(tag));
|
||||
if (pag) {
|
||||
trace_xfs_perag_get_next_tag(pag, _RET_IP_);
|
||||
atomic_inc(&pag->pag_ref);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
return pag;
|
||||
}
|
||||
@ -332,7 +336,6 @@ xfs_perag_grab_next_tag(
|
||||
int tag)
|
||||
{
|
||||
unsigned long index = 0;
|
||||
int found;
|
||||
|
||||
if (pag) {
|
||||
index = pag->pag_agno + 1;
|
||||
@ -340,15 +343,12 @@ xfs_perag_grab_next_tag(
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
found = radix_tree_gang_lookup_tag(&mp->m_perag_tree,
|
||||
(void **)&pag, index, 1, tag);
|
||||
if (found <= 0) {
|
||||
rcu_read_unlock();
|
||||
return NULL;
|
||||
}
|
||||
pag = xa_find(&mp->m_perags, &index, ULONG_MAX, ici_tag_to_mark(tag));
|
||||
if (pag) {
|
||||
trace_xfs_perag_grab_next_tag(pag, _RET_IP_);
|
||||
if (!atomic_inc_not_zero(&pag->pag_active_ref))
|
||||
pag = NULL;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
return pag;
|
||||
}
|
||||
@ -1038,7 +1038,7 @@ xfs_reclaim_inodes(
|
||||
if (xfs_want_reclaim_sick(mp))
|
||||
icw.icw_flags |= XFS_ICWALK_FLAG_RECLAIM_SICK;
|
||||
|
||||
while (radix_tree_tagged(&mp->m_perag_tree, XFS_ICI_RECLAIM_TAG)) {
|
||||
while (xa_marked(&mp->m_perags, XFS_PERAG_RECLAIM_MARK)) {
|
||||
xfs_ail_push_all_sync(mp->m_ail);
|
||||
xfs_icwalk(mp, XFS_ICWALK_RECLAIM, &icw);
|
||||
}
|
||||
|
@ -208,8 +208,7 @@ typedef struct xfs_mount {
|
||||
*/
|
||||
atomic64_t m_allocbt_blks;
|
||||
|
||||
struct radix_tree_root m_perag_tree; /* per-ag accounting info */
|
||||
spinlock_t m_perag_lock; /* lock for m_perag_tree */
|
||||
struct xarray m_perags; /* per-ag accounting info */
|
||||
uint64_t m_resblks; /* total reserved blocks */
|
||||
uint64_t m_resblks_avail;/* available reserved blocks */
|
||||
uint64_t m_resblks_save; /* reserved blks @ remount,ro */
|
||||
|
@ -2009,8 +2009,7 @@ static int xfs_init_fs_context(
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_init(&mp->m_sb_lock);
|
||||
INIT_RADIX_TREE(&mp->m_perag_tree, GFP_ATOMIC);
|
||||
spin_lock_init(&mp->m_perag_lock);
|
||||
xa_init(&mp->m_perags);
|
||||
mutex_init(&mp->m_growlock);
|
||||
INIT_WORK(&mp->m_flush_inodes_work, xfs_flush_inodes_worker);
|
||||
INIT_DELAYED_WORK(&mp->m_reclaim_work, xfs_reclaim_worker);
|
||||
|
Loading…
Reference in New Issue
Block a user