/* * initialize a buffer full of dquots and log the whole thing */ STATIC void xfs_qm_init_dquot_blk( xfs_trans_t *tp, xfs_mount_t *mp, xfs_dqid_t id, uint type, xfs_buf_t *bp) { xfs_dqblk_t *d; int curid, i; ASSERT(tp); ASSERT(XFS_BUF_ISBUSY(bp)); ASSERT(XFS_BUF_VALUSEMA(bp) <= 0); d = (xfs_dqblk_t *)XFS_BUF_PTR(bp); /* * ID of the first dquot in the block - id's are zero based. */ curid = id - (id % XFS_QM_DQPERBLK(mp)); ASSERT(curid >= 0); memset(d, 0, BBTOB(XFS_QI_DQCHUNKLEN(mp))); for (i = 0; i < XFS_QM_DQPERBLK(mp); i++, d++, curid++) xfs_qm_dqinit_core(curid, type, d); xfs_trans_dquot_buf(tp, bp, (type & XFS_DQ_USER ? XFS_BLI_UDQUOT_BUF : ((type & XFS_DQ_PROJ) ? XFS_BLI_PDQUOT_BUF : XFS_BLI_GDQUOT_BUF))); xfs_trans_log_buf(tp, bp, 0, BBTOB(XFS_QI_DQCHUNKLEN(mp)) - 1); }
/* ARGSUSED */ int xfs_qm_dqcheck( xfs_disk_dquot_t *ddq, xfs_dqid_t id, uint type, /* used only when IO_dorepair is true */ uint flags, char *str) { int errs; errs = 0; /* ASSERT(flags & (XFS_QMOPT_DQREPAIR|XFS_QMOPT_DOWARN)); */ /* * We can encounter an uninitialized dquot buffer for 2 reasons: * 1. If we crash while deleting the quotainode(s), and those blks get used * for some user data. This is because we take the path of regular * file deletion; however, the size field of quotainodes is never * updated, so all the tricks that we play in itruncate_finish * don't quite matter. * * 2. We don't play the quota buffers when there's a quotaoff logitem. * But the allocation will be replayed so we'll end up with an * uninitialized quota block. * * This is all fine; things are still consistent, and we haven't lost * any quota information. Just don't complain about bad dquot blks. */ if (INT_GET(ddq->d_magic, ARCH_CONVERT) != XFS_DQUOT_MAGIC) { if (flags & XFS_QMOPT_DOWARN) cmn_err(CE_ALERT, "%s : XFS dquot ID 0x%x, magic 0x%x != 0x%x", str, id, INT_GET(ddq->d_magic, ARCH_CONVERT), XFS_DQUOT_MAGIC); errs++; } if (INT_GET(ddq->d_version, ARCH_CONVERT) != XFS_DQUOT_VERSION) { if (flags & XFS_QMOPT_DOWARN) cmn_err(CE_ALERT, "%s : XFS dquot ID 0x%x, version 0x%x != 0x%x", str, id, INT_GET(ddq->d_magic, ARCH_CONVERT), XFS_DQUOT_VERSION); errs++; } if (INT_GET(ddq->d_flags, ARCH_CONVERT) != XFS_DQ_USER && INT_GET(ddq->d_flags, ARCH_CONVERT) != XFS_DQ_GROUP) { if (flags & XFS_QMOPT_DOWARN) cmn_err(CE_ALERT, "%s : XFS dquot ID 0x%x, unknown flags 0x%x", str, id, INT_GET(ddq->d_flags, ARCH_CONVERT)); errs++; } if (id != -1 && id != INT_GET(ddq->d_id, ARCH_CONVERT)) { if (flags & XFS_QMOPT_DOWARN) cmn_err(CE_ALERT, "%s : ondisk-dquot 0x%x, ID mismatch: " "0x%x expected, found id 0x%x", str, ddq, id, INT_GET(ddq->d_id, ARCH_CONVERT)); errs++; } if (! errs) { if (INT_GET(ddq->d_blk_softlimit, ARCH_CONVERT) && INT_GET(ddq->d_bcount, ARCH_CONVERT) >= INT_GET(ddq->d_blk_softlimit, ARCH_CONVERT)) { if (INT_ISZERO(ddq->d_btimer, ARCH_CONVERT) && !INT_ISZERO(ddq->d_id, ARCH_CONVERT)) { if (flags & XFS_QMOPT_DOWARN) cmn_err(CE_ALERT, "%s : Dquot ID 0x%x (0x%x) " "BLK TIMER NOT STARTED", str, (int) INT_GET(ddq->d_id, ARCH_CONVERT), ddq); errs++; } } if (INT_GET(ddq->d_ino_softlimit, ARCH_CONVERT) && INT_GET(ddq->d_icount, ARCH_CONVERT) >= INT_GET(ddq->d_ino_softlimit, ARCH_CONVERT)) { if (INT_ISZERO(ddq->d_itimer, ARCH_CONVERT) && !INT_ISZERO(ddq->d_id, ARCH_CONVERT)) { if (flags & XFS_QMOPT_DOWARN) cmn_err(CE_ALERT, "%s : Dquot ID 0x%x (0x%x) " "INODE TIMER NOT STARTED", str, (int) INT_GET(ddq->d_id, ARCH_CONVERT), ddq); errs++; } } } if (!errs || !(flags & XFS_QMOPT_DQREPAIR)) return (errs); if (flags & XFS_QMOPT_DOWARN) cmn_err(CE_NOTE, "Re-initializing dquot ID 0x%x", id); /* * Typically, a repair is only requested by quotacheck. */ ASSERT(id != -1); ASSERT(flags & XFS_QMOPT_DQREPAIR); bzero(ddq, sizeof(xfs_dqblk_t)); xfs_qm_dqinit_core(id, type, (xfs_dqblk_t *)ddq); return (errs); }