Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 22 Mar 2013 07:57:28 +0000 (UTC)
From:      Martin Matuska <mm@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org
Subject:   svn commit: r248611 - in stable/9: cddl/contrib/opensolaris/cmd/zfs cddl/contrib/opensolaris/lib/libzfs/common sys/cddl/contrib/opensolaris/uts/common/fs/zfs
Message-ID:  <201303220757.r2M7vSZj029359@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mm
Date: Fri Mar 22 07:57:28 2013
New Revision: 248611
URL: http://svnweb.freebsd.org/changeset/base/248611

Log:
  MFC r240870 (pjd):
  It is possible to recursively destroy snapshots even if the snapshot
  doesn't exist on a dataset we are starting from. For example if we
  have the following configuration:
  
  	tank
  	tank/foo
  	tank/foo@snap
  	tank/bar
  	tank/bar@snap
  
  We can execute:
  
  	# zfs destroy -t tank@snap
  
  eventhough tank@snap doesn't exit.
  
  Unfortunately it is not possible to do the same with recursive rename:
  
  	# zfs rename -r tank@snap tank@pans
  	cannot open 'tank@snap': dataset does not exist
  
  ...until now. This change allows to recursively rename snapshots even if
  snapshot doesn't exist on the starting dataset.
  
  Sponsored by:	rsync.net

Modified:
  stable/9/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c
  stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h
  stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
Directory Properties:
  stable/9/cddl/contrib/opensolaris/   (props changed)
  stable/9/cddl/contrib/opensolaris/cmd/zfs/   (props changed)
  stable/9/cddl/contrib/opensolaris/lib/libzfs/   (props changed)
  stable/9/sys/   (props changed)
  stable/9/sys/cddl/contrib/opensolaris/   (props changed)

Modified: stable/9/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c
==============================================================================
--- stable/9/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c	Fri Mar 22 07:40:34 2013	(r248610)
+++ stable/9/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c	Fri Mar 22 07:57:28 2013	(r248611)
@@ -3070,6 +3070,7 @@ zfs_do_rename(int argc, char **argv)
 	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 @@ zfs_do_rename(int argc, char **argv)
 	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 @@ zfs_do_rename(int argc, char **argv)
 		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: stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h
==============================================================================
--- stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h	Fri Mar 22 07:40:34 2013	(r248610)
+++ stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h	Fri Mar 22 07:57:28 2013	(r248611)
@@ -571,7 +571,8 @@ typedef struct renameflags {
 	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: stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
==============================================================================
--- stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c	Fri Mar 22 07:40:34 2013	(r248610)
+++ stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c	Fri Mar 22 07:57:28 2013	(r248611)
@@ -611,6 +611,22 @@ zfs_open(libzfs_handle_t *hdl, const cha
 		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 @@ zfs_rollback(zfs_handle_t *zhp, zfs_hand
  * 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 @@ zfs_rename(zfs_handle_t *zhp, const char
 	(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: stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
==============================================================================
--- stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c	Fri Mar 22 07:40:34 2013	(r248610)
+++ stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c	Fri Mar 22 07:57:28 2013	(r248611)
@@ -2520,6 +2520,7 @@ struct renamesnaparg {
 	char failed[MAXPATHLEN];
 	char *oldsnap;
 	char *newsnap;
+	int error;
 };
 
 static int
@@ -2557,6 +2558,9 @@ dsl_snapshot_rename_one(const char *name
 	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 @@ dsl_recursive_rename(char *oldname, cons
 	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: stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
==============================================================================
--- stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c	Fri Mar 22 07:40:34 2013	(r248610)
+++ stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c	Fri Mar 22 07:57:28 2013	(r248611)
@@ -780,7 +780,26 @@ zfs_secpolicy_rename_perms(const char *f
 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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201303220757.r2M7vSZj029359>