⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xfs_trans_dquot.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
					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_rtblk_res != qtrx->qt_rtblk_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;			}			ASSERT(dqp->q_res_bcount >=				be64_to_cpu(dqp->q_core.d_bcount));			ASSERT(dqp->q_res_icount >=				be64_to_cpu(dqp->q_core.d_icount));			ASSERT(dqp->q_res_rtbcount >=				be64_to_cpu(dqp->q_core.d_rtbcount));		}		/*		 * Do the group quotas next		 */		qa = tp->t_dqinfo->dqa_grpdquots;	}}/* * Release the reservations, and adjust the dquots accordingly. * This is called only when the transaction is being aborted. If by * any chance we have done dquot modifications incore (ie. deltas) already, * we simply throw those away, since that's the expected behavior * when a transaction is curtailed without a commit. */STATIC voidxfs_trans_unreserve_and_mod_dquots(	xfs_trans_t		*tp){	int			i, j;	xfs_dquot_t		*dqp;	xfs_dqtrx_t		*qtrx, *qa;	boolean_t		locked;	if (!tp->t_dqinfo || !(tp->t_flags & XFS_TRANS_DQ_DIRTY))		return;	qa = tp->t_dqinfo->dqa_usrdquots;	for (j = 0; j < 2; j++) {		for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {			qtrx = &qa[i];			/*			 * We assume that the array of dquots is filled			 * sequentially, not sparsely.			 */			if ((dqp = qtrx->qt_dquot) == NULL)				break;			/*			 * Unreserve the original reservation. We don't care			 * about the number of blocks used field, or deltas.			 * Also we don't bother to zero the fields.			 */			locked = B_FALSE;			if (qtrx->qt_blk_res) {				xfs_dqlock(dqp);				locked = B_TRUE;				dqp->q_res_bcount -=					(xfs_qcnt_t)qtrx->qt_blk_res;			}			if (qtrx->qt_ino_res) {				if (!locked) {					xfs_dqlock(dqp);					locked = B_TRUE;				}				dqp->q_res_icount -=					(xfs_qcnt_t)qtrx->qt_ino_res;			}			if (qtrx->qt_rtblk_res) {				if (!locked) {					xfs_dqlock(dqp);					locked = B_TRUE;				}				dqp->q_res_rtbcount -=					(xfs_qcnt_t)qtrx->qt_rtblk_res;			}			if (locked)				xfs_dqunlock(dqp);		}		qa = tp->t_dqinfo->dqa_grpdquots;	}}/* * This reserves disk blocks and inodes against a dquot. * Flags indicate if the dquot is to be locked here and also * if the blk reservation is for RT or regular blocks. * Sending in XFS_QMOPT_FORCE_RES flag skips the quota check. * Returns EDQUOT if quota is exceeded. */STATIC intxfs_trans_dqresv(	xfs_trans_t	*tp,	xfs_mount_t	*mp,	xfs_dquot_t	*dqp,	long		nblks,	long		ninos,	uint		flags){	int		error;	xfs_qcnt_t	hardlimit;	xfs_qcnt_t	softlimit;	time_t		timer;	xfs_qwarncnt_t	warns;	xfs_qwarncnt_t	warnlimit;	xfs_qcnt_t	count;	xfs_qcnt_t	*resbcountp;	xfs_quotainfo_t	*q = mp->m_quotainfo;	if (! (flags & XFS_QMOPT_DQLOCK)) {		xfs_dqlock(dqp);	}	ASSERT(XFS_DQ_IS_LOCKED(dqp));	if (flags & XFS_TRANS_DQ_RES_BLKS) {		hardlimit = be64_to_cpu(dqp->q_core.d_blk_hardlimit);		if (!hardlimit)			hardlimit = q->qi_bhardlimit;		softlimit = be64_to_cpu(dqp->q_core.d_blk_softlimit);		if (!softlimit)			softlimit = q->qi_bsoftlimit;		timer = be32_to_cpu(dqp->q_core.d_btimer);		warns = be16_to_cpu(dqp->q_core.d_bwarns);		warnlimit = XFS_QI_BWARNLIMIT(dqp->q_mount);		resbcountp = &dqp->q_res_bcount;	} else {		ASSERT(flags & XFS_TRANS_DQ_RES_RTBLKS);		hardlimit = be64_to_cpu(dqp->q_core.d_rtb_hardlimit);		if (!hardlimit)			hardlimit = q->qi_rtbhardlimit;		softlimit = be64_to_cpu(dqp->q_core.d_rtb_softlimit);		if (!softlimit)			softlimit = q->qi_rtbsoftlimit;		timer = be32_to_cpu(dqp->q_core.d_rtbtimer);		warns = be16_to_cpu(dqp->q_core.d_rtbwarns);		warnlimit = XFS_QI_RTBWARNLIMIT(dqp->q_mount);		resbcountp = &dqp->q_res_rtbcount;	}	error = 0;	if ((flags & XFS_QMOPT_FORCE_RES) == 0 &&	    dqp->q_core.d_id &&	    XFS_IS_QUOTA_ENFORCED(dqp->q_mount)) {#ifdef QUOTADEBUG		cmn_err(CE_DEBUG, "BLK Res: nblks=%ld + resbcount=%Ld"			  " > hardlimit=%Ld?", nblks, *resbcountp, hardlimit);#endif		if (nblks > 0) {			/*			 * dquot is locked already. See if we'd go over the			 * hardlimit or exceed the timelimit if we allocate			 * nblks.			 */			if (hardlimit > 0ULL &&			     (hardlimit <= nblks + *resbcountp)) {				error = EDQUOT;				goto error_return;			}			if (softlimit > 0ULL &&			     (softlimit <= nblks + *resbcountp)) {				/*				 * If timer or warnings has expired,				 * return EDQUOT				 */				if ((timer != 0 && get_seconds() > timer) ||				    (warns != 0 && warns >= warnlimit)) {					error = EDQUOT;					goto error_return;				}			}		}		if (ninos > 0) {			count = be64_to_cpu(dqp->q_core.d_icount);			timer = be32_to_cpu(dqp->q_core.d_itimer);			warns = be16_to_cpu(dqp->q_core.d_iwarns);			warnlimit = XFS_QI_IWARNLIMIT(dqp->q_mount);			hardlimit = be64_to_cpu(dqp->q_core.d_ino_hardlimit);			if (!hardlimit)				hardlimit = q->qi_ihardlimit;			softlimit = be64_to_cpu(dqp->q_core.d_ino_softlimit);			if (!softlimit)				softlimit = q->qi_isoftlimit;			if (hardlimit > 0ULL && count >= hardlimit) {				error = EDQUOT;				goto error_return;			} else if (softlimit > 0ULL && count >= softlimit) {				/*				 * If timer or warnings has expired,				 * return EDQUOT				 */				if ((timer != 0 && get_seconds() > timer) ||				     (warns != 0 && warns >= warnlimit)) {					error = EDQUOT;					goto error_return;				}			}		}	}	/*	 * Change the reservation, but not the actual usage.	 * Note that q_res_bcount = q_core.d_bcount + resv	 */	(*resbcountp) += (xfs_qcnt_t)nblks;	if (ninos != 0)		dqp->q_res_icount += (xfs_qcnt_t)ninos;	/*	 * note the reservation amt in the trans struct too,	 * so that the transaction knows how much was reserved by	 * it against this particular dquot.	 * We don't do this when we are reserving for a delayed allocation,	 * because we don't have the luxury of a transaction envelope then.	 */	if (tp) {		ASSERT(tp->t_dqinfo);		ASSERT(flags & XFS_QMOPT_RESBLK_MASK);		if (nblks != 0)			xfs_trans_mod_dquot(tp, dqp,					    flags & XFS_QMOPT_RESBLK_MASK,					    nblks);		if (ninos != 0)			xfs_trans_mod_dquot(tp, dqp,					    XFS_TRANS_DQ_RES_INOS,					    ninos);	}	ASSERT(dqp->q_res_bcount >= be64_to_cpu(dqp->q_core.d_bcount));	ASSERT(dqp->q_res_rtbcount >= be64_to_cpu(dqp->q_core.d_rtbcount));	ASSERT(dqp->q_res_icount >= be64_to_cpu(dqp->q_core.d_icount));error_return:	if (! (flags & XFS_QMOPT_DQLOCK)) {		xfs_dqunlock(dqp);	}	return (error);}/* * Given a dquot(s), make disk block and/or inode reservations against them. * The fact that this does the reservation against both the usr and * grp quotas is important, because this follows a both-or-nothing * approach. * * flags = XFS_QMOPT_DQLOCK indicate if dquot(s) need to be locked. *	   XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown. *	   XFS_TRANS_DQ_RES_BLKS reserves regular disk blocks *	   XFS_TRANS_DQ_RES_RTBLKS reserves realtime disk blocks * dquots are unlocked on return, if they were not locked by caller. */intxfs_trans_reserve_quota_bydquots(	xfs_trans_t	*tp,	xfs_mount_t	*mp,	xfs_dquot_t	*udqp,	xfs_dquot_t	*gdqp,	long		nblks,	long		ninos,	uint		flags){	int		resvd;	if (! XFS_IS_QUOTA_ON(mp))		return (0);	if (tp && tp->t_dqinfo == NULL)		xfs_trans_alloc_dqinfo(tp);	ASSERT(flags & XFS_QMOPT_RESBLK_MASK);	resvd = 0;	if (udqp) {		if (xfs_trans_dqresv(tp, mp, udqp, nblks, ninos, flags))			return (EDQUOT);		resvd = 1;	}	if (gdqp) {		if (xfs_trans_dqresv(tp, mp, gdqp, nblks, ninos, flags)) {			/*			 * can't do it, so backout previous reservation			 */			if (resvd) {				flags |= XFS_QMOPT_FORCE_RES;				xfs_trans_dqresv(tp, mp, udqp,						 -nblks, -ninos, flags);			}			return (EDQUOT);		}	}	/*	 * Didnt change anything critical, so, no need to log	 */	return (0);}/* * Lock the dquot and change the reservation if we can. * This doesn't change the actual usage, just the reservation. * The inode sent in is locked. * * Returns 0 on success, EDQUOT or other errors otherwise */STATIC intxfs_trans_reserve_quota_nblks(	xfs_trans_t	*tp,	xfs_mount_t	*mp,	xfs_inode_t	*ip,	long		nblks,	long		ninos,	uint		type){	int		error;	if (!XFS_IS_QUOTA_ON(mp))		return (0);	ASSERT(ip->i_ino != mp->m_sb.sb_uquotino);	ASSERT(ip->i_ino != mp->m_sb.sb_gquotino);	ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));	ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount));	ASSERT((type & ~XFS_QMOPT_FORCE_RES) == XFS_TRANS_DQ_RES_RTBLKS ||	       (type & ~XFS_QMOPT_FORCE_RES) == XFS_TRANS_DQ_RES_BLKS);	/*	 * Reserve nblks against these dquots, with trans as the mediator.	 */	error = xfs_trans_reserve_quota_bydquots(tp, mp,						 ip->i_udquot, ip->i_gdquot,						 nblks, ninos,						 type);	return (error);}/* * This routine is called to allocate a quotaoff log item. */xfs_qoff_logitem_t *xfs_trans_get_qoff_item(	xfs_trans_t		*tp,	xfs_qoff_logitem_t	*startqoff,	uint			flags){	xfs_qoff_logitem_t	*q;	ASSERT(tp != NULL);	q = xfs_qm_qoff_logitem_init(tp->t_mountp, startqoff, flags);	ASSERT(q != NULL);	/*	 * Get a log_item_desc to point at the new item.	 */	(void) xfs_trans_add_item(tp, (xfs_log_item_t*)q);	return (q);}/* * This is called to mark the quotaoff logitem as needing * to be logged when the transaction is committed.  The logitem must * already be associated with the given transaction. */voidxfs_trans_log_quotaoff_item(	xfs_trans_t		*tp,	xfs_qoff_logitem_t	*qlp){	xfs_log_item_desc_t	*lidp;	lidp = xfs_trans_find_item(tp, (xfs_log_item_t *)qlp);	ASSERT(lidp != NULL);	tp->t_flags |= XFS_TRANS_DIRTY;	lidp->lid_flags |= XFS_LID_DIRTY;}STATIC voidxfs_trans_alloc_dqinfo(	xfs_trans_t	*tp){	(tp)->t_dqinfo = kmem_zone_zalloc(xfs_Gqm->qm_dqtrxzone, KM_SLEEP);}STATIC voidxfs_trans_free_dqinfo(	xfs_trans_t	*tp){	if (!tp->t_dqinfo)		return;	kmem_zone_free(xfs_Gqm->qm_dqtrxzone, (tp)->t_dqinfo);	(tp)->t_dqinfo = NULL;}xfs_dqtrxops_t	xfs_trans_dquot_ops = {	.qo_dup_dqinfo			= xfs_trans_dup_dqinfo,	.qo_free_dqinfo			= xfs_trans_free_dqinfo,	.qo_mod_dquot_byino		= xfs_trans_mod_dquot_byino,	.qo_apply_dquot_deltas		= xfs_trans_apply_dquot_deltas,	.qo_reserve_quota_nblks		= xfs_trans_reserve_quota_nblks,	.qo_reserve_quota_bydquots	= xfs_trans_reserve_quota_bydquots,	.qo_unreserve_and_mod_dquots	= xfs_trans_unreserve_and_mod_dquots,};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -