Module Name: src Committed By: bouyer Date: Wed Feb 9 16:15:01 UTC 2011
Modified Files: src/sys/ufs [bouyer-quota2]: files.ufs src/sys/ufs/ufs [bouyer-quota2]: ufs_quota.c ufs_quota.h ufs_quota1.c Log Message: Reimplement quotactl commands for quota1 To generate a diff of this commit: cvs rdiff -u -r1.24.6.2 -r1.24.6.3 src/sys/ufs/files.ufs cvs rdiff -u -r1.68.4.10 -r1.68.4.11 src/sys/ufs/ufs/ufs_quota.c cvs rdiff -u -r1.1.2.8 -r1.1.2.9 src/sys/ufs/ufs/ufs_quota.h cvs rdiff -u -r1.1.2.4 -r1.1.2.5 src/sys/ufs/ufs/ufs_quota1.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/ufs/files.ufs diff -u src/sys/ufs/files.ufs:1.24.6.2 src/sys/ufs/files.ufs:1.24.6.3 --- src/sys/ufs/files.ufs:1.24.6.2 Wed Feb 9 11:18:29 2011 +++ src/sys/ufs/files.ufs Wed Feb 9 16:15:01 2011 @@ -1,4 +1,4 @@ -# $NetBSD: files.ufs,v 1.24.6.2 2011/02/09 11:18:29 bouyer Exp $ +# $NetBSD: files.ufs,v 1.24.6.3 2011/02/09 16:15:01 bouyer Exp $ deffs FFS deffs EXT2FS @@ -62,6 +62,7 @@ file ufs/ufs/ufs_quota.c (quota | quota2) & (ffs | lfs | mfs | ext2fs) file ufs/ufs/ufs_quota1.c quota & (ffs | lfs | mfs | ext2fs) file ufs/ufs/ufs_quota2.c quota2 & (ffs | lfs | mfs | ext2fs) +file ufs/ufs/quota1_subr.c quota & (ffs | lfs | mfs | ext2fs) file ufs/ufs/quota2_subr.c quota2 & (ffs | lfs | mfs | ext2fs) file ufs/ufs/quota2_prop.c (quota | quota2) & (ffs | lfs | mfs | ext2fs) file ufs/ufs/ufs_vfsops.c ffs | lfs | mfs | ext2fs Index: src/sys/ufs/ufs/ufs_quota.c diff -u src/sys/ufs/ufs/ufs_quota.c:1.68.4.10 src/sys/ufs/ufs/ufs_quota.c:1.68.4.11 --- src/sys/ufs/ufs/ufs_quota.c:1.68.4.10 Wed Feb 9 11:18:30 2011 +++ src/sys/ufs/ufs/ufs_quota.c Wed Feb 9 16:15:01 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: ufs_quota.c,v 1.68.4.10 2011/02/09 11:18:30 bouyer Exp $ */ +/* $NetBSD: ufs_quota.c,v 1.68.4.11 2011/02/09 16:15:01 bouyer Exp $ */ /* * Copyright (c) 1982, 1986, 1990, 1993, 1995 @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ufs_quota.c,v 1.68.4.10 2011/02/09 11:18:30 bouyer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ufs_quota.c,v 1.68.4.11 2011/02/09 16:15:01 bouyer Exp $"); #if defined(_KERNEL_OPT) #include "opt_quota.h" @@ -82,6 +82,10 @@ prop_dictionary_t, int, prop_array_t); static int quota_handle_cmd_clear(struct mount *, struct lwp *, prop_dictionary_t, int, prop_array_t); +static int quota_handle_cmd_quotaon(struct mount *, struct lwp *, + prop_dictionary_t, int, prop_array_t); +static int quota_handle_cmd_quotaoff(struct mount *, struct lwp *, + prop_dictionary_t, int, prop_array_t); /* * Initialize the quota fields of an inode. */ @@ -171,6 +175,16 @@ error = quota_handle_cmd_get_version(mp, l, cmddict, datas); goto end; } + if (strcmp(cmd, "quotaon") == 0) { + error = quota_handle_cmd_quotaon(mp, l, cmddict, + q2type, datas); + goto end; + } + if (strcmp(cmd, "quotaoff") == 0) { + error = quota_handle_cmd_quotaoff(mp, l, cmddict, + q2type, datas); + goto end; + } if (strcmp(cmd, "get") == 0) { error = quota_handle_cmd_get(mp, l, cmddict, q2type, datas); goto end; @@ -487,6 +501,69 @@ return error; } +static int +quota_handle_cmd_quotaon(struct mount *mp, struct lwp *l, + prop_dictionary_t cmddict, int type, prop_array_t datas) +{ + prop_dictionary_t data; + struct ufsmount *ump = VFSTOUFS(mp); + int error; + const char *qfile; + + if ((ump->um_flags & UFS_QUOTA2) != 0) + return EBUSY; + + if (prop_array_count(datas) != 1) + return EINVAL; + + data = prop_array_get(datas, 0); + if (data == NULL) + return ENOMEM; + if (!prop_dictionary_get_cstring_nocopy(data, "quotafile", + &qfile)) + return EINVAL; + + error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA, + KAUTH_REQ_SYSTEM_FS_QUOTA_ONOFF, mp, NULL, NULL); + if (error != 0) { + return error; + } +#ifdef QUOTA + error = quota1_handle_cmd_quotaon(l, ump, type, qfile); +#else + error = EOPNOTSUPP; +#endif + + return error; +} + +static int +quota_handle_cmd_quotaoff(struct mount *mp, struct lwp *l, + prop_dictionary_t cmddict, int type, prop_array_t datas) +{ + struct ufsmount *ump = VFSTOUFS(mp); + int error; + + if ((ump->um_flags & UFS_QUOTA2) != 0) + return EOPNOTSUPP; + + if (prop_array_count(datas) != 0) + return EINVAL; + + error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA, + KAUTH_REQ_SYSTEM_FS_QUOTA_ONOFF, mp, NULL, NULL); + if (error != 0) { + return error; + } +#ifdef QUOTA + error = quota1_handle_cmd_quotaoff(l, ump, type); +#else + error = EOPNOTSUPP; +#endif + + return error; +} + /* * Initialize the quota system. */ Index: src/sys/ufs/ufs/ufs_quota.h diff -u src/sys/ufs/ufs/ufs_quota.h:1.1.2.8 src/sys/ufs/ufs/ufs_quota.h:1.1.2.9 --- src/sys/ufs/ufs/ufs_quota.h:1.1.2.8 Wed Feb 9 11:18:30 2011 +++ src/sys/ufs/ufs/ufs_quota.h Wed Feb 9 16:15:01 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: ufs_quota.h,v 1.1.2.8 2011/02/09 11:18:30 bouyer Exp $ */ +/* $NetBSD: ufs_quota.h,v 1.1.2.9 2011/02/09 16:15:01 bouyer Exp $ */ /* * Copyright (c) 1982, 1986, 1990, 1993, 1995 @@ -115,6 +115,9 @@ int dq1sync(struct vnode *, struct dquot *); int quota1_handle_cmd_get(struct ufsmount *, int, int, int, prop_array_t); int quota1_handle_cmd_set(struct ufsmount *, int, int, int, prop_dictionary_t); +int quota1_handle_cmd_quotaon(struct lwp *, struct ufsmount *, int, + const char *); +int quota1_handle_cmd_quotaoff(struct lwp *, struct ufsmount *, int); int chkdq2(struct inode *, int64_t, kauth_cred_t, int); int chkiq2(struct inode *, int32_t, kauth_cred_t, int); Index: src/sys/ufs/ufs/ufs_quota1.c diff -u src/sys/ufs/ufs/ufs_quota1.c:1.1.2.4 src/sys/ufs/ufs/ufs_quota1.c:1.1.2.5 --- src/sys/ufs/ufs/ufs_quota1.c:1.1.2.4 Wed Feb 9 12:01:20 2011 +++ src/sys/ufs/ufs/ufs_quota1.c Wed Feb 9 16:15:01 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: ufs_quota1.c,v 1.1.2.4 2011/02/09 12:01:20 bouyer Exp $ */ +/* $NetBSD: ufs_quota1.c,v 1.1.2.5 2011/02/09 16:15:01 bouyer Exp $ */ /* * Copyright (c) 1982, 1986, 1990, 1993, 1995 @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ufs_quota1.c,v 1.1.2.4 2011/02/09 12:01:20 bouyer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ufs_quota1.c,v 1.1.2.5 2011/02/09 16:15:01 bouyer Exp $"); #include <sys/param.h> #include <sys/kernel.h> @@ -47,6 +47,7 @@ #include <sys/mount.h> #include <sys/kauth.h> +#include <ufs/ufs/quota2_prop.h> #include <ufs/ufs/quota1.h> #include <ufs/ufs/inode.h> #include <ufs/ufs/ufsmount.h> @@ -55,7 +56,6 @@ static int chkdqchg(struct inode *, int64_t, kauth_cred_t, int); static int chkiqchg(struct inode *, int32_t, kauth_cred_t, int); -static int quotaoff(struct lwp *, struct mount *, int); /* * Update disk usage, and take corrective action. @@ -287,7 +287,7 @@ for (i = 0; i < MAXQUOTAS; i++) { if (ump->um_quotas[i] != NULLVP) { - quotaoff(l, mp, i); + quota1_handle_cmd_quotaoff(l, ump, i); } } return 0; @@ -297,14 +297,14 @@ * Code to process quotactl commands. */ -#if 0 /* * set up a quota file for a particular file system. */ -static int -quotaon(struct lwp *l, struct mount *mp, int type, void *fname) +int +quota1_handle_cmd_quotaon(struct lwp *l, struct ufsmount *ump, int type, + const char *fname) { - struct ufsmount *ump = VFSTOUFS(mp); + struct mount *mp = ump->um_mountp; struct vnode *vp, **vpp, *mvp; struct dquot *dq; int error; @@ -317,9 +317,8 @@ return (EBUSY); } - /* XXX XXX XXX */ if (mp->mnt_wapbl != NULL) { - printf("%s: quotas cannot yet be used with -o log\n", + printf("%s: quota v1 cannot be used with -o log\n", mp->mnt_stat.f_mntonname); return (EOPNOTSUPP); } @@ -344,7 +343,7 @@ return (EACCES); } if (*vpp != vp) - quotaoff(l, mp, type); + quota1_handle_cmd_quotaoff(l, ump, type); mutex_enter(&dqlock); while ((ump->umq1_qflags[type] & (QTF_CLOSING | QTF_OPENING)) != 0) cv_wait(&dqcv, &dqlock); @@ -414,20 +413,19 @@ ump->um_flags |= UFS_QUOTA; mutex_exit(&dqlock); if (error) - quotaoff(l, mp, type); + quota1_handle_cmd_quotaoff(l, ump, type); return (error); } -#endif /* * turn off disk quotas for a filesystem. */ -static int -quotaoff(struct lwp *l, struct mount *mp, int type) +int +quota1_handle_cmd_quotaoff(struct lwp *l, struct ufsmount *ump, int type) { + struct mount *mp = ump->um_mountp; struct vnode *vp; struct vnode *qvp, *mvp; - struct ufsmount *ump = VFSTOUFS(mp); struct dquot *dq; struct inode *ip; kauth_cred_t cred; @@ -502,34 +500,108 @@ quota1_handle_cmd_get(struct ufsmount *ump, int type, int id, int defaultq, prop_array_t replies) { - return EOPNOTSUPP; + struct dquot *dq; + struct quota2_entry q2e; + prop_dictionary_t dict; + int error; + + if (ump->um_quotas[type] == NULLVP) + return ENODEV; + + if (defaultq) { /* we want the grace period of id 0 */ + if ((error = dqget(NULLVP, 0, ump, type, &dq)) != 0) + return error; + } else { + if ((error = dqget(NULLVP, id, ump, type, &dq)) != 0) + return error; + } + dqblk2q2e(&dq->dq_un.dq1_dqb, &q2e); + dqrele(NULLVP, dq); + if (defaultq) { + q2e.q2e_val[QL_BLOCK].q2v_grace = q2e.q2e_val[QL_BLOCK].q2v_time; + q2e.q2e_val[QL_FILE].q2v_grace = q2e.q2e_val[QL_FILE].q2v_time; + } + dict = q2etoprop(&q2e, defaultq); + if (dict == NULL) + return ENOMEM; + if (!prop_array_add_and_rel(replies, dict)) + return ENOMEM; + return 0; } int quota1_handle_cmd_set(struct ufsmount *ump, int type, int id, int defaultq, prop_dictionary_t data) { - return EOPNOTSUPP; -} - - -#if 0 -/* - * Q_GETQUOTA - return current values in a dqblk structure. - */ -int -getquota1(struct mount *mp, u_long id, int type, struct dqblk *dqb) -{ struct dquot *dq; + struct quota2_entry q2e; + struct dqblk dqb; int error; - if ((error = dqget(NULLVP, id, VFSTOUFS(mp), type, &dq)) != 0) + if (ump->um_quotas[type] == NULLVP) + return ENODEV; + + error = quota2_dict_update_q2e_limits(data, &q2e); + if (error) + return error; + + if (defaultq) { + /* just update grace times */ + if ((error = dqget(NULLVP, id, ump, type, &dq)) != 0) + return error; + mutex_enter(&dq->dq_interlock); + ump->umq1_btime[type] = dq->dq_btime = + q2e.q2e_val[QL_BLOCK].q2v_grace; + ump->umq1_itime[type] = dq->dq_itime = + q2e.q2e_val[QL_FILE].q2v_grace; + mutex_exit(&dq->dq_interlock); + dq->dq_flags |= DQ_MOD; + dqrele(NULLVP, dq); + return 0; + } + + q2e2dqblk(&q2e, &dqb); + + if ((error = dqget(NULLVP, id, ump, type, &dq)) != 0) return (error); - memcpy(dqb, (void *)&dq->dq_un.dq1_dqb, sizeof (struct dqblk)); + mutex_enter(&dq->dq_interlock); + /* + * Copy all but the current values. + * Reset time limit if previously had no soft limit or were + * under it, but now have a soft limit and are over it. + */ + dqb.dqb_curblocks = dq->dq_curblocks; + dqb.dqb_curinodes = dq->dq_curinodes; + if (dq->dq_id != 0) { + dqb.dqb_btime = dq->dq_btime; + dqb.dqb_itime = dq->dq_itime; + } + if (dqb.dqb_bsoftlimit && + dq->dq_curblocks >= dqb.dqb_bsoftlimit && + (dq->dq_bsoftlimit == 0 || dq->dq_curblocks < dq->dq_bsoftlimit)) + dqb.dqb_btime = time_second + ump->umq1_btime[type]; + if (dqb.dqb_isoftlimit && + dq->dq_curinodes >= dqb.dqb_isoftlimit && + (dq->dq_isoftlimit == 0 || dq->dq_curinodes < dq->dq_isoftlimit)) + dqb.dqb_itime = time_second + ump->umq1_itime[type]; + dq->dq_un.dq1_dqb = dqb; + if (dq->dq_curblocks < dq->dq_bsoftlimit) + dq->dq_flags &= ~DQ_WARN(QL_BLOCK); + if (dq->dq_curinodes < dq->dq_isoftlimit) + dq->dq_flags &= ~DQ_WARN(QL_FILE); + if (dq->dq_isoftlimit == 0 && dq->dq_bsoftlimit == 0 && + dq->dq_ihardlimit == 0 && dq->dq_bhardlimit == 0) + dq->dq_flags |= DQ_FAKE; + else + dq->dq_flags &= ~DQ_FAKE; + dq->dq_flags |= DQ_MOD; + mutex_exit(&dq->dq_interlock); dqrele(NULLVP, dq); - return (error); + return (0); } + +#if 0 /* * Q_SETQUOTA - assign an entire dqblk structure. */ @@ -539,7 +611,7 @@ struct dquot *dq; struct dquot *ndq; struct ufsmount *ump = VFSTOUFS(mp); - int error; + if ((error = dqget(NULLVP, id, ump, type, &ndq)) != 0) return (error);