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