@@ -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;
}
@@ -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__ */
@@ -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;
}
@@ -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__ */
};
@@ -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);
@@ -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);
}
@@ -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 */ };
@@ -4689,35 +4689,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 */