diff usr/src/uts/common/fs/zfs/dsl_dataset.c @ 12527:693dd2cad55f

6884007 zfs_send() can leave temporary holds around 6954429 ZFS_IOC_VDEV_SPLIT missing from truss/codes.c
author Chris Kirby <Chris.Kirby@oracle.com>
date Tue, 01 Jun 2010 17:04:42 -0600
parents 54258108784b
children 16aef3d16470
line wrap: on
line diff
--- a/usr/src/uts/common/fs/zfs/dsl_dataset.c	Tue Jun 01 17:33:59 2010 -0400
+++ b/usr/src/uts/common/fs/zfs/dsl_dataset.c	Tue Jun 01 17:04:42 2010 -0600
@@ -37,6 +37,7 @@
 #include <sys/zfs_ioctl.h>
 #include <sys/spa.h>
 #include <sys/zfs_znode.h>
+#include <sys/zfs_onexit.h>
 #include <sys/zvol.h>
 #include <sys/dsl_scan.h>
 #include <sys/dsl_deadlist.h>
@@ -3421,6 +3422,23 @@
 	char failed[MAXPATHLEN];
 };
 
+typedef struct zfs_hold_cleanup_arg {
+	char dsname[MAXNAMELEN];
+	char snapname[MAXNAMELEN];
+	char htag[MAXNAMELEN];
+	boolean_t recursive;
+} zfs_hold_cleanup_arg_t;
+
+static void
+dsl_dataset_user_release_onexit(void *arg)
+{
+	zfs_hold_cleanup_arg_t *ca = arg;
+
+	(void) dsl_dataset_user_release(ca->dsname, ca->snapname,
+	    ca->htag, ca->recursive);
+	kmem_free(ca, sizeof (zfs_hold_cleanup_arg_t));
+}
+
 /*
  * The max length of a temporary tag prefix is the number of hex digits
  * required to express UINT64_MAX plus one for the hyphen.
@@ -3525,7 +3543,7 @@
 
 int
 dsl_dataset_user_hold(char *dsname, char *snapname, char *htag,
-    boolean_t recursive, boolean_t temphold)
+    boolean_t recursive, boolean_t temphold, int cleanup_fd)
 {
 	struct dsl_ds_holdarg *ha;
 	dsl_sync_task_t *dst;
@@ -3547,6 +3565,7 @@
 	ha->snapname = snapname;
 	ha->recursive = recursive;
 	ha->temphold = temphold;
+
 	if (recursive) {
 		error = dmu_objset_find(dsname, dsl_dataset_user_hold_one,
 		    ha, DS_FIND_CHILDREN);
@@ -3574,6 +3593,24 @@
 		(void) strlcpy(dsname, ha->failed, sizeof (ha->failed));
 
 	dsl_sync_task_group_destroy(ha->dstg);
+
+	/*
+	 * If this set of temporary holds is to be removed upon process exit,
+	 * register that action now.
+	 */
+	if (error == 0 && cleanup_fd != -1 && temphold) {
+		zfs_hold_cleanup_arg_t *ca;
+		uint64_t action_handle;
+
+		ca = kmem_alloc(sizeof (zfs_hold_cleanup_arg_t), KM_SLEEP);
+		(void) strlcpy(ca->dsname, dsname, sizeof (ca->dsname));
+		(void) strlcpy(ca->snapname, snapname, sizeof (ca->snapname));
+		(void) strlcpy(ca->htag, htag, sizeof (ca->htag));
+		ca->recursive = recursive;
+		ASSERT3U(0, ==, zfs_onexit_add_cb(cleanup_fd,
+		    dsl_dataset_user_release_onexit, ca, &action_handle));
+	}
+
 	kmem_free(ha, sizeof (struct dsl_ds_holdarg));
 	spa_close(spa, FTAG);
 	return (error);