[Midnightbsd-cvs] src [8999] trunk: zfs: recursive snapshots are ok, recorsive rename is not.

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Thu Sep 29 21:34:14 EDT 2016


Revision: 8999
          http://svnweb.midnightbsd.org/src/?rev=8999
Author:   laffer1
Date:     2016-09-29 21:34:14 -0400 (Thu, 29 Sep 2016)
Log Message:
-----------
zfs: recursive snapshots are ok, recorsive rename is not.

Modified Paths:
--------------
    trunk/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c
    trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h
    trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
    trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
    trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c

Modified: trunk/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c
===================================================================
--- trunk/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c	2016-09-30 01:33:23 UTC (rev 8998)
+++ trunk/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c	2016-09-30 01:34:14 UTC (rev 8999)
@@ -3070,6 +3070,7 @@
 	int ret = 0;
 	int types;
 	boolean_t parents = B_FALSE;
+	char *snapshot = NULL;
 
 	/* check options */
 	while ((c = getopt(argc, argv, "fpru")) != -1) {
@@ -3138,6 +3139,19 @@
 	else
 		types = ZFS_TYPE_DATASET;
 
+	if (flags.recurse) {
+		/*
+		 * When we do recursive rename we are fine when the given
+		 * snapshot for the given dataset doesn't exist - it can
+		 * still exists below.
+		 */
+
+		snapshot = strchr(argv[0], '@');
+		assert(snapshot != NULL);
+		*snapshot = '\0';
+		snapshot++;
+	}
+
 	if ((zhp = zfs_open(g_zfs, argv[0], types)) == NULL)
 		return (1);
 
@@ -3148,7 +3162,7 @@
 		return (1);
 	}
 
-	ret = (zfs_rename(zhp, argv[1], flags) != 0);
+	ret = (zfs_rename(zhp, snapshot, argv[1], flags) != 0);
 
 	zfs_close(zhp);
 	return (ret);

Modified: trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h	2016-09-30 01:33:23 UTC (rev 8998)
+++ trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h	2016-09-30 01:34:14 UTC (rev 8999)
@@ -571,7 +571,8 @@
 	int forceunmount : 1;
 } renameflags_t;
 
-extern int zfs_rename(zfs_handle_t *, const char *, renameflags_t flags);
+extern int zfs_rename(zfs_handle_t *, const char *, const char *,
+    renameflags_t flags);
 
 typedef struct sendflags {
 	/* print informational messages (ie, -v was specified) */

Modified: trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
===================================================================
--- trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c	2016-09-30 01:33:23 UTC (rev 8998)
+++ trunk/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c	2016-09-30 01:34:14 UTC (rev 8999)
@@ -611,6 +611,22 @@
 		return (NULL);
 	}
 
+	if (zhp == NULL) {
+		char *at = strchr(path, '@');
+
+		if (at != NULL)
+			*at = '\0';
+		errno = 0;
+		if ((zhp = make_dataset_handle(hdl, path)) == NULL) {
+			(void) zfs_standard_error(hdl, errno, errbuf);
+			return (NULL);
+		}
+		if (at != NULL)
+			*at = '@';
+		(void) strlcpy(zhp->zfs_name, path, sizeof (zhp->zfs_name));
+		zhp->zfs_type = ZFS_TYPE_SNAPSHOT;
+	}
+
 	if (!(types & zhp->zfs_type)) {
 		(void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
 		zfs_close(zhp);
@@ -3614,7 +3630,8 @@
  * Renames the given dataset.
  */
 int
-zfs_rename(zfs_handle_t *zhp, const char *target, renameflags_t flags)
+zfs_rename(zfs_handle_t *zhp, const char *source, const char *target,
+    renameflags_t flags)
 {
 	int ret;
 	zfs_cmd_t zc = { 0 };
@@ -3634,6 +3651,18 @@
 	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
 	    "cannot rename to '%s'"), target);
 
+	if (source != NULL) {
+		/*
+		 * This is recursive snapshots rename, put snapshot name
+		 * (that might not exist) into zfs_name.
+		 */
+		assert(flags.recurse);
+
+		(void) strlcat(zhp->zfs_name, "@", sizeof(zhp->zfs_name));
+		(void) strlcat(zhp->zfs_name, source, sizeof(zhp->zfs_name));
+		zhp->zfs_type = ZFS_TYPE_SNAPSHOT;
+	}
+
 	/*
 	 * Make sure the target name is valid
 	 */

Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c	2016-09-30 01:33:23 UTC (rev 8998)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c	2016-09-30 01:34:14 UTC (rev 8999)
@@ -2520,6 +2520,7 @@
 	char failed[MAXPATHLEN];
 	char *oldsnap;
 	char *newsnap;
+	int error;
 };
 
 static int
@@ -2557,6 +2558,9 @@
 	dsl_sync_task_create(ra->dstg, dsl_dataset_snapshot_rename_check,
 	    dsl_dataset_snapshot_rename_sync, ds, ra->newsnap, 0);
 
+	/* First successful rename clears the error. */
+	ra->error = 0;
+
 	return (0);
 }
 
@@ -2585,14 +2589,16 @@
 	ra->oldsnap = strchr(oldname, '@') + 1;
 	ra->newsnap = strchr(newname, '@') + 1;
 	*ra->failed = '\0';
+	ra->error = ENOENT;
 
 	err = dmu_objset_find(fsname, dsl_snapshot_rename_one, ra,
 	    DS_FIND_CHILDREN);
 	kmem_free(fsname, len);
+	if (err == 0)
+		err = ra->error;
 
-	if (err == 0) {
+	if (err == 0)
 		err = dsl_sync_task_group_wait(ra->dstg);
-	}
 
 	for (dst = list_head(&ra->dstg->dstg_tasks); dst;
 	    dst = list_next(&ra->dstg->dstg_tasks, dst)) {

Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c	2016-09-30 01:33:23 UTC (rev 8998)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c	2016-09-30 01:34:14 UTC (rev 8999)
@@ -780,7 +780,26 @@
 static int
 zfs_secpolicy_rename(zfs_cmd_t *zc, cred_t *cr)
 {
-	return (zfs_secpolicy_rename_perms(zc->zc_name, zc->zc_value, cr));
+	char *at = NULL;
+	int error;
+
+	if ((zc->zc_cookie & 1) != 0) {
+		/*
+		 * This is recursive rename, so the starting snapshot might
+		 * not exist. Check file system or volume permission instead.
+		 */
+		at = strchr(zc->zc_name, '@');
+		if (at == NULL)
+			return (EINVAL);
+		*at = '\0';
+	}
+
+	error = zfs_secpolicy_rename_perms(zc->zc_name, zc->zc_value, cr);
+
+	if (at != NULL)
+		*at = '@';
+
+	return (error);
 }
 
 static int



More information about the Midnightbsd-cvs mailing list