summaryrefslogtreecommitdiff
path: root/usr/src/cmd/zfs/zfs_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/zfs/zfs_main.c')
-rw-r--r--usr/src/cmd/zfs/zfs_main.c92
1 files changed, 81 insertions, 11 deletions
diff --git a/usr/src/cmd/zfs/zfs_main.c b/usr/src/cmd/zfs/zfs_main.c
index a4b6a1390d..956b8b6748 100644
--- a/usr/src/cmd/zfs/zfs_main.c
+++ b/usr/src/cmd/zfs/zfs_main.c
@@ -201,7 +201,8 @@ get_usage(zfs_help_t idx)
return (gettext("\tshare -a\n"
"\tshare <filesystem>\n"));
case HELP_SNAPSHOT:
- return (gettext("\tsnapshot <filesystem@name|volume@name>\n"));
+ return (gettext("\tsnapshot [-r] "
+ "<filesystem@name|volume@name>\n"));
case HELP_UNMOUNT:
return (gettext("\tunmount [-f] -a\n"
"\tunmount [-f] <filesystem|mountpoint>\n"));
@@ -372,7 +373,7 @@ zfs_do_clone(int argc, char **argv)
/*
* zfs create fs
- * zfs create [-s] -V vol size
+ * zfs create [-s] [-b blocksize] -V vol size
*
* Create a new dataset. This command can be used to create filesystems
* and volumes. Snapshot creation is handled by 'zfs snapshot'.
@@ -499,6 +500,7 @@ typedef struct destroy_cbdata {
int cb_needforce;
int cb_doclones;
zfs_handle_t *cb_target;
+ char *cb_snapname;
} destroy_cbdata_t;
/*
@@ -588,6 +590,29 @@ destroy_callback(zfs_handle_t *zhp, void *data)
return (0);
}
+static int
+destroy_snap_clones(zfs_handle_t *zhp, void *arg)
+{
+ destroy_cbdata_t *cbp = arg;
+ char thissnap[MAXPATHLEN];
+ zfs_handle_t *szhp;
+
+ (void) snprintf(thissnap, sizeof (thissnap),
+ "%s@%s", zfs_get_name(zhp), cbp->cb_snapname);
+
+ libzfs_print_on_error(g_zfs, B_FALSE);
+ szhp = zfs_open(g_zfs, thissnap, ZFS_TYPE_SNAPSHOT);
+ libzfs_print_on_error(g_zfs, B_TRUE);
+ if (szhp) {
+ /*
+ * Destroy any clones of this snapshot
+ */
+ (void) zfs_iter_dependents(szhp, destroy_callback, cbp);
+ zfs_close(szhp);
+ }
+
+ return (zfs_iter_filesystems(zhp, destroy_snap_clones, arg));
+}
static int
zfs_do_destroy(int argc, char **argv)
@@ -595,6 +620,7 @@ zfs_do_destroy(int argc, char **argv)
destroy_cbdata_t cb = { 0 };
int c;
zfs_handle_t *zhp;
+ char *cp;
/* check options */
while ((c = getopt(argc, argv, "frR")) != -1) {
@@ -630,6 +656,34 @@ zfs_do_destroy(int argc, char **argv)
usage(B_FALSE);
}
+ /*
+ * If we are doing recursive destroy of a snapshot, then the
+ * named snapshot may not exist. Go straight to libzfs.
+ */
+ if (cb.cb_recurse && (cp = strchr(argv[0], '@'))) {
+ int ret;
+
+ *cp = '\0';
+ if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_ANY)) == NULL)
+ return (1);
+ *cp = '@';
+ cp++;
+
+ if (cb.cb_doclones) {
+ cb.cb_snapname = cp;
+ (void) destroy_snap_clones(zhp, &cb);
+ }
+
+ ret = zfs_destroy_snaps(zhp, cp);
+ zfs_close(zhp);
+ if (ret) {
+ (void) fprintf(stderr,
+ gettext("no snapshots destroyed\n"));
+ }
+ return (ret != 0);
+ }
+
+
/* Open the given dataset */
if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_ANY)) == NULL)
return (1);
@@ -653,7 +707,6 @@ zfs_do_destroy(int argc, char **argv)
return (1);
}
-
/*
* Check for any dependents and/or clones.
*/
@@ -1728,7 +1781,7 @@ zfs_do_set(int argc, char **argv)
}
/*
- * zfs snapshot <fs@snap>
+ * zfs snapshot [-r] <fs@snap>
*
* Creates a snapshot with the given name. While functionally equivalent to
* 'zfs create', it is a separate command to diffferentiate intent.
@@ -1736,24 +1789,41 @@ zfs_do_set(int argc, char **argv)
static int
zfs_do_snapshot(int argc, char **argv)
{
+ int recursive = B_FALSE;
+ int ret;
+ char c;
+
/* check options */
- if (argc > 1 && argv[1][0] == '-') {
- (void) fprintf(stderr, gettext("invalid option '%c'\n"),
- argv[1][1]);
- usage(B_FALSE);
+ while ((c = getopt(argc, argv, ":r")) != -1) {
+ switch (c) {
+ case 'r':
+ recursive = B_TRUE;
+ break;
+ case '?':
+ (void) fprintf(stderr, gettext("invalid option '%c'\n"),
+ optopt);
+ usage(B_FALSE);
+ }
}
+ argc -= optind;
+ argv += optind;
+
/* check number of arguments */
- if (argc < 2) {
+ if (argc < 1) {
(void) fprintf(stderr, gettext("missing snapshot argument\n"));
usage(B_FALSE);
}
- if (argc > 2) {
+ if (argc > 1) {
(void) fprintf(stderr, gettext("too many arguments\n"));
usage(B_FALSE);
}
- return (zfs_snapshot(g_zfs, argv[1]) != 0);
+ ret = zfs_snapshot(g_zfs, argv[0], recursive);
+ if (ret && recursive)
+ (void) fprintf(stderr, gettext("no snapshots were created\n"));
+ return (ret != 0);
+
}
/*