static void test_channel_program(const char *pool) { const char *program = "arg = ...\n" "argv = arg[\"argv\"]\n" "return argv[1]"; char *const argv[1] = { "Hello World!" }; nvlist_t *required = fnvlist_alloc(); nvlist_t *optional = fnvlist_alloc(); nvlist_t *args = fnvlist_alloc(); fnvlist_add_string(required, "program", program); fnvlist_add_string_array(args, "argv", argv, 1); fnvlist_add_nvlist(required, "arg", args); fnvlist_add_boolean_value(optional, "sync", B_TRUE); fnvlist_add_uint64(optional, "instrlimit", 1000 * 1000); fnvlist_add_uint64(optional, "memlimit", 8192 * 1024); IOC_INPUT_TEST(ZFS_IOC_CHANNEL_PROGRAM, pool, required, optional, 0); nvlist_free(args); nvlist_free(optional); nvlist_free(required); }
static void test_pool_sync(const char *pool) { nvlist_t *required = fnvlist_alloc(); fnvlist_add_boolean_value(required, "force", B_TRUE); IOC_INPUT_TEST(ZFS_IOC_POOL_SYNC, pool, required, NULL, 0); nvlist_free(required); }
static void test_pool_reopen(const char *pool) { nvlist_t *required = fnvlist_alloc(); fnvlist_add_boolean_value(required, "scrub_restart", B_FALSE); IOC_INPUT_TEST(ZFS_IOC_POOL_REOPEN, pool, required, NULL, 0); nvlist_free(required); }
int lzc_reopen(const char *pool_name, boolean_t scrub_restart) { nvlist_t *args = fnvlist_alloc(); int error; fnvlist_add_boolean_value(args, "scrub_restart", scrub_restart); error = lzc_ioctl(ZFS_IOC_POOL_REOPEN, pool_name, args, NULL); nvlist_free(args); return (error); }
/* * Convert a value from the given index into the lua stack to an nvpair, adding * it to an nvlist with the given key. * * Values are converted as follows: * * string -> string * number -> int64 * boolean -> boolean * nil -> boolean (no value) * * Lua tables are converted to nvlists and then inserted. The table's keys * are converted to strings then used as keys in the nvlist to store each table * element. Keys are converted as follows: * * string -> no change * number -> "%lld" * boolean -> "true" | "false" * nil -> error * * In the case of a key collision, an error is thrown. * * If an error is encountered, a nonzero error code is returned, and an error * string will be pushed onto the Lua stack. */ static int zcp_lua_to_nvlist_impl(lua_State *state, int index, nvlist_t *nvl, const char *key, int depth) { /* * Verify that we have enough remaining space in the lua stack to parse * a key-value pair and push an error. */ if (!lua_checkstack(state, 3)) { (void) lua_pushstring(state, "Lua stack overflow"); return (1); } index = lua_absindex(state, index); switch (lua_type(state, index)) { case LUA_TNIL: fnvlist_add_boolean(nvl, key); break; case LUA_TBOOLEAN: fnvlist_add_boolean_value(nvl, key, lua_toboolean(state, index)); break; case LUA_TNUMBER: fnvlist_add_int64(nvl, key, lua_tonumber(state, index)); break; case LUA_TSTRING: fnvlist_add_string(nvl, key, lua_tostring(state, index)); break; case LUA_TTABLE: { nvlist_t *value_nvl = zcp_table_to_nvlist(state, index, depth); if (value_nvl == NULL) return (EINVAL); fnvlist_add_nvlist(nvl, key, value_nvl); fnvlist_free(value_nvl); break; } default: (void) lua_pushfstring(state, "Invalid value type '%s' for key '%s'", lua_typename(state, lua_type(state, index)), key); return (EINVAL); } return (0); }
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); }
static int pool_active(void *unused, const char *name, uint64_t guid, boolean_t *isactive) { zfs_cmd_t *zcp; nvlist_t *innvl; char *packed = NULL; size_t size = 0; int fd, ret; /* * Use ZFS_IOC_POOL_SYNC to confirm if a pool is active */ fd = open("/dev/zfs", O_RDWR); if (fd < 0) return (-1); zcp = umem_zalloc(sizeof (zfs_cmd_t), UMEM_NOFAIL); innvl = fnvlist_alloc(); fnvlist_add_boolean_value(innvl, "force", B_FALSE); (void) strlcpy(zcp->zc_name, name, sizeof (zcp->zc_name)); packed = fnvlist_pack(innvl, &size); zcp->zc_nvlist_src = (uint64_t)(uintptr_t)packed; zcp->zc_nvlist_src_size = size; ret = ioctl(fd, ZFS_IOC_POOL_SYNC, zcp); fnvlist_pack_free(packed, size); free((void *)(uintptr_t)zcp->zc_nvlist_dst); nvlist_free(innvl); umem_free(zcp, sizeof (zfs_cmd_t)); (void) close(fd); *isactive = (ret == 0); return (0); }
static void run_tests(void) { const char *key = "key"; /* Note: maximum nvlist key length is 32KB */ int len = 1024 * 31; char *bigstring = malloc(len); for (int i = 0; i < len; i++) bigstring[i] = 'a' + i % 26; bigstring[len - 1] = '\0'; nvl = fnvlist_alloc(); fnvlist_add_boolean(nvl, key); test("boolean", B_TRUE, B_FALSE); fnvlist_add_boolean_value(nvl, key, B_TRUE); test("boolean_value", B_FALSE, B_FALSE); fnvlist_add_byte(nvl, key, 1); test("byte", B_FALSE, B_FALSE); fnvlist_add_int8(nvl, key, 1); test("int8", B_FALSE, B_FALSE); fnvlist_add_uint8(nvl, key, 1); test("uint8", B_FALSE, B_FALSE); fnvlist_add_int16(nvl, key, 1); test("int16", B_FALSE, B_FALSE); fnvlist_add_uint16(nvl, key, 1); test("uint16", B_FALSE, B_FALSE); fnvlist_add_int32(nvl, key, 1); test("int32", B_FALSE, B_FALSE); fnvlist_add_uint32(nvl, key, 1); test("uint32", B_FALSE, B_FALSE); fnvlist_add_int64(nvl, key, 1); test("int64", B_TRUE, B_TRUE); fnvlist_add_uint64(nvl, key, 1); test("uint64", B_FALSE, B_FALSE); fnvlist_add_string(nvl, key, "1"); test("string", B_TRUE, B_TRUE); { nvlist_t *val = fnvlist_alloc(); fnvlist_add_string(val, "subkey", "subvalue"); fnvlist_add_nvlist(nvl, key, val); fnvlist_free(val); test("nvlist", B_TRUE, B_TRUE); } { boolean_t val[2] = { B_FALSE, B_TRUE }; fnvlist_add_boolean_array(nvl, key, val, 2); test("boolean_array", B_FALSE, B_FALSE); } { uchar_t val[2] = { 0, 1 }; fnvlist_add_byte_array(nvl, key, val, 2); test("byte_array", B_FALSE, B_FALSE); } { int8_t val[2] = { 0, 1 }; fnvlist_add_int8_array(nvl, key, val, 2); test("int8_array", B_FALSE, B_FALSE); } { uint8_t val[2] = { 0, 1 }; fnvlist_add_uint8_array(nvl, key, val, 2); test("uint8_array", B_FALSE, B_FALSE); } { int16_t val[2] = { 0, 1 }; fnvlist_add_int16_array(nvl, key, val, 2); test("int16_array", B_FALSE, B_FALSE); } { uint16_t val[2] = { 0, 1 }; fnvlist_add_uint16_array(nvl, key, val, 2); test("uint16_array", B_FALSE, B_FALSE); } { int32_t val[2] = { 0, 1 }; fnvlist_add_int32_array(nvl, key, val, 2); test("int32_array", B_FALSE, B_FALSE); } { uint32_t val[2] = { 0, 1 }; fnvlist_add_uint32_array(nvl, key, val, 2); test("uint32_array", B_FALSE, B_FALSE); } { int64_t val[2] = { 0, 1 }; fnvlist_add_int64_array(nvl, key, val, 2); test("int64_array", B_TRUE, B_FALSE); } { uint64_t val[2] = { 0, 1 }; fnvlist_add_uint64_array(nvl, key, val, 2); test("uint64_array", B_FALSE, B_FALSE); } { char *const val[2] = { "0", "1" }; fnvlist_add_string_array(nvl, key, val, 2); test("string_array", B_TRUE, B_FALSE); } { nvlist_t *val[2]; val[0] = fnvlist_alloc(); fnvlist_add_string(val[0], "subkey", "subvalue"); val[1] = fnvlist_alloc(); fnvlist_add_string(val[1], "subkey2", "subvalue2"); fnvlist_add_nvlist_array(nvl, key, val, 2); fnvlist_free(val[0]); fnvlist_free(val[1]); test("nvlist_array", B_FALSE, B_FALSE); } { fnvlist_add_string(nvl, bigstring, "1"); test("large_key", B_TRUE, B_TRUE); } { fnvlist_add_string(nvl, key, bigstring); test("large_value", B_TRUE, B_TRUE); } { for (int i = 0; i < 1024; i++) { char buf[32]; (void) snprintf(buf, sizeof (buf), "key-%u", i); fnvlist_add_int64(nvl, buf, i); } test("many_keys", B_TRUE, B_TRUE); } #ifndef __sparc__ { for (int i = 0; i < 10; i++) { nvlist_t *newval = fnvlist_alloc(); fnvlist_add_nvlist(newval, "key", nvl); fnvlist_free(nvl); nvl = newval; } test("deeply_nested_pos", B_TRUE, B_TRUE); } { for (int i = 0; i < 90; i++) { nvlist_t *newval = fnvlist_alloc(); fnvlist_add_nvlist(newval, "key", nvl); fnvlist_free(nvl); nvl = newval; } test("deeply_nested_neg", B_FALSE, B_FALSE); } #endif free(bigstring); fnvlist_free(nvl); }