Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 14 Apr 2017 18:01:43 +0000 (UTC)
From:      Andriy Gapon <avg@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-vendor@freebsd.org
Subject:   svn commit: r316891 - vendor-sys/illumos/dist/common/zfs vendor/illumos/dist/cmd/zfs vendor/illumos/dist/lib/libzfs/common vendor/illumos/dist/man/man1m
Message-ID:  <201704141801.v3EI1h3X060309@repo.freebsd.org>

index | next in thread | raw e-mail

Author: avg
Date: Fri Apr 14 18:01:43 2017
New Revision: 316891
URL: https://svnweb.freebsd.org/changeset/base/316891

Log:
  7386 zfs get does not work properly with bookmarks
  
  illumos/illumos-gate@edb901aab9c738b5eb15aa55933e82b0f2f9d9a2
  https://github.com/illumos/illumos-gate/commit/edb901aab9c738b5eb15aa55933e82b0f2f9d9a2
  
  https://www.illumos.org/issues/7386
    The zfs get command does not work with the bookmark parameter while it works
    properly with both filesystem and snapshot:
    # zfs get -t all -r creation rpool/test
    NAME               PROPERTY  VALUE                  SOURCE
    rpool/test         creation  Fri Sep 16 15:00 2016  -
    rpool/test@snap    creation  Fri Sep 16 15:00 2016  -
    rpool/test#bkmark  creation  Fri Sep 16 15:00 2016  -
    # zfs get -t all -r creation rpool/test@snap
    NAME             PROPERTY  VALUE                  SOURCE
    rpool/test@snap  creation  Fri Sep 16 15:00 2016  -
    # zfs get -t all -r creation rpool/test#bkmark
    cannot open 'rpool/test#bkmark': invalid dataset name
    #
    The zfs get command should be modified to work properly with bookmarks too.
  
  Reviewed by: Simon Klinkert <simon.klinkert@gmail.com>
  Reviewed by: Paul Dagnelie <pcd@delphix.com>
  Approved by: Matthew Ahrens <mahrens@delphix.com>
  Author: Marcel Telka <marcel@telka.sk>

Modified:
  vendor/illumos/dist/cmd/zfs/zfs_main.c
  vendor/illumos/dist/lib/libzfs/common/libzfs_dataset.c
  vendor/illumos/dist/lib/libzfs/common/libzfs_pool.c
  vendor/illumos/dist/lib/libzfs/common/libzfs_util.c
  vendor/illumos/dist/man/man1m/zfs.1m

Changes in other areas also in this revision:
Modified:
  vendor-sys/illumos/dist/common/zfs/zfs_namecheck.c
  vendor-sys/illumos/dist/common/zfs/zfs_namecheck.h

Modified: vendor/illumos/dist/cmd/zfs/zfs_main.c
==============================================================================
--- vendor/illumos/dist/cmd/zfs/zfs_main.c	Fri Apr 14 18:00:42 2017	(r316890)
+++ vendor/illumos/dist/cmd/zfs/zfs_main.c	Fri Apr 14 18:01:43 2017	(r316891)
@@ -232,7 +232,7 @@ get_usage(zfs_help_t idx)
 		    "[-o \"all\" | field[,...]]\n"
 		    "\t    [-t type[,...]] [-s source[,...]]\n"
 		    "\t    <\"all\" | property[,...]> "
-		    "[filesystem|volume|snapshot] ...\n"));
+		    "[filesystem|volume|snapshot|bookmark] ...\n"));
 	case HELP_INHERIT:
 		return (gettext("\tinherit [-rS] <property> "
 		    "<filesystem|volume|snapshot> ...\n"));
@@ -1594,7 +1594,7 @@ zfs_do_get(int argc, char **argv)
 {
 	zprop_get_cbdata_t cb = { 0 };
 	int i, c, flags = ZFS_ITER_ARGS_CAN_BE_PATHS;
-	int types = ZFS_TYPE_DATASET;
+	int types = ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK;
 	char *value, *fields;
 	int ret = 0;
 	int limit = 0;

Modified: vendor/illumos/dist/lib/libzfs/common/libzfs_dataset.c
==============================================================================
--- vendor/illumos/dist/lib/libzfs/common/libzfs_dataset.c	Fri Apr 14 18:00:42 2017	(r316890)
+++ vendor/illumos/dist/lib/libzfs/common/libzfs_dataset.c	Fri Apr 14 18:01:43 2017	(r316891)
@@ -105,7 +105,7 @@ zfs_validate_name(libzfs_handle_t *hdl, 
 	char what;
 
 	(void) zfs_prop_get_table();
-	if (dataset_namecheck(path, &why, &what) != 0) {
+	if (entity_namecheck(path, &why, &what) != 0) {
 		if (hdl != NULL) {
 			switch (why) {
 			case NAME_ERR_TOOLONG:
@@ -134,9 +134,10 @@ zfs_validate_name(libzfs_handle_t *hdl, 
 				    "'%c' in name"), what);
 				break;
 
-			case NAME_ERR_MULTIPLE_AT:
+			case NAME_ERR_MULTIPLE_DELIMITERS:
 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
-				    "multiple '@' delimiters in name"));
+				    "multiple '@' and/or '#' delimiters in "
+				    "name"));
 				break;
 
 			case NAME_ERR_NOLETTER:
@@ -167,7 +168,7 @@ zfs_validate_name(libzfs_handle_t *hdl, 
 	if (!(type & ZFS_TYPE_SNAPSHOT) && strchr(path, '@') != NULL) {
 		if (hdl != NULL)
 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
-			    "snapshot delimiter '@' in filesystem name"));
+			    "snapshot delimiter '@' is not expected here"));
 		return (0);
 	}
 
