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