Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 21 Jan 2018 19:26:39 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-vendor@freebsd.org
Subject:   svn commit: r328220 - vendor-sys/illumos/dist/uts/common/fs/zfs vendor-sys/illumos/dist/uts/common/fs/zfs/sys vendor-sys/illumos/dist/uts/common/sys/fs vendor/illumos/dist/cmd/zfs vendor/illumos/di...
Message-ID:  <201801211926.w0LJQdad099075@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Sun Jan 21 19:26:38 2018
New Revision: 328220
URL: https://svnweb.freebsd.org/changeset/base/328220

Log:
  8677 Open-Context Channel Programs
  
  illumos/illumos-gate@a3b2868063897ff0083dea538f55f9873eec981f
  
  https://www.illumos.org/issues/8677
    We want to be able to run channel programs outside of synching context.
    This would greatly improve performance of channel program that just gather
    information, as we won't have to wait for synching context anymore.
  
    This feature should introduce the following:
    - A new command line flag in "zfs program" to specify our intention to
    run in open context.
    - A new flag/option within the channel program ioctl which selects the
    context.
    - Appropriate error handling whenever we try a channel program in
    open-context that contains zfs.sync* expressions.
    - Documentation for the new feature in the manual pages.
  
  Reviewed by: Matt Ahrens <mahrens@delphix.com>
  Reviewed by: Chris Williamson <chris.williamson@delphix.com>
  Reviewed by: Pavel Zakharov <pavel.zakharov@delphix.com>
  Approved by: Robert Mustacchi <rm@joyent.com>
  Author:	Serapheim Dimitropoulos <serapheim@delphix.com>

Modified:
  vendor/illumos/dist/cmd/zfs/zfs_main.c
  vendor/illumos/dist/lib/libzfs/common/libzfs_dataset.c
  vendor/illumos/dist/lib/libzfs_core/common/libzfs_core.c
  vendor/illumos/dist/lib/libzfs_core/common/libzfs_core.h
  vendor/illumos/dist/man/man1m/zfs-program.1m
  vendor/illumos/dist/man/man1m/zfs.1m

Changes in other areas also in this revision:
Modified:
  vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_destroy.c
  vendor-sys/illumos/dist/uts/common/fs/zfs/sys/zcp.h
  vendor-sys/illumos/dist/uts/common/fs/zfs/zcp.c
  vendor-sys/illumos/dist/uts/common/fs/zfs/zcp_synctask.c
  vendor-sys/illumos/dist/uts/common/fs/zfs/zfs_ioctl.c
  vendor-sys/illumos/dist/uts/common/sys/fs/zfs.h

Modified: vendor/illumos/dist/cmd/zfs/zfs_main.c
==============================================================================
--- vendor/illumos/dist/cmd/zfs/zfs_main.c	Sun Jan 21 17:31:31 2018	(r328219)
+++ vendor/illumos/dist/cmd/zfs/zfs_main.c	Sun Jan 21 19:26:38 2018	(r328220)
@@ -329,7 +329,7 @@ get_usage(zfs_help_t idx)
 	case HELP_BOOKMARK:
 		return (gettext("\tbookmark <snapshot> <bookmark>\n"));
 	case HELP_CHANNEL_PROGRAM:
