diff options
Diffstat (limited to 'fs/xfs/xfs_drain.c')
-rw-r--r-- | fs/xfs/xfs_drain.c | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/fs/xfs/xfs_drain.c b/fs/xfs/xfs_drain.c new file mode 100644 index 000000000000..e8fced914f88 --- /dev/null +++ b/fs/xfs/xfs_drain.c @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2022 Oracle. All Rights Reserved. + * Author: Darrick J. Wong <djwong@kernel.org> + */ +#include "xfs.h" +#include "xfs_fs.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_trans_resv.h" +#include "xfs_mount.h" +#include "xfs_ag.h" +#include "xfs_trace.h" + +void +xfs_drain_init( + struct xfs_drain *dr) +{ + atomic_set(&dr->dr_count, 0); + init_waitqueue_head(&dr->dr_waiters); +} + +void +xfs_drain_free(struct xfs_drain *dr) +{ + ASSERT(atomic_read(&dr->dr_count) == 0); +} + +/* Increase the pending intent count. */ +static inline void xfs_drain_bump(struct xfs_drain *dr) +{ + atomic_inc(&dr->dr_count); +} + +/* Decrease the pending intent count, and wake any waiters, if appropriate. */ +static inline void xfs_drain_drop(struct xfs_drain *dr) +{ + if (atomic_dec_and_test(&dr->dr_count) && + wq_has_sleeper(&dr->dr_waiters)) + wake_up(&dr->dr_waiters); +} + +/* Are there work items pending? */ +static inline bool xfs_drain_busy(struct xfs_drain *dr) +{ + return atomic_read(&dr->dr_count) > 0; +} + +/* + * Wait for the pending intent count for a drain to hit zero. + * + * Callers must not hold any locks that would prevent intents from being + * finished. + */ +static inline int xfs_drain_wait(struct xfs_drain *dr) +{ + return wait_event_killable(dr->dr_waiters, !xfs_drain_busy(dr)); +} + +/* Add an item to the pending count. */ +void +xfs_perag_bump_intents( + struct xfs_perag *pag) +{ + trace_xfs_perag_bump_intents(pag, __return_address); + xfs_drain_bump(&pag->pag_intents); +} + +/* Remove an item from the pending count. */ +void +xfs_perag_drop_intents( + struct xfs_perag *pag) +{ + trace_xfs_perag_drop_intents(pag, __return_address); + xfs_drain_drop(&pag->pag_intents); +} + +/* + * Wait for the pending intent count for AG metadata to hit zero. + * Callers must not hold any AG header buffers. + */ +int +xfs_perag_drain_intents( + struct xfs_perag *pag) +{ + trace_xfs_perag_wait_intents(pag, __return_address); + return xfs_drain_wait(&pag->pag_intents); +} + +/* Might someone else be processing intents for this AG? */ +bool +xfs_perag_intents_busy( + struct xfs_perag *pag) +{ + return xfs_drain_busy(&pag->pag_intents); +} |