mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-27 04:32:16 +03:00
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:
committed by
Brian Behlendorf
parent
8824a7f133
commit
d99a015343
+69
-11
@@ -27,7 +27,7 @@
|
||||
* Copyright (c) 2014, 2016 Joyent, Inc. All rights reserved.
|
||||
* Copyright 2016 Nexenta Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2014, Joyent, Inc. All rights reserved.
|
||||
* Copyright (c) 2011, 2015 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011, 2016 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
|
||||
* Copyright (c) 2013 Steven Hartland. All rights reserved.
|
||||
* Copyright (c) 2014 Integros [integros.com]
|
||||
@@ -193,6 +193,7 @@
|
||||
#include <sys/dsl_bookmark.h>
|
||||
#include <sys/dsl_userhold.h>
|
||||
#include <sys/zfeature.h>
|
||||
#include <sys/zcp.h>
|
||||
#include <sys/zio_checksum.h>
|
||||
|
||||
#include <linux/miscdevice.h>
|
||||
@@ -203,6 +204,9 @@
|
||||
#include "zfs_deleg.h"
|
||||
#include "zfs_comutil.h"
|
||||
|
||||
#include <sys/lua/lua.h>
|
||||
#include <sys/lua/lauxlib.h>
|
||||
|
||||
/*
|
||||
* Limit maximum nvlist size. We don't want users passing in insane values
|
||||
* for zc->zc_nvlist_src_size, since we will need to allocate that much memory.
|
||||
@@ -1414,17 +1418,11 @@ put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl)
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
getzfsvfs(const char *dsname, zfsvfs_t **zfvp)
|
||||
int
|
||||
getzfsvfs_impl(objset_t *os, zfsvfs_t **zfvp)
|
||||
{
|
||||
objset_t *os;
|
||||
int error;
|
||||
|
||||
error = dmu_objset_hold(dsname, FTAG, &os);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
int error = 0;
|
||||
if (dmu_objset_type(os) != DMU_OST_ZFS) {
|
||||
dmu_objset_rele(os, FTAG);
|
||||
return (SET_ERROR(EINVAL));
|
||||
}
|
||||
|
||||
@@ -1436,6 +1434,20 @@ getzfsvfs(const char *dsname, zfsvfs_t **zfvp)
|
||||
error = SET_ERROR(ESRCH);
|
||||
}
|
||||
mutex_exit(&os->os_user_ptr_lock);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
getzfsvfs(const char *dsname, zfsvfs_t **zfvp)
|
||||
{
|
||||
objset_t *os;
|
||||
int error;
|
||||
|
||||
error = dmu_objset_hold(dsname, FTAG, &os);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
error = getzfsvfs_impl(os, zfvp);
|
||||
dmu_objset_rele(os, FTAG);
|
||||
return (error);
|
||||
}
|
||||
@@ -3660,6 +3672,36 @@ zfs_ioc_destroy_bookmarks(const char *poolname, nvlist_t *innvl,
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
zfs_ioc_channel_program(const char *poolname, nvlist_t *innvl,
|
||||
nvlist_t *outnvl)
|
||||
{
|
||||
char *program;
|
||||
uint64_t instrlimit, memlimit;
|
||||
nvpair_t *nvarg = NULL;
|
||||
|
||||
if (0 != nvlist_lookup_string(innvl, ZCP_ARG_PROGRAM, &program)) {
|
||||
return (EINVAL);
|
||||
}
|
||||
if (0 != nvlist_lookup_uint64(innvl, ZCP_ARG_INSTRLIMIT, &instrlimit)) {
|
||||
instrlimit = ZCP_DEFAULT_INSTRLIMIT;
|
||||
}
|
||||
if (0 != nvlist_lookup_uint64(innvl, ZCP_ARG_MEMLIMIT, &memlimit)) {
|
||||
memlimit = ZCP_DEFAULT_MEMLIMIT;
|
||||
}
|
||||
if (0 != nvlist_lookup_nvpair(innvl, ZCP_ARG_ARGLIST, &nvarg)) {
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
if (instrlimit == 0 || instrlimit > zfs_lua_max_instrlimit)
|
||||
return (EINVAL);
|
||||
if (memlimit == 0 || memlimit > ZCP_MAX_MEMLIMIT)
|
||||
return (EINVAL);
|
||||
|
||||
return (zcp_eval(poolname, program, instrlimit, memlimit,
|
||||
nvarg, outnvl));
|
||||
}
|
||||
|
||||
/*
|
||||
* inputs:
|
||||
* zc_name name of dataset to destroy
|
||||
@@ -6333,6 +6375,11 @@ zfs_ioctl_init(void)
|
||||
zfs_secpolicy_config, POOL_NAME, POOL_CHECK_SUSPENDED, B_TRUE,
|
||||
B_TRUE);
|
||||
|
||||
zfs_ioctl_register("channel_program", ZFS_IOC_CHANNEL_PROGRAM,
|
||||
zfs_ioc_channel_program, zfs_secpolicy_config,
|
||||
POOL_NAME, POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_TRUE,
|
||||
B_TRUE);
|
||||
|
||||
/* IOCTLS that use the legacy function signature */
|
||||
|
||||
zfs_ioctl_register_legacy(ZFS_IOC_POOL_FREEZE, zfs_ioc_pool_freeze,
|
||||
@@ -6803,12 +6850,23 @@ zfsdev_ioctl(struct file *filp, unsigned cmd, unsigned long arg)
|
||||
error = vec->zvec_func(zc->zc_name, innvl, outnvl);
|
||||
spl_fstrans_unmark(cookie);
|
||||
|
||||
if (error == 0 && vec->zvec_allow_log &&
|
||||
/*
|
||||
* Some commands can partially execute, modify state, and still
|
||||
* return an error. In these cases, attempt to record what
|
||||
* was modified.
|
||||
*/
|
||||
if ((error == 0 ||
|
||||
(cmd == ZFS_IOC_CHANNEL_PROGRAM && error != EINVAL)) &&
|
||||
vec->zvec_allow_log &&
|
||||
spa_open(zc->zc_name, &spa, FTAG) == 0) {
|
||||
if (!nvlist_empty(outnvl)) {
|
||||
fnvlist_add_nvlist(lognv, ZPOOL_HIST_OUTPUT_NVL,
|
||||
outnvl);
|
||||
}
|
||||
if (error != 0) {
|
||||
fnvlist_add_int64(lognv, ZPOOL_HIST_ERRNO,
|
||||
error);
|
||||
}
|
||||
(void) spa_history_log_nvl(spa, lognv);
|
||||
spa_close(spa, FTAG);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user