summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/fs/zfs/zfs_ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/fs/zfs/zfs_ioctl.c')
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_ioctl.c80
1 files changed, 69 insertions, 11 deletions
diff --git a/usr/src/uts/common/fs/zfs/zfs_ioctl.c b/usr/src/uts/common/fs/zfs/zfs_ioctl.c
index d93c1f02c3..b8302e0a28 100644
--- a/usr/src/uts/common/fs/zfs/zfs_ioctl.c
+++ b/usr/src/uts/common/fs/zfs/zfs_ioctl.c
@@ -26,7 +26,7 @@
* Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved.
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2014, 2016 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]
@@ -185,6 +185,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 "zfs_namecheck.h"
@@ -192,6 +193,9 @@
#include "zfs_deleg.h"
#include "zfs_comutil.h"
+#include "lua.h"
+#include "lauxlib.h"
+
extern struct modlfs zfs_modlfs;
extern void zfs_init(void);
@@ -1393,17 +1397,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));
}
@@ -1415,6 +1413,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);
}
@@ -3605,6 +3617,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
@@ -5757,6 +5799,11 @@ zfs_ioctl_init(void)
POOL_NAME,
POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, 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,
@@ -6123,12 +6170,23 @@ zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp)
outnvl = fnvlist_alloc();
error = vec->zvec_func(zc->zc_name, innvl, outnvl);
- if (error == 0 && vec->zvec_allow_log &&
+ /*
+ * Some commands can partially execute, modfiy 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);
}