Module Name:    src
Committed By:   dholland
Date:           Sun Jan 29 07:02:07 UTC 2012

Modified Files:
        src/sys/kern: vfs_quotactl.c
        src/sys/sys: quotactl.h
        src/sys/ufs/ufs: ufs_quota.c ufs_quota.h ufs_quota2.c

Log Message:
Hack QUOTACTL_GETALL to return results without using proplib.

(this interface is abusive and is going to be cleaned up in the
immediate future)

Note: this change requires a kernel version bump.


To generate a diff of this commit:
cvs rdiff -u -r1.22 -r1.23 src/sys/kern/vfs_quotactl.c
cvs rdiff -u -r1.20 -r1.21 src/sys/sys/quotactl.h
cvs rdiff -u -r1.94 -r1.95 src/sys/ufs/ufs/ufs_quota.c
cvs rdiff -u -r1.16 -r1.17 src/sys/ufs/ufs/ufs_quota.h
cvs rdiff -u -r1.17 -r1.18 src/sys/ufs/ufs/ufs_quota2.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/kern/vfs_quotactl.c
diff -u src/sys/kern/vfs_quotactl.c:1.22 src/sys/kern/vfs_quotactl.c:1.23
--- src/sys/kern/vfs_quotactl.c:1.22	Sun Jan 29 07:00:39 2012
+++ src/sys/kern/vfs_quotactl.c	Sun Jan 29 07:02:06 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_quotactl.c,v 1.22 2012/01/29 07:00:39 dholland Exp $	*/
+/*	$NetBSD: vfs_quotactl.c,v 1.23 2012/01/29 07:02:06 dholland Exp $	*/
 
 /*
  * Copyright (c) 1991, 1993, 1994
@@ -80,8 +80,9 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_quotactl.c,v 1.22 2012/01/29 07:00:39 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_quotactl.c,v 1.23 2012/01/29 07:02:06 dholland Exp $");
 
+#include <sys/malloc.h> /* XXX: temporary */
 #include <sys/mount.h>
 #include <sys/quota.h>
 #include <sys/quotactl.h>
@@ -437,14 +438,84 @@ err:
 	return error;
 }
 
+static prop_dictionary_t
+vfs_quotactl_getall_makereply(id_t id, int def,
+			      const struct quotaval *blocks,
+			      const struct quotaval *files)
+{
+#define INITQVNAMES_ALL { \
+    QUOTADICT_LIMIT_HARD, \
+    QUOTADICT_LIMIT_SOFT, \
+    QUOTADICT_LIMIT_USAGE, \
+    QUOTADICT_LIMIT_ETIME, \
+    QUOTADICT_LIMIT_GTIME \
+    }
+#define N_QV 5
+
+	const char *val_names[] = INITQVNAMES_ALL;
+	uint64_t vals[N_QV];
+	prop_dictionary_t dict1 = prop_dictionary_create();
+	prop_dictionary_t dict2;
+
+	if (dict1 == NULL)
+		return NULL;
+
+	if (def) {
+		if (!prop_dictionary_set_cstring_nocopy(dict1, "id",
+		    "default")) {
+			goto err;
+		}
+	} else {
+		if (!prop_dictionary_set_uint32(dict1, "id", id)) {
+			goto err;
+		}
+	}
+
+	vals[0] = blocks->qv_hardlimit;
+	vals[1] = blocks->qv_softlimit;
+	vals[2] = blocks->qv_usage;
+	vals[3] = blocks->qv_expiretime;
+	vals[4] = blocks->qv_grace;
+	dict2 = limits64toprop(vals, val_names, N_QV);
+	if (dict2 == NULL)
+		goto err;
+	if (!prop_dictionary_set_and_rel(dict1, QUOTADICT_LTYPE_BLOCK, dict2))
+		goto err;
+
+
+	vals[0] = files->qv_hardlimit;
+	vals[1] = files->qv_softlimit;
+	vals[2] = files->qv_usage;
+	vals[3] = files->qv_expiretime;
+	vals[4] = files->qv_grace;
+	dict2 = limits64toprop(vals, val_names, N_QV);
+	if (dict2 == NULL)
+		goto err;
+	if (!prop_dictionary_set_and_rel(dict1, QUOTADICT_LTYPE_FILE, dict2))
+		goto err;
+
+	return dict1;
+
+err:
+	prop_object_release(dict1);
+	return NULL;
+}
+
 static int
 vfs_quotactl_getall(struct mount *mp,
 			prop_dictionary_t cmddict, int q2type,
 			prop_array_t datas)
 {
 	struct quotakcursor cursor;
+	struct quota_getall_result result;
 	struct vfs_quotactl_args args;
+	prop_array_t replies;
+	prop_dictionary_t dict;
+	unsigned i;
 	int error, error2;
+	int skip = 0;
+
+	KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY);
 
 	args.qc_type = QCT_CURSOROPEN;
 	args.u.cursoropen.qc_cursor = &cursor;
