xfs: move draining of deferred operations to the generic group structure

Prepare supporting the upcoming realtime groups feature by moving the
deferred operation draining to the generic xfs_group structure.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
This commit is contained in:
Christoph Hellwig 2024-11-03 20:18:41 -08:00 committed by Darrick J. Wong
parent 2ed27a5464
commit 34cf3a6f39
8 changed files with 66 additions and 55 deletions

View File

@ -112,7 +112,6 @@ xfs_perag_uninit(
#ifdef __KERNEL__
struct xfs_perag *pag = to_perag(xg);
xfs_defer_drain_free(&pag->pag_intents_drain);
cancel_delayed_work_sync(&pag->pag_blockgc_work);
xfs_buf_cache_destroy(&pag->pag_bcache);
#endif
@ -234,7 +233,6 @@ xfs_perag_alloc(
spin_lock_init(&pag->pagb_lock);
INIT_DELAYED_WORK(&pag->pag_blockgc_work, xfs_blockgc_worker);
INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC);
xfs_defer_drain_init(&pag->pag_intents_drain);
init_waitqueue_head(&pag->pagb_wait);
pag->pagb_tree = RB_ROOT;
xfs_hooks_init(&pag->pag_rmap_update_hooks);
@ -242,7 +240,7 @@ xfs_perag_alloc(
error = xfs_buf_cache_init(&pag->pag_bcache);
if (error)
goto out_defer_drain_free;
goto out_free_perag;
/*
* Pre-calculated geometry
@ -260,8 +258,7 @@ xfs_perag_alloc(
out_buf_cache_destroy:
xfs_buf_cache_destroy(&pag->pag_bcache);
out_defer_drain_free:
xfs_defer_drain_free(&pag->pag_intents_drain);
out_free_perag:
kfree(pag);
return error;
}

View File

@ -97,15 +97,6 @@ struct xfs_perag {
/* background prealloc block trimming */
struct delayed_work pag_blockgc_work;
/*
* We use xfs_drain to track the number of deferred log intent items
* that have been queued (but not yet processed) so that waiters (e.g.
* scrub) will not lock resources when other threads are in the middle
* of processing a chain of intent items only to find momentary
* inconsistencies.
*/
struct xfs_defer_drain pag_intents_drain;
/* Hook to feed rmapbt updates to an active online repair. */
struct xfs_hooks pag_rmap_update_hooks;
#endif /* __KERNEL__ */

View File

@ -160,6 +160,8 @@ xfs_group_free(
XFS_IS_CORRUPT(mp, atomic_read(&xg->xg_ref) != 0);
xfs_defer_drain_free(&xg->xg_intents_drain);
if (uninit)
uninit(xg);
@ -185,6 +187,7 @@ xfs_group_insert(
#ifdef __KERNEL__
spin_lock_init(&xg->xg_state_lock);
#endif
xfs_defer_drain_init(&xg->xg_intents_drain);
/* Active ref owned by mount indicates group is online. */
atomic_set(&xg->xg_active_ref, 1);
@ -192,6 +195,7 @@ xfs_group_insert(
error = xa_insert(&mp->m_groups[type].xa, index, xg, GFP_KERNEL);
if (error) {
WARN_ON_ONCE(error == -EBUSY);
xfs_defer_drain_free(&xg->xg_intents_drain);
return error;
}

View File

@ -22,6 +22,15 @@ struct xfs_group {
uint16_t xg_checked;
uint16_t xg_sick;
spinlock_t xg_state_lock;
/*
* We use xfs_drain to track the number of deferred log intent items
* that have been queued (but not yet processed) so that waiters (e.g.
* scrub) will not lock resources when other threads are in the middle
* of processing a chain of intent items only to find momentary
* inconsistencies.
*/
struct xfs_defer_drain xg_intents_drain;
#endif /* __KERNEL__ */
};

View File

@ -513,7 +513,7 @@ xchk_perag_drain_and_lock(
* Obviously, this should be slanted against scrub and in favor
* of runtime threads.
*/
if (!xfs_perag_intent_busy(sa->pag))
if (!xfs_group_intent_busy(pag_group(sa->pag)))
return 0;
if (sa->agf_bp) {
@ -528,7 +528,7 @@ xchk_perag_drain_and_lock(
if (!(sc->flags & XCHK_FSGATES_DRAIN))
return -ECHRNG;
error = xfs_perag_intent_drain(sa->pag);
error = xfs_group_intent_drain(pag_group(sa->pag));
if (error == -ERESTARTSYS)
error = -EINTR;
} while (!error);

View File

@ -94,24 +94,26 @@ static inline int xfs_defer_drain_wait(struct xfs_defer_drain *dr)
}
/*
* Declare an intent to update AG metadata. Other threads that need exclusive
* access can decide to back off if they see declared intentions.
* Declare an intent to update group metadata. Other threads that need
* exclusive access can decide to back off if they see declared intentions.
*/
static void
xfs_perag_intent_hold(
struct xfs_perag *pag)
xfs_group_intent_hold(
struct xfs_group *xg)
{
trace_xfs_perag_intent_hold(pag, __return_address);
xfs_defer_drain_grab(&pag->pag_intents_drain);
trace_xfs_group_intent_hold(xg, __return_address);
xfs_defer_drain_grab(&xg->xg_intents_drain);
}
/* Release our intent to update this AG's metadata. */
/*
* Release our intent to update this groups metadata.
*/
static void
xfs_perag_intent_rele(
struct xfs_perag *pag)
xfs_group_intent_rele(
struct xfs_group *xg)
{
trace_xfs_perag_intent_rele(pag, __return_address);
xfs_defer_drain_rele(&pag->pag_intents_drain);
trace_xfs_group_intent_rele(xg, __return_address);
xfs_defer_drain_rele(&xg->xg_intents_drain);
}
/*
@ -129,7 +131,7 @@ xfs_perag_intent_get(
if (!pag)
return NULL;
xfs_perag_intent_hold(pag);
xfs_group_intent_hold(pag_group(pag));
return pag;
}
@ -141,7 +143,7 @@ void
xfs_perag_intent_put(
struct xfs_perag *pag)
{
xfs_perag_intent_rele(pag);
xfs_group_intent_rele(pag_group(pag));
xfs_perag_put(pag);
}
@ -150,17 +152,19 @@ xfs_perag_intent_put(
* Callers must not hold any AG header buffers.
*/
int
xfs_perag_intent_drain(
struct xfs_perag *pag)
xfs_group_intent_drain(
struct xfs_group *xg)
{
trace_xfs_perag_wait_intents(pag, __return_address);
return xfs_defer_drain_wait(&pag->pag_intents_drain);
trace_xfs_group_wait_intents(xg, __return_address);
return xfs_defer_drain_wait(&xg->xg_intents_drain);
}
/* Has anyone declared an intent to update this AG? */
/*
* Has anyone declared an intent to update this group?
*/
bool
xfs_perag_intent_busy(
struct xfs_perag *pag)
xfs_group_intent_busy(
struct xfs_group *xg)
{
return xfs_defer_drain_busy(&pag->pag_intents_drain);
return xfs_defer_drain_busy(&xg->xg_intents_drain);
}

View File

@ -6,6 +6,7 @@
#ifndef XFS_DRAIN_H_
#define XFS_DRAIN_H_
struct xfs_group;
struct xfs_perag;
#ifdef CONFIG_XFS_DRAIN_INTENTS
@ -65,8 +66,9 @@ struct xfs_perag *xfs_perag_intent_get(struct xfs_mount *mp,
xfs_fsblock_t fsbno);
void xfs_perag_intent_put(struct xfs_perag *pag);
int xfs_perag_intent_drain(struct xfs_perag *pag);
bool xfs_perag_intent_busy(struct xfs_perag *pag);
int xfs_group_intent_drain(struct xfs_group *xg);
bool xfs_group_intent_busy(struct xfs_group *xg);
#else
struct xfs_defer_drain { /* empty */ };

View File

@ -4684,35 +4684,39 @@ TRACE_EVENT(xfs_force_shutdown,
);
#ifdef CONFIG_XFS_DRAIN_INTENTS
DECLARE_EVENT_CLASS(xfs_perag_intents_class,
TP_PROTO(const struct xfs_perag *pag, void *caller_ip),
TP_ARGS(pag, caller_ip),
DECLARE_EVENT_CLASS(xfs_group_intents_class,
TP_PROTO(const struct xfs_group *xg, void *caller_ip),
TP_ARGS(xg, caller_ip),
TP_STRUCT__entry(
__field(dev_t, dev)
__field(xfs_agnumber_t, agno)
__field(enum xfs_group_type, type)
__field(uint32_t, index)
__field(long, nr_intents)
__field(void *, caller_ip)
),
TP_fast_assign(
__entry->dev = pag_mount(pag)->m_super->s_dev;
__entry->agno = pag_agno(pag);
__entry->nr_intents = atomic_read(&pag->pag_intents_drain.dr_count);
__entry->dev = xg->xg_mount->m_super->s_dev;
__entry->type = xg->xg_type;
__entry->index = xg->xg_gno;
__entry->nr_intents =
atomic_read(&xg->xg_intents_drain.dr_count);
__entry->caller_ip = caller_ip;
),
TP_printk("dev %d:%d agno 0x%x intents %ld caller %pS",
TP_printk("dev %d:%d %sno 0x%x intents %ld caller %pS",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
__print_symbolic(__entry->type, XG_TYPE_STRINGS),
__entry->index,
__entry->nr_intents,
__entry->caller_ip)
);
#define DEFINE_PERAG_INTENTS_EVENT(name) \
DEFINE_EVENT(xfs_perag_intents_class, name, \
TP_PROTO(const struct xfs_perag *pag, void *caller_ip), \
TP_ARGS(pag, caller_ip))
DEFINE_PERAG_INTENTS_EVENT(xfs_perag_intent_hold);
DEFINE_PERAG_INTENTS_EVENT(xfs_perag_intent_rele);
DEFINE_PERAG_INTENTS_EVENT(xfs_perag_wait_intents);
#define DEFINE_GROUP_INTENTS_EVENT(name) \
DEFINE_EVENT(xfs_group_intents_class, name, \
TP_PROTO(const struct xfs_group *xg, void *caller_ip), \
TP_ARGS(xg, caller_ip))
DEFINE_GROUP_INTENTS_EVENT(xfs_group_intent_hold);
DEFINE_GROUP_INTENTS_EVENT(xfs_group_intent_rele);
DEFINE_GROUP_INTENTS_EVENT(xfs_group_wait_intents);
#endif /* CONFIG_XFS_DRAIN_INTENTS */