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

Reply via email to