@@ -453,11 +524,75 @@ vfs_quotactl_getall(struct mount *mp,
 		return error;
 	}
 
+	result.qr_keys = NULL;
+	result.qr_vals = NULL;
+
 	args.qc_type = QCT_GETALL;
 	args.u.getall.qc_cursor = &cursor;
 	args.u.getall.qc_idtype = q2type;
-	args.u.getall.qc_cmddict = cmddict;
+	args.u.getall.qc_result = &result;
 	error = VFS_QUOTACTL(mp, QUOTACTL_GETALL, &args);
+	/*
+	 * XXX this is bogus but up until now *all* errors
+	 * from inside quotactl_getall were suppressed by the
+	 * dispatching code in ufs_quota.c. Fixing that causes
+	 * repquota to break in an undesirable way; this is a
+	 * workaround.
+	 */
+	if (error == ENODEV || error == ENXIO) {
+		skip = 1;
+		error = 0;
+	}
+	if (error) {
+		goto err;
+	}
+
+	replies = prop_array_create();
+	if (replies == NULL) {
+		error = ENOMEM;
+		goto err;
+	}
+
+	if (skip) {
+		goto skip;
+	}
+
+	dict = vfs_quotactl_getall_makereply(0, 1, &result.qr_defblocks,
+					     &result.qr_deffiles);
+	if (!prop_array_add_and_rel(replies, dict)) {
+		error = ENOMEM;
+		goto err;
+	}
+
+	for (i = 0; i < result.qr_num; i += 2) {
+		dict = vfs_quotactl_getall_makereply(result.qr_keys[i].qk_id,0,
+						     &result.qr_vals[i],
+						     &result.qr_vals[i+1]);
+		if (dict == NULL) {
+			error = ENOMEM;
+			goto err;
+		}
+		if (!prop_array_add_and_rel(replies, dict)) {
+			error = ENOMEM;
+			goto err;
+		}
+	}
+
+skip:
+
+	if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) {
+		error = ENOMEM;
+		goto err;
+	}
+
+	error = 0;
+ err:
+	if (result.qr_keys) {
+		free(result.qr_keys, M_TEMP);
+	}
+	if (result.qr_vals) {
+		free(result.qr_vals, M_TEMP);
+	}
 
 	args.qc_type = QCT_CURSORCLOSE;
 	args.u.cursorclose.qc_cursor = &cursor;

Index: src/sys/sys/quotactl.h
diff -u src/sys/sys/quotactl.h:1.20 src/sys/sys/quotactl.h:1.21
--- src/sys/sys/quotactl.h:1.20	Sun Jan 29 07:00:39 2012
+++ src/sys/sys/quotactl.h	Sun Jan 29 07:02:06 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: quotactl.h,v 1.20 2012/01/29 07:00:39 dholland Exp $	*/
+/*	$NetBSD: quotactl.h,v 1.21 2012/01/29 07:02:06 dholland Exp $	*/
 /*-
  * Copyright (c) 2011 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -37,6 +37,8 @@
  * use the <quota.h> API instead.
  */
 
