aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_dquot.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_dquot.c')
-rw-r--r--fs/xfs/xfs_dquot.c112
1 files changed, 99 insertions, 13 deletions
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index 45bb08f6ba17..a41f8bf1da37 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -36,6 +36,7 @@
36#include "xfs_trans_space.h" 36#include "xfs_trans_space.h"
37#include "xfs_trans_priv.h" 37#include "xfs_trans_priv.h"
38#include "xfs_qm.h" 38#include "xfs_qm.h"
39#include "xfs_cksum.h"
39#include "xfs_trace.h" 40#include "xfs_trace.h"
40 41
41/* 42/*
@@ -248,6 +249,8 @@ xfs_qm_init_dquot_blk(
248 d->dd_diskdq.d_version = XFS_DQUOT_VERSION; 249 d->dd_diskdq.d_version = XFS_DQUOT_VERSION;
249 d->dd_diskdq.d_id = cpu_to_be32(curid); 250 d->dd_diskdq.d_id = cpu_to_be32(curid);
250 d->dd_diskdq.d_flags = type; 251 d->dd_diskdq.d_flags = type;
252 if (xfs_sb_version_hascrc(&mp->m_sb))
253 uuid_copy(&d->dd_uuid, &mp->m_sb.sb_uuid);
251 } 254 }
252 255
253 xfs_trans_dquot_buf(tp, bp, 256 xfs_trans_dquot_buf(tp, bp,
@@ -283,25 +286,87 @@ xfs_dquot_set_prealloc_limits(struct xfs_dquot *dqp)
283 dqp->q_low_space[XFS_QLOWSP_5_PCNT] = space * 5; 286 dqp->q_low_space[XFS_QLOWSP_5_PCNT] = space * 5;
284} 287}
285 288
286static void 289STATIC void
290xfs_dquot_buf_calc_crc(
291 struct xfs_mount *mp,
292 struct xfs_buf *bp)
293{
294 struct xfs_dqblk *d = (struct xfs_dqblk *)bp->b_addr;
295 int i;
296
297 if (!xfs_sb_version_hascrc(&mp->m_sb))
298 return;
299
300 for (i = 0; i < mp->m_quotainfo->qi_dqperchunk; i++, d++) {
301 xfs_update_cksum((char *)d, sizeof(struct xfs_dqblk),
302 offsetof(struct xfs_dqblk, dd_crc));
303 }
304}
305
306STATIC bool
307xfs_dquot_buf_verify_crc(
308 struct xfs_mount *mp,
309 struct xfs_buf *bp)
310{
311 struct xfs_dqblk *d = (struct xfs_dqblk *)bp->b_addr;
312 int ndquots;
313 int i;
314
315 if (!xfs_sb_version_hascrc(&mp->m_sb))
316 return true;
317
318 /*
319 * if we are in log recovery, the quota subsystem has not been
320 * initialised so we have no quotainfo structure. In that case, we need
321 * to manually calculate the number of dquots in the buffer.
322 */
323 if (mp->m_quotainfo)
324 ndquots = mp->m_quotainfo->qi_dqperchunk;
325 else
326 ndquots = xfs_qm_calc_dquots_per_chunk(mp,
327 XFS_BB_TO_FSB(mp, bp->b_length));
328
329 for (i = 0; i < ndquots; i++, d++) {
330 if (!xfs_verify_cksum((char *)d, sizeof(struct xfs_dqblk),
331 offsetof(struct xfs_dqblk, dd_crc)))
332 return false;
333 if (!uuid_equal(&d->dd_uuid, &mp->m_sb.sb_uuid))
334 return false;
335 }
336
337 return true;
338}
339
340STATIC bool
287xfs_dquot_buf_verify( 341xfs_dquot_buf_verify(
342 struct xfs_mount *mp,
288 struct xfs_buf *bp) 343 struct xfs_buf *bp)
289{ 344{
290 struct xfs_mount *mp = bp->b_target->bt_mount;
291 struct xfs_dqblk *d = (struct xfs_dqblk *)bp->b_addr; 345 struct xfs_dqblk *d = (struct xfs_dqblk *)bp->b_addr;
292 struct xfs_disk_dquot *ddq;
293 xfs_dqid_t id = 0; 346 xfs_dqid_t id = 0;
347 int ndquots;
294 int i; 348 int i;
295 349
296 /* 350 /*
351 * if we are in log recovery, the quota subsystem has not been
352 * initialised so we have no quotainfo structure. In that case, we need
353 * to manually calculate the number of dquots in the buffer.
354 */
355 if (mp->m_quotainfo)
356 ndquots = mp->m_quotainfo->qi_dqperchunk;
357 else
358 ndquots = xfs_qm_calc_dquots_per_chunk(mp, bp->b_length);
359
360 /*
297 * On the first read of the buffer, verify that each dquot is valid. 361 * On the first read of the buffer, verify that each dquot is valid.
298 * We don't know what the id of the dquot is supposed to be, just that 362 * We don't know what the id of the dquot is supposed to be, just that
299 * they should be increasing monotonically within the buffer. If the 363 * they should be increasing monotonically within the buffer. If the
300 * first id is corrupt, then it will fail on the second dquot in the 364 * first id is corrupt, then it will fail on the second dquot in the
301 * buffer so corruptions could point to the wrong dquot in this case. 365 * buffer so corruptions could point to the wrong dquot in this case.
302 */ 366 */
303 for (i = 0; i < mp->m_quotainfo->qi_dqperchunk; i++) { 367 for (i = 0; i < ndquots; i++) {
304 int error; 368 struct xfs_disk_dquot *ddq;
369 int error;
305 370
306 ddq = &d[i].dd_diskdq; 371 ddq = &d[i].dd_diskdq;
307 372
@@ -309,27 +374,37 @@ xfs_dquot_buf_verify(
309 id = be32_to_cpu(ddq->d_id); 374 id = be32_to_cpu(ddq->d_id);
310 375
311 error = xfs_qm_dqcheck(mp, ddq, id + i, 0, XFS_QMOPT_DOWARN, 376 error = xfs_qm_dqcheck(mp, ddq, id + i, 0, XFS_QMOPT_DOWARN,
312 "xfs_dquot_read_verify"); 377 "xfs_dquot_buf_verify");
313 if (error) { 378 if (error)
314 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, d); 379 return false;
315 xfs_buf_ioerror(bp, EFSCORRUPTED);
316 break;
317 }
318 } 380 }
381 return true;
319} 382}
320 383
321static void 384static void
322xfs_dquot_buf_read_verify( 385xfs_dquot_buf_read_verify(
323 struct xfs_buf *bp) 386 struct xfs_buf *bp)
324{ 387{
325 xfs_dquot_buf_verify(bp); 388 struct xfs_mount *mp = bp->b_target->bt_mount;
389
390 if (!xfs_dquot_buf_verify_crc(mp, bp) || !xfs_dquot_buf_verify(mp, bp)) {
391 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
392 xfs_buf_ioerror(bp, EFSCORRUPTED);
393 }
326} 394}
327 395
328void 396void
329xfs_dquot_buf_write_verify( 397xfs_dquot_buf_write_verify(
330 struct xfs_buf *bp) 398 struct xfs_buf *bp)
331{ 399{
332 xfs_dquot_buf_verify(bp); 400 struct xfs_mount *mp = bp->b_target->bt_mount;
401
402 if (!xfs_dquot_buf_verify(mp, bp)) {
403 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
404 xfs_buf_ioerror(bp, EFSCORRUPTED);
405 return;
406 }
407 xfs_dquot_buf_calc_crc(mp, bp);
333} 408}
334 409
335const struct xfs_buf_ops xfs_dquot_buf_ops = { 410const struct xfs_buf_ops xfs_dquot_buf_ops = {
@@ -1073,6 +1148,17 @@ xfs_qm_dqflush(
1073 &dqp->q_logitem.qli_item.li_lsn); 1148 &dqp->q_logitem.qli_item.li_lsn);
1074 1149
1075 /* 1150 /*
1151 * copy the lsn into the on-disk dquot now while we have the in memory
1152 * dquot here. This can't be done later in the write verifier as we
1153 * can't get access to the log item at that point in time.
1154 */
1155 if (xfs_sb_version_hascrc(&mp->m_sb)) {
1156 struct xfs_dqblk *dqb = (struct xfs_dqblk *)ddqp;
1157
1158 dqb->dd_lsn = cpu_to_be64(dqp->q_logitem.qli_item.li_lsn);
1159 }
1160
1161 /*
1076 * Attach an iodone routine so that we can remove this dquot from the 1162 * Attach an iodone routine so that we can remove this dquot from the
1077 * AIL and release the flush lock once the dquot is synced to disk. 1163 * AIL and release the flush lock once the dquot is synced to disk.
1078 */ 1164 */