Exemplo n.º 1
0
/*
 * Increment or reset warnings of a given dquot.
 */
int
xfs_qm_dqwarn(
	xfs_disk_dquot_t	*d,
	uint			flags)
{
	int	warned;

	/*
	 * root's limits are not real limits.
	 */
	if (INT_ISZERO(d->d_id, ARCH_CONVERT))
		return (0);

	warned = 0;
	if (INT_GET(d->d_blk_softlimit, ARCH_CONVERT) &&
	    (INT_GET(d->d_bcount, ARCH_CONVERT) >=
	     INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) {
		if (flags & XFS_QMOPT_DOWARN) {
			INT_MOD(d->d_bwarns, ARCH_CONVERT, +1);
			warned++;
		}
	} else {
		if (INT_ISZERO(d->d_blk_softlimit, ARCH_CONVERT) ||
		    (INT_GET(d->d_bcount, ARCH_CONVERT) <
		     INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) {
			INT_ZERO(d->d_bwarns, ARCH_CONVERT);
		}
	}

	if (INT_GET(d->d_ino_softlimit, ARCH_CONVERT) > 0 &&
	    (INT_GET(d->d_icount, ARCH_CONVERT) >=
	     INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) {
		if (flags & XFS_QMOPT_DOWARN) {
			INT_MOD(d->d_iwarns, ARCH_CONVERT, +1);
			warned++;
		}
	} else {
		if ((INT_ISZERO(d->d_ino_softlimit, ARCH_CONVERT)) ||
		    (INT_GET(d->d_icount, ARCH_CONVERT) <
		     INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) {
			INT_ZERO(d->d_iwarns, ARCH_CONVERT);
		}
	}
#ifdef QUOTADEBUG
	if (INT_GET(d->d_iwarns, ARCH_CONVERT))
		cmn_err(CE_DEBUG,
			"--------@@Inode warnings running : %Lu >= %Lu",
			INT_GET(d->d_icount, ARCH_CONVERT),
			INT_GET(d->d_ino_softlimit, ARCH_CONVERT));
	if (INT_GET(d->d_bwarns, ARCH_CONVERT))
		cmn_err(CE_DEBUG,
			"--------@@Blks warnings running : %Lu >= %Lu",
			INT_GET(d->d_bcount, ARCH_CONVERT),
			INT_GET(d->d_blk_softlimit, ARCH_CONVERT));
#endif
	return (warned);
}
Exemplo n.º 2
0
/*
 * xfs_trans_apply_sb_deltas() is called from the commit code
 * to bring the superblock buffer into the current transaction
 * and modify it as requested by earlier calls to xfs_trans_mod_sb().
 *
 * For now we just look at each field allowed to change and change
 * it if necessary.
 */
STATIC void
xfs_trans_apply_sb_deltas(
	xfs_trans_t	*tp)
{
	xfs_sb_t	*sbp;
	xfs_buf_t	*bp;
	int		whole = 0;

	bp = xfs_trans_getsb(tp, tp->t_mountp, 0);
	sbp = XFS_BUF_TO_SBP(bp);

	/*
	 * Check that superblock mods match the mods made to AGF counters.
	 */
	ASSERT((tp->t_fdblocks_delta + tp->t_res_fdblocks_delta) ==
	       (tp->t_ag_freeblks_delta + tp->t_ag_flist_delta +
		tp->t_ag_btree_delta));

	if (tp->t_icount_delta != 0) {
		INT_MOD(sbp->sb_icount, ARCH_CONVERT, tp->t_icount_delta);
	}
	if (tp->t_ifree_delta != 0) {
		INT_MOD(sbp->sb_ifree, ARCH_CONVERT, tp->t_ifree_delta);
	}

	if (tp->t_fdblocks_delta != 0) {
		INT_MOD(sbp->sb_fdblocks, ARCH_CONVERT, tp->t_fdblocks_delta);
	}
	if (tp->t_res_fdblocks_delta != 0) {
		INT_MOD(sbp->sb_fdblocks, ARCH_CONVERT, tp->t_res_fdblocks_delta);
	}

	if (tp->t_frextents_delta != 0) {
		INT_MOD(sbp->sb_frextents, ARCH_CONVERT, tp->t_frextents_delta);
	}
	if (tp->t_res_frextents_delta != 0) {
		INT_MOD(sbp->sb_frextents, ARCH_CONVERT, tp->t_res_frextents_delta);
	}
	if (tp->t_dblocks_delta != 0) {
		INT_MOD(sbp->sb_dblocks, ARCH_CONVERT, tp->t_dblocks_delta);
		whole = 1;
	}
	if (tp->t_agcount_delta != 0) {
		INT_MOD(sbp->sb_agcount, ARCH_CONVERT, tp->t_agcount_delta);
		whole = 1;
	}
	if (tp->t_imaxpct_delta != 0) {
		INT_MOD(sbp->sb_imax_pct, ARCH_CONVERT, tp->t_imaxpct_delta);
		whole = 1;
	}
	if (tp->t_rextsize_delta != 0) {
		INT_MOD(sbp->sb_rextsize, ARCH_CONVERT, tp->t_rextsize_delta);
		whole = 1;
	}
	if (tp->t_rbmblocks_delta != 0) {
		INT_MOD(sbp->sb_rbmblocks, ARCH_CONVERT, tp->t_rbmblocks_delta);
		whole = 1;
	}
	if (tp->t_rblocks_delta != 0) {
		INT_MOD(sbp->sb_rblocks, ARCH_CONVERT, tp->t_rblocks_delta);
		whole = 1;
	}
	if (tp->t_rextents_delta != 0) {
		INT_MOD(sbp->sb_rextents, ARCH_CONVERT, tp->t_rextents_delta);
		whole = 1;
	}
	if (tp->t_rextslog_delta != 0) {
		INT_MOD(sbp->sb_rextslog, ARCH_CONVERT, tp->t_rextslog_delta);
		whole = 1;
	}

	if (whole)
		/*
		 * Log the whole thing, the fields are noncontiguous.
		 */
		xfs_trans_log_buf(tp, bp, 0, sizeof(xfs_sb_t) - 1);
	else
		/*
		 * Since all the modifiable fields are contiguous, we
		 * can get away with this.
		 */
		xfs_trans_log_buf(tp, bp, offsetof(xfs_sb_t, sb_icount),
				  offsetof(xfs_sb_t, sb_frextents) +
				  sizeof(sbp->sb_frextents) - 1);

#ifdef XXXKAN
	XFS_MTOVFS(tp->t_mountp)->vfs_super->s_dirt = 1;
#endif
}
Exemplo n.º 3
0
/*
 * Called by xfs_trans_commit() and similar in spirit to
 * xfs_trans_apply_sb_deltas().
 * Go thru all the dquots belonging to this transaction and modify the
 * INCORE dquot to reflect the actual usages.
 * Unreserve just the reservations done by this transaction
 * dquot is still left locked at exit.
 */
void
xfs_trans_apply_dquot_deltas(
	xfs_trans_t		*tp)
{
	int			i, j;
	xfs_dquot_t		*dqp;
	xfs_dqtrx_t		*qtrx, *qa;
	xfs_disk_dquot_t	*d;
	long			totalbdelta;
	long			totalrtbdelta;

	ASSERT(tp->t_dqinfo);
	qa = tp->t_dqinfo->dqa_usrdquots;
	for (j = 0; j < 2; j++) {
		if (qa[0].qt_dquot == NULL) {
			qa = tp->t_dqinfo->dqa_grpdquots;
			continue;
		}

		/*
		 * Lock all of the dquots and join them to the transaction.
		 */
		xfs_trans_dqlockedjoin(tp, qa);

		for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {
			qtrx = &qa[i];
			/*
			 * The array of dquots is filled
			 * sequentially, not sparsely.
			 */
			if ((dqp = qtrx->qt_dquot) == NULL)
				break;

			ASSERT(XFS_DQ_IS_LOCKED(dqp));
			ASSERT(XFS_DQ_IS_ADDEDTO_TRX(tp, dqp));

			/*
			 * adjust the actual number of blocks used
			 */
			d = &dqp->q_core;

			/*
			 * The issue here is - sometimes we don't make a blkquota
			 * reservation intentionally to be fair to users
			 * (when the amount is small). On the other hand,
			 * delayed allocs do make reservations, but that's
			 * outside of a transaction, so we have no
			 * idea how much was really reserved.
			 * So, here we've accumulated delayed allocation blks and
			 * non-delay blks. The assumption is that the
			 * delayed ones are always reserved (outside of a
			 * transaction), and the others may or may not have
			 * quota reservations.
			 */
			totalbdelta = qtrx->qt_bcount_delta +
				qtrx->qt_delbcnt_delta;
			totalrtbdelta = qtrx->qt_rtbcount_delta +
				qtrx->qt_delrtb_delta;
#ifdef QUOTADEBUG
			if (totalbdelta < 0)
				ASSERT(INT_GET(d->d_bcount, ARCH_CONVERT) >=
				       (xfs_qcnt_t) -totalbdelta);

			if (totalrtbdelta < 0)
				ASSERT(INT_GET(d->d_rtbcount, ARCH_CONVERT) >=
				       (xfs_qcnt_t) -totalrtbdelta);

			if (qtrx->qt_icount_delta < 0)
				ASSERT(INT_GET(d->d_icount, ARCH_CONVERT) >=
				       (xfs_qcnt_t) -qtrx->qt_icount_delta);
#endif
			if (totalbdelta)
				INT_MOD(d->d_bcount, ARCH_CONVERT, (xfs_qcnt_t)totalbdelta);

			if (qtrx->qt_icount_delta)
				INT_MOD(d->d_icount, ARCH_CONVERT, (xfs_qcnt_t)qtrx->qt_icount_delta);

			if (totalrtbdelta)
				INT_MOD(d->d_rtbcount, ARCH_CONVERT, (xfs_qcnt_t)totalrtbdelta);

			/*
			 * Start/reset the timer(s) if needed.
			 */
			xfs_qm_adjust_dqtimers(tp->t_mountp, d);

			dqp->dq_flags |= XFS_DQ_DIRTY;
			/*
			 * add this to the list of items to get logged
			 */
			xfs_trans_log_dquot(tp, dqp);
			/*
			 * Take off what's left of the original reservation.
			 * In case of delayed allocations, there's no
			 * reservation that a transaction structure knows of.
			 */
			if (qtrx->qt_blk_res != 0) {
				if (qtrx->qt_blk_res != qtrx->qt_blk_res_used) {
					if (qtrx->qt_blk_res >
					    qtrx->qt_blk_res_used)
						dqp->q_res_bcount -= (xfs_qcnt_t)
							(qtrx->qt_blk_res -
							 qtrx->qt_blk_res_used);
					else
						dqp->q_res_bcount -= (xfs_qcnt_t)
							(qtrx->qt_blk_res_used -
							 qtrx->qt_blk_res);
				}
			} else {
				/*
				 * These blks were never reserved, either inside
				 * a transaction or outside one (in a delayed
				 * allocation). Also, this isn't always a
				 * negative number since we sometimes
				 * deliberately skip quota reservations.
				 */
				if (qtrx->qt_bcount_delta) {
					dqp->q_res_bcount +=
					      (xfs_qcnt_t)qtrx->qt_bcount_delta;
				}
			}
			/*
			 * Adjust the RT reservation.
			 */
			if (qtrx->qt_rtblk_res != 0) {
				if (qtrx->qt_blk_res != qtrx->qt_blk_res_used) {
					if (qtrx->qt_rtblk_res >
					    qtrx->qt_rtblk_res_used)
					       dqp->q_res_rtbcount -= (xfs_qcnt_t)
						       (qtrx->qt_rtblk_res -
							qtrx->qt_rtblk_res_used);
					else
					       dqp->q_res_rtbcount -= (xfs_qcnt_t)
						       (qtrx->qt_rtblk_res_used -
							qtrx->qt_rtblk_res);
				}
			} else {
				if (qtrx->qt_rtbcount_delta)
					dqp->q_res_rtbcount +=
					    (xfs_qcnt_t)qtrx->qt_rtbcount_delta;
			}

			/*
			 * Adjust the inode reservation.
			 */
			if (qtrx->qt_ino_res != 0) {
				ASSERT(qtrx->qt_ino_res >=
				       qtrx->qt_ino_res_used);
				if (qtrx->qt_ino_res > qtrx->qt_ino_res_used)
					dqp->q_res_icount -= (xfs_qcnt_t)
						(qtrx->qt_ino_res -
						 qtrx->qt_ino_res_used);
			} else {
				if (qtrx->qt_icount_delta)
					dqp->q_res_icount +=
					    (xfs_qcnt_t)qtrx->qt_icount_delta;
			}


#ifdef QUOTADEBUG
			if (qtrx->qt_rtblk_res != 0)
				printk("RT res %d for 0x%p\n",
				      (int) qtrx->qt_rtblk_res,
				      dqp);
#endif
			ASSERT(dqp->q_res_bcount >= INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT));
			ASSERT(dqp->q_res_icount >= INT_GET(dqp->q_core.d_icount, ARCH_CONVERT));
			ASSERT(dqp->q_res_rtbcount >= INT_GET(dqp->q_core.d_rtbcount, ARCH_CONVERT));
		}
		/*
		 * Do the group quotas next
		 */
		qa = tp->t_dqinfo->dqa_grpdquots;
	}
}