+#include <sys/quota.h>
+
 /*
  * Semi-opaque structure for cursors. This holds the cursor state in
  * userland; the size is exposed only to libquota, not to client code,
@@ -104,7 +106,13 @@ struct vfs_quotactl_args {
 		struct {
 			struct quotakcursor *qc_cursor;
 			int qc_idtype;
-			prop_dictionary_t qc_cmddict;
+			struct quota_getall_result {
+				struct quotaval qr_defblocks;
+				struct quotaval qr_deffiles;
+				struct quotakey *qr_keys;
+				struct quotaval *qr_vals;
+				unsigned qr_num;
+			} *qc_result;
 		} getall;
 	} u;
 };

Index: src/sys/ufs/ufs/ufs_quota.c
diff -u src/sys/ufs/ufs/ufs_quota.c:1.94 src/sys/ufs/ufs/ufs_quota.c:1.95
--- src/sys/ufs/ufs/ufs_quota.c:1.94	Sun Jan 29 07:00:39 2012
+++ src/sys/ufs/ufs/ufs_quota.c	Sun Jan 29 07:02:06 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: ufs_quota.c,v 1.94 2012/01/29 07:00:39 dholland Exp $	*/
+/*	$NetBSD: ufs_quota.c,v 1.95 2012/01/29 07:02:06 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.94 2012/01/29 07:00:39 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ufs_quota.c,v 1.95 2012/01/29 07:02:06 dholland Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_quota.h"
@@ -368,19 +368,16 @@ static int 
 quota_handle_cmd_getall(struct mount *mp, struct lwp *l, 
     struct vfs_quotactl_args *args)
 {
-	prop_array_t replies;
 	struct ufsmount *ump = VFSTOUFS(mp);
 	struct quotakcursor *cursor;
 	int idtype;
-	prop_dictionary_t cmddict;
+	struct quota_getall_result *result;
 	int error;
 
 	KASSERT(args->qc_type == QCT_GETALL);
 	cursor = args->u.getall.qc_cursor;
 	idtype = args->u.getall.qc_idtype;
-	cmddict = args->u.getall.qc_cmddict;
-
-	KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY);
+	result = args->u.getall.qc_result;
 
 	if ((ump->um_flags & UFS_QUOTA2) == 0)
 		return EOPNOTSUPP;
@@ -390,21 +387,13 @@ quota_handle_cmd_getall(struct mount *mp
 	if (error)
 		return error;
 		
-	replies = prop_array_create();
-	if (replies == NULL)
-		return ENOMEM;
-
 #ifdef QUOTA2
 	if (ump->um_flags & UFS_QUOTA2) {
-		error = quota2_handle_cmd_getall(ump, cursor, idtype, replies);
+		error = quota2_handle_cmd_getall(ump, cursor, idtype, result);
 	} else
 #endif
 		panic("quota_handle_cmd_getall: no support ?");
-	if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) {
-		error = ENOMEM;
-	} else {
-		error = 0;
-	}
+
 	return error;
 }
 

Index: src/sys/ufs/ufs/ufs_quota.h
diff -u src/sys/ufs/ufs/ufs_quota.h:1.16 src/sys/ufs/ufs/ufs_quota.h:1.17
--- src/sys/ufs/ufs/ufs_quota.h:1.16	Sun Jan 29 07:00:40 2012
+++ src/sys/ufs/ufs/ufs_quota.h	Sun Jan 29 07:02:06 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: ufs_quota.h,v 1.16 2012/01/29 07:00:40 dholland Exp $	*/
+/*	$NetBSD: ufs_quota.h,v 1.17 2012/01/29 07:02:06 dholland Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1990, 1993, 1995
@@ -37,6 +37,7 @@
 #include <ufs/ufs/quota2.h>
 
 struct quotakcursor; /* from <sys/quotactl.h> */
+struct quota_getall_result; /* ditto, but: XXX temporary */
 
 
 /* link to this quota in the quota inode (for QUOTA2) */
