Module Name: src
Committed By: dholland
Date: Sun Jan 29 07:10:25 UTC 2012
Modified Files:
src/sys/kern: vfs_quotactl.c
Log Message:
Use QUOTACTL_CURSORSKIPIDTYPE and QUOTACTL_CURSORATEND in
vfs_quotactl. Have it restart from the beginning if it receives
EDEADLK, which requires QUOTACTL_CURSORREWIND.
To generate a diff of this commit:
cvs rdiff -u -r1.29 -r1.30 src/sys/kern/vfs_quotactl.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.29 src/sys/kern/vfs_quotactl.c:1.30
--- src/sys/kern/vfs_quotactl.c:1.29 Sun Jan 29 07:09:52 2012
+++ src/sys/kern/vfs_quotactl.c Sun Jan 29 07:10:24 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: vfs_quotactl.c,v 1.29 2012/01/29 07:09:52 dholland Exp $ */
+/* $NetBSD: vfs_quotactl.c,v 1.30 2012/01/29 07:10:24 dholland Exp $ */
/*
* Copyright (c) 1991, 1993, 1994
@@ -80,7 +80,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_quotactl.c,v 1.29 2012/01/29 07:09:52 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_quotactl.c,v 1.30 2012/01/29 07:10:24 dholland Exp $");
#include <sys/malloc.h> /* XXX: temporary */
#include <sys/mount.h>
@@ -529,8 +529,10 @@ vfs_quotactl_getall(struct mount *mp,
struct quotaval *vals;
unsigned loopmax = 8;
unsigned loopnum;
+ int skipidtype;
struct vfs_quotactl_args args;
prop_array_t replies;
+ int atend, atzero;
struct quotakey *key;
struct quotaval *val;
id_t lastid;
@@ -550,6 +552,15 @@ vfs_quotactl_getall(struct mount *mp,
keys = malloc(loopmax * sizeof(keys[0]), M_TEMP, M_WAITOK);
vals = malloc(loopmax * sizeof(vals[0]), M_TEMP, M_WAITOK);
+ skipidtype = (q2type == QUOTA_IDTYPE_USER ?
+ QUOTA_IDTYPE_GROUP : QUOTA_IDTYPE_USER);
+ args.qc_type = QCT_CURSORSKIPIDTYPE;
+ args.u.cursorskipidtype.qc_cursor = &cursor;
+ args.u.cursorskipidtype.qc_idtype = skipidtype;
+ error = VFS_QUOTACTL(mp, QUOTACTL_CURSORSKIPIDTYPE, &args);
+ /* ignore if it fails */
+ (void)error;
+
replies = prop_array_create();
if (replies == NULL) {
error = ENOMEM;
@@ -558,8 +569,20 @@ vfs_quotactl_getall(struct mount *mp,
thisreply = NULL;
lastid = 0; /* value not actually referenced */
+ atzero = 0;
while (1) {
+ args.qc_type = QCT_CURSORATEND;
+ args.u.cursoratend.qc_cursor = &cursor;
+ args.u.cursoratend.qc_ret = &atend;
+ error = VFS_QUOTACTL(mp, QUOTACTL_CURSORATEND, &args);
+ if (error) {
+ goto err;
+ }
+ if (atend) {
+ break;
+ }
+
args.qc_type = QCT_CURSORGET;
args.u.cursorget.qc_cursor = &cursor;
args.u.cursorget.qc_keys = keys;
@@ -568,13 +591,58 @@ vfs_quotactl_getall(struct mount *mp,
args.u.cursorget.qc_ret = &loopnum;
error = VFS_QUOTACTL(mp, QUOTACTL_CURSORGET, &args);
+ if (error == EDEADLK) {
+ /*
+ * transaction abort, start over
+ */
+
+ args.qc_type = QCT_CURSORREWIND;
+ args.u.cursorrewind.qc_cursor = &cursor;
+ error = VFS_QUOTACTL(mp, QUOTACTL_CURSORREWIND, &args);
+ if (error) {
+ goto err;
+ }
+
+ args.qc_type = QCT_CURSORSKIPIDTYPE;
+ args.u.cursorskipidtype.qc_cursor = &cursor;
+ args.u.cursorskipidtype.qc_idtype = skipidtype;
+ error = VFS_QUOTACTL(mp, QUOTACTL_CURSORSKIPIDTYPE,
+ &args);
+ /* ignore if it fails */
+ (void)error;
+
+ prop_object_release(replies);
+ replies = prop_array_create();
+ if (replies == NULL) {
+ error = ENOMEM;
+ goto err;
+ }
+
+ thisreply = NULL;
+ lastid = 0;
+ atzero = 0;
+
+ continue;
+ }
if (error) {
goto err;
}
if (loopnum == 0) {
- /* end of iteration */
- break;
+ /*
+ * This is not supposed to happen. However,
+ * allow a return of zero items once as long
+ * as something happens (including an atend
+ * indication) on the next pass. If it happens
+ * twice, warn and assume end of iteration.
+ */
+ if (atzero) {
+ printf("vfs_quotactl: zero items returned\n");
+ break;
+ }
+ atzero = 1;
+ } else {
+ atzero = 0;
}
for (i = 0; i < loopnum; i++) {
@@ -616,15 +684,21 @@ vfs_quotactl_getall(struct mount *mp,
}
if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) {
+ replies = NULL;
error = ENOMEM;
goto err;
}
-
+ replies = NULL;
error = 0;
+
err:
free(keys, M_TEMP);
free(vals, M_TEMP);
+ if (replies != NULL) {
+ prop_object_release(replies);
+ }
+
args.qc_type = QCT_CURSORCLOSE;
args.u.cursorclose.qc_cursor = &cursor;
error2 = VFS_QUOTACTL(mp, QUOTACTL_CURSORCLOSE, &args);