mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-11-18 10:21:01 +03:00
e625030c11
Problem Statement ================= ZFS Channel program scripts currently require a timeout, so that hung or long-running scripts return a timeout error instead of causing ZFS to get wedged. This limit can currently be set up to 100 million Lua instructions. Even with a limit in place, it would be desirable to have a sys admin (support engineer) be able to cancel a script that is taking a long time. Proposed Solution ================= Make it possible to abort a channel program by sending an interrupt signal.In the underlying txg_wait_sync function, switch the cv_wait to a cv_wait_sig to catch the signal. Once a signal is encountered, the dsl_sync_task function can install a Lua hook that will get called before the Lua interpreter executes a new line of code. The dsl_sync_task can resume with a standard txg_wait_sync call and wait for the txg to complete. Meanwhile, the hook will abort the script and indicate that the channel program was canceled. The kernel returns a EINTR to indicate that the channel program run was canceled. Porting notes: Added missing return value from cv_wait_sig() Authored by: Don Brady <don.brady@delphix.com> Reviewed by: Sebastien Roy <sebastien.roy@delphix.com> Reviewed by: Serapheim Dimitropoulos <serapheim.dimitro@delphix.com> Reviewed by: Matt Ahrens <matt@delphix.com> Reviewed by: Sara Hartse <sara.hartse@delphix.com> Reviewed by: Brian Behlendorf <behlendorf1@llnl.gov> Approved by: Robert Mustacchi <rm@joyent.com> Ported-by: Don Brady <don.brady@delphix.com> Signed-off-by: Don Brady <don.brady@delphix.com> OpenZFS-issue: https://www.illumos.org/issues/9425 OpenZFS-commit: https://github.com/illumos/illumos-gate/commit/d0cb1fb926 Closes #8904
186 lines
4.6 KiB
C
186 lines
4.6 KiB
C
/*
|
|
* CDDL HEADER START
|
|
*
|
|
* This file and its contents are supplied under the terms of the
|
|
* Common Development and Distribution License ("CDDL"), version 1.0.
|
|
* You may only use this file in accordance with the terms of version
|
|
* 1.0 of the CDDL.
|
|
*
|
|
* A full copy of the text of the CDDL should have accompanied this
|
|
* source. A copy of the CDDL is also available via the Internet at
|
|
* http://www.illumos.org/license/CDDL.
|
|
*
|
|
* CDDL HEADER END
|
|
*/
|
|
|
|
/*
|
|
* Copyright (c) 2016, 2018 by Delphix. All rights reserved.
|
|
*/
|
|
|
|
#ifndef _SYS_ZCP_H
|
|
#define _SYS_ZCP_H
|
|
|
|
#include <sys/dmu_tx.h>
|
|
#include <sys/dsl_pool.h>
|
|
|
|
#include <sys/lua/lua.h>
|
|
#include <sys/lua/lualib.h>
|
|
#include <sys/lua/lauxlib.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#define ZCP_RUN_INFO_KEY "runinfo"
|
|
|
|
extern unsigned long zfs_lua_max_instrlimit;
|
|
extern unsigned long zfs_lua_max_memlimit;
|
|
|
|
int zcp_argerror(lua_State *, int, const char *, ...);
|
|
|
|
int zcp_eval(const char *, const char *, boolean_t, uint64_t, uint64_t,
|
|
nvpair_t *, nvlist_t *);
|
|
|
|
int zcp_load_list_lib(lua_State *);
|
|
|
|
int zcp_load_synctask_lib(lua_State *, boolean_t);
|
|
|
|
typedef void (zcp_cleanup_t)(void *);
|
|
typedef struct zcp_cleanup_handler {
|
|
zcp_cleanup_t *zch_cleanup_func;
|
|
void *zch_cleanup_arg;
|
|
list_node_t zch_node;
|
|
} zcp_cleanup_handler_t;
|
|
|
|
typedef struct zcp_alloc_arg {
|
|
boolean_t aa_must_succeed;
|
|
int64_t aa_alloc_remaining;
|
|
int64_t aa_alloc_limit;
|
|
} zcp_alloc_arg_t;
|
|
|
|
typedef struct zcp_run_info {
|
|
dsl_pool_t *zri_pool;
|
|
|
|
/*
|
|
* An estimate of the total amount of space consumed by all
|
|
* synctasks we have successfully performed so far in this
|
|
* channel program. Used to generate ENOSPC errors for syncfuncs.
|
|
*/
|
|
int zri_space_used;
|
|
|
|
/*
|
|
* The credentials of the thread which originally invoked the channel
|
|
* program. Since channel programs are always invoked from the synctask
|
|
* thread they should always do permissions checks against this cred
|
|
* rather than the 'current' thread's.
|
|
*/
|
|
cred_t *zri_cred;
|
|
|
|
/*
|
|
* The tx in which this channel program is running.
|
|
*/
|
|
dmu_tx_t *zri_tx;
|
|
|
|
/*
|
|
* The maximum number of Lua instructions the channel program is allowed
|
|
* to execute. If it takes longer than this it will time out. A value
|
|
* of 0 indicates no instruction limit.
|
|
*/
|
|
uint64_t zri_maxinstrs;
|
|
|
|
/*
|
|
* The number of Lua instructions the channel program has executed.
|
|
*/
|
|
uint64_t zri_curinstrs;
|
|
|
|
/*
|
|
* Boolean indicating whether or not the channel program exited
|
|
* because it timed out.
|
|
*/
|
|
boolean_t zri_timed_out;
|
|
|
|
/*
|
|
* Channel program was canceled by user
|
|
*/
|
|
boolean_t zri_canceled;
|
|
|
|
/*
|
|
* Boolean indicating whether or not we are running in syncing
|
|
* context.
|
|
*/
|
|
boolean_t zri_sync;
|
|
|
|
/*
|
|
* List of currently registered cleanup handlers, which will be
|
|
* triggered in the event of a fatal error.
|
|
*/
|
|
list_t zri_cleanup_handlers;
|
|
|
|
/*
|
|
* The Lua state context of our channel program.
|
|
*/
|
|
lua_State *zri_state;
|
|
|
|
/*
|
|
* Lua memory allocator arguments.
|
|
*/
|
|
zcp_alloc_arg_t *zri_allocargs;
|
|
|
|
/*
|
|
* Contains output values from zcp script or error string.
|
|
*/
|
|
nvlist_t *zri_outnvl;
|
|
|
|
/*
|
|
* The errno number returned to caller of zcp_eval().
|
|
*/
|
|
int zri_result;
|
|
} zcp_run_info_t;
|
|
|
|
zcp_run_info_t *zcp_run_info(lua_State *);
|
|
zcp_cleanup_handler_t *zcp_register_cleanup(lua_State *, zcp_cleanup_t, void *);
|
|
void zcp_deregister_cleanup(lua_State *, zcp_cleanup_handler_t *);
|
|
void zcp_cleanup(lua_State *);
|
|
|
|
/*
|
|
* Argument parsing routines for channel program callback functions.
|
|
*/
|
|
typedef struct zcp_arg {
|
|
/*
|
|
* The name of this argument. For keyword arguments this is the name
|
|
* functions will use to set the argument. For positional arguments
|
|
* the name has no programatic meaning, but will appear in error
|
|
* messages and help output.
|
|
*/
|
|
const char *za_name;
|
|
|
|
/*
|
|
* The Lua type this argument should have (e.g. LUA_TSTRING,
|
|
* LUA_TBOOLEAN) see the lua_type() function documentation for a
|
|
* complete list. Calling a function with an argument that does
|
|
* not match the expected type will result in the program terminating.
|
|
*/
|
|
const int za_lua_type;
|
|
} zcp_arg_t;
|
|
|
|
void zcp_parse_args(lua_State *, const char *, const zcp_arg_t *,
|
|
const zcp_arg_t *);
|
|
int zcp_nvlist_to_lua(lua_State *, nvlist_t *, char *, int);
|
|
int zcp_dataset_hold_error(lua_State *, dsl_pool_t *, const char *, int);
|
|
struct dsl_dataset *zcp_dataset_hold(lua_State *, dsl_pool_t *,
|
|
const char *, void *);
|
|
|
|
typedef int (zcp_lib_func_t)(lua_State *);
|
|
typedef struct zcp_lib_info {
|
|
const char *name;
|
|
zcp_lib_func_t *func;
|
|
const zcp_arg_t pargs[4];
|
|
const zcp_arg_t kwargs[2];
|
|
} zcp_lib_info_t;
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* _SYS_ZCP_H */
|