[PATCH] zfs prefetch patch

Martin Matuska mm at FreeBSD.org
Fri Aug 12 14:29:04 UTC 2011


Please review my attached patch, I have decided to go for the minimalistic version for 9.0-RELEASE.

Since upgrade to zfs v28 I have been experiencing temporary clones left over (not deleted) by incremental zfs receive. This made
the parent snapshots undeletable. This has been also reported by several users in mailing lists.
I have investigated this issue, and the cause is a race between dmu_objset_prefetch() invoked from zfs_ioc_dataset_list_next()
and dsl_dir_destroy_check() indirectly invoked from dmu_recv_existing_end() via dsl_dataset_destroy().

In addition, the calling of dmu_objset_prefetch() from with internal datasets, temporary clones and invisible datasets is useless
as it either fails (internal datsets) or we are not going to process these datasets later (they are skipped in the following code).

Last, fix calling of dmu_objset_prefetch() from zvol_create_minors() by using absolute instead of relative dataset name.

PR: kern/157728 (reported on Jun 9, 2011)

Filed as Illumos bug #1346
https://www.illumos.org/issues/1346

Thank you very much.

-- 
Martin Matuska
FreeBSD committer
http://blog.vx.sk

-------------- next part --------------
Index: zfs_ioctl.c
===================================================================
--- zfs_ioctl.c	(revision 224794)
+++ zfs_ioctl.c	(working copy)
@@ -1964,7 +1964,8 @@ zfs_ioc_dataset_list_next(zfs_cmd_t *zc)
 		int len = sizeof (zc->zc_name) - (p - zc->zc_name);
 
 		while (dmu_dir_list_next(os, len, p, NULL, &cookie) == 0)
-			(void) dmu_objset_prefetch(zc->zc_name, NULL);
+			if (dataset_name_hidden(zc->zc_name) == B_FALSE)
+				(void) dmu_objset_prefetch(zc->zc_name, NULL);
 	}
 
 	do {
Index: zvol.c
===================================================================
--- zvol.c	(revision 224794)
+++ zvol.c	(working copy)
@@ -2197,12 +2197,9 @@ zvol_create_minors(const char *name)
 	p = osname + strlen(osname);
 	len = MAXPATHLEN - (p - osname);
 
-	if (strchr(name, '/') == NULL) {
-		/* Prefetch only for pool name. */
-		cookie = 0;
-		while (dmu_dir_list_next(os, len, p, NULL, &cookie) == 0)
-			(void) dmu_objset_prefetch(p, NULL);
-	}
+	/* Prefetch only for pool name. */
+	if (strchr(name, '/') == NULL)
+		(void) dmu_objset_prefetch(name, NULL);
 
 	cookie = 0;
 	while (dmu_dir_list_next(os, MAXPATHLEN - (p - osname), p, NULL,
-------------- next part --------------
Fix race between dmu_objset_prefetch() invoked from
zfs_ioc_dataset_list_next() and dsl_dir_destroy_check() indirectly
invoked from dmu_recv_existing_end() via dsl_dataset_destroy() by not
prefetching temporary clones, as these count as always inconsistent.
In addition, do not prefetch hidden datasets at all as we are not
going to process these later. [1]

Fix calling of dmu_objset_prefetch() from zvol_create_minors()
by using absolute instead of relative dataset name.

Filed as Illumos Bug 1346 [1]

PR:				kern/157728 [1]
Tested by:		Borja Marcos <borjam at sarenet.es> [1], mm
Approved by:	re ()
MFC after:		1 week 


More information about the zfs-devel mailing list