Author | Tokens | Token Proportion | Commits | Commit Proportion |
---|---|---|---|---|
Darrick J. Wong | 290 | 74.55% | 5 | 26.32% |
Christoph Hellwig | 79 | 20.31% | 6 | 31.58% |
David Chinner | 14 | 3.60% | 6 | 31.58% |
Michal Marek | 4 | 1.03% | 1 | 5.26% |
Russell Cattelan | 2 | 0.51% | 1 | 5.26% |
Total | 389 | 19 |
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (C) 2022-2023 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" /* * Use a static key here to reduce the overhead of xfs_drain_rele. If the * compiler supports jump labels, the static branch will be replaced by a nop * sled when there are no xfs_drain_wait callers. Online fsck is currently * the only caller, so this is a reasonable tradeoff. * * Note: Patching the kernel code requires taking the cpu hotplug lock. Other * parts of the kernel allocate memory with that lock held, which means that * XFS callers cannot hold any locks that might be used by memory reclaim or * writeback when calling the static_branch_{inc,dec} functions. */ static DEFINE_STATIC_KEY_FALSE(xfs_drain_waiter_gate); void xfs_drain_wait_disable(void) { static_branch_dec(&xfs_drain_waiter_gate); } void xfs_drain_wait_enable(void) { static_branch_inc(&xfs_drain_waiter_gate); } void xfs_defer_drain_init( struct xfs_defer_drain *dr) { atomic_set(&dr->dr_count, 0); init_waitqueue_head(&dr->dr_waiters); } void xfs_defer_drain_free(struct xfs_defer_drain *dr) { ASSERT(atomic_read(&dr->dr_count) == 0); } /* Increase the pending intent count. */ static inline void xfs_defer_drain_grab(struct xfs_defer_drain *dr) { atomic_inc(&dr->dr_count); } static inline bool has_waiters(struct wait_queue_head *wq_head) { /* * This memory barrier is paired with the one in set_current_state on * the waiting side. */ smp_mb__after_atomic(); return waitqueue_active(wq_head); } /* Decrease the pending intent count, and wake any waiters, if appropriate. */ static inline void xfs_defer_drain_rele(struct xfs_defer_drain *dr) { if (atomic_dec_and_test(&dr->dr_count) && static_branch_unlikely(&xfs_drain_waiter_gate) && has_waiters(&dr->dr_waiters)) wake_up(&dr->dr_waiters); } /* Are there intents pending? */ static inline bool xfs_defer_drain_busy(struct xfs_defer_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_defer_drain_wait(struct xfs_defer_drain *dr) { return wait_event_killable(dr->dr_waiters, !xfs_defer_drain_busy(dr)); } /* * Get a passive reference to the group that contains a fsbno and declare an * intent to update its metadata. * * Other threads that need exclusive access can decide to back off if they see * declared intentions. */ struct xfs_group * xfs_group_intent_get( struct xfs_mount *mp, xfs_fsblock_t fsbno, enum xfs_group_type type) { struct xfs_group *xg; xg = xfs_group_get_by_fsb(mp, fsbno, type); if (!xg) return NULL; trace_xfs_group_intent_hold(xg, __return_address); xfs_defer_drain_grab(&xg->xg_intents_drain); return xg; } /* * Release our intent to update this groups metadata, and then release our * passive ref to it. */ void xfs_group_intent_put( struct xfs_group *xg) { trace_xfs_group_intent_rele(xg, __return_address); xfs_defer_drain_rele(&xg->xg_intents_drain); xfs_group_put(xg); } /* * Wait for the intent update count for this AG to hit zero. * Callers must not hold any AG header buffers. */ int xfs_group_intent_drain( struct xfs_group *xg) { 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 group? */ bool xfs_group_intent_busy( struct xfs_group *xg) { return xfs_defer_drain_busy(&xg->xg_intents_drain); }
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with Cregit http://github.com/cregit/cregit
Version 2.0-RC1