OpenZFS 7431 - ZFS Channel Programs

Authored by: Chris Williamson <chris.williamson@delphix.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: John Kennedy <john.kennedy@delphix.com>
Reviewed by: Dan Kimmel <dan.kimmel@delphix.com>
Approved by: Garrett D'Amore <garrett@damore.org>
Ported-by: Don Brady <don.brady@delphix.com>
Ported-by: John Kennedy <john.kennedy@delphix.com>

OpenZFS-issue: https://www.illumos.org/issues/7431
OpenZFS-commit: https://github.com/openzfs/openzfs/commit/dfc11533

Porting Notes:
* The CLI long option arguments for '-t' and '-m' don't parse on linux
* Switched from kmem_alloc to vmem_alloc in zcp_lua_alloc
* Lua implementation is built as its own module (zlua.ko)
* Lua headers consumed directly by zfs code moved to 'include/sys/lua/'
* There is no native setjmp/longjump available in stock Linux kernel.
  Brought over implementations from illumos and FreeBSD
* The get_temporary_prop() was adapted due to VFS platform differences
* Use of inline functions in lua parser to reduce stack usage per C call
* Skip some ZFS Test Suite ZCP tests on sparc64 to avoid stack overflow
This commit is contained in:
Chris Williamson
2018-02-08 09:16:23 -07:00
committed by Brian Behlendorf
parent 8824a7f133
commit d99a015343
179 changed files with 27056 additions and 273 deletions
+2 -1
View File
@@ -12,7 +12,8 @@ USER_C = \
nodist_libzfs_core_la_SOURCES = $(USER_C)
libzfs_core_la_LIBADD = \
$(top_builddir)/lib/libnvpair/libnvpair.la
$(top_builddir)/lib/libnvpair/libnvpair.la \
$(top_builddir)/lib/libuutil/libuutil.la
libzfs_core_la_LDFLAGS = -version-info 1:0:0
+62 -2
View File
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
* Copyright (c) 2012, 2016 by Delphix. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
* Copyright (c) 2017 Datto Inc.
* Copyright 2017 RackTop Systems.
@@ -156,7 +156,15 @@ lzc_ioctl(zfs_ioc_t ioc, const char *name,
}
while (ioctl(g_fd, ioc, &zc) != 0) {
if (errno == ENOMEM && resultp != NULL) {
/*
* If ioctl exited with ENOMEM, we retry the ioctl after
* increasing the size of the destination nvlist.
*
* Channel programs that exit with ENOMEM probably ran over the
* lua memory sandbox; they should not be retried.
*/
if (errno == ENOMEM && resultp != NULL &&
ioc != ZFS_IOC_CHANNEL_PROGRAM) {
free((void *)(uintptr_t)zc.zc_nvlist_dst);
zc.zc_nvlist_dst_size *= 2;
zc.zc_nvlist_dst = (uint64_t)(uintptr_t)
@@ -1050,6 +1058,57 @@ lzc_destroy_bookmarks(nvlist_t *bmarks, nvlist_t **errlist)
return (error);
}
/*
* Executes a channel program.
*
* If this function returns 0 the channel program was successfully loaded and
* ran without failing. Note that individual commands the channel program ran
* may have failed and the channel program is responsible for reporting such
* errors through outnvl if they are important.
*
* This method may also return:
*
* EINVAL The program contains syntax errors, or an invalid memory or time
* limit was given. No part of the channel program was executed.
* If caused by syntax errors, 'outnvl' contains information about the
* errors.
*
* ECHRNG The program was executed, but encountered a runtime error, such as
* calling a function with incorrect arguments, invoking the error()
* function directly, failing an assert() command, etc. Some portion
* of the channel program may have executed and committed changes.
* Information about the failure can be found in 'outnvl'.
*
* ENOMEM The program fully executed, but the output buffer was not large
* enough to store the returned value. No output is returned through
* 'outnvl'.
*
* ENOSPC The program was terminated because it exceeded its memory usage
* limit. Some portion of the channel program may have executed and
* committed changes to disk. No output is returned through 'outnvl'.
*
* ETIME The program was terminated because it exceeded its Lua instruction
* limit. Some portion of the channel program may have executed and
* committed changes to disk. No output is returned through 'outnvl'.
*/
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;
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);
}
/*
* Performs key management functions
*
@@ -1110,6 +1169,7 @@ lzc_change_key(const char *fsname, uint64_t crypt_cmd, nvlist_t *props,
error = lzc_ioctl(ZFS_IOC_CHANGE_KEY, fsname, ioc_args, NULL);
nvlist_free(hidden_args);
nvlist_free(ioc_args);
return (error);
}