usr/src/lib/libzfs/common/libzfs_dataset.c
changeset 2417 694d5de97348
parent 2199 712a788c2dfd
child 2440 9281a87e8a9e
--- a/usr/src/lib/libzfs/common/libzfs_dataset.c	Sat Jul 22 09:11:10 2006 -0700
+++ b/usr/src/lib/libzfs/common/libzfs_dataset.c	Sat Jul 22 14:30:52 2006 -0700
@@ -2139,31 +2139,19 @@
 {
 	promote_data_t *pd = data;
 	zfs_handle_t *szhp;
-	int err;
 	char snapname[MAXPATHLEN];
-	char *cp;
 
 	/* We don't care about snapshots after the pivot point */
 	if (zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) > pd->cb_pivot_txg)
 		return (0);
 
-	/*
-	 * Unmount it.  We actually need to open it to provoke it to be
-	 * mounted first, because if it is not mounted, umount2 will
-	 * mount it!
-	 */
-	(void) strcpy(snapname, pd->cb_mountpoint);
-	(void) strcat(snapname, "/.zfs/snapshot/");
-	cp = strchr(zhp->zfs_name, '@');
-	(void) strcat(snapname, cp+1);
-	err = open(snapname, O_RDONLY);
-	if (err != -1)
-		(void) close(err);
-	(void) umount2(snapname, MS_FORCE);
+	/* Remove the device link if it's a zvol. */
+	if (zhp->zfs_volblocksize != 0)
+		(void) zvol_remove_link(zhp->zfs_hdl, zhp->zfs_name);
 
 	/* Check for conflicting names */
 	(void) strcpy(snapname, pd->cb_target);
-	(void) strcat(snapname, cp);
+	(void) strcat(snapname, strchr(zhp->zfs_name, '@'));
 	szhp = make_dataset_handle(zhp->zfs_hdl, snapname);
 	if (szhp != NULL) {
 		zfs_close(szhp);
@@ -2176,6 +2164,22 @@
 	return (0);
 }
 
+static int
+promote_snap_done_cb(zfs_handle_t *zhp, void *data)
+{
+	promote_data_t *pd = data;
+
+	/* We don't care about snapshots after the pivot point */
+	if (zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) > pd->cb_pivot_txg)
+		return (0);
+
+	/* Create the device link if it's a zvol. */
+	if (zhp->zfs_volblocksize != 0)
+		(void) zvol_create_link(zhp->zfs_hdl, zhp->zfs_name);
+
+	return (0);
+}
+
 /*
  * Promotes the given clone fs to be the clone parent.
  */
@@ -2223,16 +2227,24 @@
 	(void) zfs_prop_get(pzhp, ZFS_PROP_MOUNTPOINT, pd.cb_mountpoint,
 	    sizeof (pd.cb_mountpoint), NULL, NULL, 0, FALSE);
 	ret = zfs_iter_snapshots(pzhp, promote_snap_cb, &pd);
-	if (ret != 0)
+	if (ret != 0) {
+		zfs_close(pzhp);
 		return (-1);
+	}
 
 	/* issue the ioctl */
+	(void) strlcpy(zc.zc_prop_value, zhp->zfs_dmustats.dds_clone_of,
+	    sizeof (zc.zc_prop_value));
 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
 	ret = ioctl(hdl->libzfs_fd, ZFS_IOC_PROMOTE, &zc);
 
 	if (ret != 0) {
-		switch (errno) {
-
+		int save_errno = errno;
+
+		(void) zfs_iter_snapshots(pzhp, promote_snap_done_cb, &pd);
+		zfs_close(pzhp);
+
+		switch (save_errno) {
 		case EEXIST:
 			/*
 			 * There is a conflicting snapshot name.  We
@@ -2245,10 +2257,13 @@
 			return (zfs_error(hdl, EZFS_EXISTS, errbuf));
 
 		default:
-			return (zfs_standard_error(hdl, errno, errbuf));
+			return (zfs_standard_error(hdl, save_errno, errbuf));
 		}
+	} else {
+		(void) zfs_iter_snapshots(zhp, promote_snap_done_cb, &pd);
 	}
 
+	zfs_close(pzhp);
 	return (ret);
 }