]> xenbits.xensource.com Git - people/liuw/freebsd.git/commitdiff
Allow 'zfs holds -r' to recurse over a file system or volume to find holds
authorallanjude <allanjude@FreeBSD.org>
Mon, 26 Oct 2015 17:07:22 +0000 (17:07 +0000)
committerallanjude <allanjude@FreeBSD.org>
Mon, 26 Oct 2015 17:07:22 +0000 (17:07 +0000)
Previously, the parameters of 'zfs holds' could only be snapshots

Add -d <depth> flag to limit depth of recursion
Add -p flag to print literal values, rather than interpreted values
Add -H flag to suppress header output and use tabs rather than whitespace

Reviewed by: mahrens, smh, dteske
Approved by: bapt (mentor)
MFC after: 3 weeks
Relnotes: yes
Sponsored by: ScaleEngine Inc.
Differential Revision: https://reviews.freebsd.org/D3994

cddl/contrib/opensolaris/cmd/zfs/zfs.8
cddl/contrib/opensolaris/cmd/zfs/zfs_main.c

index 5eca00fe0080c515688616ea6b8035b1d65872a8..418f253d1414e5f51eed7e3e30c52055a8ff3ef5 100644 (file)
@@ -31,7 +31,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd September 14, 2015
+.Dd October 24, 2015
 .Dt ZFS 8
 .Os
 .Sh NAME
 .Ar tag snapshot Ns ...
 .Nm
 .Cm holds
-.Op Fl r
-.Ar snapshot Ns ...
+.Op Fl Hp
+.Op Fl r Ns | Ns Fl d Ar depth
+.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot Ns
+.Ns ...
 .Nm
 .Cm release
 .Op Fl r
@@ -3159,15 +3161,26 @@ snapshots of all descendent file systems.
 .It Xo
 .Nm
 .Cm holds
-.Op Fl r
-.Ar snapshot Ns ...
+.Op Fl Hp
+.Op Fl r Ns | Ns Fl d Ar depth
+.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot Ns
+.Ns ...
 .Xc
 .Pp
-Lists all existing user references for the given snapshot or snapshots.
+Lists all existing user references for the given dataset or datasets.
 .Bl -tag -width indent
+.It Fl H
+Used for scripting mode. Do not print headers and separate fields by a single
+tab instead of arbitrary white space.
+.It Fl p
+Display numbers in parsable (exact) values.
 .It Fl r
-Lists the holds that are set on the named descendent snapshots, in addition to
-listing the holds on the named snapshot.
+Lists the holds that are set on the descendent snapshots of the named datasets
+or snapshots, in addition to listing the holds on the named snapshots, if any.
+.It Fl d Ar depth
+Recursively display any holds on the named snapshots, or descendent snapshots of
+the named datasets or snapshots, limiting the recursion to
+.Ar depth .
 .El
 .It Xo
 .Nm
index b8466fe24e17aa8fdde595ecbf4a25afbedc64bc..9db2f73278d8c680f3a9f4b76154619f92fcf8de 100644 (file)
@@ -329,7 +329,8 @@ get_usage(zfs_help_t idx)
        case HELP_HOLD:
                return (gettext("\thold [-r] <tag> <snapshot> ...\n"));
        case HELP_HOLDS:
-               return (gettext("\tholds [-r] <snapshot> ...\n"));
+               return (gettext("\tholds [-Hp] [-r|-d depth] "
+                   "<filesystem|volume|snapshot> ...\n"));
        case HELP_RELEASE:
                return (gettext("\trelease [-r] <tag> <snapshot> ...\n"));
        case HELP_DIFF:
