xfs_dquot_item_recover.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2000-2006 Silicon Graphics, Inc.
  4. * All Rights Reserved.
  5. */
  6. #include "xfs.h"
  7. #include "xfs_fs.h"
  8. #include "xfs_shared.h"
  9. #include "xfs_format.h"
  10. #include "xfs_log_format.h"
  11. #include "xfs_trans_resv.h"
  12. #include "xfs_mount.h"
  13. #include "xfs_inode.h"
  14. #include "xfs_quota.h"
  15. #include "xfs_trans.h"
  16. #include "xfs_buf_item.h"
  17. #include "xfs_trans_priv.h"
  18. #include "xfs_qm.h"
  19. #include "xfs_log.h"
  20. #include "xfs_log_priv.h"
  21. #include "xfs_log_recover.h"
  22. #include "xfs_error.h"
  23. STATIC void
  24. xlog_recover_dquot_ra_pass2(
  25. struct xlog *log,
  26. struct xlog_recover_item *item)
  27. {
  28. struct xfs_mount *mp = log->l_mp;
  29. struct xfs_disk_dquot *recddq;
  30. struct xfs_dq_logformat *dq_f;
  31. uint type;
  32. if (mp->m_qflags == 0)
  33. return;
  34. recddq = item->ri_buf[1].i_addr;
  35. if (recddq == NULL)
  36. return;
  37. if (item->ri_buf[1].i_len < sizeof(struct xfs_disk_dquot))
  38. return;
  39. type = recddq->d_type & XFS_DQTYPE_REC_MASK;
  40. ASSERT(type);
  41. if (log->l_quotaoffs_flag & type)
  42. return;
  43. dq_f = item->ri_buf[0].i_addr;
  44. ASSERT(dq_f);
  45. ASSERT(dq_f->qlf_len == 1);
  46. xlog_buf_readahead(log, dq_f->qlf_blkno,
  47. XFS_FSB_TO_BB(mp, dq_f->qlf_len),
  48. &xfs_dquot_buf_ra_ops);
  49. }
  50. /*
  51. * Recover a dquot record
  52. */
  53. STATIC int
  54. xlog_recover_dquot_commit_pass2(
  55. struct xlog *log,
  56. struct list_head *buffer_list,
  57. struct xlog_recover_item *item,
  58. xfs_lsn_t current_lsn)
  59. {
  60. struct xfs_mount *mp = log->l_mp;
  61. struct xfs_buf *bp;
  62. struct xfs_dqblk *dqb;
  63. struct xfs_disk_dquot *ddq, *recddq;
  64. struct xfs_dq_logformat *dq_f;
  65. xfs_failaddr_t fa;
  66. int error;
  67. uint type;
  68. /*
  69. * Filesystems are required to send in quota flags at mount time.
  70. */
  71. if (mp->m_qflags == 0)
  72. return 0;
  73. recddq = item->ri_buf[1].i_addr;
  74. if (recddq == NULL) {
  75. xfs_alert(log->l_mp, "NULL dquot in %s.", __func__);
  76. return -EFSCORRUPTED;
  77. }
  78. if (item->ri_buf[1].i_len < sizeof(struct xfs_disk_dquot)) {
  79. xfs_alert(log->l_mp, "dquot too small (%d) in %s.",
  80. item->ri_buf[1].i_len, __func__);
  81. return -EFSCORRUPTED;
  82. }
  83. /*
  84. * This type of quotas was turned off, so ignore this record.
  85. */
  86. type = recddq->d_type & XFS_DQTYPE_REC_MASK;
  87. ASSERT(type);
  88. if (log->l_quotaoffs_flag & type)
  89. return 0;
  90. /*
  91. * At this point we know that quota was _not_ turned off.
  92. * Since the mount flags are not indicating to us otherwise, this
  93. * must mean that quota is on, and the dquot needs to be replayed.
  94. * Remember that we may not have fully recovered the superblock yet,
  95. * so we can't do the usual trick of looking at the SB quota bits.
  96. *
  97. * The other possibility, of course, is that the quota subsystem was
  98. * removed since the last mount - ENOSYS.
  99. */
  100. dq_f = item->ri_buf[0].i_addr;
  101. ASSERT(dq_f);
  102. fa = xfs_dquot_verify(mp, recddq, dq_f->qlf_id);
  103. if (fa) {
  104. xfs_alert(mp, "corrupt dquot ID 0x%x in log at %pS",
  105. dq_f->qlf_id, fa);
  106. return -EFSCORRUPTED;
  107. }
  108. ASSERT(dq_f->qlf_len == 1);
  109. /*
  110. * At this point we are assuming that the dquots have been allocated
  111. * and hence the buffer has valid dquots stamped in it. It should,
  112. * therefore, pass verifier validation. If the dquot is bad, then the
  113. * we'll return an error here, so we don't need to specifically check
  114. * the dquot in the buffer after the verifier has run.
  115. */
  116. error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, dq_f->qlf_blkno,
  117. XFS_FSB_TO_BB(mp, dq_f->qlf_len), 0, &bp,
  118. &xfs_dquot_buf_ops);
  119. if (error)
  120. return error;
  121. ASSERT(bp);
  122. dqb = xfs_buf_offset(bp, dq_f->qlf_boffset);
  123. ddq = &dqb->dd_diskdq;
  124. /*
  125. * If the dquot has an LSN in it, recover the dquot only if it's less
  126. * than the lsn of the transaction we are replaying.
  127. */
  128. if (xfs_has_crc(mp)) {
  129. xfs_lsn_t lsn = be64_to_cpu(dqb->dd_lsn);
  130. if (lsn && lsn != -1 && XFS_LSN_CMP(lsn, current_lsn) >= 0) {
  131. goto out_release;
  132. }
  133. }
  134. memcpy(ddq, recddq, item->ri_buf[1].i_len);
  135. if (xfs_has_crc(mp)) {
  136. xfs_update_cksum((char *)dqb, sizeof(struct xfs_dqblk),
  137. XFS_DQUOT_CRC_OFF);
  138. }
  139. /* Validate the recovered dquot. */
  140. fa = xfs_dqblk_verify(log->l_mp, dqb, dq_f->qlf_id);
  141. if (fa) {
  142. XFS_CORRUPTION_ERROR("Bad dquot after recovery",
  143. XFS_ERRLEVEL_LOW, mp, dqb,
  144. sizeof(struct xfs_dqblk));
  145. xfs_alert(mp,
  146. "Metadata corruption detected at %pS, dquot 0x%x",
  147. fa, dq_f->qlf_id);
  148. error = -EFSCORRUPTED;
  149. goto out_release;
  150. }
  151. ASSERT(dq_f->qlf_size == 2);
  152. ASSERT(bp->b_mount == mp);
  153. bp->b_flags |= _XBF_LOGRECOVERY;
  154. xfs_buf_delwri_queue(bp, buffer_list);
  155. out_release:
  156. xfs_buf_relse(bp);
  157. return 0;
  158. }
  159. const struct xlog_recover_item_ops xlog_dquot_item_ops = {
  160. .item_type = XFS_LI_DQUOT,
  161. .ra_pass2 = xlog_recover_dquot_ra_pass2,
  162. .commit_pass2 = xlog_recover_dquot_commit_pass2,
  163. };
  164. /*
  165. * Recover QUOTAOFF records. We simply make a note of it in the xlog
  166. * structure, so that we know not to do any dquot item or dquot buffer recovery,
  167. * of that type.
  168. */
  169. STATIC int
  170. xlog_recover_quotaoff_commit_pass1(
  171. struct xlog *log,
  172. struct xlog_recover_item *item)
  173. {
  174. struct xfs_qoff_logformat *qoff_f = item->ri_buf[0].i_addr;
  175. ASSERT(qoff_f);
  176. /*
  177. * The logitem format's flag tells us if this was user quotaoff,
  178. * group/project quotaoff or both.
  179. */
  180. if (qoff_f->qf_flags & XFS_UQUOTA_ACCT)
  181. log->l_quotaoffs_flag |= XFS_DQTYPE_USER;
  182. if (qoff_f->qf_flags & XFS_PQUOTA_ACCT)
  183. log->l_quotaoffs_flag |= XFS_DQTYPE_PROJ;
  184. if (qoff_f->qf_flags & XFS_GQUOTA_ACCT)
  185. log->l_quotaoffs_flag |= XFS_DQTYPE_GROUP;
  186. return 0;
  187. }
  188. const struct xlog_recover_item_ops xlog_quotaoff_item_ops = {
  189. .item_type = XFS_LI_QUOTAOFF,
  190. .commit_pass1 = xlog_recover_quotaoff_commit_pass1,
  191. /* nothing to commit in pass2 */
  192. };