aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_log_recover.c
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2014-08-03 22:59:31 -0400
committerDave Chinner <david@fromorbit.com>2014-08-03 22:59:31 -0400
commitad3714b82c631a34724da09a7daa53afcab952fa (patch)
tree8f19be2ba9e28ce7d943d0cefc48a745004f5c10 /fs/xfs/xfs_log_recover.c
parent5fd364fee81a7888af806e42ed8a91c845894f2d (diff)
xfs: dquot recovery needs verifiers
dquot recovery should add verifiers to the dquot buffers that it recovers changes into. Unfortunately, it doesn't attached the verifiers to the buffers in a consistent manner. For example, xlog_recover_dquot_pass2() reads dquot buffers without a verifier and then writes it without ever having attached a verifier to the buffer. Further, dquot buffer recovery may write a dquot buffer that has not been modified, or indeed, shoul dbe written because quotas are not enabled and hence changes to the buffer were not replayed. In this case, we again write buffers without verifiers attached because that doesn't happen until after the buffer changes have been replayed. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Brian Foster <bfoster@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs/xfs_log_recover.c')
-rw-r--r--fs/xfs/xfs_log_recover.c44
1 files changed, 23 insertions, 21 deletions
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 8a7d8a79a7be..1fd5787add99 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -2399,8 +2399,11 @@ xlog_recover_do_reg_buffer(
2399 * Simple algorithm: if we have found a QUOTAOFF log item of the same type 2399 * Simple algorithm: if we have found a QUOTAOFF log item of the same type
2400 * (ie. USR or GRP), then just toss this buffer away; don't recover it. 2400 * (ie. USR or GRP), then just toss this buffer away; don't recover it.
2401 * Else, treat it as a regular buffer and do recovery. 2401 * Else, treat it as a regular buffer and do recovery.
2402 *
2403 * Return false if the buffer was tossed and true if we recovered the buffer to
2404 * indicate to the caller if the buffer needs writing.
2402 */ 2405 */
2403STATIC void 2406STATIC bool
2404xlog_recover_do_dquot_buffer( 2407xlog_recover_do_dquot_buffer(
2405 struct xfs_mount *mp, 2408 struct xfs_mount *mp,
2406 struct xlog *log, 2409 struct xlog *log,
@@ -2415,9 +2418,8 @@ xlog_recover_do_dquot_buffer(
2415 /* 2418 /*
2416 * Filesystems are required to send in quota flags at mount time. 2419 * Filesystems are required to send in quota flags at mount time.
2417 */ 2420 */
2418 if (mp->m_qflags == 0) { 2421 if (!mp->m_qflags)
2419 return; 2422 return false;
2420 }
2421 2423
2422 type = 0; 2424 type = 0;
2423 if (buf_f->blf_flags & XFS_BLF_UDQUOT_BUF) 2425 if (buf_f->blf_flags & XFS_BLF_UDQUOT_BUF)
@@ -2430,9 +2432,10 @@ xlog_recover_do_dquot_buffer(
2430 * This type of quotas was turned off, so ignore this buffer 2432 * This type of quotas was turned off, so ignore this buffer
2431 */ 2433 */
2432 if (log->l_quotaoffs_flag & type) 2434 if (log->l_quotaoffs_flag & type)
2433 return; 2435 return false;
2434 2436
2435 xlog_recover_do_reg_buffer(mp, item, bp, buf_f); 2437 xlog_recover_do_reg_buffer(mp, item, bp, buf_f);
2438 return true;
2436} 2439}
2437 2440
2438/* 2441/*
@@ -2525,14 +2528,18 @@ xlog_recover_buffer_pass2(
2525 2528
2526 if (buf_f->blf_flags & XFS_BLF_INODE_BUF) { 2529 if (buf_f->blf_flags & XFS_BLF_INODE_BUF) {
2527 error = xlog_recover_do_inode_buffer(mp, item, bp, buf_f); 2530 error = xlog_recover_do_inode_buffer(mp, item, bp, buf_f);
2531 if (error)
2532 goto out_release;
2528 } else if (buf_f->blf_flags & 2533 } else if (buf_f->blf_flags &
2529 (XFS_BLF_UDQUOT_BUF|XFS_BLF_PDQUOT_BUF|XFS_BLF_GDQUOT_BUF)) { 2534 (XFS_BLF_UDQUOT_BUF|XFS_BLF_PDQUOT_BUF|XFS_BLF_GDQUOT_BUF)) {
2530 xlog_recover_do_dquot_buffer(mp, log, item, bp, buf_f); 2535 bool dirty;
2536
2537 dirty = xlog_recover_do_dquot_buffer(mp, log, item, bp, buf_f);
2538 if (!dirty)
2539 goto out_release;
2531 } else { 2540 } else {
2532 xlog_recover_do_reg_buffer(mp, item, bp, buf_f); 2541 xlog_recover_do_reg_buffer(mp, item, bp, buf_f);
2533 } 2542 }
2534 if (error)
2535 goto out_release;
2536 2543
2537 /* 2544 /*
2538 * Perform delayed write on the buffer. Asynchronous writes will be 2545 * Perform delayed write on the buffer. Asynchronous writes will be
@@ -3022,9 +3029,16 @@ xlog_recover_dquot_pass2(
3022 return -EIO; 3029 return -EIO;
3023 ASSERT(dq_f->qlf_len == 1); 3030 ASSERT(dq_f->qlf_len == 1);
3024 3031
3032 /*
3033 * At this point we are assuming that the dquots have been allocated
3034 * and hence the buffer has valid dquots stamped in it. It should,
3035 * therefore, pass verifier validation. If the dquot is bad, then the
3036 * we'll return an error here, so we don't need to specifically check
3037 * the dquot in the buffer after the verifier has run.
3038 */
3025 error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, dq_f->qlf_blkno, 3039 error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, dq_f->qlf_blkno,
3026 XFS_FSB_TO_BB(mp, dq_f->qlf_len), 0, &bp, 3040 XFS_FSB_TO_BB(mp, dq_f->qlf_len), 0, &bp,
3027 NULL); 3041 &xfs_dquot_buf_ops);
3028 if (error) 3042 if (error)
3029 return error; 3043 return error;
3030 3044
@@ -3032,18 +3046,6 @@ xlog_recover_dquot_pass2(
3032 ddq = (xfs_disk_dquot_t *)xfs_buf_offset(bp, dq_f->qlf_boffset); 3046 ddq = (xfs_disk_dquot_t *)xfs_buf_offset(bp, dq_f->qlf_boffset);
3033 3047
3034 /* 3048 /*
3035 * At least the magic num portion should be on disk because this
3036 * was among a chunk of dquots created earlier, and we did some
3037 * minimal initialization then.
3038 */
3039 error = xfs_dqcheck(mp, ddq, dq_f->qlf_id, 0, XFS_QMOPT_DOWARN,
3040 "xlog_recover_dquot_pass2");
3041 if (error) {
3042 xfs_buf_relse(bp);
3043 return -EIO;
3044 }
3045
3046 /*
3047 * If the dquot has an LSN in it, recover the dquot only if it's less 3049 * If the dquot has an LSN in it, recover the dquot only if it's less
3048 * than the lsn of the transaction we are replaying. 3050 * than the lsn of the transaction we are replaying.
3049 */ 3051 */