@@ -178,6 +179,20 @@ zfs_validate_name(libzfs_handle_t *hdl, 
 		return (0);
 	}
 
+	if (!(type & ZFS_TYPE_BOOKMARK) && strchr(path, '#') != NULL) {
+		if (hdl != NULL)
+			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+			    "bookmark delimiter '#' is not expected here"));
+		return (0);
+	}
+
+	if (type == ZFS_TYPE_BOOKMARK && strchr(path, '#') == NULL) {
+		if (hdl != NULL)
+			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+			    "missing '#' delimiter in bookmark name"));
+		return (0);
+	}
+
 	if (modifying && strchr(path, '%') != NULL) {
 		if (hdl != NULL)
 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
@@ -615,8 +630,36 @@ make_bookmark_handle(zfs_handle_t *paren
 	return (zhp);
 }
 
+struct zfs_open_bookmarks_cb_data {
+	const char *path;
+	zfs_handle_t *zhp;
+};
+
+static int
+zfs_open_bookmarks_cb(zfs_handle_t *zhp, void *data)
+{
+	struct zfs_open_bookmarks_cb_data *dp = data;
+
+	/*
+	 * Is it the one we are looking for?
+	 */
+	if (strcmp(dp->path, zfs_get_name(zhp)) == 0) {
+		/*
+		 * We found it.  Save it and let the caller know we are done.
+		 */
+		dp->zhp = zhp;
+		return (EEXIST);
+	}
+
+	/*
+	 * Not found.  Close the handle and ask for another one.
+	 */
+	zfs_close(zhp);
+	return (0);
+}
+
 /*
- * Opens the given snapshot, filesystem, or volume.   The 'types'
+ * Opens the given snapshot, bookmark, filesystem, or volume.   The 'types'
  * argument is a mask of acceptable types.  The function will print an
  * appropriate error message and return NULL if it can't be opened.
  */
@@ -625,6 +668,7 @@ zfs_open(libzfs_handle_t *hdl, const cha
 {
 	zfs_handle_t *zhp;
 	char errbuf[1024];
+	char *bookp;
 
 	(void) snprintf(errbuf, sizeof (errbuf),
 	    dgettext(TEXT_DOMAIN, "cannot open '%s'"), path);
@@ -632,20 +676,68 @@ zfs_open(libzfs_handle_t *hdl, const cha
 	/*
 	 * Validate the name before we even try to open it.
 	 */
-	if (!zfs_validate_name(hdl, path, ZFS_TYPE_DATASET, B_FALSE)) {
-		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
-		    "invalid dataset name"));
+	if (!zfs_validate_name(hdl, path, types, B_FALSE)) {
 		(void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
 		return (NULL);
 	}
 
 	/*
-	 * Try to get stats for the dataset, which will tell us if it exists.
+	 * Bookmarks needs to be handled separately.
 	 */
-	errno = 0;
-	if ((zhp = make_dataset_handle(hdl, path)) == NULL) {
-		(void) zfs_standard_error(hdl, errno, errbuf);
-		return (NULL);
+	bookp = strchr(path, '#');
+	if (bookp == NULL) {
+		/*
+		 * Try to get stats for the dataset, which will tell us if it
+		 * exists.
+		 */
+		errno = 0;
+		if ((zhp = make_dataset_handle(hdl, path)) == NULL) {
+			(void) zfs_standard_error(hdl, errno, errbuf);
+			return (NULL);
+		}
+	} else {
+		char dsname[ZFS_MAX_DATASET_NAME_LEN];
+		zfs_handle_t *pzhp;
+		struct zfs_open_bookmarks_cb_data cb_data = {path, NULL};
+
+		/*
+		 * We need to cut out '#' and everything after '#'
+		 * to get the parent dataset name only.
+		 */
+		assert(bookp - path < sizeof (dsname));
+		(void) strncpy(dsname, path, bookp - path);
+		dsname[bookp - path] = '\0';
+
+		/*
+		 * Create handle for the parent dataset.
+		 */
+		errno = 0;
+		if ((pzhp = make_dataset_handle(hdl, dsname)) == NULL) {
+			(void) zfs_standard_error(hdl, errno, errbuf);
+			return (NULL);
+		}
+
+		/*
+		 * Iterate bookmarks to find the right one.
+		 */
+		errno = 0;
+		if ((zfs_iter_bookmarks(pzhp, zfs_open_bookmarks_cb,
+		    &cb_data) == 0) && (cb_data.zhp == NULL)) {
+			(void) zfs_error(hdl, EZFS_NOENT, errbuf);
+			zfs_close(pzhp);
+			return (NULL);
+		}
+		if (cb_data.zhp == NULL) {
+			(void) zfs_standard_error(hdl, errno, errbuf);
+			zfs_close(pzhp);
+			return (NULL);
+		}
+		zhp = cb_data.zhp;
+
+		/*
+		 * Cleanup.
+		 */
+		zfs_close(pzhp);
 	}
 
 	if (!(types & zhp->zfs_type)) {

Modified: vendor/illumos/dist/lib/libzfs/common/libzfs_pool.c
==============================================================================
--- vendor/illumos/dist/lib/libzfs/common/libzfs_pool.c	Fri Apr 14 18:00:42 2017	(r316890)
+++ vendor/illumos/dist/lib/libzfs/common/libzfs_pool.c	Fri Apr 14 18:01:43 2017	(r316891)
@@ -946,9 +946,10 @@ zpool_name_valid(libzfs_handle_t *hdl, b
 				    "trailing slash in name"));
 				break;
 
-			case NAME_ERR_MULTIPLE_AT:
+			case NAME_ERR_MULTIPLE_DELIMITERS:
 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
-				    "multiple '@' delimiters in name"));
+				    "multiple '@' and/or '#' delimiters in "
+				    "name"));
 				break;
 
 			default:

Modified: vendor/illumos/dist/lib/libzfs/common/libzfs_util.c
==============================================================================
--- vendor/illumos/dist/lib/libzfs/common/libzfs_util.c	Fri Apr 14 18:00:42 2017	(r316890)
+++ vendor/illumos/dist/lib/libzfs/common/libzfs_util.c	Fri Apr 14 18:01:43 2017	(r316891)
@@ -689,7 +689,7 @@ zfs_get_pool_handle(const zfs_handle_t *
  * Given a name, determine whether or not it's a valid path
  * (starts with '/' or "./").  If so, walk the mnttab trying
  * to match the device number.  If not, treat the path as an
- * fs/vol/snap name.
+ * fs/vol/snap/bkmark name.
  */
 zfs_handle_t *
 zfs_path_to_zhandle(libzfs_handle_t *hdl, char *path, zfs_type_t argtype)

Modified: vendor/illumos/dist/man/man1m/zfs.1m
==============================================================================
--- vendor/illumos/dist/man/man1m/zfs.1m	Fri Apr 14 18:00:42 2017	(r316890)
+++ vendor/illumos/dist/man/man1m/zfs.1m	Fri Apr 14 18:01:43 2017	(r316891)
@@ -28,7 +28,7 @@
 .\" Copyright (c) 2014 Integros [integros.com]
 .\" Copyright 2016 Nexenta Systems, Inc.
 .\"
-.Dd September 3, 2016
+.Dd September 16, 2016
 .Dt ZFS 1M
 .Os
 .Sh NAME
@@ -112,7 +112,7 @@
 .Oo Fl s Ar source Ns Oo , Ns Ar source Oc Ns ... Oc
 .Oo Fl t Ar type Ns Oo , Ns Ar type Oc Ns ... Oc
 .Cm all | Ar property Ns Oo , Ns Ar property Oc Ns ...
-.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot Ns ...
+.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot Ns | Ns Ar bookmark Ns ...
 .Nm
 .Cm inherit
 .Op Fl rS
@@ -2122,7 +2122,7 @@ section.
 .Oo Fl s Ar source Ns Oo , Ns Ar source Oc Ns ... Oc
 .Oo Fl t Ar type Ns Oo , Ns Ar type Oc Ns ... Oc
 .Cm all | Ar property Ns Oo , Ns Ar property Oc Ns ...
-.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot Ns ...
+.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot Ns | Ns Ar bookmark Ns ...
 .Xc
 Displays properties for the given datasets. If no datasets are specified, then
 the command displays properties for all datasets on the system. For each


home | help

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