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