Module Name: src
Committed By: dholland
Date: Sun Jan 29 07:07:22 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:
Call QUOTACTL_GETALL in a loop to get results 8 at a time. Make
the QUOTACTL_GETALL interface less abusive.
Note: this change requires a kernel version bump.
To generate a diff of this commit:
cvs rdiff -u -r1.26 -r1.27 src/sys/kern/vfs_quotactl.c
cvs rdiff -u -r1.23 -r1.24 src/sys/sys/quotactl.h
cvs rdiff -u -r1.95 -r1.96 src/sys/ufs/ufs/ufs_quota.c
cvs rdiff -u -r1.17 -r1.18 src/sys/ufs/ufs/ufs_quota.h
cvs rdiff -u -r1.22 -r1.23 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.26 src/sys/kern/vfs_quotactl.c:1.27
--- src/sys/kern/vfs_quotactl.c:1.26 Sun Jan 29 07:06:37 2012
+++ src/sys/kern/vfs_quotactl.c Sun Jan 29 07:07:22 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: vfs_quotactl.c,v 1.26 2012/01/29 07:06:37 dholland Exp $ */
+/* $NetBSD: vfs_quotactl.c,v 1.27 2012/01/29 07:07:22 dholland Exp $ */
/*
* Copyright (c) 1991, 1993, 1994
@@ -80,7 +80,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_quotactl.c,v 1.26 2012/01/29 07:06:37 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_quotactl.c,v 1.27 2012/01/29 07:07:22 dholland Exp $");
#include <sys/malloc.h> /* XXX: temporary */
#include <sys/mount.h>
@@ -525,16 +525,18 @@ vfs_quotactl_getall(struct mount *mp,
prop_array_t datas)
{
struct quotakcursor cursor;
- struct quota_getall_result result;
+ struct quotakey *keys;
+ struct quotaval *vals;
+ unsigned loopmax = 8;
+ unsigned loopnum;
struct vfs_quotactl_args args;
prop_array_t replies;
- prop_dictionary_t thisreply;
struct quotakey *key;
struct quotaval *val;
id_t lastid;
+ prop_dictionary_t thisreply;
unsigned i;
int error, error2;
- int skip = 0;
KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY);
@@ -545,30 +547,8 @@ vfs_quotactl_getall(struct mount *mp,
return error;
}
- result.qr_keys = NULL;
- result.qr_vals = NULL;
- result.qr_num = 0;
- result.qr_max = 0x7fffffff; /* XXX bogus; but temporary */
-
- args.qc_type = QCT_GETALL;
- args.u.getall.qc_cursor = &cursor;
- args.u.getall.qc_idtype = q2type;
- 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;
- }
+ keys = malloc(loopmax * sizeof(keys[0]), M_TEMP, M_WAITOK);
+ vals = malloc(loopmax * sizeof(vals[0]), M_TEMP, M_WAITOK);
replies = prop_array_create();
if (replies == NULL) {
@@ -576,43 +556,72 @@ vfs_quotactl_getall(struct mount *mp,
goto err;
}
- if (skip) {
- goto skip;
- }
-
thisreply = NULL;
lastid = 0; /* value not actually referenced */
- for (i = 0; i < result.qr_num; i++) {
- key = &result.qr_keys[i];
- val = &result.qr_vals[i];
-
- if (thisreply == NULL || key->qk_id != lastid) {
- lastid = key->qk_id;
- thisreply = vfs_quotactl_getall_makereply(key);
- if (thisreply == NULL) {
- error = ENOMEM;
- goto err;
- }
- /*
- * Note: while we release our reference to
- * thisreply here, we can (and do) continue to
- * use the pointer in the loop because the
- * copy attached to the replies array is not
- * going away.
- */
- if (!prop_array_add_and_rel(replies, thisreply)) {
- error = ENOMEM;
- goto err;
- }
+
+ while (1) {
+ args.qc_type = QCT_GETALL;
+ args.u.getall.qc_cursor = &cursor;
+ args.u.getall.qc_keys = keys;
+ args.u.getall.qc_vals = vals;
+ args.u.getall.qc_maxnum = loopmax;
+ args.u.getall.qc_ret = &loopnum;
+ args.u.getall.qc_idtype = q2type; /* XXX */
+
+ 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) {
+ error = 0;
+ break;
}
- error = vfs_quotactl_getall_addreply(thisreply, key, val);
if (error) {
goto err;
}
- }
-skip:
+ if (loopnum == 0) {
+ /* end of iteration */
+ break;
+ }
+
+ for (i = 0; i < loopnum; i++) {
+ key = &keys[i];
+ val = &vals[i];
+
+ if (thisreply == NULL || key->qk_id != lastid) {
+ lastid = key->qk_id;
+ thisreply = vfs_quotactl_getall_makereply(key);
+ if (thisreply == NULL) {
+ error = ENOMEM;
+ goto err;
+ }
+ /*
+ * Note: while we release our reference to
+ * thisreply here, we can (and do) continue to
+ * use the pointer in the loop because the
+ * copy attached to the replies array is not
+ * going away.
+ */
+ if (!prop_array_add_and_rel(replies,
+ thisreply)) {
+ error = ENOMEM;
+ goto err;
+ }
+ }
+
+ error = vfs_quotactl_getall_addreply(thisreply,
+ key, val);
+ if (error) {
+ goto err;
+ }
+ }
+ }
if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) {
error = ENOMEM;
@@ -621,12 +630,8 @@ skip:
error = 0;
err:
- if (result.qr_keys) {
- free(result.qr_keys, M_TEMP);
- }
- if (result.qr_vals) {
- free(result.qr_vals, M_TEMP);
- }
+ free(keys, M_TEMP);
+ free(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.23 src/sys/sys/quotactl.h:1.24
--- src/sys/sys/quotactl.h:1.23 Sun Jan 29 07:06:01 2012
+++ src/sys/sys/quotactl.h Sun Jan 29 07:07:22 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: quotactl.h,v 1.23 2012/01/29 07:06:01 dholland Exp $ */
+/* $NetBSD: quotactl.h,v 1.24 2012/01/29 07:07:22 dholland Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -37,8 +37,6 @@
* 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,
@@ -105,13 +103,11 @@ struct vfs_quotactl_args {
} cursorclose;
struct {
struct quotakcursor *qc_cursor;
+ struct quotakey *qc_keys;
+ struct quotaval *qc_vals;
+ unsigned qc_maxnum;
+ unsigned *qc_ret;
int qc_idtype;
- struct quota_getall_result {
- struct quotakey *qr_keys;
- struct quotaval *qr_vals;
- unsigned qr_num;
- unsigned qr_max;
- } *qc_result;
} getall;
} u;
};
Index: src/sys/ufs/ufs/ufs_quota.c
diff -u src/sys/ufs/ufs/ufs_quota.c:1.95 src/sys/ufs/ufs/ufs_quota.c:1.96
--- src/sys/ufs/ufs/ufs_quota.c:1.95 Sun Jan 29 07:02:06 2012
+++ src/sys/ufs/ufs/ufs_quota.c Sun Jan 29 07:07:22 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: ufs_quota.c,v 1.95 2012/01/29 07:02:06 dholland Exp $ */
+/* $NetBSD: ufs_quota.c,v 1.96 2012/01/29 07:07:22 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.95 2012/01/29 07:02:06 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ufs_quota.c,v 1.96 2012/01/29 07:07:22 dholland Exp $");
#if defined(_KERNEL_OPT)
#include "opt_quota.h"
@@ -370,14 +370,20 @@ quota_handle_cmd_getall(struct mount *mp
{
struct ufsmount *ump = VFSTOUFS(mp);
struct quotakcursor *cursor;
+ struct quotakey *keys;
+ struct quotaval *vals;
+ unsigned maxnum;
+ unsigned *ret;
int idtype;
- struct quota_getall_result *result;
int error;
KASSERT(args->qc_type == QCT_GETALL);
cursor = args->u.getall.qc_cursor;
+ keys = args->u.getall.qc_keys;
+ vals = args->u.getall.qc_vals;
+ maxnum = args->u.getall.qc_maxnum;
+ ret = args->u.getall.qc_ret;
idtype = args->u.getall.qc_idtype;
- result = args->u.getall.qc_result;
if ((ump->um_flags & UFS_QUOTA2) == 0)
return EOPNOTSUPP;
@@ -389,7 +395,8 @@ quota_handle_cmd_getall(struct mount *mp
#ifdef QUOTA2
if (ump->um_flags & UFS_QUOTA2) {
- error = quota2_handle_cmd_getall(ump, cursor, idtype, result);
+ error = quota2_handle_cmd_getall(ump, cursor, idtype,
+ keys, vals, maxnum, ret);
} else
#endif
panic("quota_handle_cmd_getall: no support ?");
Index: src/sys/ufs/ufs/ufs_quota.h
diff -u src/sys/ufs/ufs/ufs_quota.h:1.17 src/sys/ufs/ufs/ufs_quota.h:1.18
--- src/sys/ufs/ufs/ufs_quota.h:1.17 Sun Jan 29 07:02:06 2012
+++ src/sys/ufs/ufs/ufs_quota.h Sun Jan 29 07:07:22 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: ufs_quota.h,v 1.17 2012/01/29 07:02:06 dholland Exp $ */
+/* $NetBSD: ufs_quota.h,v 1.18 2012/01/29 07:07:22 dholland Exp $ */
/*
* Copyright (c) 1982, 1986, 1990, 1993, 1995
@@ -37,7 +37,6 @@
#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) */
@@ -133,7 +132,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,
- struct quota_getall_result *);
+ struct quotakey *, struct quotaval *, unsigned, unsigned *);
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.22 src/sys/ufs/ufs/ufs_quota2.c:1.23
--- src/sys/ufs/ufs/ufs_quota2.c:1.22 Sun Jan 29 07:06:02 2012
+++ src/sys/ufs/ufs/ufs_quota2.c Sun Jan 29 07:07:22 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: ufs_quota2.c,v 1.22 2012/01/29 07:06:02 dholland Exp $ */
+/* $NetBSD: ufs_quota2.c,v 1.23 2012/01/29 07:07:22 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.22 2012/01/29 07:06:02 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ufs_quota2.c,v 1.23 2012/01/29 07:07:22 dholland Exp $");
#include <sys/buf.h>
#include <sys/param.h>
@@ -829,7 +829,7 @@ out_dq:
static int
quota2_result_add_q2e(struct ufsmount *ump, int idtype,
- int id, struct quota_getall_result *result, unsigned pos,
+ int id, struct quotakey *keys, struct quotaval *vals, unsigned pos,
int skipfirst, int skiplast)
{
struct dquot *dq;
@@ -861,18 +861,18 @@ quota2_result_add_q2e(struct ufsmount *u
dqrele(NULLVP, dq);
if (skipfirst == 0) {
- 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]);
+ keys[pos].qk_idtype = idtype;
+ keys[pos].qk_objtype = QUOTA_OBJTYPE_BLOCKS;
+ q2e_to_quotaval(&q2e, 0, &keys[pos].qk_id,
+ QL_BLOCK, &vals[pos]);
pos++;
}
if (skiplast == 0) {
- result->qr_keys[pos].qk_idtype = idtype;
- result->qr_keys[pos].qk_objtype = QUOTA_OBJTYPE_FILES;
- q2e_to_quotaval(&q2e, 0, &result->qr_keys[pos].qk_id,
- QL_FILE, &result->qr_vals[pos]);
+ keys[pos].qk_idtype = idtype;
+ keys[pos].qk_objtype = QUOTA_OBJTYPE_FILES;
+ q2e_to_quotaval(&q2e, 0, &keys[pos].qk_id,
+ QL_FILE, &vals[pos]);
pos++;
}
@@ -1042,7 +1042,8 @@ quota2_getuids_callback(struct ufsmount
int
quota2_handle_cmd_getall(struct ufsmount *ump, struct quotakcursor *qkc,
- int idtype, struct quota_getall_result *result)
+ int idtype, struct quotakey *keys, struct quotaval *vals,
+ unsigned maxreturn, unsigned *ret)
{
int error;
struct ufsq2_cursor *cursor;
@@ -1054,13 +1055,12 @@ quota2_handle_cmd_getall(struct ufsmount
int quota2_hash_size;
const int needswap = UFS_MPNEEDSWAP(ump);
struct getuids gu;
+ long excess;
id_t junkid;
- struct quotakey bkey, fkey;
- struct quotaval bval, fval;
- int dobval = 0, dofval = 0;
+ struct quotaval qv;
unsigned num, maxnum;
int skipfirst, skiplast;
- int maxreturn, numreturn;
+ int numreturn;
cursor = Q2CURSOR(qkc);
error = q2cursor_check(cursor);
@@ -1072,7 +1072,6 @@ quota2_handle_cmd_getall(struct ufsmount
return ENODEV;
}
- maxreturn = result->qr_max;
numreturn = 0;
mutex_enter(&dqlock);
@@ -1085,19 +1084,19 @@ quota2_handle_cmd_getall(struct ufsmount
if (cursor->q2c_defaults_done == 0) {
quota2_ufs_rwq2e(&q2h->q2h_defentry, &q2e, needswap);
if (cursor->q2c_blocks_done == 0) {
- q2e_to_quotaval(&q2e, 1, &junkid, QL_BLOCK, &bval);
- bkey.qk_idtype = idtype;
- bkey.qk_id = QUOTA_DEFAULTID;
- bkey.qk_objtype = QUOTA_OBJTYPE_BLOCKS;
- dobval = 1;
+ q2e_to_quotaval(&q2e, 1, &junkid, QL_BLOCK, &qv);
+ keys[numreturn].qk_idtype = idtype;
+ keys[numreturn].qk_id = QUOTA_DEFAULTID;
+ keys[numreturn].qk_objtype = QUOTA_OBJTYPE_BLOCKS;
+ vals[numreturn++] = qv;
cursor->q2c_blocks_done = 1;
}
if (cursor->q2c_blocks_done == 1) {
- q2e_to_quotaval(&q2e, 1, &junkid, QL_FILE, &fval);
- fkey.qk_idtype = idtype;
- fkey.qk_id = QUOTA_DEFAULTID;
- fkey.qk_objtype = QUOTA_OBJTYPE_FILES;
- dofval = 1;
+ q2e_to_quotaval(&q2e, 1, &junkid, QL_FILE, &qv);
+ keys[numreturn].qk_idtype = idtype;
+ keys[numreturn].qk_id = QUOTA_DEFAULTID;
+ keys[numreturn].qk_objtype = QUOTA_OBJTYPE_FILES;
+ vals[numreturn++] = qv;
cursor->q2c_blocks_done = 0;
cursor->q2c_defaults_done = 1;
}
@@ -1126,26 +1125,31 @@ quota2_handle_cmd_getall(struct ufsmount
if (gu.limit == 0 && (maxreturn - numreturn) > 0) {
gu.limit = 1;
}
- if (dobval && gu.limit > 0)
- gu.limit--;
- if (dofval && gu.limit > 0)
- gu.limit--;
for (i = cursor->q2c_hashpos; i < quota2_hash_size ; i++) {
offset = q2h->q2h_entries[i];
gu.seen = 0;
error = quota2_walk_list(ump, hbp, idtype, &offset, 0, &gu,
quota2_getuids_callback);
+ if (error && error != Q2WL_ABORT) {
+ if (gu.uids != NULL)
+ free(gu.uids, M_TEMP);
+ break;
+ }
if (error == Q2WL_ABORT) {
/* got enough uids for now */
error = 0;
- break;
}
- if (error) {
- if (gu.uids != NULL)
- free(gu.uids, M_TEMP);
+ if (gu.nuids > gu.limit) {
+ excess = gu.nuids - gu.limit;
+ KASSERT(excess < gu.seen);
+ gu.seen -= excess;
+ gu.nuids -= excess;
+ }
+ if (gu.nuids == gu.limit) {
break;
}
}
+ KASSERT(gu.nuids <= gu.limit);
cursor->q2c_hashpos = i;
cursor->q2c_uidpos = gu.seen;
@@ -1156,28 +1160,6 @@ fail:
return error;
maxnum = gu.nuids*2;
- if (dobval)
- maxnum++;
- if (dofval)
- maxnum++;
- 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);
-
- if (dobval && numreturn < maxreturn) {
- result->qr_keys[numreturn] = bkey;
- result->qr_vals[numreturn] = bval;
- numreturn++;
- }
- if (dofval && numreturn < maxreturn) {
- result->qr_keys[numreturn] = fkey;
- result->qr_vals[numreturn] = fval;
- numreturn++;
- }
- if (numreturn == maxreturn) {
- return 0;
- }
/*
* If we've already sent back the blocks value for the first id,
@@ -1188,11 +1170,11 @@ fail:
* leave off the last result entry (skiplast).
*/
skipfirst = (cursor->q2c_blocks_done != 0);
- skiplast = skipfirst == 0 && (result->qr_max < maxnum);
+ skiplast = skipfirst == 0 && (maxreturn < maxnum);
num = 0;
for (j = 0; j < gu.nuids; j++) {
error = quota2_result_add_q2e(ump, idtype,
- gu.uids[j], result, numreturn + j*2,
+ gu.uids[j], keys, vals, numreturn + j*2,
j == 0 && skipfirst,
j + 1 == gu.nuids && skiplast);
if (error == ENOENT)
@@ -1206,11 +1188,12 @@ fail:
}
}
numreturn += num;
- result->qr_num = numreturn;
+ *ret = numreturn;
cursor->q2c_blocks_done = skiplast;
- free(gu.uids, M_TEMP);
+ if (gu.uids != NULL)
+ free(gu.uids, M_TEMP);
return error;
}