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
Martin Matuska
mm at FreeBSD.org
Fri Mar 22 07:57:30 UTC 2013
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 at snap
tank/bar
tank/bar at snap
We can execute:
# zfs destroy -t tank at snap
eventhough tank at snap doesn't exit.
Unfortunately it is not possible to do the same with recursive rename:
# zfs rename -r tank at snap tank at pans
cannot open 'tank at 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
More information about the svn-src-stable-9
mailing list