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

Reply via email to