xfs_dquot_item_recover.c 5.1 KB

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