Sun Jan 29 06:40:58 2012 UTC ()
Per the FS-independent schema, get one quotaval at a time from the
filesystem, instead of blocks and files together.

This results in fetching each FS-level quota entry twice and therefore
doing slightly more work, but (1) quota access isn't a critical path
and (2) after fetching the block values the file values will be hot in
the cache, so it won't add much total time.

Also move more of the FS-independent defintions from <quota.h> to
<sys/quota.h> so we can use them internally.

Step 4 of 5 for QUOTACTL_GET.

Note: this change requires a kernel version bump.


(dholland)
diff -r1.2 -r1.3 src/include/quota.h
diff -r1.8 -r1.9 src/sys/kern/vfs_quotactl.c
diff -r1.8 -r1.9 src/sys/sys/quota.h
diff -r1.6 -r1.7 src/sys/sys/quotactl.h
diff -r1.76 -r1.77 src/sys/ufs/ufs/ufs_quota.c
diff -r1.3 -r1.4 src/sys/ufs/ufs/ufs_quota.h
diff -r1.8 -r1.9 src/sys/ufs/ufs/ufs_quota1.c
diff -r1.5 -r1.6 src/sys/ufs/ufs/ufs_quota2.c

cvs diff -r1.2 -r1.3 src/include/quota.h (expand / switch to context diff)
--- src/include/quota.h 2012/01/29 06:38:23 1.2
+++ src/include/quota.h 2012/01/29 06:40:57 1.3
@@ -36,26 +36,6 @@
 struct quotahandle; /* Opaque. */
 struct quotacursor; /* Opaque. */
 
-/* quota id types (entities being billed) */
-#define QUOTA_IDTYPE_USER	0
-#define QUOTA_IDTYPE_GROUP	1
-
-/* quota object types (things being limited) */
-#define QUOTA_OBJTYPE_BLOCKS	0
-#define QUOTA_OBJTYPE_FILES	1
-
-/* limit value for "no limit" */
-#define QUOTA_NOLIMIT		((uint64_t)0xffffffffffffffffULL)
-
-/* time value for "no time" */
-#define QUOTA_NOTIME		((time_t)-1)
-
-
-struct quotakey {
-	int qk_idtype;
-	id_t qk_id;
-	int qk_objtype;
-};
 
 void quotaval_clear(struct quotaval *);
 

