예제 #1
0
파일: xfs_dquot.c 프로젝트: avagin/linux
/*
 * If default limits are in force, push them into the dquot now.
 * We overwrite the dquot limits only if they are zero and this
 * is not the root dquot.
 */
void
xfs_qm_adjust_dqlimits(
	struct xfs_mount	*mp,
	struct xfs_dquot	*dq)
{
	struct xfs_quotainfo	*q = mp->m_quotainfo;
	struct xfs_disk_dquot	*d = &dq->q_core;
	struct xfs_def_quota	*defq;
	int			prealloc = 0;

	ASSERT(d->d_id);
	defq = xfs_get_defquota(dq, q);

	if (defq->bsoftlimit && !d->d_blk_softlimit) {
		d->d_blk_softlimit = cpu_to_be64(defq->bsoftlimit);
		prealloc = 1;
	}
	if (defq->bhardlimit && !d->d_blk_hardlimit) {
		d->d_blk_hardlimit = cpu_to_be64(defq->bhardlimit);
		prealloc = 1;
	}
	if (defq->isoftlimit && !d->d_ino_softlimit)
		d->d_ino_softlimit = cpu_to_be64(defq->isoftlimit);
	if (defq->ihardlimit && !d->d_ino_hardlimit)
		d->d_ino_hardlimit = cpu_to_be64(defq->ihardlimit);
	if (defq->rtbsoftlimit && !d->d_rtb_softlimit)
		d->d_rtb_softlimit = cpu_to_be64(defq->rtbsoftlimit);
	if (defq->rtbhardlimit && !d->d_rtb_hardlimit)
		d->d_rtb_hardlimit = cpu_to_be64(defq->rtbhardlimit);

	if (prealloc)
		xfs_dquot_set_prealloc_limits(dq);
}
예제 #2
0
/*
 * 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.
 */
STATIC int
xfs_trans_dqresv(
    xfs_trans_t	*tp,
    xfs_mount_t	*mp,
    xfs_dquot_t	*dqp,
    long		nblks,
    long		ninos,
    uint		flags)
{
    xfs_qcnt_t	hardlimit;
    xfs_qcnt_t	softlimit;
    time_t		timer;
    xfs_qwarncnt_t	warns;
    xfs_qwarncnt_t	warnlimit;
    xfs_qcnt_t	total_count;
    xfs_qcnt_t	*resbcountp;
    xfs_quotainfo_t	*q = mp->m_quotainfo;
    struct xfs_def_quota	*defq;


    xfs_dqlock(dqp);

    defq = xfs_get_defquota(dqp, q);

    if (flags & XFS_TRANS_DQ_RES_BLKS) {
        hardlimit = be64_to_cpu(dqp->q_core.d_blk_hardlimit);
        if (!hardlimit)
            hardlimit = defq->bhardlimit;
        softlimit = be64_to_cpu(dqp->q_core.d_blk_softlimit);
        if (!softlimit)
            softlimit = defq->bsoftlimit;
        timer = be32_to_cpu(dqp->q_core.d_btimer);
        warns = be16_to_cpu(dqp->q_core.d_bwarns);
        warnlimit = dqp->q_mount->m_quotainfo->qi_bwarnlimit;
        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 = defq->rtbhardlimit;
        softlimit = be64_to_cpu(dqp->q_core.d_rtb_softlimit);
        if (!softlimit)
            softlimit = defq->rtbsoftlimit;
        timer = be32_to_cpu(dqp->q_core.d_rtbtimer);
        warns = be16_to_cpu(dqp->q_core.d_rtbwarns);
        warnlimit = dqp->q_mount->m_quotainfo->qi_rtbwarnlimit;
        resbcountp = &dqp->q_res_rtbcount;
    }

    if ((flags & XFS_QMOPT_FORCE_RES) == 0 &&
            dqp->q_core.d_id &&
            ((XFS_IS_UQUOTA_ENFORCED(dqp->q_mount) && XFS_QM_ISUDQ(dqp)) ||
             (XFS_IS_GQUOTA_ENFORCED(dqp->q_mount) && XFS_QM_ISGDQ(dqp)) ||
             (XFS_IS_PQUOTA_ENFORCED(dqp->q_mount) && XFS_QM_ISPDQ(dqp)))) {
        if (nblks > 0) {
            /*
             * dquot is locked already. See if we'd go over the
             * hardlimit or exceed the timelimit if we allocate
             * nblks.
             */
            total_count = *resbcountp + nblks;
            if (hardlimit && total_count > hardlimit) {
                xfs_quota_warn(mp, dqp, QUOTA_NL_BHARDWARN);
                goto error_return;
            }
            if (softlimit && total_count > softlimit) {
                if ((timer != 0 && get_seconds() > timer) ||
                        (warns != 0 && warns >= warnlimit)) {
                    xfs_quota_warn(mp, dqp,
                                   QUOTA_NL_BSOFTLONGWARN);
                    goto error_return;
                }

                xfs_quota_warn(mp, dqp, QUOTA_NL_BSOFTWARN);
            }
        }
        if (ninos > 0) {
            total_count = be64_to_cpu(dqp->q_core.d_icount) + ninos;
            timer = be32_to_cpu(dqp->q_core.d_itimer);
            warns = be16_to_cpu(dqp->q_core.d_iwarns);
            warnlimit = dqp->q_mount->m_quotainfo->qi_iwarnlimit;
            hardlimit = be64_to_cpu(dqp->q_core.d_ino_hardlimit);
            if (!hardlimit)
                hardlimit = defq->ihardlimit;
            softlimit = be64_to_cpu(dqp->q_core.d_ino_softlimit);
            if (!softlimit)
                softlimit = defq->isoftlimit;

            if (hardlimit && total_count > hardlimit) {
                xfs_quota_warn(mp, dqp, QUOTA_NL_IHARDWARN);
                goto error_return;
            }
            if (softlimit && total_count > softlimit) {
                if  ((timer != 0 && get_seconds() > timer) ||
                        (warns != 0 && warns >= warnlimit)) {
                    xfs_quota_warn(mp, dqp,
                                   QUOTA_NL_ISOFTLONGWARN);
                    goto error_return;
                }
                xfs_quota_warn(mp, dqp, QUOTA_NL_ISOFTWARN);
            }
        }
    }

    /*
     * 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));

    xfs_dqunlock(dqp);
    return 0;

error_return:
    xfs_dqunlock(dqp);
    if (flags & XFS_QMOPT_ENOSPC)
        return -ENOSPC;
    return -EDQUOT;
}