@@ -132,7 +133,7 @@ int quota2_handle_cmd_put(struct ufsmoun
     const struct quotaval *);
 int quota2_handle_cmd_delete(struct ufsmount *, const struct quotakey *);
 int quota2_handle_cmd_getall(struct ufsmount *, struct quotakcursor *, int,
-    prop_array_t);
+    struct quota_getall_result *);
 int quota2_handle_cmd_cursoropen(struct ufsmount *, struct quotakcursor *);
 int quota2_handle_cmd_cursorclose(struct ufsmount *, struct quotakcursor *);
 int q2sync(struct mount *);

Index: src/sys/ufs/ufs/ufs_quota2.c
diff -u src/sys/ufs/ufs/ufs_quota2.c:1.17 src/sys/ufs/ufs/ufs_quota2.c:1.18
--- src/sys/ufs/ufs/ufs_quota2.c:1.17	Sun Jan 29 07:00:40 2012
+++ src/sys/ufs/ufs/ufs_quota2.c	Sun Jan 29 07:02:06 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: ufs_quota2.c,v 1.17 2012/01/29 07:00:40 dholland Exp $ */
+/* $NetBSD: ufs_quota2.c,v 1.18 2012/01/29 07:02:06 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.17 2012/01/29 07:00:40 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ufs_quota2.c,v 1.18 2012/01/29 07:02:06 dholland Exp $");
 
 #include <sys/buf.h>
 #include <sys/param.h>
@@ -75,7 +75,9 @@ static int quota2_walk_list(struct ufsmo
     int (*func)(struct ufsmount *, uint64_t *, struct quota2_entry *,
       uint64_t, void *));
 
+#if 0
 static prop_dictionary_t q2etoprop(struct quota2_entry *, int);
+#endif
 
 static const char *limnames[] = INITQLNAMES;
 
@@ -92,6 +94,7 @@ quota2_dict_update_q2e_limits(int objtyp
 	q2e->q2e_val[objtype].q2v_grace = val->qv_grace;
 }
 
+#if 0
 static prop_dictionary_t
 q2etoprop(struct quota2_entry *q2e, int def)
 {
@@ -127,6 +130,7 @@ err:
 	prop_object_release(dict1);
 	return NULL;
 }
+#endif
 
 /*
  * Convert internal representation to FS-independent representation.
@@ -824,17 +828,16 @@ out_dq:
 }
 
 static int
-quota2_array_add_q2e(struct ufsmount *ump, int type,
-    int id, prop_array_t replies)
+quota2_result_add_q2e(struct ufsmount *ump, int idtype,
+    int id, struct quota_getall_result *result, unsigned pos)
 {
 	struct dquot *dq;
 	int error;
 	struct quota2_entry *q2ep, q2e;
 	struct buf  *bp;
 	const int needswap = UFS_MPNEEDSWAP(ump);
-	prop_dictionary_t dict;
 
-	error = dqget(NULLVP, id, ump, type, &dq);
+	error = dqget(NULLVP, id, ump, idtype, &dq);
 	if (error)
 		return error;
 
@@ -844,7 +847,7 @@ quota2_array_add_q2e(struct ufsmount *um
 		dqrele(NULLVP, dq);
 		return ENOENT;
 	}
-	error = getq2e(ump, type, dq->dq2_lblkno, dq->dq2_blkoff,
+	error = getq2e(ump, idtype, dq->dq2_lblkno, dq->dq2_blkoff,
 	    &bp, &q2ep, 0);
 	if (error) {
 		mutex_exit(&dq->dq_interlock);
@@ -856,11 +859,16 @@ quota2_array_add_q2e(struct ufsmount *um
 	mutex_exit(&dq->dq_interlock);
 	dqrele(NULLVP, dq);
 
-	dict = q2etoprop(&q2e, 0);
-	if (dict == NULL)
-		return ENOMEM;
-	if (!prop_array_add_and_rel(replies, dict))
-		return ENOMEM;
+	result->qr_keys[pos].qk_idtype = idtype;
+	result->qr_keys[pos].qk_objtype = QUOTA_OBJTYPE_BLOCKS;
+	q2e_to_quotaval(&q2e, 0, &result->qr_keys[pos].qk_id,
+			QL_BLOCK, &result->qr_vals[pos]);
+
+	result->qr_keys[pos+1].qk_idtype = idtype;
+	result->qr_keys[pos+1].qk_objtype = QUOTA_OBJTYPE_FILES;
+	q2e_to_quotaval(&q2e, 0, &result->qr_keys[pos+1].qk_id,
+			QL_FILE, &result->qr_vals[pos+1]);
+
 	return 0;
 }
 
@@ -989,39 +997,39 @@ quota2_getuids_callback(struct ufsmount 
 
 int
 quota2_handle_cmd_getall(struct ufsmount *ump, struct quotakcursor *qkc,
-    int type, prop_array_t replies)
+    int idtype, struct quota_getall_result *result)
 {
 	int error;
 	struct ufsq2_cursor *cursor;
 	struct quota2_header *q2h;
 	struct quota2_entry  q2e;
 	struct buf *hbp;
-	prop_dictionary_t dict;
 	uint64_t offset;
 	int i, j;
 	int quota2_hash_size;
 	const int needswap = UFS_MPNEEDSWAP(ump);
 	struct getuids gu;
+	id_t junkid;
+	unsigned num, maxnum;
 
 	cursor = Q2CURSOR(qkc);
 	if (cursor->q2c_magic != Q2C_MAGIC) {
 		return EINVAL;
 	}
 
-	if (ump->um_quotas[type] == NULLVP)
+	if (ump->um_quotas[idtype] == NULLVP)
 		return ENODEV;
+
 	mutex_enter(&dqlock);
-	error = getq2h(ump, type, &hbp, &q2h, 0);
+	error = getq2h(ump, idtype, &hbp, &q2h, 0);
 	if (error) {
 		mutex_exit(&dqlock);
 		return error;
 	}
 	quota2_ufs_rwq2e(&q2h->q2h_defentry, &q2e, needswap);
-	dict = q2etoprop(&q2e, 1);
-	if (!prop_array_add_and_rel(replies, dict)) {
-		error = ENOMEM;
-		goto error_bp;
-	}
+	q2e_to_quotaval(&q2e, 1, &junkid, QL_BLOCK, &result->qr_defblocks);
+	q2e_to_quotaval(&q2e, 1, &junkid, QL_FILE, &result->qr_deffiles);
+
 	/*
 	 * we can't directly get entries as we can't walk the list
 	 * with qdlock and grab dq_interlock to read the entries
@@ -1032,7 +1040,7 @@ quota2_handle_cmd_getall(struct ufsmount
 	quota2_hash_size = ufs_rw16(q2h->q2h_hash_size, needswap);
 	for (i = 0; i < quota2_hash_size ; i++) {
 		offset = q2h->q2h_entries[i];
-		error = quota2_walk_list(ump, hbp, type, &offset, 0, &gu,
+		error = quota2_walk_list(ump, hbp, idtype, &offset, 0, &gu,
 		    quota2_getuids_callback);
 		if (error) {
 			if (gu.uids != NULL)
@@ -1040,17 +1048,30 @@ quota2_handle_cmd_getall(struct ufsmount
 			break;
 		}
 	}
-error_bp:
+
 	mutex_exit(&dqlock);
 	brelse(hbp, 0);
 	if (error)
 		return error;
+
+	maxnum = gu.nuids*2;
+	result->qr_keys = malloc(maxnum * sizeof(result->qr_keys[0]),
+				 M_TEMP, M_WAITOK);
+	result->qr_vals = malloc(maxnum * sizeof(result->qr_vals[0]),
+				 M_TEMP, M_WAITOK);
+
+	num = 0;
 	for (j = 0; j < gu.nuids; j++) {
-		error = quota2_array_add_q2e(ump, type,
-		    gu.uids[j], replies);
-		if (error && error != ENOENT)
+		error = quota2_result_add_q2e(ump, idtype,
+		    gu.uids[j], result, j*2);
+		if (error == ENOENT)
+			continue;
+		if (error)
 			break;
+		num += 2;
 	}
+	result->qr_num = num;
+
 	free(gu.uids, M_TEMP);
 	return error;
 }

Reply via email to