-		return (gettext("\tprogram [-t <instruction limit>] "
+		return (gettext("\tprogram [-n] [-t <instruction limit>] "
 		    "[-m <memory limit (b)>] <pool> <program file> "
 		    "[lua args...]\n"));
 	}
@@ -6982,11 +6982,12 @@ zfs_do_channel_program(int argc, char **argv)
 	nvlist_t *outnvl;
 	uint64_t instrlimit = ZCP_DEFAULT_INSTRLIMIT;
 	uint64_t memlimit = ZCP_DEFAULT_MEMLIMIT;
+	boolean_t sync_flag = B_TRUE;
 	zpool_handle_t *zhp;
 
 	/* check options */
 	while (-1 !=
-	    (c = getopt(argc, argv, "t:(instr-limit)m:(memory-limit)"))) {
+	    (c = getopt(argc, argv, "nt:(instr-limit)m:(memory-limit)"))) {
 		switch (c) {
 		case 't':
 		case 'm': {
@@ -7024,6 +7025,10 @@ zfs_do_channel_program(int argc, char **argv)
 			}
 			break;
 		}
+		case 'n': {
+			sync_flag = B_FALSE;
+			break;
+		}
 		case '?':
 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
 			    optopt);
@@ -7095,8 +7100,13 @@ zfs_do_channel_program(int argc, char **argv)
 	nvlist_t *argnvl = fnvlist_alloc();
 	fnvlist_add_string_array(argnvl, ZCP_ARG_CLIARGV, argv + 2, argc - 2);
 
-	ret = lzc_channel_program(poolname, progbuf, instrlimit, memlimit,
-	    argnvl, &outnvl);
+	if (sync_flag) {
+		ret = lzc_channel_program(poolname, progbuf,
+		    instrlimit, memlimit, argnvl, &outnvl);
+	} else {
+		ret = lzc_channel_program_nosync(poolname, progbuf,
+		    instrlimit, memlimit, argnvl, &outnvl);
+	}
 
 	if (ret != 0) {
 		/*

Modified: vendor/illumos/dist/lib/libzfs/common/libzfs_dataset.c
==============================================================================
--- vendor/illumos/dist/lib/libzfs/common/libzfs_dataset.c	Sun Jan 21 17:31:31 2018	(r328219)
+++ vendor/illumos/dist/lib/libzfs/common/libzfs_dataset.c	Sun Jan 21 19:26:38 2018	(r328220)
@@ -2348,7 +2348,7 @@ zcp_check(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t
 	fnvlist_add_string(argnvl, "dataset", zhp->zfs_name);
 	fnvlist_add_string(argnvl, "property", zfs_prop_to_name(prop));
 
-	error = lzc_channel_program(poolname, program,
+	error = lzc_channel_program_nosync(poolname, program,
 	    10 * 1000 * 1000, 10 * 1024 * 1024, argnvl, &outnvl);
 
 	if (error == 0) {

Modified: vendor/illumos/dist/lib/libzfs_core/common/libzfs_core.c
==============================================================================
--- vendor/illumos/dist/lib/libzfs_core/common/libzfs_core.c	Sun Jan 21 17:31:31 2018	(r328219)
+++ vendor/illumos/dist/lib/libzfs_core/common/libzfs_core.c	Sun Jan 21 19:26:38 2018	(r328220)
@@ -881,6 +881,25 @@ lzc_destroy_bookmarks(nvlist_t *bmarks, nvlist_t **err
 	return (error);
 }
 
+static int
+lzc_channel_program_impl(const char *pool, const char *program, boolean_t sync,
+    uint64_t instrlimit, uint64_t memlimit, nvlist_t *argnvl, nvlist_t **outnvl)
+{
+	int error;
+	nvlist_t *args;
+
+	args = fnvlist_alloc();
+	fnvlist_add_string(args, ZCP_ARG_PROGRAM, program);
+	fnvlist_add_nvlist(args, ZCP_ARG_ARGLIST, argnvl);
+	fnvlist_add_boolean_value(args, ZCP_ARG_SYNC, sync);
+	fnvlist_add_uint64(args, ZCP_ARG_INSTRLIMIT, instrlimit);
+	fnvlist_add_uint64(args, ZCP_ARG_MEMLIMIT, memlimit);
+	error = lzc_ioctl(ZFS_IOC_CHANNEL_PROGRAM, pool, args, outnvl);
+	fnvlist_free(args);
+
+	return (error);
+}
+
 /*
  * Executes a channel program.
  *
@@ -918,16 +937,26 @@ int
 lzc_channel_program(const char *pool, const char *program, uint64_t instrlimit,
     uint64_t memlimit, nvlist_t *argnvl, nvlist_t **outnvl)
 {
-	int error;
-	nvlist_t *args;
+	return (lzc_channel_program_impl(pool, program, B_TRUE, instrlimit,
+	    memlimit, argnvl, outnvl));
+}
 
-	args = fnvlist_alloc();
-	fnvlist_add_string(args, ZCP_ARG_PROGRAM, program);
-	fnvlist_add_nvlist(args, ZCP_ARG_ARGLIST, argnvl);
-	fnvlist_add_uint64(args, ZCP_ARG_INSTRLIMIT, instrlimit);
-	fnvlist_add_uint64(args, ZCP_ARG_MEMLIMIT, memlimit);
-	error = lzc_ioctl(ZFS_IOC_CHANNEL_PROGRAM, pool, args, outnvl);
-	fnvlist_free(args);
-
-	return (error);
+/*
+ * Executes a read-only channel program.
+ *
+ * A read-only channel program works programmatically the same way as a
+ * normal channel program executed with lzc_channel_program(). The only
+ * difference is it runs exclusively in open-context and therefore can
+ * return faster. The downside to that, is that the program cannot change
+ * on-disk state by calling functions from the zfs.sync submodule.
+ *
+ * The return values of this function (and their meaning) are exactly the
+ * same as the ones described in lzc_channel_program().
+ */
+int
+lzc_channel_program_nosync(const char *pool, const char *program,
+    uint64_t timeout, uint64_t memlimit, nvlist_t *argnvl, nvlist_t **outnvl)
+{
+	return (lzc_channel_program_impl(pool, program, B_FALSE, timeout,
+	    memlimit, argnvl, outnvl));
 }

Modified: vendor/illumos/dist/lib/libzfs_core/common/libzfs_core.h
==============================================================================
--- vendor/illumos/dist/lib/libzfs_core/common/libzfs_core.h	Sun Jan 21 17:31:31 2018	(r328219)
+++ vendor/illumos/dist/lib/libzfs_core/common/libzfs_core.h	Sun Jan 21 19:26:38 2018	(r328220)
@@ -86,8 +86,10 @@ boolean_t lzc_exists(const char *);
 int lzc_rollback(const char *, char *, int);
 int lzc_rollback_to(const char *, const char *);
 
-int lzc_channel_program(const char *, const char *, uint64_t, uint64_t,
-    nvlist_t *, nvlist_t **);
+int lzc_channel_program(const char *, const char *, uint64_t,
+    uint64_t, nvlist_t *, nvlist_t **);
+int lzc_channel_program_nosync(const char *, const char *, uint64_t,
+    uint64_t, nvlist_t *, nvlist_t **);
 
 #ifdef	__cplusplus
 }

Modified: vendor/illumos/dist/man/man1m/zfs-program.1m
==============================================================================
--- vendor/illumos/dist/man/man1m/zfs-program.1m	Sun Jan 21 17:31:31 2018	(r328219)
+++ vendor/illumos/dist/man/man1m/zfs-program.1m	Sun Jan 21 19:26:38 2018	(r328220)
@@ -14,10 +14,11 @@
 .Dt ZFS-PROGRAM 1M
 .Os
 .Sh NAME
-.Nm zfs program
+.Nm "zfs program"
 .Nd executes ZFS channel programs
 .Sh SYNOPSIS
-.Cm zfs program
+.Cm "zfs program"
+.Op Fl n
 .Op Fl t Ar instruction-limit
 .Op Fl m Ar memory-limit
 .Ar pool
@@ -45,6 +46,14 @@ will be run on
 and any attempts to access or modify other pools will cause an error.
 .Sh OPTIONS
 .Bl -tag -width "-t"
+.It Fl n
+Executes a read-only channel program, which runs faster.
+The program cannot change on-disk state by calling functions from the
+zfs.sync submodule.
+The program can be used to gather information such as properties and
+determining if changes would succeed (zfs.check.*).
+Without this flag, all pending changes must be synced to disk before a
+channel program can complete.
 .It Fl t Ar instruction-limit
 Execution time limit, in number of Lua instructions to execute.
 If a channel program executes more than the specified number of instructions,

Modified: vendor/illumos/dist/man/man1m/zfs.1m
==============================================================================
--- vendor/illumos/dist/man/man1m/zfs.1m	Sun Jan 21 17:31:31 2018	(r328219)
+++ vendor/illumos/dist/man/man1m/zfs.1m	Sun Jan 21 19:26:38 2018	(r328220)
@@ -267,6 +267,7 @@
 .Ar snapshot Ar snapshot Ns | Ns Ar filesystem
 .Nm
 .Cm program
+.Op Fl n
 .Op Fl t Ar timeout
 .Op Fl m Ar memory_limit
 .Ar pool script
@@ -3408,6 +3409,7 @@ Display the path's inode change time as the first colu
 .It Xo
 .Nm
 .Cm program
+.Op Fl n
 .Op Fl t Ar timeout
 .Op Fl m Ar memory_limit
 .Ar pool script
@@ -3427,8 +3429,15 @@ Channel programs may only be run with root privileges.
 .sp
 For full documentation of the ZFS channel program interface, see the manual
 page for
-.Xr zfs-program 1M .
 .Bl -tag -width ""
+.It Fl n
+Executes a read-only channel program, which runs faster.
+The program cannot change on-disk state by calling functions from
+the zfs.sync submodule.
+The program can be used to gather information such as properties and
+determining if changes would succeed (zfs.check.*).
+Without this flag, all pending changes must be synced to disk before
+a channel program can complete.
 .It Fl t Ar timeout
 Execution time limit, in milliseconds.
 If a channel program executes for longer than the provided timeout, it will



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