changeset 10951:56fd5475e8fe

6896756 assertion failed: 0 == dsl_pool_user_hold(dp, ds->ds_object, htag, &now, tx) 6897005 zfs holds broken on 32-bit i86pc
author Chris Kirby <Chris.Kirby@sun.com>
date Wed, 04 Nov 2009 09:10:12 -0700
parents 588ee15c1f19
children b08b5e896bbd
files usr/src/lib/libzfs/common/libzfs_dataset.c usr/src/uts/common/fs/zfs/dsl_dataset.c usr/src/uts/common/fs/zfs/dsl_pool.c usr/src/uts/common/fs/zfs/sys/dsl_pool.h
diffstat 4 files changed, 24 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/lib/libzfs/common/libzfs_dataset.c	Wed Nov 04 07:57:07 2009 -0700
+++ b/usr/src/lib/libzfs/common/libzfs_dataset.c	Wed Nov 04 09:10:12 2009 -0700
@@ -3714,6 +3714,14 @@
 		(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
 		    "cannot hold '%s@%s'"), zc.zc_name, snapname);
 		switch (errno) {
+		case E2BIG:
+			/*
+			 * Temporary tags wind up having the ds object id
+			 * prepended. So even if we passed the length check
+			 * above, it's still possible for the tag to wind
+			 * up being slightly too long.
+			 */
+			return (zfs_error(hdl, EZFS_TAGTOOLONG, errbuf));
 		case ENOTSUP:
 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 			    "pool must be upgraded"));
--- a/usr/src/uts/common/fs/zfs/dsl_dataset.c	Wed Nov 04 07:57:07 2009 -0700
+++ b/usr/src/uts/common/fs/zfs/dsl_dataset.c	Wed Nov 04 09:10:12 2009 -0700
@@ -3239,6 +3239,12 @@
 	char failed[MAXPATHLEN];
 };
 
+/*
+ * The max length of a temporary tag prefix is the number of hex digits
+ * required to express UINT64_MAX plus one for the hyphen.
+ */
+#define	MAX_TAG_PREFIX_LEN	17
+
 static int
 dsl_dataset_user_hold_check(void *arg1, void *arg2, dmu_tx_t *tx)
 {
@@ -3266,6 +3272,10 @@
 	}
 	mutex_exit(&ds->ds_lock);
 
+	if (error == 0 && ha->temphold &&
+	    strlen(htag) + MAX_TAG_PREFIX_LEN >= MAXNAMELEN)
+		error = E2BIG;
+
 	return (error);
 }
 
@@ -3277,7 +3287,7 @@
 	char *htag = ha->htag;
 	dsl_pool_t *dp = ds->ds_dir->dd_pool;
 	objset_t *mos = dp->dp_meta_objset;
-	time_t now = gethrestime_sec();
+	uint64_t now = gethrestime_sec();
 	uint64_t zapobj;
 
 	mutex_enter(&ds->ds_lock);
--- a/usr/src/uts/common/fs/zfs/dsl_pool.c	Wed Nov 04 07:57:07 2009 -0700
+++ b/usr/src/uts/common/fs/zfs/dsl_pool.c	Wed Nov 04 09:10:12 2009 -0700
@@ -722,7 +722,7 @@
 
 static int
 dsl_pool_user_hold_rele_impl(dsl_pool_t *dp, uint64_t dsobj,
-    const char *tag, time_t *t, dmu_tx_t *tx, boolean_t holding)
+    const char *tag, uint64_t *now, dmu_tx_t *tx, boolean_t holding)
 {
 	objset_t *mos = dp->dp_meta_objset;
 	uint64_t zapobj = dp->dp_tmp_userrefs_obj;
@@ -747,7 +747,7 @@
 
 	name = kmem_asprintf("%llx-%s", (u_longlong_t)dsobj, tag);
 	if (holding)
-		error = zap_add(mos, zapobj, name, 8, 1, t, tx);
+		error = zap_add(mos, zapobj, name, 8, 1, now, tx);
 	else
 		error = zap_remove(mos, zapobj, name, tx);
 	strfree(name);
@@ -760,9 +760,9 @@
  */
 int
 dsl_pool_user_hold(dsl_pool_t *dp, uint64_t dsobj, const char *tag,
-    time_t *t, dmu_tx_t *tx)
+    uint64_t *now, dmu_tx_t *tx)
 {
-	return (dsl_pool_user_hold_rele_impl(dp, dsobj, tag, t, tx, B_TRUE));
+	return (dsl_pool_user_hold_rele_impl(dp, dsobj, tag, now, tx, B_TRUE));
 }
 
 /*
--- a/usr/src/uts/common/fs/zfs/sys/dsl_pool.h	Wed Nov 04 07:57:07 2009 -0700
+++ b/usr/src/uts/common/fs/zfs/sys/dsl_pool.h	Wed Nov 04 09:10:12 2009 -0700
@@ -149,7 +149,7 @@
 taskq_t *dsl_pool_vnrele_taskq(dsl_pool_t *dp);
 
 extern int dsl_pool_user_hold(dsl_pool_t *dp, uint64_t dsobj,
-    const char *tag, time_t *t, dmu_tx_t *tx);
+    const char *tag, uint64_t *now, dmu_tx_t *tx);
 extern int dsl_pool_user_release(dsl_pool_t *dp, uint64_t dsobj,
     const char *tag, dmu_tx_t *tx);
 extern void dsl_pool_clean_tmp_userrefs(dsl_pool_t *dp);