Example #1
0
/*
 * Check the inode limit, applying corrective action.
 */
int
lfs_chkiq1(struct inode *ip, int32_t change, kauth_cred_t cred, int flags)
{
	struct dquot *dq;
	int i;
	int ncurinodes, error;

	if ((error = lfs_getinoquota(ip)) != 0)
		return error;
	if (change == 0)
		return (0);
	if (change < 0) {
		for (i = 0; i < ULFS_MAXQUOTAS; i++) {
			if ((dq = ip->i_dquot[i]) == NODQUOT)
				continue;
			mutex_enter(&dq->dq_interlock);
			ncurinodes = dq->dq_curinodes + change;
			if (ncurinodes >= 0)
				dq->dq_curinodes = ncurinodes;
			else
				dq->dq_curinodes = 0;
			dq->dq_flags &= ~DQ_WARN(QL_FILE);
			dq->dq_flags |= DQ_MOD;
			mutex_exit(&dq->dq_interlock);
		}
		return (0);
	}
	for (i = 0; i < ULFS_MAXQUOTAS; i++) {
		if ((dq = ip->i_dquot[i]) == NODQUOT)
			continue;
		if ((flags & FORCE) == 0 && kauth_authorize_system(cred,
		    KAUTH_SYSTEM_FS_QUOTA, KAUTH_REQ_SYSTEM_FS_QUOTA_NOLIMIT,
		    KAUTH_ARG(i), KAUTH_ARG(QL_FILE), NULL) != 0) {
			mutex_enter(&dq->dq_interlock);
			error = chkiqchg(ip, change, cred, i);
			mutex_exit(&dq->dq_interlock);
			if (error != 0)
				return (error);
		}
	}
	for (i = 0; i < ULFS_MAXQUOTAS; i++) {
		if ((dq = ip->i_dquot[i]) == NODQUOT)
			continue;
		mutex_enter(&dq->dq_interlock);
		dq->dq_curinodes += change;
		dq->dq_flags |= DQ_MOD;
		mutex_exit(&dq->dq_interlock);
	}
	return (0);
}
Example #2
0
/*
 * Check the inode limit, applying corrective action.
 */
int
chkiq(struct inode *ip, int32_t change, kauth_cred_t cred, int flags)
{
	struct dquot *dq;
	int i;
	int ncurinodes, error;

	if ((error = getinoquota(ip)) != 0)
		return error;
	if (change == 0)
		return (0);
	if (change < 0) {
		for (i = 0; i < MAXQUOTAS; i++) {
			if ((dq = ip->i_dquot[i]) == NODQUOT)
				continue;
			mutex_enter(&dq->dq_interlock);
			ncurinodes = dq->dq_curinodes + change;
			if (ncurinodes >= 0)
				dq->dq_curinodes = ncurinodes;
			else
				dq->dq_curinodes = 0;
			dq->dq_flags &= ~DQ_INODS;
			dq->dq_flags |= DQ_MOD;
			mutex_exit(&dq->dq_interlock);
		}
		return (0);
	}
	if ((flags & FORCE) == 0 && kauth_authorize_generic(cred,
	    KAUTH_GENERIC_ISSUSER, NULL) != 0) {
		for (i = 0; i < MAXQUOTAS; i++) {
			if ((dq = ip->i_dquot[i]) == NODQUOT)
				continue;
			mutex_enter(&dq->dq_interlock);
			error = chkiqchg(ip, change, cred, i);
			mutex_exit(&dq->dq_interlock);
			if (error != 0)
				return (error);
		}
	}
	for (i = 0; i < MAXQUOTAS; i++) {
		if ((dq = ip->i_dquot[i]) == NODQUOT)
			continue;
		mutex_enter(&dq->dq_interlock);
		dq->dq_curinodes += change;
		dq->dq_flags |= DQ_MOD;
		mutex_exit(&dq->dq_interlock);
	}
	return (0);
}
Example #3
0
/*
 * Check the inode limit, applying corrective action.
 */
int
chkiq(struct inode *ip, int change, struct ucred *cred, int flags)
{
    struct dquot *dq;
    int i, error, warn, do_check;

#ifdef DIAGNOSTIC
    if ((flags & CHOWN) == 0)
        chkdquot(ip);
#endif
    if (change == 0)
        return (0);
    if (change < 0) {
        for (i = 0; i < MAXQUOTAS; i++) {
            if ((dq = ip->i_dquot[i]) == NODQUOT)
                continue;
            DQI_LOCK(dq);
            DQI_WAIT(dq, PINOD+1, "chkiq1");
            if (dq->dq_curinodes >= -change)
                dq->dq_curinodes += change;
            else
                dq->dq_curinodes = 0;
            dq->dq_flags &= ~DQ_INODS;
            dq->dq_flags |= DQ_MOD;
            DQI_UNLOCK(dq);
        }
        return (0);
    }
    if ((flags & FORCE) == 0 &&
            priv_check_cred(cred, PRIV_VFS_EXCEEDQUOTA, 0))
        do_check = 1;
    else
        do_check = 0;
    for (i = 0; i < MAXQUOTAS; i++) {
        if ((dq = ip->i_dquot[i]) == NODQUOT)
            continue;
        warn = 0;
        DQI_LOCK(dq);
        DQI_WAIT(dq, PINOD+1, "chkiq2");
        if (do_check) {
            error = chkiqchg(ip, change, cred, i, &warn);
            if (error) {
                /*
                 * Roll back user quota changes when
                 * group quota failed.
                 */
                while (i > 0) {
                    --i;
                    dq = ip->i_dquot[i];
                    if (dq == NODQUOT)
                        continue;
                    DQI_LOCK(dq);
                    DQI_WAIT(dq, PINOD+1, "chkiq3");
                    if (dq->dq_curinodes >= change)
                        dq->dq_curinodes -= change;
                    else
                        dq->dq_curinodes = 0;
                    dq->dq_flags &= ~DQ_INODS;
                    dq->dq_flags |= DQ_MOD;
                    DQI_UNLOCK(dq);
                }
                return (error);
            }
        }
        /* Reset timer when crossing soft limit */
        if (dq->dq_curinodes + change >= dq->dq_isoftlimit &&
                dq->dq_curinodes < dq->dq_isoftlimit)
            dq->dq_itime = time_second + ITOUMP(ip)->um_itime[i];
        dq->dq_curinodes += change;
        dq->dq_flags |= DQ_MOD;
        DQI_UNLOCK(dq);
        if (warn)
            uprintf("\n%s: warning, %s inode quota exceeded\n",
                    ITOVFS(ip)->mnt_stat.f_mntonname,
                    quotatypes[i]);
    }
    return (0);
}