summaryrefslogtreecommitdiffstats
path: root/cddl
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2012-09-23 20:12:10 +0000
committerpjd <pjd@FreeBSD.org>2012-09-23 20:12:10 +0000
commit212634d921b6016d77a964b0299d6df7a93aacc1 (patch)
tree0772e4df508e44f9ca88d1971c54fb2acb4e2d85 /cddl
parent462a1240363ef90831d9b6cf6d345fc3c6e2ee0d (diff)
downloadFreeBSD-src-212634d921b6016d77a964b0299d6df7a93aacc1.zip
FreeBSD-src-212634d921b6016d77a964b0299d6df7a93aacc1.tar.gz
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 MFC after: 2 weeks
Diffstat (limited to 'cddl')
-rw-r--r--cddl/contrib/opensolaris/cmd/zfs/zfs_main.c16
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h3
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c31
3 files changed, 47 insertions, 3 deletions
diff --git a/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c b/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c
index e0bc3d7..ea313ba 100644
--- a/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c
+++ b/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c
@@ -3081,6 +3081,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) {
@@ -3149,6 +3150,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);
@@ -3159,7 +3173,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);
diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h
index 3a35410..2660059 100644
--- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h
+++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h
@@ -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) */
diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
index 4116e1b..2261978 100644
--- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
+++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
@@ -611,6 +611,22 @@ zfs_open(libzfs_handle_t *hdl, const char *path, int types)
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_handle_t *snap, boolean_t force)
* 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 *target, renameflags_t flags)
(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
*/
OpenPOWER on IntegriCloud