/*
 * 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);
}
Esempio n. 2
0
/* 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);
}