/* * Given dquot(s), make disk block and/or inode reservations against them. * The fact that this does the reservation against user, group and * project quotas is important, because this follows a all-or-nothing * approach. * * flags = XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown. * XFS_QMOPT_ENOSPC returns ENOSPC not EDQUOT. Used by pquota. * 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. */ int xfs_trans_reserve_quota_bydquots( struct xfs_trans *tp, struct xfs_mount *mp, struct xfs_dquot *udqp, struct xfs_dquot *gdqp, struct xfs_dquot *pdqp, long nblks, long ninos, uint flags) { int error; if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp)) return 0; if (tp && tp->t_dqinfo == NULL) xfs_trans_alloc_dqinfo(tp); ASSERT(flags & XFS_QMOPT_RESBLK_MASK); if (udqp) { error = xfs_trans_dqresv(tp, mp, udqp, nblks, ninos, (flags & ~XFS_QMOPT_ENOSPC)); if (error) return error; } if (gdqp) { error = xfs_trans_dqresv(tp, mp, gdqp, nblks, ninos, flags); if (error) goto unwind_usr; } if (pdqp) { error = xfs_trans_dqresv(tp, mp, pdqp, nblks, ninos, flags); if (error) goto unwind_grp; } /* * Didn't change anything critical, so, no need to log */ return 0; unwind_grp: flags |= XFS_QMOPT_FORCE_RES; if (gdqp) xfs_trans_dqresv(tp, mp, gdqp, -nblks, -ninos, flags); unwind_usr: flags |= XFS_QMOPT_FORCE_RES; if (udqp) xfs_trans_dqresv(tp, mp, udqp, -nblks, -ninos, flags); return error; }
/* * Given dquot(s), make disk block and/or inode reservations against them. * The fact that this does the reservation against both the usr and * grp/prj quotas is important, because this follows a both-or-nothing * approach. * * flags = XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown. * XFS_QMOPT_ENOSPC returns ENOSPC not EDQUOT. Used by pquota. * 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. */ int xfs_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 = 0, error; if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp)) return 0; if (tp && tp->t_dqinfo == NULL) xfs_trans_alloc_dqinfo(tp); ASSERT(flags & XFS_QMOPT_RESBLK_MASK); if (udqp) { error = xfs_trans_dqresv(tp, mp, udqp, nblks, ninos, (flags & ~XFS_QMOPT_ENOSPC)); if (error) return error; resvd = 1; } if (gdqp) { error = xfs_trans_dqresv(tp, mp, gdqp, nblks, ninos, flags); if (error) { /* * 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 error; } } /* * Didn't change anything critical, so, no need to log */ return 0; }
/* * 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. */ int xfs_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, udqp, nblks, ninos, flags)) return (EDQUOT); resvd = 1; } if (gdqp) { if (xfs_trans_dqresv(tp, gdqp, nblks, ninos, flags)) { /* * can't do it, so backout previous reservation */ if (resvd) { xfs_trans_dqresv(tp, udqp, -nblks, -ninos, flags); } return (EDQUOT); } } /* * Didnt change anything critical, so, no need to log */ return (0); }