cvs diff -r1.8 -r1.9 src/sys/kern/vfs_quotactl.c (expand / switch to context diff)
--- src/sys/kern/vfs_quotactl.c 2012/01/29 06:39:36 1.8
+++ src/sys/kern/vfs_quotactl.c 2012/01/29 06:40:57 1.9
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_quotactl.c,v 1.8 2012/01/29 06:39:36 dholland Exp $	*/
+/*	$NetBSD: vfs_quotactl.c,v 1.9 2012/01/29 06:40:57 dholland Exp $	*/
 
 /*
  * Copyright (c) 1991, 1993, 1994
@@ -80,7 +80,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_quotactl.c,v 1.8 2012/01/29 06:39:36 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_quotactl.c,v 1.9 2012/01/29 06:40:57 dholland Exp $");
 
 #include <sys/mount.h>
 #include <sys/quota.h>
@@ -241,8 +241,25 @@
 		args.u.get.qc_q2type = q2type;
 		args.u.get.qc_id = id;
 		args.u.get.qc_defaultq = defaultq;
-		args.u.get.qc_blocks_ret = &blocks;
-		args.u.get.qc_files_ret = &files;
+		args.u.get.qc_objtype = QUOTA_OBJTYPE_BLOCKS;
+		args.u.get.qc_ret = &blocks;
+		error = VFS_QUOTACTL(mp, QUOTACTL_GET, &args);
+		if (error == EPERM) {
+			/* XXX does this make sense? */
+			continue;
+		} else if (error == ENOENT) {
+			/* XXX does *this* make sense? */
+			continue;
+		} else if (error) {
+			goto fail;
+		}
+
+		args.qc_type = QCT_GET;
+		args.u.get.qc_q2type = q2type;
+		args.u.get.qc_id = id;
+		args.u.get.qc_defaultq = defaultq;
+		args.u.get.qc_objtype = QUOTA_OBJTYPE_FILES;
+		args.u.get.qc_ret = &files;
 		error = VFS_QUOTACTL(mp, QUOTACTL_GET, &args);
 		if (error == EPERM) {
 			/* XXX does this make sense? */

cvs diff -r1.8 -r1.9 src/sys/sys/quota.h (expand / switch to context diff)
--- src/sys/sys/quota.h 2012/01/29 06:38:23 1.8
+++ src/sys/sys/quota.h 2012/01/29 06:40:57 1.9
@@ -1,4 +1,4 @@
-/* $NetBSD: quota.h,v 1.8 2012/01/29 06:38:23 dholland Exp $ */
+/* $NetBSD: quota.h,v 1.9 2012/01/29 06:40:57 dholland Exp $ */
 /*-
   * Copyright (c) 2010 Manuel Bouyer
   * All rights reserved.
@@ -30,8 +30,29 @@
 
 #include <sys/types.h>
 
+/* quota id types (entities being billed) */
+#define QUOTA_IDTYPE_USER	0
+#define QUOTA_IDTYPE_GROUP	1
+
+/* quota object types (things being limited) */
+#define QUOTA_OBJTYPE_BLOCKS	0
+#define QUOTA_OBJTYPE_FILES	1
+
 /* id value for "default" */
 #define QUOTA_DEFAULTID		((id_t)-1)
+
+/* limit value for "no limit" */
+#define QUOTA_NOLIMIT		((uint64_t)0xffffffffffffffffULL)
+
+/* time value for "no time" */
+#define QUOTA_NOTIME		((time_t)-1)
+
+
+struct quotakey {
+	int qk_idtype;
+	id_t qk_id;
+	int qk_objtype;
+};
 
 /*
  * Structure used to describe the value part of a quota record.

cvs diff -r1.6 -r1.7 src/sys/sys/quotactl.h (expand / switch to context diff)
--- src/sys/sys/quotactl.h 2012/01/29 06:39:36 1.6
+++ src/sys/sys/quotactl.h 2012/01/29 06:40:57 1.7
@@ -1,4 +1,4 @@
-/*	$NetBSD: quotactl.h,v 1.6 2012/01/29 06:39:36 dholland Exp $	*/
+/*	$NetBSD: quotactl.h,v 1.7 2012/01/29 06:40:57 dholland Exp $	*/
 /*-
  * Copyright (c) 2011 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -67,8 +67,8 @@
 			int qc_q2type;
 			id_t qc_id;
 			int qc_defaultq;
-			struct quotaval *qc_blocks_ret;
-			struct quotaval *qc_files_ret;
+			int qc_objtype;
+			struct quotaval *qc_ret;
 		} get;
 	} u;
 };

cvs diff -r1.76 -r1.77 src/sys/ufs/ufs/ufs_quota.c (expand / switch to context diff)
--- src/sys/ufs/ufs/ufs_quota.c 2012/01/29 06:39:37 1.76
+++ src/sys/ufs/ufs/ufs_quota.c 2012/01/29 06:40:57 1.77
@@ -1,4 +1,4 @@
-/*	$NetBSD: ufs_quota.c,v 1.76 2012/01/29 06:39:37 dholland Exp $	*/
+/*	$NetBSD: ufs_quota.c,v 1.77 2012/01/29 06:40:57 dholland 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.76 2012/01/29 06:39:37 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ufs_quota.c,v 1.77 2012/01/29 06:40:57 dholland Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_quota.h"
@@ -235,14 +235,15 @@
 	id_t id;
 	int q2type;
 	int defaultq;
-	struct quotaval *blocks, *files;
+	int objtype;
+	struct quotaval *ret;
 
 	KASSERT(args->qc_type == QCT_GET);
 	id = args->u.get.qc_id;
 	q2type = args->u.get.qc_q2type;
 	defaultq = args->u.get.qc_defaultq;
-	blocks = args->u.get.qc_blocks_ret;
-	files = args->u.get.qc_files_ret;
+	objtype = args->u.get.qc_objtype;
+	ret = args->u.get.qc_ret;
 
 	if ((ump->um_flags & (UFS_QUOTA|UFS_QUOTA2)) == 0)
 		return EOPNOTSUPP;
@@ -254,13 +255,13 @@
 #ifdef QUOTA
 		if (ump->um_flags & UFS_QUOTA) {
 			error = quota1_handle_cmd_get(ump, q2type, id, defaultq,
-			    blocks, files);
+			    objtype, ret);
 		} else
 #endif
 #ifdef QUOTA2
 		if (ump->um_flags & UFS_QUOTA2) {
 			error = quota2_handle_cmd_get(ump, q2type, id, defaultq,
-			    blocks, files);
+			    objtype, ret);
 		} else
 #endif
 			panic("quota_handle_cmd_get: no support ?");

cvs diff -r1.3 -r1.4 src/sys/ufs/ufs/ufs_quota.h (expand / switch to context diff)
--- src/sys/ufs/ufs/ufs_quota.h 2012/01/29 06:38:24 1.3
+++ src/sys/ufs/ufs/ufs_quota.h 2012/01/29 06:40:57 1.4
@@ -1,4 +1,4 @@
-/*	$NetBSD: ufs_quota.h,v 1.3 2012/01/29 06:38:24 dholland Exp $	*/
+/*	$NetBSD: ufs_quota.h,v 1.4 2012/01/29 06:40:57 dholland Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1990, 1993, 1995
@@ -113,8 +113,8 @@
 int q1sync(struct mount *);
 int dq1get(struct vnode *, u_long, struct ufsmount *, int, struct dquot *);
 int dq1sync(struct vnode *, struct dquot *);
-int quota1_handle_cmd_get(struct ufsmount *, int, int, int,
-    struct quotaval *, struct quotaval *);
+int quota1_handle_cmd_get(struct ufsmount *, int, int, int, int,
+    struct quotaval *);
 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 *);
@@ -122,8 +122,8 @@
 
 int chkdq2(struct inode *, int64_t, kauth_cred_t, int);
 int chkiq2(struct inode *, int32_t, kauth_cred_t, int);
-int quota2_handle_cmd_get(struct ufsmount *, int, int, int,
-    struct quotaval *, struct quotaval *);
+int quota2_handle_cmd_get(struct ufsmount *, int, int, int, int,
+    struct quotaval *);
 int quota2_handle_cmd_set(struct ufsmount *, int, int, int, prop_dictionary_t);
 int quota2_handle_cmd_clear(struct ufsmount *, int, int, int, prop_dictionary_t);
 int quota2_handle_cmd_getall(struct ufsmount *, int, prop_array_t);

cvs diff -r1.8 -r1.9 src/sys/ufs/ufs/ufs_quota1.c (expand / switch to context diff)
--- src/sys/ufs/ufs/ufs_quota1.c 2012/01/29 06:38:24 1.8
+++ src/sys/ufs/ufs/ufs_quota1.c 2012/01/29 06:40:57 1.9
@@ -1,4 +1,4 @@
-/*	$NetBSD: ufs_quota1.c,v 1.8 2012/01/29 06:38:24 dholland Exp $	*/
+/*	$NetBSD: ufs_quota1.c,v 1.9 2012/01/29 06:40:57 dholland 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.8 2012/01/29 06:38:24 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ufs_quota1.c,v 1.9 2012/01/29 06:40:57 dholland Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -494,15 +494,12 @@
 
 int             
 quota1_handle_cmd_get(struct ufsmount *ump, int idtype, int id,
-    int defaultq, struct quotaval *blocks, struct quotaval *files)
+    int defaultq, int objtype, struct quotaval *ret)
 {
 	struct dquot *dq;
 	int error;
-	uint64_t *valuesp[QUOTA_NLIMITS];
+	struct quotaval blocks, files;
 
-	valuesp[QUOTA_LIMIT_BLOCK] = &blocks->qv_hardlimit;
-	valuesp[QUOTA_LIMIT_FILE] = &files->qv_hardlimit;
-
 	if (ump->um_quotas[idtype] == NULLVP)
 		return ENODEV;
 
@@ -514,18 +511,30 @@
 		if ((error = dqget(NULLVP, id, ump, idtype, &dq)) != 0)
 			return error;
 	}
-	dqblk_to_quotavals(&dq->dq_un.dq1_dqb, blocks, files);
+	dqblk_to_quotavals(&dq->dq_un.dq1_dqb, &blocks, &files);
 	dqrele(NULLVP, dq);
 	if (defaultq) {
-		if (blocks->qv_expiretime > 0)
-			blocks->qv_grace = blocks->qv_expiretime;
+		if (blocks.qv_expiretime > 0)
+			blocks.qv_grace = blocks.qv_expiretime;
 		else
-			blocks->qv_grace = MAX_DQ_TIME;
-		if (files->qv_expiretime > 0)
-			files->qv_grace = files->qv_expiretime;
+			blocks.qv_grace = MAX_DQ_TIME;
+		if (files.qv_expiretime > 0)
+			files.qv_grace = files.qv_expiretime;
 		else
-			files->qv_grace = MAX_DQ_TIME;
+			files.qv_grace = MAX_DQ_TIME;
 	}
+
+	switch (objtype) {
+	    case QUOTA_OBJTYPE_BLOCKS:
+		*ret = blocks;
+		break;
+	    case QUOTA_OBJTYPE_FILES:
+		*ret = files;
+		break;
+	    default:
+		return EINVAL;
+	}
+
 	return 0;
 }
 

cvs diff -r1.5 -r1.6 src/sys/ufs/ufs/ufs_quota2.c (expand / switch to context diff)
--- src/sys/ufs/ufs/ufs_quota2.c 2012/01/29 06:38:24 1.5
+++ src/sys/ufs/ufs/ufs_quota2.c 2012/01/29 06:40:58 1.6
@@ -1,4 +1,4 @@
-/* $NetBSD: ufs_quota2.c,v 1.5 2012/01/29 06:38:24 dholland Exp $ */
+/* $NetBSD: ufs_quota2.c,v 1.6 2012/01/29 06:40:58 dholland Exp $ */
 /*-
   * Copyright (c) 2010 Manuel Bouyer
   * All rights reserved.
@@ -26,7 +26,7 @@
   */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ufs_quota2.c,v 1.5 2012/01/29 06:38:24 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ufs_quota2.c,v 1.6 2012/01/29 06:40:58 dholland Exp $");
 
 #include <sys/buf.h>
 #include <sys/param.h>
@@ -77,8 +77,6 @@
 static int quota2_dict_update_q2e_limits(prop_dictionary_t,
     struct quota2_entry *);
 static prop_dictionary_t q2etoprop(struct quota2_entry *, int);
-static void q2e_to_quotavals(struct quota2_entry *, int, id_t *,
-    struct quotaval *, struct quotaval *);
 
 static const char *limnames[] = INITQLNAMES;
 
@@ -159,8 +157,8 @@
  * representation.
  */
 static void
-q2e_to_quotavals(struct quota2_entry *q2e, int def,
-	       id_t *id, struct quotaval *blocks, struct quotaval *files)
+q2e_to_quotaval(struct quota2_entry *q2e, int def,
+	       id_t *id, int objtype, struct quotaval *ret)
 {
 	if (def) {
 		*id = QUOTA_DEFAULTID;
@@ -168,9 +166,8 @@
 		*id = q2e->q2e_uid;
 	}
 
-	CTASSERT(N_QL == 2);
-	q2val_to_quotaval(&q2e->q2e_val[QL_BLOCK], blocks);
-	q2val_to_quotaval(&q2e->q2e_val[QL_FILE], files);
+	KASSERT(objtype >= 0 && objtype < N_QL);
+	q2val_to_quotaval(&q2e->q2e_val[objtype], ret);
 }
 
 
@@ -857,7 +854,7 @@
 
 static int
 quota2_fetch_q2e(struct ufsmount *ump, int type,
-    int id, struct quotaval *blocks, struct quotaval *files)
+    int id, int objtype, struct quotaval *ret)
 {
 	struct dquot *dq;
 	int error;
@@ -888,14 +885,14 @@
 	mutex_exit(&dq->dq_interlock);
 	dqrele(NULLVP, dq);
 
-	q2e_to_quotavals(&q2e, 0, &id2, blocks, files);
+	q2e_to_quotaval(&q2e, 0, &id2, objtype, ret);
 	KASSERT(id2 == id);
 	return 0;
 }
 
 int
 quota2_handle_cmd_get(struct ufsmount *ump, int type, int id,
-    int defaultq, struct quotaval *blocks, struct quotaval *files)
+    int defaultq, int objtype, struct quotaval *ret)
 {
 	int error;
 	struct quota2_header *q2h;
@@ -904,6 +901,19 @@
 	const int needswap = UFS_MPNEEDSWAP(ump);
 	id_t id2;
 
+	/*
+	 * Make sure the FS-independent codes match the internal ones,
+	 * so we can use the passed-in objtype without having to
+	 * convert it explicitly to QL_BLOCK/QL_FILE.
+	 */
+	CTASSERT(QL_BLOCK == QUOTA_OBJTYPE_BLOCKS);
+	CTASSERT(QL_FILE == QUOTA_OBJTYPE_FILES);
+	CTASSERT(N_QL == 2);
+
+	if (objtype < 0 || objtype >= N_QL) {
+		return EINVAL;
+	}
+
 	if (ump->um_quotas[type] == NULLVP)
 		return ENODEV;
 	if (defaultq) {
@@ -916,10 +926,10 @@
 		quota2_ufs_rwq2e(&q2h->q2h_defentry, &q2e, needswap);
 		mutex_exit(&dqlock);
 		brelse(bp, 0);
-		q2e_to_quotavals(&q2e, defaultq, &id2, blocks, files);
+		q2e_to_quotaval(&q2e, defaultq, &id2, objtype, ret);
 		(void)id2;
 	} else
-		error = quota2_fetch_q2e(ump, type, id, blocks, files);
+		error = quota2_fetch_q2e(ump, type, id, objtype, ret);
 	
 	return error;
 }