usr/src/uts/common/fs/zfs/dsl_dataset.c
changeset 10242 c40d075fbca6
parent 10204 83c3a84aecef
child 10268 cb380b2e9410
equal deleted inserted replaced
10241:356a64b58ebc 10242:c40d075fbca6
    37 #include <sys/zfs_context.h>
    37 #include <sys/zfs_context.h>
    38 #include <sys/zfs_ioctl.h>
    38 #include <sys/zfs_ioctl.h>
    39 #include <sys/spa.h>
    39 #include <sys/spa.h>
    40 #include <sys/zfs_znode.h>
    40 #include <sys/zfs_znode.h>
    41 #include <sys/sunddi.h>
    41 #include <sys/sunddi.h>
       
    42 #include <sys/zvol.h>
    42 
    43 
    43 static char *dsl_reaper = "the grim reaper";
    44 static char *dsl_reaper = "the grim reaper";
    44 
    45 
    45 static dsl_checkfunc_t dsl_dataset_destroy_begin_check;
    46 static dsl_checkfunc_t dsl_dataset_destroy_begin_check;
    46 static dsl_syncfunc_t dsl_dataset_destroy_begin_sync;
    47 static dsl_syncfunc_t dsl_dataset_destroy_begin_sync;
   407 					ds->ds_origin_txg =
   408 					ds->ds_origin_txg =
   408 					    origin->ds_phys->ds_creation_txg;
   409 					    origin->ds_phys->ds_creation_txg;
   409 					dsl_dataset_rele(origin, FTAG);
   410 					dsl_dataset_rele(origin, FTAG);
   410 				}
   411 				}
   411 			}
   412 			}
   412 		} else if (zfs_flags & ZFS_DEBUG_SNAPNAMES) {
   413 		} else {
   413 			err = dsl_dataset_get_snapname(ds);
   414 			if (zfs_flags & ZFS_DEBUG_SNAPNAMES)
       
   415 				err = dsl_dataset_get_snapname(ds);
       
   416 			if (err == 0 && ds->ds_phys->ds_userrefs_obj != 0) {
       
   417 				err = zap_count(
       
   418 				    ds->ds_dir->dd_pool->dp_meta_objset,
       
   419 				    ds->ds_phys->ds_userrefs_obj,
       
   420 				    &ds->ds_userrefs);
       
   421 			}
   414 		}
   422 		}
   415 
   423 
   416 		if (err == 0 && !dsl_dataset_is_snapshot(ds)) {
   424 		if (err == 0 && !dsl_dataset_is_snapshot(ds)) {
   417 			/*
   425 			/*
   418 			 * In sync context, we're called with either no lock
   426 			 * In sync context, we're called with either no lock
   847 
   855 
   848 struct destroyarg {
   856 struct destroyarg {
   849 	dsl_sync_task_group_t *dstg;
   857 	dsl_sync_task_group_t *dstg;
   850 	char *snapname;
   858 	char *snapname;
   851 	char *failed;
   859 	char *failed;
       
   860 	boolean_t defer;
   852 };
   861 };
   853 
   862 
   854 static int
   863 static int
   855 dsl_snapshot_destroy_one(char *name, void *arg)
   864 dsl_snapshot_destroy_one(char *name, void *arg)
   856 {
   865 {
   857 	struct destroyarg *da = arg;
   866 	struct destroyarg *da = arg;
   858 	dsl_dataset_t *ds;
   867 	dsl_dataset_t *ds;
   859 	char *cp;
       
   860 	int err;
   868 	int err;
   861 
   869 	char *dsname;
   862 	(void) strcat(name, "@");
   870 	size_t buflen;
   863 	(void) strcat(name, da->snapname);
   871 
   864 	err = dsl_dataset_own(name, DS_MODE_READONLY | DS_MODE_INCONSISTENT,
   872 	/* alloc a buffer to hold name@snapname, plus the terminating NULL */
       
   873 	buflen = strlen(name) + strlen(da->snapname) + 2;
       
   874 	dsname = kmem_alloc(buflen, KM_SLEEP);
       
   875 	(void) snprintf(dsname, buflen, "%s@%s", name, da->snapname);
       
   876 	err = dsl_dataset_own(dsname, DS_MODE_READONLY | DS_MODE_INCONSISTENT,
   865 	    da->dstg, &ds);
   877 	    da->dstg, &ds);
   866 	cp = strchr(name, '@');
   878 	kmem_free(dsname, buflen);
   867 	*cp = '\0';
       
   868 	if (err == 0) {
   879 	if (err == 0) {
       
   880 		struct dsl_ds_destroyarg *dsda;
       
   881 
   869 		dsl_dataset_make_exclusive(ds, da->dstg);
   882 		dsl_dataset_make_exclusive(ds, da->dstg);
   870 		if (ds->ds_user_ptr) {
   883 		if (ds->ds_user_ptr) {
   871 			ds->ds_user_evict_func(ds, ds->ds_user_ptr);
   884 			ds->ds_user_evict_func(ds, ds->ds_user_ptr);
   872 			ds->ds_user_ptr = NULL;
   885 			ds->ds_user_ptr = NULL;
   873 		}
   886 		}
       
   887 		dsda = kmem_zalloc(sizeof (struct dsl_ds_destroyarg), KM_SLEEP);
       
   888 		dsda->ds = ds;
       
   889 		dsda->defer = da->defer;
   874 		dsl_sync_task_create(da->dstg, dsl_dataset_destroy_check,
   890 		dsl_sync_task_create(da->dstg, dsl_dataset_destroy_check,
   875 		    dsl_dataset_destroy_sync, ds, da->dstg, 0);
   891 		    dsl_dataset_destroy_sync, dsda, da->dstg, 0);
   876 	} else if (err == ENOENT) {
   892 	} else if (err == ENOENT) {
   877 		err = 0;
   893 		err = 0;
   878 	} else {
   894 	} else {
   879 		(void) strcpy(da->failed, name);
   895 		(void) strcpy(da->failed, name);
   880 	}
   896 	}
   884 /*
   900 /*
   885  * Destroy 'snapname' in all descendants of 'fsname'.
   901  * Destroy 'snapname' in all descendants of 'fsname'.
   886  */
   902  */
   887 #pragma weak dmu_snapshots_destroy = dsl_snapshots_destroy
   903 #pragma weak dmu_snapshots_destroy = dsl_snapshots_destroy
   888 int
   904 int
   889 dsl_snapshots_destroy(char *fsname, char *snapname)
   905 dsl_snapshots_destroy(char *fsname, char *snapname, boolean_t defer)
   890 {
   906 {
   891 	int err;
   907 	int err;
   892 	struct destroyarg da;
   908 	struct destroyarg da;
   893 	dsl_sync_task_t *dst;
   909 	dsl_sync_task_t *dst;
   894 	spa_t *spa;
   910 	spa_t *spa;
   897 	if (err)
   913 	if (err)
   898 		return (err);
   914 		return (err);
   899 	da.dstg = dsl_sync_task_group_create(spa_get_dsl(spa));
   915 	da.dstg = dsl_sync_task_group_create(spa_get_dsl(spa));
   900 	da.snapname = snapname;
   916 	da.snapname = snapname;
   901 	da.failed = fsname;
   917 	da.failed = fsname;
       
   918 	da.defer = defer;
   902 
   919 
   903 	err = dmu_objset_find(fsname,
   920 	err = dmu_objset_find(fsname,
   904 	    dsl_snapshot_destroy_one, &da, DS_FIND_CHILDREN);
   921 	    dsl_snapshot_destroy_one, &da, DS_FIND_CHILDREN);
   905 
   922 
   906 	if (err == 0)
   923 	if (err == 0)
   907 		err = dsl_sync_task_group_wait(da.dstg);
   924 		err = dsl_sync_task_group_wait(da.dstg);
   908 
   925 
   909 	for (dst = list_head(&da.dstg->dstg_tasks); dst;
   926 	for (dst = list_head(&da.dstg->dstg_tasks); dst;
   910 	    dst = list_next(&da.dstg->dstg_tasks, dst)) {
   927 	    dst = list_next(&da.dstg->dstg_tasks, dst)) {
   911 		dsl_dataset_t *ds = dst->dst_arg1;
   928 		struct dsl_ds_destroyarg *dsda = dst->dst_arg1;
       
   929 		dsl_dataset_t *ds = dsda->ds;
       
   930 
   912 		/*
   931 		/*
   913 		 * Return the file system name that triggered the error
   932 		 * Return the file system name that triggered the error
   914 		 */
   933 		 */
   915 		if (dst->dst_err) {
   934 		if (dst->dst_err) {
   916 			dsl_dataset_name(ds, fsname);
   935 			dsl_dataset_name(ds, fsname);
   917 			*strchr(fsname, '@') = '\0';
   936 			*strchr(fsname, '@') = '\0';
   918 		}
   937 		}
       
   938 		ASSERT3P(dsda->rm_origin, ==, NULL);
   919 		dsl_dataset_disown(ds, da.dstg);
   939 		dsl_dataset_disown(ds, da.dstg);
       
   940 		kmem_free(dsda, sizeof (struct dsl_ds_destroyarg));
   920 	}
   941 	}
   921 
   942 
   922 	dsl_sync_task_group_destroy(da.dstg);
   943 	dsl_sync_task_group_destroy(da.dstg);
   923 	spa_close(spa, FTAG);
   944 	spa_close(spa, FTAG);
   924 	return (err);
   945 	return (err);
       
   946 }
       
   947 
       
   948 static boolean_t
       
   949 dsl_dataset_might_destroy_origin(dsl_dataset_t *ds)
       
   950 {
       
   951 	boolean_t might_destroy = B_FALSE;
       
   952 
       
   953 	mutex_enter(&ds->ds_lock);
       
   954 	if (ds->ds_phys->ds_num_children == 2 && ds->ds_userrefs == 0 &&
       
   955 	    DS_IS_DEFER_DESTROY(ds))
       
   956 		might_destroy = B_TRUE;
       
   957 	mutex_exit(&ds->ds_lock);
       
   958 
       
   959 	return (might_destroy);
       
   960 }
       
   961 
       
   962 #ifdef _KERNEL
       
   963 static int
       
   964 dsl_dataset_zvol_cleanup(dsl_dataset_t *ds, const char *name)
       
   965 {
       
   966 	int error;
       
   967 	objset_t *os;
       
   968 
       
   969 	error = dmu_objset_open_ds(ds, DMU_OST_ANY, &os);
       
   970 	if (error)
       
   971 		return (error);
       
   972 
       
   973 	if (dmu_objset_type(os) == DMU_OST_ZVOL)
       
   974 		error = zvol_remove_minor(name);
       
   975 	dmu_objset_close(os);
       
   976 
       
   977 	return (error);
       
   978 }
       
   979 #endif
       
   980 
       
   981 /*
       
   982  * If we're removing a clone, and these three conditions are true:
       
   983  *	1) the clone's origin has no other children
       
   984  *	2) the clone's origin has no user references
       
   985  *	3) the clone's origin has been marked for deferred destruction
       
   986  * Then, prepare to remove the origin as part of this sync task group.
       
   987  */
       
   988 static int
       
   989 dsl_dataset_origin_rm_prep(struct dsl_ds_destroyarg *dsda, void *tag)
       
   990 {
       
   991 	dsl_dataset_t *ds = dsda->ds;
       
   992 	dsl_dataset_t *origin = ds->ds_prev;
       
   993 
       
   994 	if (dsl_dataset_might_destroy_origin(origin)) {
       
   995 		char *name;
       
   996 		int namelen;
       
   997 		int error;
       
   998 
       
   999 		namelen = dsl_dataset_namelen(origin) + 1;
       
  1000 		name = kmem_alloc(namelen, KM_SLEEP);
       
  1001 		dsl_dataset_name(origin, name);
       
  1002 #ifdef _KERNEL
       
  1003 		error = zfs_unmount_snap(name, NULL);
       
  1004 		if (error) {
       
  1005 			kmem_free(name, namelen);
       
  1006 			return (error);
       
  1007 		}
       
  1008 		error = dsl_dataset_zvol_cleanup(origin, name);
       
  1009 		if (error) {
       
  1010 			kmem_free(name, namelen);
       
  1011 			return (error);
       
  1012 		}
       
  1013 #endif
       
  1014 		error = dsl_dataset_own(name,
       
  1015 		    DS_MODE_READONLY | DS_MODE_INCONSISTENT,
       
  1016 		    tag, &origin);
       
  1017 		kmem_free(name, namelen);
       
  1018 		if (error)
       
  1019 			return (error);
       
  1020 		dsda->rm_origin = origin;
       
  1021 		dsl_dataset_make_exclusive(origin, tag);
       
  1022 	}
       
  1023 
       
  1024 	return (0);
   925 }
  1025 }
   926 
  1026 
   927 /*
  1027 /*
   928  * ds must be opened as OWNER.  On return (whether successful or not),
  1028  * ds must be opened as OWNER.  On return (whether successful or not),
   929  * ds will be closed and caller can no longer dereference it.
  1029  * ds will be closed and caller can no longer dereference it.
   930  */
  1030  */
   931 int
  1031 int
   932 dsl_dataset_destroy(dsl_dataset_t *ds, void *tag)
  1032 dsl_dataset_destroy(dsl_dataset_t *ds, void *tag, boolean_t defer)
   933 {
  1033 {
   934 	int err;
  1034 	int err;
   935 	dsl_sync_task_group_t *dstg;
  1035 	dsl_sync_task_group_t *dstg;
   936 	objset_t *os;
  1036 	objset_t *os;
   937 	dsl_dir_t *dd;
  1037 	dsl_dir_t *dd;
   938 	uint64_t obj;
  1038 	uint64_t obj;
       
  1039 	struct dsl_ds_destroyarg dsda = {0};
       
  1040 
       
  1041 	dsda.ds = ds;
   939 
  1042 
   940 	if (dsl_dataset_is_snapshot(ds)) {
  1043 	if (dsl_dataset_is_snapshot(ds)) {
   941 		/* Destroying a snapshot is simpler */
  1044 		/* Destroying a snapshot is simpler */
   942 		dsl_dataset_make_exclusive(ds, tag);
  1045 		dsl_dataset_make_exclusive(ds, tag);
   943 
  1046 
   944 		if (ds->ds_user_ptr) {
  1047 		if (ds->ds_user_ptr) {
   945 			ds->ds_user_evict_func(ds, ds->ds_user_ptr);
  1048 			ds->ds_user_evict_func(ds, ds->ds_user_ptr);
   946 			ds->ds_user_ptr = NULL;
  1049 			ds->ds_user_ptr = NULL;
   947 		}
  1050 		}
       
  1051 		/* NOTE: defer is always B_FALSE for non-snapshots */
       
  1052 		dsda.defer = defer;
   948 		err = dsl_sync_task_do(ds->ds_dir->dd_pool,
  1053 		err = dsl_sync_task_do(ds->ds_dir->dd_pool,
   949 		    dsl_dataset_destroy_check, dsl_dataset_destroy_sync,
  1054 		    dsl_dataset_destroy_check, dsl_dataset_destroy_sync,
   950 		    ds, tag, 0);
  1055 		    &dsda, tag, 0);
       
  1056 		ASSERT3P(dsda.rm_origin, ==, NULL);
   951 		goto out;
  1057 		goto out;
   952 	}
  1058 	}
   953 
  1059 
   954 	dd = ds->ds_dir;
  1060 	dd = ds->ds_dir;
   955 
  1061 
  1026 	dsl_dataset_make_exclusive(ds, tag);
  1132 	dsl_dataset_make_exclusive(ds, tag);
  1027 	if (ds->ds_user_ptr) {
  1133 	if (ds->ds_user_ptr) {
  1028 		ds->ds_user_evict_func(ds, ds->ds_user_ptr);
  1134 		ds->ds_user_evict_func(ds, ds->ds_user_ptr);
  1029 		ds->ds_user_ptr = NULL;
  1135 		ds->ds_user_ptr = NULL;
  1030 	}
  1136 	}
  1031 	dstg = dsl_sync_task_group_create(ds->ds_dir->dd_pool);
  1137 
  1032 	dsl_sync_task_create(dstg, dsl_dataset_destroy_check,
  1138 	/*
  1033 	    dsl_dataset_destroy_sync, ds, tag, 0);
  1139 	 * If we're removing a clone, we might also need to remove its
  1034 	dsl_sync_task_create(dstg, dsl_dir_destroy_check,
  1140 	 * origin.
  1035 	    dsl_dir_destroy_sync, dd, FTAG, 0);
  1141 	 */
  1036 	err = dsl_sync_task_group_wait(dstg);
  1142 	do {
  1037 	dsl_sync_task_group_destroy(dstg);
  1143 		dsda.need_prep = B_FALSE;
       
  1144 		if (dsl_dir_is_clone(dd)) {
       
  1145 			err = dsl_dataset_origin_rm_prep(&dsda, tag);
       
  1146 			if (err) {
       
  1147 				dsl_dir_close(dd, FTAG);
       
  1148 				goto out;
       
  1149 			}
       
  1150 		}
       
  1151 
       
  1152 		dstg = dsl_sync_task_group_create(ds->ds_dir->dd_pool);
       
  1153 		dsl_sync_task_create(dstg, dsl_dataset_destroy_check,
       
  1154 		    dsl_dataset_destroy_sync, &dsda, tag, 0);
       
  1155 		dsl_sync_task_create(dstg, dsl_dir_destroy_check,
       
  1156 		    dsl_dir_destroy_sync, dd, FTAG, 0);
       
  1157 		err = dsl_sync_task_group_wait(dstg);
       
  1158 		dsl_sync_task_group_destroy(dstg);
       
  1159 
       
  1160 		/*
       
  1161 		 * We could be racing against 'zfs release' or 'zfs destroy -d'
       
  1162 		 * on the origin snap, in which case we can get EBUSY if we
       
  1163 		 * needed to destroy the origin snap but were not ready to
       
  1164 		 * do so.
       
  1165 		 */
       
  1166 		if (dsda.need_prep) {
       
  1167 			ASSERT(err == EBUSY);
       
  1168 			ASSERT(dsl_dir_is_clone(dd));
       
  1169 			ASSERT(dsda.rm_origin == NULL);
       
  1170 		}
       
  1171 	} while (dsda.need_prep);
       
  1172 
       
  1173 	if (dsda.rm_origin != NULL)
       
  1174 		dsl_dataset_disown(dsda.rm_origin, tag);
       
  1175 
  1038 	/* if it is successful, dsl_dir_destroy_sync will close the dd */
  1176 	/* if it is successful, dsl_dir_destroy_sync will close the dd */
  1039 	if (err)
  1177 	if (err)
  1040 		dsl_dir_close(dd, FTAG);
  1178 		dsl_dir_close(dd, FTAG);
  1041 out:
  1179 out:
  1042 	dsl_dataset_disown(ds, tag);
  1180 	dsl_dataset_disown(ds, tag);
  1389 
  1527 
  1390 	spa_history_internal_log(LOG_DS_DESTROY_BEGIN, dp->dp_spa, tx,
  1528 	spa_history_internal_log(LOG_DS_DESTROY_BEGIN, dp->dp_spa, tx,
  1391 	    cr, "dataset = %llu", ds->ds_object);
  1529 	    cr, "dataset = %llu", ds->ds_object);
  1392 }
  1530 }
  1393 
  1531 
       
  1532 static int
       
  1533 dsl_dataset_origin_check(struct dsl_ds_destroyarg *dsda, void *tag,
       
  1534     dmu_tx_t *tx)
       
  1535 {
       
  1536 	dsl_dataset_t *ds = dsda->ds;
       
  1537 	dsl_dataset_t *ds_prev = ds->ds_prev;
       
  1538 
       
  1539 	if (dsl_dataset_might_destroy_origin(ds_prev)) {
       
  1540 		struct dsl_ds_destroyarg ndsda = {0};
       
  1541 
       
  1542 		/*
       
  1543 		 * If we're not prepared to remove the origin, don't remove
       
  1544 		 * the clone either.
       
  1545 		 */
       
  1546 		if (dsda->rm_origin == NULL) {
       
  1547 			dsda->need_prep = B_TRUE;
       
  1548 			return (EBUSY);
       
  1549 		}
       
  1550 
       
  1551 		ndsda.ds = ds_prev;
       
  1552 		ndsda.is_origin_rm = B_TRUE;
       
  1553 		return (dsl_dataset_destroy_check(&ndsda, tag, tx));
       
  1554 	}
       
  1555 
       
  1556 	/*
       
  1557 	 * If we're not going to remove the origin after all,
       
  1558 	 * undo the open context setup.
       
  1559 	 */
       
  1560 	if (dsda->rm_origin != NULL) {
       
  1561 		dsl_dataset_disown(dsda->rm_origin, tag);
       
  1562 		dsda->rm_origin = NULL;
       
  1563 	}
       
  1564 
       
  1565 	return (0);
       
  1566 }
       
  1567 
  1394 /* ARGSUSED */
  1568 /* ARGSUSED */
  1395 int
  1569 int
  1396 dsl_dataset_destroy_check(void *arg1, void *arg2, dmu_tx_t *tx)
  1570 dsl_dataset_destroy_check(void *arg1, void *arg2, dmu_tx_t *tx)
  1397 {
  1571 {
  1398 	dsl_dataset_t *ds = arg1;
  1572 	struct dsl_ds_destroyarg *dsda = arg1;
       
  1573 	dsl_dataset_t *ds = dsda->ds;
  1399 
  1574 
  1400 	/* we have an owner hold, so noone else can destroy us */
  1575 	/* we have an owner hold, so noone else can destroy us */
  1401 	ASSERT(!DSL_DATASET_IS_DESTROYED(ds));
  1576 	ASSERT(!DSL_DATASET_IS_DESTROYED(ds));
  1402 
  1577 
  1403 	/* Can't delete a branch point. */
  1578 	/*
  1404 	if (ds->ds_phys->ds_num_children > 1)
  1579 	 * Only allow deferred destroy on pools that support it.
  1405 		return (EEXIST);
  1580 	 * NOTE: deferred destroy is only supported on snapshots.
       
  1581 	 */
       
  1582 	if (dsda->defer) {
       
  1583 		if (spa_version(ds->ds_dir->dd_pool->dp_spa) <
       
  1584 		    SPA_VERSION_USERREFS)
       
  1585 			return (ENOTSUP);
       
  1586 		ASSERT(dsl_dataset_is_snapshot(ds));
       
  1587 		return (0);
       
  1588 	}
  1406 
  1589 
  1407 	/*
  1590 	/*
  1408 	 * Can't delete a head dataset if there are snapshots of it.
  1591 	 * Can't delete a head dataset if there are snapshots of it.
  1409 	 * (Except if the only snapshots are from the branch we cloned
  1592 	 * (Except if the only snapshots are from the branch we cloned
  1410 	 * from.)
  1593 	 * from.)
  1417 	 * If we made changes this txg, traverse_dsl_dataset won't find
  1600 	 * If we made changes this txg, traverse_dsl_dataset won't find
  1418 	 * them.  Try again.
  1601 	 * them.  Try again.
  1419 	 */
  1602 	 */
  1420 	if (ds->ds_phys->ds_bp.blk_birth >= tx->tx_txg)
  1603 	if (ds->ds_phys->ds_bp.blk_birth >= tx->tx_txg)
  1421 		return (EAGAIN);
  1604 		return (EAGAIN);
       
  1605 
       
  1606 	if (dsl_dataset_is_snapshot(ds)) {
       
  1607 		/*
       
  1608 		 * If this snapshot has an elevated user reference count,
       
  1609 		 * we can't destroy it yet.
       
  1610 		 */
       
  1611 		if (ds->ds_userrefs > 0 && !dsda->releasing)
       
  1612 			return (EBUSY);
       
  1613 
       
  1614 		mutex_enter(&ds->ds_lock);
       
  1615 		/*
       
  1616 		 * Can't delete a branch point. However, if we're destroying
       
  1617 		 * a clone and removing its origin due to it having a user
       
  1618 		 * hold count of 0 and having been marked for deferred destroy,
       
  1619 		 * it's OK for the origin to have a single clone.
       
  1620 		 */
       
  1621 		if (ds->ds_phys->ds_num_children >
       
  1622 		    (dsda->is_origin_rm ? 2 : 1)) {
       
  1623 			mutex_exit(&ds->ds_lock);
       
  1624 			return (EEXIST);
       
  1625 		}
       
  1626 		mutex_exit(&ds->ds_lock);
       
  1627 	} else if (dsl_dir_is_clone(ds->ds_dir)) {
       
  1628 		return (dsl_dataset_origin_check(dsda, arg2, tx));
       
  1629 	}
  1422 
  1630 
  1423 	/* XXX we should do some i/o error checking... */
  1631 	/* XXX we should do some i/o error checking... */
  1424 	return (0);
  1632 	return (0);
  1425 }
  1633 }
  1426 
  1634 
  1465 }
  1673 }
  1466 
  1674 
  1467 void
  1675 void
  1468 dsl_dataset_destroy_sync(void *arg1, void *tag, cred_t *cr, dmu_tx_t *tx)
  1676 dsl_dataset_destroy_sync(void *arg1, void *tag, cred_t *cr, dmu_tx_t *tx)
  1469 {
  1677 {
  1470 	dsl_dataset_t *ds = arg1;
  1678 	struct dsl_ds_destroyarg *dsda = arg1;
       
  1679 	dsl_dataset_t *ds = dsda->ds;
  1471 	zio_t *zio;
  1680 	zio_t *zio;
  1472 	int err;
  1681 	int err;
  1473 	int after_branch_point = FALSE;
  1682 	int after_branch_point = FALSE;
  1474 	dsl_pool_t *dp = ds->ds_dir->dd_pool;
  1683 	dsl_pool_t *dp = ds->ds_dir->dd_pool;
  1475 	objset_t *mos = dp->dp_meta_objset;
  1684 	objset_t *mos = dp->dp_meta_objset;
  1476 	dsl_dataset_t *ds_prev = NULL;
  1685 	dsl_dataset_t *ds_prev = NULL;
  1477 	uint64_t obj;
  1686 	uint64_t obj;
  1478 
  1687 
  1479 	ASSERT(ds->ds_owner);
  1688 	ASSERT(ds->ds_owner);
  1480 	ASSERT3U(ds->ds_phys->ds_num_children, <=, 1);
  1689 	ASSERT(dsda->defer || ds->ds_phys->ds_num_children <= 1);
  1481 	ASSERT(ds->ds_prev == NULL ||
  1690 	ASSERT(ds->ds_prev == NULL ||
  1482 	    ds->ds_prev->ds_phys->ds_next_snap_obj != ds->ds_object);
  1691 	    ds->ds_prev->ds_phys->ds_next_snap_obj != ds->ds_object);
  1483 	ASSERT3U(ds->ds_phys->ds_bp.blk_birth, <=, tx->tx_txg);
  1692 	ASSERT3U(ds->ds_phys->ds_bp.blk_birth, <=, tx->tx_txg);
       
  1693 
       
  1694 	if (dsda->defer) {
       
  1695 		ASSERT(spa_version(dp->dp_spa) >= SPA_VERSION_USERREFS);
       
  1696 		if (ds->ds_userrefs > 0 || ds->ds_phys->ds_num_children > 1) {
       
  1697 			dmu_buf_will_dirty(ds->ds_dbuf, tx);
       
  1698 			ds->ds_phys->ds_flags |= DS_FLAG_DEFER_DESTROY;
       
  1699 			return;
       
  1700 		}
       
  1701 	}
  1484 
  1702 
  1485 	/* signal any waiters that this dataset is going away */
  1703 	/* signal any waiters that this dataset is going away */
  1486 	mutex_enter(&ds->ds_lock);
  1704 	mutex_enter(&ds->ds_lock);
  1487 	ds->ds_owner = dsl_reaper;
  1705 	ds->ds_owner = dsl_reaper;
  1488 	cv_broadcast(&ds->ds_exclusive_cv);
  1706 	cv_broadcast(&ds->ds_exclusive_cv);
  1525 		if (after_branch_point &&
  1743 		if (after_branch_point &&
  1526 		    ds->ds_phys->ds_next_snap_obj == 0) {
  1744 		    ds->ds_phys->ds_next_snap_obj == 0) {
  1527 			/* This clone is toast. */
  1745 			/* This clone is toast. */
  1528 			ASSERT(ds_prev->ds_phys->ds_num_children > 1);
  1746 			ASSERT(ds_prev->ds_phys->ds_num_children > 1);
  1529 			ds_prev->ds_phys->ds_num_children--;
  1747 			ds_prev->ds_phys->ds_num_children--;
       
  1748 
       
  1749 			/*
       
  1750 			 * If the clone's origin has no other clones, no
       
  1751 			 * user holds, and has been marked for deferred
       
  1752 			 * deletion, then we should have done the necessary
       
  1753 			 * destroy setup for it.
       
  1754 			 */
       
  1755 			if (ds_prev->ds_phys->ds_num_children == 1 &&
       
  1756 			    ds_prev->ds_userrefs == 0 &&
       
  1757 			    DS_IS_DEFER_DESTROY(ds_prev)) {
       
  1758 				ASSERT3P(dsda->rm_origin, !=, NULL);
       
  1759 			} else {
       
  1760 				ASSERT3P(dsda->rm_origin, ==, NULL);
       
  1761 			}
  1530 		} else if (!after_branch_point) {
  1762 		} else if (!after_branch_point) {
  1531 			ds_prev->ds_phys->ds_next_snap_obj =
  1763 			ds_prev->ds_phys->ds_next_snap_obj =
  1532 			    ds->ds_phys->ds_next_snap_obj;
  1764 			    ds->ds_phys->ds_next_snap_obj;
  1533 		}
  1765 		}
  1534 	}
  1766 	}
  1737 		VERIFY(0 == dmu_object_free(mos,
  1969 		VERIFY(0 == dmu_object_free(mos,
  1738 		    ds->ds_phys->ds_next_clones_obj, tx));
  1970 		    ds->ds_phys->ds_next_clones_obj, tx));
  1739 	}
  1971 	}
  1740 	if (ds->ds_phys->ds_props_obj != 0)
  1972 	if (ds->ds_phys->ds_props_obj != 0)
  1741 		VERIFY(0 == zap_destroy(mos, ds->ds_phys->ds_props_obj, tx));
  1973 		VERIFY(0 == zap_destroy(mos, ds->ds_phys->ds_props_obj, tx));
       
  1974 	if (ds->ds_phys->ds_userrefs_obj != 0)
       
  1975 		VERIFY(0 == zap_destroy(mos, ds->ds_phys->ds_userrefs_obj, tx));
  1742 	dsl_dir_close(ds->ds_dir, ds);
  1976 	dsl_dir_close(ds->ds_dir, ds);
  1743 	ds->ds_dir = NULL;
  1977 	ds->ds_dir = NULL;
  1744 	dsl_dataset_drain_refs(ds, tag);
  1978 	dsl_dataset_drain_refs(ds, tag);
  1745 	VERIFY(0 == dmu_object_free(mos, obj, tx));
  1979 	VERIFY(0 == dmu_object_free(mos, obj, tx));
       
  1980 
       
  1981 	if (dsda->rm_origin) {
       
  1982 		/*
       
  1983 		 * Remove the origin of the clone we just destroyed.
       
  1984 		 */
       
  1985 		dsl_dataset_t *origin = ds->ds_prev;
       
  1986 		struct dsl_ds_destroyarg ndsda = {0};
       
  1987 
       
  1988 		ASSERT3P(origin, ==, dsda->rm_origin);
       
  1989 		if (origin->ds_user_ptr) {
       
  1990 			origin->ds_user_evict_func(origin, origin->ds_user_ptr);
       
  1991 			origin->ds_user_ptr = NULL;
       
  1992 		}
       
  1993 
       
  1994 		dsl_dataset_rele(origin, tag);
       
  1995 		ds->ds_prev = NULL;
       
  1996 
       
  1997 		ndsda.ds = origin;
       
  1998 		dsl_dataset_destroy_sync(&ndsda, tag, cr, tx);
       
  1999 	}
  1746 }
  2000 }
  1747 
  2001 
  1748 static int
  2002 static int
  1749 dsl_dataset_snapshot_reserve_space(dsl_dataset_t *ds, dmu_tx_t *tx)
  2003 dsl_dataset_snapshot_reserve_space(dsl_dataset_t *ds, dmu_tx_t *tx)
  1750 {
  2004 {
  1955 	    ds->ds_quota);
  2209 	    ds->ds_quota);
  1956 	dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REFRESERVATION,
  2210 	dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REFRESERVATION,
  1957 	    ds->ds_reserved);
  2211 	    ds->ds_reserved);
  1958 	dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_GUID,
  2212 	dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_GUID,
  1959 	    ds->ds_phys->ds_guid);
  2213 	    ds->ds_phys->ds_guid);
       
  2214 	dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USERREFS, ds->ds_userrefs);
       
  2215 	dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_DEFER_DESTROY,
       
  2216 	    DS_IS_DEFER_DESTROY(ds) ? 1 : 0);
  1960 
  2217 
  1961 	if (ds->ds_phys->ds_next_snap_obj) {
  2218 	if (ds->ds_phys->ds_next_snap_obj) {
  1962 		/*
  2219 		/*
  1963 		 * This is a snapshot; override the dd's space used with
  2220 		 * This is a snapshot; override the dd's space used with
  1964 		 * our unique space and compression ratio.
  2221 		 * our unique space and compression ratio.
  3023 
  3280 
  3024 	dmu_buf_will_dirty(ds->ds_dbuf, tx);
  3281 	dmu_buf_will_dirty(ds->ds_dbuf, tx);
  3025 
  3282 
  3026 	ds->ds_quota = new_quota;
  3283 	ds->ds_quota = new_quota;
  3027 
  3284 
  3028 	dsl_prop_set_uint64_sync(ds->ds_dir, "refquota", new_quota, cr, tx);
  3285 	dsl_dir_prop_set_uint64_sync(ds->ds_dir, "refquota", new_quota, cr, tx);
  3029 
  3286 
  3030 	spa_history_internal_log(LOG_DS_REFQUOTA, ds->ds_dir->dd_pool->dp_spa,
  3287 	spa_history_internal_log(LOG_DS_REFQUOTA, ds->ds_dir->dd_pool->dp_spa,
  3031 	    tx, cr, "%lld dataset = %llu ",
  3288 	    tx, cr, "%lld dataset = %llu ",
  3032 	    (longlong_t)new_quota, ds->ds_object);
  3289 	    (longlong_t)new_quota, ds->ds_object);
  3033 }
  3290 }
  3118 	ds->ds_reserved = new_reservation;
  3375 	ds->ds_reserved = new_reservation;
  3119 	mutex_exit(&ds->ds_lock);
  3376 	mutex_exit(&ds->ds_lock);
  3120 
  3377 
  3121 	dsl_dir_diduse_space(ds->ds_dir, DD_USED_REFRSRV, delta, 0, 0, tx);
  3378 	dsl_dir_diduse_space(ds->ds_dir, DD_USED_REFRSRV, delta, 0, 0, tx);
  3122 	mutex_exit(&ds->ds_dir->dd_lock);
  3379 	mutex_exit(&ds->ds_dir->dd_lock);
  3123 	dsl_prop_set_uint64_sync(ds->ds_dir, "refreservation",
  3380 	dsl_dir_prop_set_uint64_sync(ds->ds_dir, "refreservation",
  3124 	    new_reservation, cr, tx);
  3381 	    new_reservation, cr, tx);
  3125 
  3382 
  3126 	spa_history_internal_log(LOG_DS_REFRESERV,
  3383 	spa_history_internal_log(LOG_DS_REFRESERV,
  3127 	    ds->ds_dir->dd_pool->dp_spa, tx, cr, "%lld dataset = %llu",
  3384 	    ds->ds_dir->dd_pool->dp_spa, tx, cr, "%lld dataset = %llu",
  3128 	    (longlong_t)new_reservation, ds->ds_object);
  3385 	    (longlong_t)new_reservation, ds->ds_object);
  3142 	    dsl_dataset_set_reservation_check,
  3399 	    dsl_dataset_set_reservation_check,
  3143 	    dsl_dataset_set_reservation_sync, ds, &reservation, 0);
  3400 	    dsl_dataset_set_reservation_sync, ds, &reservation, 0);
  3144 	dsl_dataset_rele(ds, FTAG);
  3401 	dsl_dataset_rele(ds, FTAG);
  3145 	return (err);
  3402 	return (err);
  3146 }
  3403 }
       
  3404 
       
  3405 static int
       
  3406 dsl_dataset_user_hold_check(void *arg1, void *arg2, dmu_tx_t *tx)
       
  3407 {
       
  3408 	dsl_dataset_t *ds = arg1;
       
  3409 	char *htag = arg2;
       
  3410 	objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
       
  3411 	int error = 0;
       
  3412 
       
  3413 	if (spa_version(ds->ds_dir->dd_pool->dp_spa) < SPA_VERSION_USERREFS)
       
  3414 		return (ENOTSUP);
       
  3415 
       
  3416 	if (!dsl_dataset_is_snapshot(ds))
       
  3417 		return (EINVAL);
       
  3418 
       
  3419 	if (strlen(htag) >= ZAP_MAXNAMELEN)
       
  3420 		return (ENAMETOOLONG);
       
  3421 
       
  3422 	/* tags must be unique */
       
  3423 	mutex_enter(&ds->ds_lock);
       
  3424 	if (ds->ds_phys->ds_userrefs_obj) {
       
  3425 		error = zap_lookup(mos, ds->ds_phys->ds_userrefs_obj, htag,
       
  3426 		    8, 1, tx);
       
  3427 		if (error == 0)
       
  3428 			error = EEXIST;
       
  3429 		else if (error == ENOENT)
       
  3430 			error = 0;
       
  3431 	}
       
  3432 	mutex_exit(&ds->ds_lock);
       
  3433 
       
  3434 	return (error);
       
  3435 }
       
  3436 
       
  3437 static void
       
  3438 dsl_dataset_user_hold_sync(void *arg1, void *arg2, cred_t *cr, dmu_tx_t *tx)
       
  3439 {
       
  3440 	dsl_dataset_t *ds = arg1;
       
  3441 	char *htag = arg2;
       
  3442 	objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
       
  3443 	time_t now = gethrestime_sec();
       
  3444 	uint64_t zapobj;
       
  3445 
       
  3446 	mutex_enter(&ds->ds_lock);
       
  3447 	if (ds->ds_phys->ds_userrefs_obj == 0) {
       
  3448 		/*
       
  3449 		 * This is the first user hold for this dataset.  Create
       
  3450 		 * the userrefs zap object.
       
  3451 		 */
       
  3452 		dmu_buf_will_dirty(ds->ds_dbuf, tx);
       
  3453 		zapobj = ds->ds_phys->ds_userrefs_obj =
       
  3454 		    zap_create(mos, DMU_OT_USERREFS, DMU_OT_NONE, 0, tx);
       
  3455 	} else {
       
  3456 		zapobj = ds->ds_phys->ds_userrefs_obj;
       
  3457 	}
       
  3458 	ds->ds_userrefs++;
       
  3459 	mutex_exit(&ds->ds_lock);
       
  3460 
       
  3461 	VERIFY(0 == zap_add(mos, zapobj, htag, 8, 1, &now, tx));
       
  3462 
       
  3463 	spa_history_internal_log(LOG_DS_USER_HOLD,
       
  3464 	    ds->ds_dir->dd_pool->dp_spa, tx, cr, "<%s> dataset = %llu",
       
  3465 	    htag, ds->ds_object);
       
  3466 }
       
  3467 
       
  3468 struct dsl_ds_holdarg {
       
  3469 	dsl_sync_task_group_t *dstg;
       
  3470 	char *htag;
       
  3471 	char *snapname;
       
  3472 	boolean_t recursive;
       
  3473 	char failed[MAXPATHLEN];
       
  3474 };
       
  3475 
       
  3476 static int
       
  3477 dsl_dataset_user_hold_one(char *dsname, void *arg)
       
  3478 {
       
  3479 	struct dsl_ds_holdarg *ha = arg;
       
  3480 	dsl_dataset_t *ds;
       
  3481 	int error;
       
  3482 	char *name;
       
  3483 	size_t buflen;
       
  3484 
       
  3485 	/* alloc a buffer to hold dsname@snapname plus terminating NULL */
       
  3486 	buflen = strlen(dsname) + strlen(ha->snapname) + 2;
       
  3487 	name = kmem_alloc(buflen, KM_SLEEP);
       
  3488 	(void) snprintf(name, buflen, "%s@%s", dsname, ha->snapname);
       
  3489 	error = dsl_dataset_hold(name, ha->dstg, &ds);
       
  3490 	kmem_free(name, buflen);
       
  3491 	if (error == 0) {
       
  3492 		dsl_sync_task_create(ha->dstg, dsl_dataset_user_hold_check,
       
  3493 		    dsl_dataset_user_hold_sync, ds, ha->htag, 0);
       
  3494 	} else if (error == ENOENT && ha->recursive) {
       
  3495 		error = 0;
       
  3496 	} else {
       
  3497 		(void) strcpy(ha->failed, dsname);
       
  3498 	}
       
  3499 	return (error);
       
  3500 }
       
  3501 
       
  3502 int
       
  3503 dsl_dataset_user_hold(char *dsname, char *snapname, char *htag,
       
  3504     boolean_t recursive)
       
  3505 {
       
  3506 	struct dsl_ds_holdarg *ha;
       
  3507 	dsl_sync_task_t *dst;
       
  3508 	spa_t *spa;
       
  3509 	int error;
       
  3510 
       
  3511 	ha = kmem_zalloc(sizeof (struct dsl_ds_holdarg), KM_SLEEP);
       
  3512 
       
  3513 	(void) strlcpy(ha->failed, dsname, sizeof (ha->failed));
       
  3514 
       
  3515 	error = spa_open(dsname, &spa, FTAG);
       
  3516 	if (error) {
       
  3517 		kmem_free(ha, sizeof (struct dsl_ds_holdarg));
       
  3518 		return (error);
       
  3519 	}
       
  3520 
       
  3521 	ha->dstg = dsl_sync_task_group_create(spa_get_dsl(spa));
       
  3522 	ha->htag = htag;
       
  3523 	ha->snapname = snapname;
       
  3524 	ha->recursive = recursive;
       
  3525 	if (recursive) {
       
  3526 		error = dmu_objset_find(dsname, dsl_dataset_user_hold_one,
       
  3527 		    ha, DS_FIND_CHILDREN);
       
  3528 	} else {
       
  3529 		error = dsl_dataset_user_hold_one(dsname, ha);
       
  3530 	}
       
  3531 	if (error == 0)
       
  3532 		error = dsl_sync_task_group_wait(ha->dstg);
       
  3533 
       
  3534 	for (dst = list_head(&ha->dstg->dstg_tasks); dst;
       
  3535 	    dst = list_next(&ha->dstg->dstg_tasks, dst)) {
       
  3536 		dsl_dataset_t *ds = dst->dst_arg1;
       
  3537 
       
  3538 		if (dst->dst_err) {
       
  3539 			dsl_dataset_name(ds, ha->failed);
       
  3540 			*strchr(ha->failed, '@') = '\0';
       
  3541 		}
       
  3542 		dsl_dataset_rele(ds, ha->dstg);
       
  3543 	}
       
  3544 
       
  3545 	if (error)
       
  3546 		(void) strcpy(dsname, ha->failed);
       
  3547 
       
  3548 	dsl_sync_task_group_destroy(ha->dstg);
       
  3549 	kmem_free(ha, sizeof (struct dsl_ds_holdarg));
       
  3550 	spa_close(spa, FTAG);
       
  3551 	return (error);
       
  3552 }
       
  3553 
       
  3554 struct dsl_ds_releasearg {
       
  3555 	dsl_dataset_t *ds;
       
  3556 	const char *htag;
       
  3557 	boolean_t own;		/* do we own or just hold ds? */
       
  3558 };
       
  3559 
       
  3560 static int
       
  3561 dsl_dataset_release_might_destroy(dsl_dataset_t *ds, const char *htag,
       
  3562     boolean_t *might_destroy)
       
  3563 {
       
  3564 	objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
       
  3565 	uint64_t zapobj;
       
  3566 	uint64_t tmp;
       
  3567 	int error;
       
  3568 
       
  3569 	*might_destroy = B_FALSE;
       
  3570 
       
  3571 	mutex_enter(&ds->ds_lock);
       
  3572 	zapobj = ds->ds_phys->ds_userrefs_obj;
       
  3573 	if (zapobj == 0) {
       
  3574 		/* The tag can't possibly exist */
       
  3575 		mutex_exit(&ds->ds_lock);
       
  3576 		return (ESRCH);
       
  3577 	}
       
  3578 
       
  3579 	/* Make sure the tag exists */
       
  3580 	error = zap_lookup(mos, zapobj, htag, 8, 1, &tmp);
       
  3581 	if (error) {
       
  3582 		mutex_exit(&ds->ds_lock);
       
  3583 		if (error == ENOENT)
       
  3584 			error = ESRCH;
       
  3585 		return (error);
       
  3586 	}
       
  3587 
       
  3588 	if (ds->ds_userrefs == 1 && ds->ds_phys->ds_num_children == 1 &&
       
  3589 	    DS_IS_DEFER_DESTROY(ds))
       
  3590 		*might_destroy = B_TRUE;
       
  3591 
       
  3592 	mutex_exit(&ds->ds_lock);
       
  3593 	return (0);
       
  3594 }
       
  3595 
       
  3596 static int
       
  3597 dsl_dataset_user_release_check(void *arg1, void *tag, dmu_tx_t *tx)
       
  3598 {
       
  3599 	struct dsl_ds_releasearg *ra = arg1;
       
  3600 	dsl_dataset_t *ds = ra->ds;
       
  3601 	boolean_t might_destroy;
       
  3602 	int error;
       
  3603 
       
  3604 	if (spa_version(ds->ds_dir->dd_pool->dp_spa) < SPA_VERSION_USERREFS)
       
  3605 		return (ENOTSUP);
       
  3606 
       
  3607 	error = dsl_dataset_release_might_destroy(ds, ra->htag, &might_destroy);
       
  3608 	if (error)
       
  3609 		return (error);
       
  3610 
       
  3611 	if (might_destroy) {
       
  3612 		struct dsl_ds_destroyarg dsda = {0};
       
  3613 
       
  3614 		if (dmu_tx_is_syncing(tx)) {
       
  3615 			/*
       
  3616 			 * If we're not prepared to remove the snapshot,
       
  3617 			 * we can't allow the release to happen right now.
       
  3618 			 */
       
  3619 			if (!ra->own)
       
  3620 				return (EBUSY);
       
  3621 			if (ds->ds_user_ptr) {
       
  3622 				ds->ds_user_evict_func(ds, ds->ds_user_ptr);
       
  3623 				ds->ds_user_ptr = NULL;
       
  3624 			}
       
  3625 		}
       
  3626 		dsda.ds = ds;
       
  3627 		dsda.releasing = B_TRUE;
       
  3628 		return (dsl_dataset_destroy_check(&dsda, tag, tx));
       
  3629 	}
       
  3630 
       
  3631 	return (0);
       
  3632 }
       
  3633 
       
  3634 static void
       
  3635 dsl_dataset_user_release_sync(void *arg1, void *tag, cred_t *cr, dmu_tx_t *tx)
       
  3636 {
       
  3637 	struct dsl_ds_releasearg *ra = arg1;
       
  3638 	dsl_dataset_t *ds = ra->ds;
       
  3639 	spa_t *spa = ds->ds_dir->dd_pool->dp_spa;
       
  3640 	objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
       
  3641 	uint64_t zapobj;
       
  3642 	uint64_t dsobj = ds->ds_object;
       
  3643 	uint64_t refs;
       
  3644 
       
  3645 	mutex_enter(&ds->ds_lock);
       
  3646 	ds->ds_userrefs--;
       
  3647 	refs = ds->ds_userrefs;
       
  3648 	mutex_exit(&ds->ds_lock);
       
  3649 	zapobj = ds->ds_phys->ds_userrefs_obj;
       
  3650 	VERIFY(0 == zap_remove(mos, zapobj, ra->htag, tx));
       
  3651 	if (ds->ds_userrefs == 0 && ds->ds_phys->ds_num_children == 1 &&
       
  3652 	    DS_IS_DEFER_DESTROY(ds)) {
       
  3653 		struct dsl_ds_destroyarg dsda = {0};
       
  3654 
       
  3655 		ASSERT(ra->own);
       
  3656 		dsda.ds = ds;
       
  3657 		dsda.releasing = B_TRUE;
       
  3658 		/* We already did the destroy_check */
       
  3659 		dsl_dataset_destroy_sync(&dsda, tag, cr, tx);
       
  3660 	}
       
  3661 
       
  3662 	spa_history_internal_log(LOG_DS_USER_RELEASE,
       
  3663 	    spa, tx, cr, "<%s> %lld dataset = %llu",
       
  3664 	    ra->htag, (longlong_t)refs, dsobj);
       
  3665 }
       
  3666 
       
  3667 static int
       
  3668 dsl_dataset_user_release_one(char *dsname, void *arg)
       
  3669 {
       
  3670 	struct dsl_ds_holdarg *ha = arg;
       
  3671 	struct dsl_ds_releasearg *ra;
       
  3672 	dsl_dataset_t *ds;
       
  3673 	int error;
       
  3674 	void *dtag = ha->dstg;
       
  3675 	char *name;
       
  3676 	size_t buflen;
       
  3677 	boolean_t own = B_FALSE;
       
  3678 	boolean_t might_destroy;
       
  3679 
       
  3680 	if (strlen(ha->htag) >= ZAP_MAXNAMELEN)
       
  3681 		return (ENAMETOOLONG);
       
  3682 
       
  3683 	/* alloc a buffer to hold dsname@snapname, plus the terminating NULL */
       
  3684 	buflen = strlen(dsname) + strlen(ha->snapname) + 2;
       
  3685 	name = kmem_alloc(buflen, KM_SLEEP);
       
  3686 	(void) snprintf(name, buflen, "%s@%s", dsname, ha->snapname);
       
  3687 	error = dsl_dataset_hold(name, dtag, &ds);
       
  3688 	kmem_free(name, buflen);
       
  3689 	if (error == ENOENT && ha->recursive)
       
  3690 		return (0);
       
  3691 	(void) strcpy(ha->failed, dsname);
       
  3692 	if (error)
       
  3693 		return (error);
       
  3694 
       
  3695 	ASSERT(dsl_dataset_is_snapshot(ds));
       
  3696 
       
  3697 	error = dsl_dataset_release_might_destroy(ds, ha->htag, &might_destroy);
       
  3698 	if (error) {
       
  3699 		dsl_dataset_rele(ds, dtag);
       
  3700 		return (error);
       
  3701 	}
       
  3702 
       
  3703 	if (might_destroy) {
       
  3704 #ifdef _KERNEL
       
  3705 		error = zfs_unmount_snap(name, NULL);
       
  3706 		if (error) {
       
  3707 			dsl_dataset_rele(ds, dtag);
       
  3708 			return (error);
       
  3709 		}
       
  3710 		error = dsl_dataset_zvol_cleanup(ds, name);
       
  3711 		if (error) {
       
  3712 			dsl_dataset_rele(ds, dtag);
       
  3713 			return (error);
       
  3714 		}
       
  3715 #endif
       
  3716 		if (!dsl_dataset_tryown(ds,
       
  3717 		    DS_MODE_READONLY | DS_MODE_INCONSISTENT, dtag)) {
       
  3718 			dsl_dataset_rele(ds, dtag);
       
  3719 			return (EBUSY);
       
  3720 		} else {
       
  3721 			own = B_TRUE;
       
  3722 			dsl_dataset_make_exclusive(ds, dtag);
       
  3723 		}
       
  3724 	}
       
  3725 
       
  3726 	ra = kmem_alloc(sizeof (struct dsl_ds_releasearg), KM_SLEEP);
       
  3727 	ra->ds = ds;
       
  3728 	ra->htag = ha->htag;
       
  3729 	ra->own = own;
       
  3730 	dsl_sync_task_create(ha->dstg, dsl_dataset_user_release_check,
       
  3731 	    dsl_dataset_user_release_sync, ra, dtag, 0);
       
  3732 
       
  3733 	return (0);
       
  3734 }
       
  3735 
       
  3736 int
       
  3737 dsl_dataset_user_release(char *dsname, char *snapname, char *htag,
       
  3738     boolean_t recursive)
       
  3739 {
       
  3740 	struct dsl_ds_holdarg *ha;
       
  3741 	dsl_sync_task_t *dst;
       
  3742 	spa_t *spa;
       
  3743 	int error;
       
  3744 
       
  3745 	ha = kmem_zalloc(sizeof (struct dsl_ds_holdarg), KM_SLEEP);
       
  3746 
       
  3747 	(void) strlcpy(ha->failed, dsname, sizeof (ha->failed));
       
  3748 
       
  3749 	error = spa_open(dsname, &spa, FTAG);
       
  3750 	if (error) {
       
  3751 		kmem_free(ha, sizeof (struct dsl_ds_holdarg));
       
  3752 		return (error);
       
  3753 	}
       
  3754 
       
  3755 	ha->dstg = dsl_sync_task_group_create(spa_get_dsl(spa));
       
  3756 	ha->htag = htag;
       
  3757 	ha->snapname = snapname;
       
  3758 	ha->recursive = recursive;
       
  3759 	if (recursive) {
       
  3760 		error = dmu_objset_find(dsname, dsl_dataset_user_release_one,
       
  3761 		    ha, DS_FIND_CHILDREN);
       
  3762 	} else {
       
  3763 		error = dsl_dataset_user_release_one(dsname, ha);
       
  3764 	}
       
  3765 	if (error == 0)
       
  3766 		error = dsl_sync_task_group_wait(ha->dstg);
       
  3767 
       
  3768 	for (dst = list_head(&ha->dstg->dstg_tasks); dst;
       
  3769 	    dst = list_next(&ha->dstg->dstg_tasks, dst)) {
       
  3770 		struct dsl_ds_releasearg *ra = dst->dst_arg1;
       
  3771 		dsl_dataset_t *ds = ra->ds;
       
  3772 
       
  3773 		if (dst->dst_err)
       
  3774 			dsl_dataset_name(ds, ha->failed);
       
  3775 
       
  3776 		if (ra->own)
       
  3777 			dsl_dataset_disown(ds, ha->dstg);
       
  3778 		else
       
  3779 			dsl_dataset_rele(ds, ha->dstg);
       
  3780 
       
  3781 		kmem_free(ra, sizeof (struct dsl_ds_releasearg));
       
  3782 	}
       
  3783 
       
  3784 	if (error)
       
  3785 		(void) strcpy(dsname, ha->failed);
       
  3786 
       
  3787 	dsl_sync_task_group_destroy(ha->dstg);
       
  3788 	kmem_free(ha, sizeof (struct dsl_ds_holdarg));
       
  3789 	spa_close(spa, FTAG);
       
  3790 	return (error);
       
  3791 }
       
  3792 
       
  3793 int
       
  3794 dsl_dataset_get_holds(const char *dsname, nvlist_t **nvp)
       
  3795 {
       
  3796 	dsl_dataset_t *ds;
       
  3797 	int err;
       
  3798 
       
  3799 	err = dsl_dataset_hold(dsname, FTAG, &ds);
       
  3800 	if (err)
       
  3801 		return (err);
       
  3802 
       
  3803 	VERIFY(0 == nvlist_alloc(nvp, NV_UNIQUE_NAME, KM_SLEEP));
       
  3804 	if (ds->ds_phys->ds_userrefs_obj != 0) {
       
  3805 		zap_attribute_t *za;
       
  3806 		zap_cursor_t zc;
       
  3807 
       
  3808 		za = kmem_alloc(sizeof (zap_attribute_t), KM_SLEEP);
       
  3809 		for (zap_cursor_init(&zc, ds->ds_dir->dd_pool->dp_meta_objset,
       
  3810 		    ds->ds_phys->ds_userrefs_obj);
       
  3811 		    zap_cursor_retrieve(&zc, za) == 0;
       
  3812 		    zap_cursor_advance(&zc)) {
       
  3813 			VERIFY(0 == nvlist_add_uint64(*nvp, za->za_name,
       
  3814 			    za->za_first_integer));
       
  3815 		}
       
  3816 		zap_cursor_fini(&zc);
       
  3817 		kmem_free(za, sizeof (zap_attribute_t));
       
  3818 	}
       
  3819 	dsl_dataset_rele(ds, FTAG);
       
  3820 	return (0);
       
  3821 }