xfs_drain.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) 2022-2023 Oracle. All Rights Reserved.
  4. * Author: Darrick J. Wong <djwong@kernel.org>
  5. */
  6. #include "xfs.h"
  7. #include "xfs_fs.h"
  8. #include "xfs_shared.h"
  9. #include "xfs_format.h"
  10. #include "xfs_trans_resv.h"
  11. #include "xfs_mount.h"
  12. #include "xfs_ag.h"
  13. #include "xfs_trace.h"
  14. /*
  15. * Use a static key here to reduce the overhead of xfs_drain_rele. If the
  16. * compiler supports jump labels, the static branch will be replaced by a nop
  17. * sled when there are no xfs_drain_wait callers. Online fsck is currently
  18. * the only caller, so this is a reasonable tradeoff.
  19. *
  20. * Note: Patching the kernel code requires taking the cpu hotplug lock. Other
  21. * parts of the kernel allocate memory with that lock held, which means that
  22. * XFS callers cannot hold any locks that might be used by memory reclaim or
  23. * writeback when calling the static_branch_{inc,dec} functions.
  24. */
  25. static DEFINE_STATIC_KEY_FALSE(xfs_drain_waiter_gate);
  26. void
  27. xfs_drain_wait_disable(void)
  28. {
  29. static_branch_dec(&xfs_drain_waiter_gate);
  30. }
  31. void
  32. xfs_drain_wait_enable(void)
  33. {
  34. static_branch_inc(&xfs_drain_waiter_gate);
  35. }
  36. void
  37. xfs_defer_drain_init(
  38. struct xfs_defer_drain *dr)
  39. {
  40. atomic_set(&dr->dr_count, 0);
  41. init_waitqueue_head(&dr->dr_waiters);
  42. }
  43. void
  44. xfs_defer_drain_free(struct xfs_defer_drain *dr)
  45. {
  46. ASSERT(atomic_read(&dr->dr_count) == 0);
  47. }
  48. /* Increase the pending intent count. */
  49. static inline void xfs_defer_drain_grab(struct xfs_defer_drain *dr)
  50. {
  51. atomic_inc(&dr->dr_count);
  52. }
  53. static inline bool has_waiters(struct wait_queue_head *wq_head)
  54. {
  55. /*
  56. * This memory barrier is paired with the one in set_current_state on
  57. * the waiting side.
  58. */
  59. smp_mb__after_atomic();
  60. return waitqueue_active(wq_head);
  61. }
  62. /* Decrease the pending intent count, and wake any waiters, if appropriate. */
  63. static inline void xfs_defer_drain_rele(struct xfs_defer_drain *dr)
  64. {
  65. if (atomic_dec_and_test(&dr->dr_count) &&
  66. static_branch_unlikely(&xfs_drain_waiter_gate) &&
  67. has_waiters(&dr->dr_waiters))
  68. wake_up(&dr->dr_waiters);
  69. }
  70. /* Are there intents pending? */
  71. static inline bool xfs_defer_drain_busy(struct xfs_defer_drain *dr)
  72. {
  73. return atomic_read(&dr->dr_count) > 0;
  74. }
  75. /*
  76. * Wait for the pending intent count for a drain to hit zero.
  77. *
  78. * Callers must not hold any locks that would prevent intents from being
  79. * finished.
  80. */
  81. static inline int xfs_defer_drain_wait(struct xfs_defer_drain *dr)
  82. {
  83. return wait_event_killable(dr->dr_waiters, !xfs_defer_drain_busy(dr));
  84. }
  85. /*
  86. * Get a passive reference to the AG that contains a fsbno and declare an intent
  87. * to update its metadata.
  88. */
  89. struct xfs_perag *
  90. xfs_perag_intent_get(
  91. struct xfs_mount *mp,
  92. xfs_fsblock_t fsbno)
  93. {
  94. struct xfs_perag *pag;
  95. pag = xfs_perag_get(mp, XFS_FSB_TO_AGNO(mp, fsbno));
  96. if (!pag)
  97. return NULL;
  98. xfs_perag_intent_hold(pag);
  99. return pag;
  100. }
  101. /*
  102. * Release our intent to update this AG's metadata, and then release our
  103. * passive ref to the AG.
  104. */
  105. void
  106. xfs_perag_intent_put(
  107. struct xfs_perag *pag)
  108. {
  109. xfs_perag_intent_rele(pag);
  110. xfs_perag_put(pag);
  111. }
  112. /*
  113. * Declare an intent to update AG metadata. Other threads that need exclusive
  114. * access can decide to back off if they see declared intentions.
  115. */
  116. void
  117. xfs_perag_intent_hold(
  118. struct xfs_perag *pag)
  119. {
  120. trace_xfs_perag_intent_hold(pag, __return_address);
  121. xfs_defer_drain_grab(&pag->pag_intents_drain);
  122. }
  123. /* Release our intent to update this AG's metadata. */
  124. void
  125. xfs_perag_intent_rele(
  126. struct xfs_perag *pag)
  127. {
  128. trace_xfs_perag_intent_rele(pag, __return_address);
  129. xfs_defer_drain_rele(&pag->pag_intents_drain);
  130. }
  131. /*
  132. * Wait for the intent update count for this AG to hit zero.
  133. * Callers must not hold any AG header buffers.
  134. */
  135. int
  136. xfs_perag_intent_drain(
  137. struct xfs_perag *pag)
  138. {
  139. trace_xfs_perag_wait_intents(pag, __return_address);
  140. return xfs_defer_drain_wait(&pag->pag_intents_drain);
  141. }
  142. /* Has anyone declared an intent to update this AG? */
  143. bool
  144. xfs_perag_intent_busy(
  145. struct xfs_perag *pag)
  146. {
  147. return xfs_defer_drain_busy(&pag->pag_intents_drain);
  148. }