xfs_notify_failure.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2022 Fujitsu. All Rights Reserved.
  4. */
  5. #include "xfs.h"
  6. #include "xfs_shared.h"
  7. #include "xfs_format.h"
  8. #include "xfs_log_format.h"
  9. #include "xfs_trans_resv.h"
  10. #include "xfs_mount.h"
  11. #include "xfs_alloc.h"
  12. #include "xfs_bit.h"
  13. #include "xfs_btree.h"
  14. #include "xfs_inode.h"
  15. #include "xfs_icache.h"
  16. #include "xfs_rmap.h"
  17. #include "xfs_rmap_btree.h"
  18. #include "xfs_rtalloc.h"
  19. #include "xfs_trans.h"
  20. #include "xfs_ag.h"
  21. #include <linux/mm.h>
  22. #include <linux/dax.h>
  23. struct xfs_failure_info {
  24. xfs_agblock_t startblock;
  25. xfs_extlen_t blockcount;
  26. int mf_flags;
  27. bool want_shutdown;
  28. };
  29. static pgoff_t
  30. xfs_failure_pgoff(
  31. struct xfs_mount *mp,
  32. const struct xfs_rmap_irec *rec,
  33. const struct xfs_failure_info *notify)
  34. {
  35. loff_t pos = XFS_FSB_TO_B(mp, rec->rm_offset);
  36. if (notify->startblock > rec->rm_startblock)
  37. pos += XFS_FSB_TO_B(mp,
  38. notify->startblock - rec->rm_startblock);
  39. return pos >> PAGE_SHIFT;
  40. }
  41. static unsigned long
  42. xfs_failure_pgcnt(
  43. struct xfs_mount *mp,
  44. const struct xfs_rmap_irec *rec,
  45. const struct xfs_failure_info *notify)
  46. {
  47. xfs_agblock_t end_rec;
  48. xfs_agblock_t end_notify;
  49. xfs_agblock_t start_cross;
  50. xfs_agblock_t end_cross;
  51. start_cross = max(rec->rm_startblock, notify->startblock);
  52. end_rec = rec->rm_startblock + rec->rm_blockcount;
  53. end_notify = notify->startblock + notify->blockcount;
  54. end_cross = min(end_rec, end_notify);
  55. return XFS_FSB_TO_B(mp, end_cross - start_cross) >> PAGE_SHIFT;
  56. }
  57. static int
  58. xfs_dax_failure_fn(
  59. struct xfs_btree_cur *cur,
  60. const struct xfs_rmap_irec *rec,
  61. void *data)
  62. {
  63. struct xfs_mount *mp = cur->bc_mp;
  64. struct xfs_inode *ip;
  65. struct xfs_failure_info *notify = data;
  66. int error = 0;
  67. if (XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) ||
  68. (rec->rm_flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))) {
  69. notify->want_shutdown = true;
  70. return 0;
  71. }
  72. /* Get files that incore, filter out others that are not in use. */
  73. error = xfs_iget(mp, cur->bc_tp, rec->rm_owner, XFS_IGET_INCORE,
  74. 0, &ip);
  75. /* Continue the rmap query if the inode isn't incore */
  76. if (error == -ENODATA)
  77. return 0;
  78. if (error) {
  79. notify->want_shutdown = true;
  80. return 0;
  81. }
  82. error = mf_dax_kill_procs(VFS_I(ip)->i_mapping,
  83. xfs_failure_pgoff(mp, rec, notify),
  84. xfs_failure_pgcnt(mp, rec, notify),
  85. notify->mf_flags);
  86. xfs_irele(ip);
  87. return error;
  88. }
  89. static int
  90. xfs_dax_notify_ddev_failure(
  91. struct xfs_mount *mp,
  92. xfs_daddr_t daddr,
  93. xfs_daddr_t bblen,
  94. int mf_flags)
  95. {
  96. struct xfs_failure_info notify = { .mf_flags = mf_flags };
  97. struct xfs_trans *tp = NULL;
  98. struct xfs_btree_cur *cur = NULL;
  99. struct xfs_buf *agf_bp = NULL;
  100. int error = 0;
  101. xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, daddr);
  102. xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, fsbno);
  103. xfs_fsblock_t end_fsbno = XFS_DADDR_TO_FSB(mp, daddr + bblen);
  104. xfs_agnumber_t end_agno = XFS_FSB_TO_AGNO(mp, end_fsbno);
  105. error = xfs_trans_alloc_empty(mp, &tp);
  106. if (error)
  107. return error;
  108. for (; agno <= end_agno; agno++) {
  109. struct xfs_rmap_irec ri_low = { };
  110. struct xfs_rmap_irec ri_high;
  111. struct xfs_agf *agf;
  112. xfs_agblock_t agend;
  113. struct xfs_perag *pag;
  114. pag = xfs_perag_get(mp, agno);
  115. error = xfs_alloc_read_agf(pag, tp, 0, &agf_bp);
  116. if (error) {
  117. xfs_perag_put(pag);
  118. break;
  119. }
  120. cur = xfs_rmapbt_init_cursor(mp, tp, agf_bp, pag);
  121. /*
  122. * Set the rmap range from ri_low to ri_high, which represents
  123. * a [start, end] where we looking for the files or metadata.
  124. */
  125. memset(&ri_high, 0xFF, sizeof(ri_high));
  126. ri_low.rm_startblock = XFS_FSB_TO_AGBNO(mp, fsbno);
  127. if (agno == end_agno)
  128. ri_high.rm_startblock = XFS_FSB_TO_AGBNO(mp, end_fsbno);
  129. agf = agf_bp->b_addr;
  130. agend = min(be32_to_cpu(agf->agf_length),
  131. ri_high.rm_startblock);
  132. notify.startblock = ri_low.rm_startblock;
  133. notify.blockcount = agend - ri_low.rm_startblock;
  134. error = xfs_rmap_query_range(cur, &ri_low, &ri_high,
  135. xfs_dax_failure_fn, &notify);
  136. xfs_btree_del_cursor(cur, error);
  137. xfs_trans_brelse(tp, agf_bp);
  138. xfs_perag_put(pag);
  139. if (error)
  140. break;
  141. fsbno = XFS_AGB_TO_FSB(mp, agno + 1, 0);
  142. }
  143. xfs_trans_cancel(tp);
  144. if (error || notify.want_shutdown) {
  145. xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_ONDISK);
  146. if (!error)
  147. error = -EFSCORRUPTED;
  148. }
  149. return error;
  150. }
  151. static int
  152. xfs_dax_notify_failure(
  153. struct dax_device *dax_dev,
  154. u64 offset,
  155. u64 len,
  156. int mf_flags)
  157. {
  158. struct xfs_mount *mp = dax_holder(dax_dev);
  159. u64 ddev_start;
  160. u64 ddev_end;
  161. if (!(mp->m_super->s_flags & SB_BORN)) {
  162. xfs_warn(mp, "filesystem is not ready for notify_failure()!");
  163. return -EIO;
  164. }
  165. if (mp->m_rtdev_targp && mp->m_rtdev_targp->bt_daxdev == dax_dev) {
  166. xfs_debug(mp,
  167. "notify_failure() not supported on realtime device!");
  168. return -EOPNOTSUPP;
  169. }
  170. if (mp->m_logdev_targp && mp->m_logdev_targp->bt_daxdev == dax_dev &&
  171. mp->m_logdev_targp != mp->m_ddev_targp) {
  172. xfs_err(mp, "ondisk log corrupt, shutting down fs!");
  173. xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_ONDISK);
  174. return -EFSCORRUPTED;
  175. }
  176. if (!xfs_has_rmapbt(mp)) {
  177. xfs_debug(mp, "notify_failure() needs rmapbt enabled!");
  178. return -EOPNOTSUPP;
  179. }
  180. ddev_start = mp->m_ddev_targp->bt_dax_part_off;
  181. ddev_end = ddev_start + bdev_nr_bytes(mp->m_ddev_targp->bt_bdev) - 1;
  182. /* Ignore the range out of filesystem area */
  183. if (offset + len < ddev_start)
  184. return -ENXIO;
  185. if (offset > ddev_end)
  186. return -ENXIO;
  187. /* Calculate the real range when it touches the boundary */
  188. if (offset > ddev_start)
  189. offset -= ddev_start;
  190. else {
  191. len -= ddev_start - offset;
  192. offset = 0;
  193. }
  194. if (offset + len > ddev_end)
  195. len -= ddev_end - offset;
  196. return xfs_dax_notify_ddev_failure(mp, BTOBB(offset), BTOBB(len),
  197. mf_flags);
  198. }
  199. const struct dax_holder_operations xfs_dax_holder_operations = {
  200. .notify_failure = xfs_dax_notify_failure,
  201. };