@@ -5543,7 +5544,8 @@ typedef struct holds_cbdata {
  *
  */
 static void
-print_holds(boolean_t scripted, size_t nwidth, size_t tagwidth, nvlist_t *nvl)
+print_holds(boolean_t scripted, boolean_t literal, size_t nwidth,
+    size_t tagwidth, nvlist_t *nvl)
 {
        int i;
        nvpair_t *nvp = NULL;
@@ -5576,10 +5578,14 @@ print_holds(boolean_t scripted, size_t nwidth, size_t tagwidth, nvlist_t *nvl)
                        size_t sepnum = scripted ? 1 : 2;
 
                        (void) nvpair_value_uint64(nvp2, &val);
-                       time = (time_t)val;
-                       (void) localtime_r(&time, &t);
-                       (void) strftime(tsbuf, DATETIME_BUF_LEN,
-                           gettext(STRFTIME_FMT_STR), &t);
+                       if (literal)
+                               snprintf(tsbuf, DATETIME_BUF_LEN, "%llu", val);
+                       else {
+                               time = (time_t)val;
+                               (void) localtime_r(&time, &t);
+                               (void) strftime(tsbuf, DATETIME_BUF_LEN,
+                                   gettext(STRFTIME_FMT_STR), &t);
+                       }
 
                        (void) printf("%-*s%*c%-*s%*c%s\n", nwidth, zname,
                            sepnum, sep, tagwidth, tagname, sepnum, sep, tsbuf);
@@ -5600,7 +5606,7 @@ holds_callback(zfs_handle_t *zhp, void *data)
        const char *zname = zfs_get_name(zhp);
        size_t znamelen = strnlen(zname, ZFS_MAXNAMELEN);
 
-       if (cbp->cb_recursive) {
+       if (cbp->cb_recursive && cbp->cb_snapname != NULL) {
                const char *snapname;
                char *delim  = strchr(zname, '@');
                if (delim == NULL)
@@ -5628,9 +5634,12 @@ holds_callback(zfs_handle_t *zhp, void *data)
 }
 
 /*
- * zfs holds [-r] <snap> ...
+ * zfs holds [-Hp] [-r | -d max] <dataset|snap> ...
  *
- *     -r      Recursively hold
+ *     -H      Suppress header output
+ *     -p      Output literal values
+ *     -r      Recursively search for holds
+ *     -d max  Limit depth of recursive search
  */
 static int
 zfs_do_holds(int argc, char **argv)
@@ -5639,8 +5648,9 @@ zfs_do_holds(int argc, char **argv)
        int c;
        int i;
        boolean_t scripted = B_FALSE;
+       boolean_t literal = B_FALSE;
        boolean_t recursive = B_FALSE;
-       const char *opts = "rH";
+       const char *opts = "d:rHp";
        nvlist_t *nvl;
 
        int types = ZFS_TYPE_SNAPSHOT;
@@ -5653,12 +5663,19 @@ zfs_do_holds(int argc, char **argv)
        /* check options */
        while ((c = getopt(argc, argv, opts)) != -1) {
                switch (c) {
+               case 'd':
+                       limit = parse_depth(optarg, &flags);
+                       recursive = B_TRUE;
+                       break;
                case 'r':
                        recursive = B_TRUE;
                        break;
                case 'H':
                        scripted = B_TRUE;
                        break;
+               case 'p':
+                       literal = B_TRUE;
+                       break;
                case '?':
                        (void) fprintf(stderr, gettext("invalid option '%c'\n"),
                            optopt);
@@ -5684,18 +5701,14 @@ zfs_do_holds(int argc, char **argv)
        for (i = 0; i < argc; ++i) {
                char *snapshot = argv[i];
                const char *delim;
-               const char *snapname;
+               const char *snapname = NULL;
 
                delim = strchr(snapshot, '@');
-               if (delim == NULL) {
-                       (void) fprintf(stderr,
-                           gettext("'%s' is not a snapshot\n"), snapshot);
-                       ++errors;
-                       continue;
+               if (delim != NULL) {
+                       snapname = delim + 1;
+                       if (recursive)
+                               snapshot[delim - snapshot] = '\0';
                }
-               snapname = delim + 1;
-               if (recursive)
-                       snapshot[delim - snapshot] = '\0';
 
                cb.cb_recursive = recursive;
                cb.cb_snapname = snapname;
@@ -5713,7 +5726,8 @@ zfs_do_holds(int argc, char **argv)
        /*
         *  2. print holds data
         */
-       print_holds(scripted, cb.cb_max_namelen, cb.cb_max_taglen, nvl);
+       print_holds(scripted, literal, cb.cb_max_namelen, cb.cb_max_taglen,
+           nvl);
 
        if (nvlist_empty(nvl))
                (void) printf(gettext("no datasets available\n"));