1eda14cbcSMatt Macy /* 2eda14cbcSMatt Macy * CDDL HEADER START 3eda14cbcSMatt Macy * 4eda14cbcSMatt Macy * This file and its contents are supplied under the terms of the 5eda14cbcSMatt Macy * Common Development and Distribution License ("CDDL"), version 1.0. 6eda14cbcSMatt Macy * You may only use this file in accordance with the terms of version 7eda14cbcSMatt Macy * 1.0 of the CDDL. 8eda14cbcSMatt Macy * 9eda14cbcSMatt Macy * A full copy of the text of the CDDL should have accompanied this 10eda14cbcSMatt Macy * source. A copy of the CDDL is also available via the Internet at 11eda14cbcSMatt Macy * http://www.illumos.org/license/CDDL. 12eda14cbcSMatt Macy * 13eda14cbcSMatt Macy * CDDL HEADER END 14eda14cbcSMatt Macy */ 15eda14cbcSMatt Macy 16eda14cbcSMatt Macy /* 17eda14cbcSMatt Macy * Copyright (c) 2016 by Delphix. All rights reserved. 18eda14cbcSMatt Macy */ 19eda14cbcSMatt Macy 20eda14cbcSMatt Macy #include <sys/lua/lua.h> 21eda14cbcSMatt Macy #include <sys/lua/lualib.h> 22eda14cbcSMatt Macy #include <sys/lua/lauxlib.h> 23eda14cbcSMatt Macy 24eda14cbcSMatt Macy #include <zfs_prop.h> 25eda14cbcSMatt Macy 26eda14cbcSMatt Macy #include <sys/dsl_prop.h> 27eda14cbcSMatt Macy #include <sys/dsl_synctask.h> 28eda14cbcSMatt Macy #include <sys/dsl_dataset.h> 29eda14cbcSMatt Macy #include <sys/dsl_dir.h> 30eda14cbcSMatt Macy #include <sys/dmu_objset.h> 31eda14cbcSMatt Macy #include <sys/mntent.h> 32eda14cbcSMatt Macy #include <sys/sunddi.h> 33eda14cbcSMatt Macy #include <sys/zap.h> 34eda14cbcSMatt Macy #include <sys/zcp.h> 35eda14cbcSMatt Macy #include <sys/zcp_iter.h> 36eda14cbcSMatt Macy #include <sys/zcp_global.h> 37eda14cbcSMatt Macy #include <sys/zcp_prop.h> 38eda14cbcSMatt Macy #include <sys/zfs_ioctl.h> 39eda14cbcSMatt Macy #include <sys/zfs_znode.h> 40eda14cbcSMatt Macy #include <sys/zvol.h> 41eda14cbcSMatt Macy 42eda14cbcSMatt Macy #ifdef _KERNEL 43eda14cbcSMatt Macy #include <sys/zfs_quota.h> 44eda14cbcSMatt Macy #include <sys/zfs_vfsops.h> 45eda14cbcSMatt Macy #endif 46eda14cbcSMatt Macy 47eda14cbcSMatt Macy static int 48eda14cbcSMatt Macy get_objset_type(dsl_dataset_t *ds, zfs_type_t *type) 49eda14cbcSMatt Macy { 50eda14cbcSMatt Macy int error; 51eda14cbcSMatt Macy objset_t *os; 52eda14cbcSMatt Macy error = dmu_objset_from_ds(ds, &os); 53eda14cbcSMatt Macy if (error != 0) 54eda14cbcSMatt Macy return (error); 55eda14cbcSMatt Macy if (ds->ds_is_snapshot) { 56eda14cbcSMatt Macy *type = ZFS_TYPE_SNAPSHOT; 57eda14cbcSMatt Macy } else { 58eda14cbcSMatt Macy switch (os->os_phys->os_type) { 59eda14cbcSMatt Macy case DMU_OST_ZFS: 60eda14cbcSMatt Macy *type = ZFS_TYPE_FILESYSTEM; 61eda14cbcSMatt Macy break; 62eda14cbcSMatt Macy case DMU_OST_ZVOL: 63eda14cbcSMatt Macy *type = ZFS_TYPE_VOLUME; 64eda14cbcSMatt Macy break; 65eda14cbcSMatt Macy default: 66eda14cbcSMatt Macy return (EINVAL); 67eda14cbcSMatt Macy } 68eda14cbcSMatt Macy } 69eda14cbcSMatt Macy return (0); 70eda14cbcSMatt Macy } 71eda14cbcSMatt Macy 72eda14cbcSMatt Macy /* 73eda14cbcSMatt Macy * Returns the string name of ds's type in str (a buffer which should be 74eda14cbcSMatt Macy * at least 12 bytes long). 75eda14cbcSMatt Macy */ 76eda14cbcSMatt Macy static int 77eda14cbcSMatt Macy get_objset_type_name(dsl_dataset_t *ds, char *str) 78eda14cbcSMatt Macy { 79c03c5b1cSMartin Matuska zfs_type_t type = ZFS_TYPE_INVALID; 80c03c5b1cSMartin Matuska int error = get_objset_type(ds, &type); 81eda14cbcSMatt Macy if (error != 0) 82eda14cbcSMatt Macy return (error); 83eda14cbcSMatt Macy switch (type) { 84eda14cbcSMatt Macy case ZFS_TYPE_SNAPSHOT: 85eda14cbcSMatt Macy (void) strlcpy(str, "snapshot", ZAP_MAXVALUELEN); 86eda14cbcSMatt Macy break; 87eda14cbcSMatt Macy case ZFS_TYPE_FILESYSTEM: 88eda14cbcSMatt Macy (void) strlcpy(str, "filesystem", ZAP_MAXVALUELEN); 89eda14cbcSMatt Macy break; 90eda14cbcSMatt Macy case ZFS_TYPE_VOLUME: 91eda14cbcSMatt Macy (void) strlcpy(str, "volume", ZAP_MAXVALUELEN); 92eda14cbcSMatt Macy break; 93eda14cbcSMatt Macy default: 94eda14cbcSMatt Macy return (EINVAL); 95eda14cbcSMatt Macy } 96eda14cbcSMatt Macy return (0); 97eda14cbcSMatt Macy } 98eda14cbcSMatt Macy 99eda14cbcSMatt Macy /* 100eda14cbcSMatt Macy * Determines the source of a property given its setpoint and 101eda14cbcSMatt Macy * property type. It pushes the source to the lua stack. 102eda14cbcSMatt Macy */ 103eda14cbcSMatt Macy static void 104eda14cbcSMatt Macy get_prop_src(lua_State *state, const char *setpoint, zfs_prop_t prop) 105eda14cbcSMatt Macy { 106eda14cbcSMatt Macy if (zfs_prop_readonly(prop) || (prop == ZFS_PROP_VERSION)) { 107eda14cbcSMatt Macy lua_pushnil(state); 108eda14cbcSMatt Macy } else { 109eda14cbcSMatt Macy const char *src; 110eda14cbcSMatt Macy if (strcmp("", setpoint) == 0) { 111eda14cbcSMatt Macy src = "default"; 112eda14cbcSMatt Macy } else { 113eda14cbcSMatt Macy src = setpoint; 114eda14cbcSMatt Macy } 115eda14cbcSMatt Macy (void) lua_pushstring(state, src); 116eda14cbcSMatt Macy } 117eda14cbcSMatt Macy } 118eda14cbcSMatt Macy 119eda14cbcSMatt Macy /* 120eda14cbcSMatt Macy * Given an error encountered while getting properties, either longjmp's for 121eda14cbcSMatt Macy * a fatal error or pushes nothing to the stack for a non fatal one. 122eda14cbcSMatt Macy */ 123eda14cbcSMatt Macy static int 124eda14cbcSMatt Macy zcp_handle_error(lua_State *state, const char *dataset_name, 125eda14cbcSMatt Macy const char *property_name, int error) 126eda14cbcSMatt Macy { 127eda14cbcSMatt Macy ASSERT3S(error, !=, 0); 128eda14cbcSMatt Macy if (error == ENOENT) { 129eda14cbcSMatt Macy return (0); 130eda14cbcSMatt Macy } else if (error == EINVAL) { 131eda14cbcSMatt Macy return (luaL_error(state, 132eda14cbcSMatt Macy "property '%s' is not a valid property on dataset '%s'", 133eda14cbcSMatt Macy property_name, dataset_name)); 134eda14cbcSMatt Macy } else if (error == EIO) { 135eda14cbcSMatt Macy return (luaL_error(state, 136eda14cbcSMatt Macy "I/O error while retrieving property '%s' on dataset '%s'", 137eda14cbcSMatt Macy property_name, dataset_name)); 138eda14cbcSMatt Macy } else { 139eda14cbcSMatt Macy return (luaL_error(state, "unexpected error %d while " 140eda14cbcSMatt Macy "retrieving property '%s' on dataset '%s'", 141eda14cbcSMatt Macy error, property_name, dataset_name)); 142eda14cbcSMatt Macy } 143eda14cbcSMatt Macy } 144eda14cbcSMatt Macy 145eda14cbcSMatt Macy /* 146eda14cbcSMatt Macy * Look up a user defined property in the zap object. If it exists, push it 147eda14cbcSMatt Macy * and the setpoint onto the stack, otherwise don't push anything. 148eda14cbcSMatt Macy */ 149eda14cbcSMatt Macy static int 150eda14cbcSMatt Macy zcp_get_user_prop(lua_State *state, dsl_pool_t *dp, const char *dataset_name, 151eda14cbcSMatt Macy const char *property_name) 152eda14cbcSMatt Macy { 153eda14cbcSMatt Macy int error; 154eda14cbcSMatt Macy char *buf; 155eda14cbcSMatt Macy char setpoint[ZFS_MAX_DATASET_NAME_LEN]; 156eda14cbcSMatt Macy /* 157eda14cbcSMatt Macy * zcp_dataset_hold will either successfully return the requested 158eda14cbcSMatt Macy * dataset or throw a lua error and longjmp out of the zfs.get_prop call 159eda14cbcSMatt Macy * without returning. 160eda14cbcSMatt Macy */ 161eda14cbcSMatt Macy dsl_dataset_t *ds = zcp_dataset_hold(state, dp, dataset_name, FTAG); 162eda14cbcSMatt Macy if (ds == NULL) 163eda14cbcSMatt Macy return (1); /* not reached; zcp_dataset_hold() longjmp'd */ 164eda14cbcSMatt Macy 165eda14cbcSMatt Macy buf = kmem_alloc(ZAP_MAXVALUELEN, KM_SLEEP); 166eda14cbcSMatt Macy error = dsl_prop_get_ds(ds, property_name, 1, ZAP_MAXVALUELEN, 167eda14cbcSMatt Macy buf, setpoint); 168eda14cbcSMatt Macy dsl_dataset_rele(ds, FTAG); 169eda14cbcSMatt Macy 170eda14cbcSMatt Macy if (error != 0) { 171eda14cbcSMatt Macy kmem_free(buf, ZAP_MAXVALUELEN); 172eda14cbcSMatt Macy return (zcp_handle_error(state, dataset_name, property_name, 173eda14cbcSMatt Macy error)); 174eda14cbcSMatt Macy } 175eda14cbcSMatt Macy (void) lua_pushstring(state, buf); 176eda14cbcSMatt Macy (void) lua_pushstring(state, setpoint); 177eda14cbcSMatt Macy kmem_free(buf, ZAP_MAXVALUELEN); 178eda14cbcSMatt Macy return (2); 179eda14cbcSMatt Macy } 180eda14cbcSMatt Macy 181eda14cbcSMatt Macy /* 182eda14cbcSMatt Macy * Check if the property we're looking for is stored in the ds_dir. If so, 183eda14cbcSMatt Macy * return it in the 'val' argument. Return 0 on success and ENOENT and if 184eda14cbcSMatt Macy * the property is not present. 185eda14cbcSMatt Macy */ 186eda14cbcSMatt Macy static int 187eda14cbcSMatt Macy get_dsl_dir_prop(dsl_dataset_t *ds, zfs_prop_t zfs_prop, 188eda14cbcSMatt Macy uint64_t *val) 189eda14cbcSMatt Macy { 190eda14cbcSMatt Macy dsl_dir_t *dd = ds->ds_dir; 191eda14cbcSMatt Macy mutex_enter(&dd->dd_lock); 192eda14cbcSMatt Macy switch (zfs_prop) { 193eda14cbcSMatt Macy case ZFS_PROP_USEDSNAP: 194eda14cbcSMatt Macy *val = dsl_dir_get_usedsnap(dd); 195eda14cbcSMatt Macy break; 196eda14cbcSMatt Macy case ZFS_PROP_USEDCHILD: 197eda14cbcSMatt Macy *val = dsl_dir_get_usedchild(dd); 198eda14cbcSMatt Macy break; 199eda14cbcSMatt Macy case ZFS_PROP_USEDDS: 200eda14cbcSMatt Macy *val = dsl_dir_get_usedds(dd); 201eda14cbcSMatt Macy break; 202eda14cbcSMatt Macy case ZFS_PROP_USEDREFRESERV: 203eda14cbcSMatt Macy *val = dsl_dir_get_usedrefreserv(dd); 204eda14cbcSMatt Macy break; 205eda14cbcSMatt Macy case ZFS_PROP_LOGICALUSED: 206eda14cbcSMatt Macy *val = dsl_dir_get_logicalused(dd); 207eda14cbcSMatt Macy break; 208eda14cbcSMatt Macy default: 209eda14cbcSMatt Macy mutex_exit(&dd->dd_lock); 210eda14cbcSMatt Macy return (SET_ERROR(ENOENT)); 211eda14cbcSMatt Macy } 212eda14cbcSMatt Macy mutex_exit(&dd->dd_lock); 213eda14cbcSMatt Macy return (0); 214eda14cbcSMatt Macy } 215eda14cbcSMatt Macy 216eda14cbcSMatt Macy /* 217eda14cbcSMatt Macy * Check if the property we're looking for is stored at the dsl_dataset or 218eda14cbcSMatt Macy * dsl_dir level. If so, push the property value and source onto the lua stack 219eda14cbcSMatt Macy * and return 0. If it is not present or a failure occurs in lookup, return a 220eda14cbcSMatt Macy * non-zero error value. 221eda14cbcSMatt Macy */ 222eda14cbcSMatt Macy static int 223eda14cbcSMatt Macy get_special_prop(lua_State *state, dsl_dataset_t *ds, const char *dsname, 224eda14cbcSMatt Macy zfs_prop_t zfs_prop) 225eda14cbcSMatt Macy { 226eda14cbcSMatt Macy int error = 0; 227eda14cbcSMatt Macy objset_t *os; 228eda14cbcSMatt Macy uint64_t numval = 0; 229eda14cbcSMatt Macy char *strval = kmem_alloc(ZAP_MAXVALUELEN, KM_SLEEP); 230eda14cbcSMatt Macy char setpoint[ZFS_MAX_DATASET_NAME_LEN] = 231eda14cbcSMatt Macy "Internal error - setpoint not determined"; 232c03c5b1cSMartin Matuska zfs_type_t ds_type = ZFS_TYPE_INVALID; 233eda14cbcSMatt Macy zprop_type_t prop_type = zfs_prop_get_type(zfs_prop); 234eda14cbcSMatt Macy (void) get_objset_type(ds, &ds_type); 235eda14cbcSMatt Macy 236eda14cbcSMatt Macy switch (zfs_prop) { 237eda14cbcSMatt Macy case ZFS_PROP_REFRATIO: 238eda14cbcSMatt Macy numval = dsl_get_refratio(ds); 239eda14cbcSMatt Macy break; 240eda14cbcSMatt Macy case ZFS_PROP_USED: 241eda14cbcSMatt Macy numval = dsl_get_used(ds); 242eda14cbcSMatt Macy break; 243eda14cbcSMatt Macy case ZFS_PROP_CLONES: { 244eda14cbcSMatt Macy nvlist_t *clones = fnvlist_alloc(); 245eda14cbcSMatt Macy error = get_clones_stat_impl(ds, clones); 246eda14cbcSMatt Macy if (error == 0) { 247eda14cbcSMatt Macy /* push list to lua stack */ 248eda14cbcSMatt Macy VERIFY0(zcp_nvlist_to_lua(state, clones, NULL, 0ULL)); 249eda14cbcSMatt Macy /* source */ 250eda14cbcSMatt Macy (void) lua_pushnil(state); 251eda14cbcSMatt Macy } 252eda14cbcSMatt Macy nvlist_free(clones); 253eda14cbcSMatt Macy kmem_free(strval, ZAP_MAXVALUELEN); 254eda14cbcSMatt Macy return (error); 255eda14cbcSMatt Macy } 256eda14cbcSMatt Macy case ZFS_PROP_COMPRESSRATIO: 257eda14cbcSMatt Macy numval = dsl_get_compressratio(ds); 258eda14cbcSMatt Macy break; 259eda14cbcSMatt Macy case ZFS_PROP_CREATION: 260eda14cbcSMatt Macy numval = dsl_get_creation(ds); 261eda14cbcSMatt Macy break; 262eda14cbcSMatt Macy case ZFS_PROP_REFERENCED: 263eda14cbcSMatt Macy numval = dsl_get_referenced(ds); 264eda14cbcSMatt Macy break; 265eda14cbcSMatt Macy case ZFS_PROP_AVAILABLE: 266eda14cbcSMatt Macy numval = dsl_get_available(ds); 267eda14cbcSMatt Macy break; 268eda14cbcSMatt Macy case ZFS_PROP_LOGICALREFERENCED: 269eda14cbcSMatt Macy numval = dsl_get_logicalreferenced(ds); 270eda14cbcSMatt Macy break; 271eda14cbcSMatt Macy case ZFS_PROP_CREATETXG: 272eda14cbcSMatt Macy numval = dsl_get_creationtxg(ds); 273eda14cbcSMatt Macy break; 274eda14cbcSMatt Macy case ZFS_PROP_GUID: 275eda14cbcSMatt Macy numval = dsl_get_guid(ds); 276eda14cbcSMatt Macy break; 277eda14cbcSMatt Macy case ZFS_PROP_UNIQUE: 278eda14cbcSMatt Macy numval = dsl_get_unique(ds); 279eda14cbcSMatt Macy break; 280eda14cbcSMatt Macy case ZFS_PROP_OBJSETID: 281eda14cbcSMatt Macy numval = dsl_get_objsetid(ds); 282eda14cbcSMatt Macy break; 283eda14cbcSMatt Macy case ZFS_PROP_ORIGIN: 284eda14cbcSMatt Macy dsl_dir_get_origin(ds->ds_dir, strval); 285eda14cbcSMatt Macy break; 286eda14cbcSMatt Macy case ZFS_PROP_USERACCOUNTING: 287eda14cbcSMatt Macy error = dmu_objset_from_ds(ds, &os); 288eda14cbcSMatt Macy if (error == 0) 289eda14cbcSMatt Macy numval = dmu_objset_userspace_present(os); 290eda14cbcSMatt Macy break; 291eda14cbcSMatt Macy case ZFS_PROP_WRITTEN: 292eda14cbcSMatt Macy error = dsl_get_written(ds, &numval); 293eda14cbcSMatt Macy break; 294eda14cbcSMatt Macy case ZFS_PROP_TYPE: 295eda14cbcSMatt Macy error = get_objset_type_name(ds, strval); 296eda14cbcSMatt Macy break; 297eda14cbcSMatt Macy case ZFS_PROP_PREV_SNAP: 298eda14cbcSMatt Macy error = dsl_get_prev_snap(ds, strval); 299eda14cbcSMatt Macy break; 300eda14cbcSMatt Macy case ZFS_PROP_NAME: 301eda14cbcSMatt Macy dsl_dataset_name(ds, strval); 302eda14cbcSMatt Macy break; 303eda14cbcSMatt Macy case ZFS_PROP_MOUNTPOINT: 304eda14cbcSMatt Macy error = dsl_get_mountpoint(ds, dsname, strval, setpoint); 305eda14cbcSMatt Macy break; 306eda14cbcSMatt Macy case ZFS_PROP_VERSION: 307eda14cbcSMatt Macy /* should be a snapshot or filesystem */ 308eda14cbcSMatt Macy ASSERT(ds_type != ZFS_TYPE_VOLUME); 309eda14cbcSMatt Macy error = dmu_objset_from_ds(ds, &os); 310eda14cbcSMatt Macy /* look in the master node for the version */ 311eda14cbcSMatt Macy if (error == 0) { 312eda14cbcSMatt Macy error = zap_lookup(os, MASTER_NODE_OBJ, ZPL_VERSION_STR, 313eda14cbcSMatt Macy sizeof (numval), 1, &numval); 314eda14cbcSMatt Macy } 315eda14cbcSMatt Macy break; 316eda14cbcSMatt Macy case ZFS_PROP_DEFER_DESTROY: 317eda14cbcSMatt Macy numval = dsl_get_defer_destroy(ds); 318eda14cbcSMatt Macy break; 319eda14cbcSMatt Macy case ZFS_PROP_USERREFS: 320eda14cbcSMatt Macy numval = dsl_get_userrefs(ds); 321eda14cbcSMatt Macy break; 322eda14cbcSMatt Macy case ZFS_PROP_FILESYSTEM_COUNT: 323eda14cbcSMatt Macy error = dsl_dir_get_filesystem_count(ds->ds_dir, &numval); 324eda14cbcSMatt Macy (void) strlcpy(setpoint, "", ZFS_MAX_DATASET_NAME_LEN); 325eda14cbcSMatt Macy break; 326eda14cbcSMatt Macy case ZFS_PROP_SNAPSHOT_COUNT: 327eda14cbcSMatt Macy error = dsl_dir_get_snapshot_count(ds->ds_dir, &numval); 328eda14cbcSMatt Macy (void) strlcpy(setpoint, "", ZFS_MAX_DATASET_NAME_LEN); 329eda14cbcSMatt Macy break; 330eda14cbcSMatt Macy case ZFS_PROP_NUMCLONES: 331eda14cbcSMatt Macy numval = dsl_get_numclones(ds); 332eda14cbcSMatt Macy break; 333eda14cbcSMatt Macy case ZFS_PROP_INCONSISTENT: 334eda14cbcSMatt Macy numval = dsl_get_inconsistent(ds); 335eda14cbcSMatt Macy break; 336eda14cbcSMatt Macy case ZFS_PROP_IVSET_GUID: 337eda14cbcSMatt Macy if (dsl_dataset_is_zapified(ds)) { 338eda14cbcSMatt Macy error = zap_lookup(ds->ds_dir->dd_pool->dp_meta_objset, 339eda14cbcSMatt Macy ds->ds_object, DS_FIELD_IVSET_GUID, 340eda14cbcSMatt Macy sizeof (numval), 1, &numval); 341eda14cbcSMatt Macy } else { 342eda14cbcSMatt Macy error = ENOENT; 343eda14cbcSMatt Macy } 344eda14cbcSMatt Macy break; 345eda14cbcSMatt Macy case ZFS_PROP_RECEIVE_RESUME_TOKEN: { 346c03c5b1cSMartin Matuska char *token = get_receive_resume_token(ds); 347c03c5b1cSMartin Matuska if (token != NULL) { 348eda14cbcSMatt Macy (void) strlcpy(strval, token, ZAP_MAXVALUELEN); 349eda14cbcSMatt Macy kmem_strfree(token); 350c03c5b1cSMartin Matuska } else { 351c03c5b1cSMartin Matuska error = ENOENT; 352c03c5b1cSMartin Matuska } 353eda14cbcSMatt Macy break; 354eda14cbcSMatt Macy } 355eda14cbcSMatt Macy case ZFS_PROP_VOLSIZE: 356eda14cbcSMatt Macy ASSERT(ds_type == ZFS_TYPE_VOLUME || 357eda14cbcSMatt Macy ds_type == ZFS_TYPE_SNAPSHOT); 358eda14cbcSMatt Macy error = dmu_objset_from_ds(ds, &os); 359eda14cbcSMatt Macy if (error == 0) { 360eda14cbcSMatt Macy error = zap_lookup(os, ZVOL_ZAP_OBJ, "size", 361eda14cbcSMatt Macy sizeof (numval), 1, &numval); 362eda14cbcSMatt Macy } 363eda14cbcSMatt Macy if (error == 0) 364eda14cbcSMatt Macy (void) strlcpy(setpoint, dsname, 365eda14cbcSMatt Macy ZFS_MAX_DATASET_NAME_LEN); 366eda14cbcSMatt Macy 367eda14cbcSMatt Macy break; 368eda14cbcSMatt Macy case ZFS_PROP_VOLBLOCKSIZE: { 369eda14cbcSMatt Macy ASSERT(ds_type == ZFS_TYPE_VOLUME); 370eda14cbcSMatt Macy dmu_object_info_t doi; 371eda14cbcSMatt Macy error = dmu_objset_from_ds(ds, &os); 372eda14cbcSMatt Macy if (error == 0) { 373eda14cbcSMatt Macy error = dmu_object_info(os, ZVOL_OBJ, &doi); 374eda14cbcSMatt Macy if (error == 0) 375eda14cbcSMatt Macy numval = doi.doi_data_block_size; 376eda14cbcSMatt Macy } 377eda14cbcSMatt Macy break; 378eda14cbcSMatt Macy } 379eda14cbcSMatt Macy 380eda14cbcSMatt Macy case ZFS_PROP_KEYSTATUS: 381eda14cbcSMatt Macy case ZFS_PROP_KEYFORMAT: { 382eda14cbcSMatt Macy /* provide defaults in case no crypto obj exists */ 383eda14cbcSMatt Macy setpoint[0] = '\0'; 384eda14cbcSMatt Macy if (zfs_prop == ZFS_PROP_KEYSTATUS) 385eda14cbcSMatt Macy numval = ZFS_KEYSTATUS_NONE; 386eda14cbcSMatt Macy else 387eda14cbcSMatt Macy numval = ZFS_KEYFORMAT_NONE; 388eda14cbcSMatt Macy 389eda14cbcSMatt Macy nvlist_t *nvl, *propval; 390eda14cbcSMatt Macy nvl = fnvlist_alloc(); 391eda14cbcSMatt Macy dsl_dataset_crypt_stats(ds, nvl); 392eda14cbcSMatt Macy if (nvlist_lookup_nvlist(nvl, zfs_prop_to_name(zfs_prop), 393eda14cbcSMatt Macy &propval) == 0) { 394*2a58b312SMartin Matuska const char *source; 395eda14cbcSMatt Macy 396eda14cbcSMatt Macy (void) nvlist_lookup_uint64(propval, ZPROP_VALUE, 397eda14cbcSMatt Macy &numval); 398eda14cbcSMatt Macy if (nvlist_lookup_string(propval, ZPROP_SOURCE, 399eda14cbcSMatt Macy &source) == 0) 400eda14cbcSMatt Macy strlcpy(setpoint, source, sizeof (setpoint)); 401eda14cbcSMatt Macy } 402eda14cbcSMatt Macy nvlist_free(nvl); 403eda14cbcSMatt Macy break; 404eda14cbcSMatt Macy } 405eda14cbcSMatt Macy 406271171e0SMartin Matuska case ZFS_PROP_SNAPSHOTS_CHANGED: 407271171e0SMartin Matuska numval = dsl_dir_snap_cmtime(ds->ds_dir).tv_sec; 408271171e0SMartin Matuska break; 409271171e0SMartin Matuska 410eda14cbcSMatt Macy default: 411eda14cbcSMatt Macy /* Did not match these props, check in the dsl_dir */ 412eda14cbcSMatt Macy error = get_dsl_dir_prop(ds, zfs_prop, &numval); 413eda14cbcSMatt Macy } 414eda14cbcSMatt Macy if (error != 0) { 415eda14cbcSMatt Macy kmem_free(strval, ZAP_MAXVALUELEN); 416eda14cbcSMatt Macy return (error); 417eda14cbcSMatt Macy } 418eda14cbcSMatt Macy 419eda14cbcSMatt Macy switch (prop_type) { 420eda14cbcSMatt Macy case PROP_TYPE_NUMBER: { 421eda14cbcSMatt Macy (void) lua_pushnumber(state, numval); 422eda14cbcSMatt Macy break; 423eda14cbcSMatt Macy } 424eda14cbcSMatt Macy case PROP_TYPE_STRING: { 425eda14cbcSMatt Macy (void) lua_pushstring(state, strval); 426eda14cbcSMatt Macy break; 427eda14cbcSMatt Macy } 428eda14cbcSMatt Macy case PROP_TYPE_INDEX: { 429eda14cbcSMatt Macy const char *propval; 430eda14cbcSMatt Macy error = zfs_prop_index_to_string(zfs_prop, numval, &propval); 431eda14cbcSMatt Macy if (error != 0) { 432eda14cbcSMatt Macy kmem_free(strval, ZAP_MAXVALUELEN); 433eda14cbcSMatt Macy return (error); 434eda14cbcSMatt Macy } 435eda14cbcSMatt Macy (void) lua_pushstring(state, propval); 436eda14cbcSMatt Macy break; 437eda14cbcSMatt Macy } 438eda14cbcSMatt Macy } 439eda14cbcSMatt Macy kmem_free(strval, ZAP_MAXVALUELEN); 440eda14cbcSMatt Macy 441eda14cbcSMatt Macy /* Push the source to the stack */ 442eda14cbcSMatt Macy get_prop_src(state, setpoint, zfs_prop); 443eda14cbcSMatt Macy return (0); 444eda14cbcSMatt Macy } 445eda14cbcSMatt Macy 446eda14cbcSMatt Macy /* 447eda14cbcSMatt Macy * Look up a property and its source in the zap object. If the value is 448eda14cbcSMatt Macy * present and successfully retrieved, push the value and source on the 449eda14cbcSMatt Macy * lua stack and return 0. On failure, return a non-zero error value. 450eda14cbcSMatt Macy */ 451eda14cbcSMatt Macy static int 452eda14cbcSMatt Macy get_zap_prop(lua_State *state, dsl_dataset_t *ds, zfs_prop_t zfs_prop) 453eda14cbcSMatt Macy { 454eda14cbcSMatt Macy int error = 0; 455eda14cbcSMatt Macy char setpoint[ZFS_MAX_DATASET_NAME_LEN]; 456eda14cbcSMatt Macy char *strval = kmem_alloc(ZAP_MAXVALUELEN, KM_SLEEP); 457eda14cbcSMatt Macy uint64_t numval; 458eda14cbcSMatt Macy const char *prop_name = zfs_prop_to_name(zfs_prop); 459eda14cbcSMatt Macy zprop_type_t prop_type = zfs_prop_get_type(zfs_prop); 460eda14cbcSMatt Macy 461eda14cbcSMatt Macy if (prop_type == PROP_TYPE_STRING) { 462eda14cbcSMatt Macy /* Push value to lua stack */ 463eda14cbcSMatt Macy error = dsl_prop_get_ds(ds, prop_name, 1, 464eda14cbcSMatt Macy ZAP_MAXVALUELEN, strval, setpoint); 465eda14cbcSMatt Macy if (error == 0) 466eda14cbcSMatt Macy (void) lua_pushstring(state, strval); 467eda14cbcSMatt Macy } else { 468eda14cbcSMatt Macy error = dsl_prop_get_ds(ds, prop_name, sizeof (numval), 469eda14cbcSMatt Macy 1, &numval, setpoint); 470dbd5678dSMartin Matuska if (error != 0) 471dbd5678dSMartin Matuska goto out; 472eda14cbcSMatt Macy #ifdef _KERNEL 473eda14cbcSMatt Macy /* Fill in temporary value for prop, if applicable */ 474eda14cbcSMatt Macy (void) zfs_get_temporary_prop(ds, zfs_prop, &numval, setpoint); 475eda14cbcSMatt Macy #else 476be181ee2SMartin Matuska kmem_free(strval, ZAP_MAXVALUELEN); 477eda14cbcSMatt Macy return (luaL_error(state, 478eda14cbcSMatt Macy "temporary properties only supported in kernel mode", 479eda14cbcSMatt Macy prop_name)); 480eda14cbcSMatt Macy #endif 481eda14cbcSMatt Macy /* Push value to lua stack */ 482eda14cbcSMatt Macy if (prop_type == PROP_TYPE_INDEX) { 483eda14cbcSMatt Macy const char *propval; 484eda14cbcSMatt Macy error = zfs_prop_index_to_string(zfs_prop, numval, 485eda14cbcSMatt Macy &propval); 486eda14cbcSMatt Macy if (error == 0) 487eda14cbcSMatt Macy (void) lua_pushstring(state, propval); 488eda14cbcSMatt Macy } else { 489eda14cbcSMatt Macy if (error == 0) 490eda14cbcSMatt Macy (void) lua_pushnumber(state, numval); 491eda14cbcSMatt Macy } 492eda14cbcSMatt Macy } 493dbd5678dSMartin Matuska out: 494eda14cbcSMatt Macy kmem_free(strval, ZAP_MAXVALUELEN); 495eda14cbcSMatt Macy if (error == 0) 496eda14cbcSMatt Macy get_prop_src(state, setpoint, zfs_prop); 497eda14cbcSMatt Macy return (error); 498eda14cbcSMatt Macy } 499eda14cbcSMatt Macy 500eda14cbcSMatt Macy /* 501eda14cbcSMatt Macy * Determine whether property is valid for a given dataset 502eda14cbcSMatt Macy */ 503eda14cbcSMatt Macy boolean_t 504eda14cbcSMatt Macy prop_valid_for_ds(dsl_dataset_t *ds, zfs_prop_t zfs_prop) 505eda14cbcSMatt Macy { 506c03c5b1cSMartin Matuska zfs_type_t zfs_type = ZFS_TYPE_INVALID; 507eda14cbcSMatt Macy 508eda14cbcSMatt Macy /* properties not supported */ 509eda14cbcSMatt Macy if ((zfs_prop == ZFS_PROP_ISCSIOPTIONS) || 510eda14cbcSMatt Macy (zfs_prop == ZFS_PROP_MOUNTED)) 511eda14cbcSMatt Macy return (B_FALSE); 512eda14cbcSMatt Macy 513eda14cbcSMatt Macy /* if we want the origin prop, ds must be a clone */ 514eda14cbcSMatt Macy if ((zfs_prop == ZFS_PROP_ORIGIN) && (!dsl_dir_is_clone(ds->ds_dir))) 515eda14cbcSMatt Macy return (B_FALSE); 516eda14cbcSMatt Macy 517c03c5b1cSMartin Matuska int error = get_objset_type(ds, &zfs_type); 518eda14cbcSMatt Macy if (error != 0) 519eda14cbcSMatt Macy return (B_FALSE); 520eda14cbcSMatt Macy return (zfs_prop_valid_for_type(zfs_prop, zfs_type, B_FALSE)); 521eda14cbcSMatt Macy } 522eda14cbcSMatt Macy 523eda14cbcSMatt Macy /* 524eda14cbcSMatt Macy * Look up a given dataset property. On success return 2, the number of 525eda14cbcSMatt Macy * values pushed to the lua stack (property value and source). On a fatal 526eda14cbcSMatt Macy * error, longjmp. On a non fatal error push nothing. 527eda14cbcSMatt Macy */ 528eda14cbcSMatt Macy static int 529eda14cbcSMatt Macy zcp_get_system_prop(lua_State *state, dsl_pool_t *dp, const char *dataset_name, 530eda14cbcSMatt Macy zfs_prop_t zfs_prop) 531eda14cbcSMatt Macy { 532eda14cbcSMatt Macy int error; 533eda14cbcSMatt Macy /* 534eda14cbcSMatt Macy * zcp_dataset_hold will either successfully return the requested 535eda14cbcSMatt Macy * dataset or throw a lua error and longjmp out of the zfs.get_prop call 536eda14cbcSMatt Macy * without returning. 537eda14cbcSMatt Macy */ 538eda14cbcSMatt Macy dsl_dataset_t *ds = zcp_dataset_hold(state, dp, dataset_name, FTAG); 539eda14cbcSMatt Macy if (ds == NULL) 540eda14cbcSMatt Macy return (1); /* not reached; zcp_dataset_hold() longjmp'd */ 541eda14cbcSMatt Macy 542eda14cbcSMatt Macy /* Check that the property is valid for the given dataset */ 543eda14cbcSMatt Macy const char *prop_name = zfs_prop_to_name(zfs_prop); 544eda14cbcSMatt Macy if (!prop_valid_for_ds(ds, zfs_prop)) { 545eda14cbcSMatt Macy dsl_dataset_rele(ds, FTAG); 546eda14cbcSMatt Macy return (0); 547eda14cbcSMatt Macy } 548eda14cbcSMatt Macy 549eda14cbcSMatt Macy /* Check if the property can be accessed directly */ 550eda14cbcSMatt Macy error = get_special_prop(state, ds, dataset_name, zfs_prop); 551eda14cbcSMatt Macy if (error == 0) { 552eda14cbcSMatt Macy dsl_dataset_rele(ds, FTAG); 553eda14cbcSMatt Macy /* The value and source have been pushed by get_special_prop */ 554eda14cbcSMatt Macy return (2); 555eda14cbcSMatt Macy } 556eda14cbcSMatt Macy if (error != ENOENT) { 557eda14cbcSMatt Macy dsl_dataset_rele(ds, FTAG); 558eda14cbcSMatt Macy return (zcp_handle_error(state, dataset_name, 559eda14cbcSMatt Macy prop_name, error)); 560eda14cbcSMatt Macy } 561eda14cbcSMatt Macy 562eda14cbcSMatt Macy /* If we were unable to find it, look in the zap object */ 563eda14cbcSMatt Macy error = get_zap_prop(state, ds, zfs_prop); 564eda14cbcSMatt Macy dsl_dataset_rele(ds, FTAG); 565eda14cbcSMatt Macy if (error != 0) { 566eda14cbcSMatt Macy return (zcp_handle_error(state, dataset_name, 567eda14cbcSMatt Macy prop_name, error)); 568eda14cbcSMatt Macy } 569eda14cbcSMatt Macy /* The value and source have been pushed by get_zap_prop */ 570eda14cbcSMatt Macy return (2); 571eda14cbcSMatt Macy } 572eda14cbcSMatt Macy 573eda14cbcSMatt Macy #ifdef _KERNEL 574eda14cbcSMatt Macy static zfs_userquota_prop_t 575eda14cbcSMatt Macy get_userquota_prop(const char *prop_name) 576eda14cbcSMatt Macy { 577eda14cbcSMatt Macy zfs_userquota_prop_t type; 578eda14cbcSMatt Macy /* Figure out the property type ({user|group}{quota|used}) */ 579eda14cbcSMatt Macy for (type = 0; type < ZFS_NUM_USERQUOTA_PROPS; type++) { 580eda14cbcSMatt Macy if (strncmp(prop_name, zfs_userquota_prop_prefixes[type], 581eda14cbcSMatt Macy strlen(zfs_userquota_prop_prefixes[type])) == 0) 582eda14cbcSMatt Macy break; 583eda14cbcSMatt Macy } 584eda14cbcSMatt Macy return (type); 585eda14cbcSMatt Macy } 586eda14cbcSMatt Macy 587eda14cbcSMatt Macy /* 588eda14cbcSMatt Macy * Given the name of a zfs_userquota_prop, this function determines the 589eda14cbcSMatt Macy * prop type as well as the numeric group/user ids based on the string 590eda14cbcSMatt Macy * following the '@' in the property name. On success, returns 0. On failure, 591eda14cbcSMatt Macy * returns a non-zero error. 592eda14cbcSMatt Macy * 'domain' must be free'd by caller using kmem_strfree() 593eda14cbcSMatt Macy */ 594eda14cbcSMatt Macy static int 595eda14cbcSMatt Macy parse_userquota_prop(const char *prop_name, zfs_userquota_prop_t *type, 596eda14cbcSMatt Macy char **domain, uint64_t *rid) 597eda14cbcSMatt Macy { 598eda14cbcSMatt Macy char *cp, *end, *domain_val; 599eda14cbcSMatt Macy 600eda14cbcSMatt Macy *type = get_userquota_prop(prop_name); 601eda14cbcSMatt Macy if (*type >= ZFS_NUM_USERQUOTA_PROPS) 602eda14cbcSMatt Macy return (EINVAL); 603eda14cbcSMatt Macy 604eda14cbcSMatt Macy *rid = 0; 605eda14cbcSMatt Macy cp = strchr(prop_name, '@') + 1; 606eda14cbcSMatt Macy if (strncmp(cp, "S-1-", 4) == 0) { 607eda14cbcSMatt Macy /* 608eda14cbcSMatt Macy * It's a numeric SID (eg "S-1-234-567-89") and we want to 609eda14cbcSMatt Macy * separate the domain id and the rid 610eda14cbcSMatt Macy */ 611eda14cbcSMatt Macy int domain_len = strrchr(cp, '-') - cp; 612eda14cbcSMatt Macy domain_val = kmem_alloc(domain_len + 1, KM_SLEEP); 613be181ee2SMartin Matuska (void) strlcpy(domain_val, cp, domain_len + 1); 614eda14cbcSMatt Macy cp += domain_len + 1; 615eda14cbcSMatt Macy 616eda14cbcSMatt Macy (void) ddi_strtoll(cp, &end, 10, (longlong_t *)rid); 617eda14cbcSMatt Macy if (*end != '\0') { 618eda14cbcSMatt Macy kmem_strfree(domain_val); 619eda14cbcSMatt Macy return (EINVAL); 620eda14cbcSMatt Macy } 621eda14cbcSMatt Macy } else { 622eda14cbcSMatt Macy /* It's only a user/group ID (eg "12345"), just get the rid */ 623eda14cbcSMatt Macy domain_val = NULL; 624eda14cbcSMatt Macy (void) ddi_strtoll(cp, &end, 10, (longlong_t *)rid); 625eda14cbcSMatt Macy if (*end != '\0') 626eda14cbcSMatt Macy return (EINVAL); 627eda14cbcSMatt Macy } 628eda14cbcSMatt Macy *domain = domain_val; 629eda14cbcSMatt Macy return (0); 630eda14cbcSMatt Macy } 631eda14cbcSMatt Macy 632eda14cbcSMatt Macy /* 633eda14cbcSMatt Macy * Look up {user|group}{quota|used} property for given dataset. On success 634eda14cbcSMatt Macy * push the value (quota or used amount) and the setpoint. On failure, push 635eda14cbcSMatt Macy * a lua error. 636eda14cbcSMatt Macy */ 637eda14cbcSMatt Macy static int 638eda14cbcSMatt Macy zcp_get_userquota_prop(lua_State *state, dsl_pool_t *dp, 639eda14cbcSMatt Macy const char *dataset_name, const char *prop_name) 640eda14cbcSMatt Macy { 641eda14cbcSMatt Macy zfsvfs_t *zfvp; 642eda14cbcSMatt Macy zfsvfs_t *zfsvfs; 643eda14cbcSMatt Macy int error; 644eda14cbcSMatt Macy zfs_userquota_prop_t type; 645eda14cbcSMatt Macy char *domain; 646eda14cbcSMatt Macy uint64_t rid, value = 0; 647eda14cbcSMatt Macy objset_t *os; 648eda14cbcSMatt Macy 649eda14cbcSMatt Macy dsl_dataset_t *ds = zcp_dataset_hold(state, dp, dataset_name, FTAG); 650eda14cbcSMatt Macy if (ds == NULL) 651eda14cbcSMatt Macy return (1); /* not reached; zcp_dataset_hold() longjmp'd */ 652eda14cbcSMatt Macy 653eda14cbcSMatt Macy error = parse_userquota_prop(prop_name, &type, &domain, &rid); 654eda14cbcSMatt Macy if (error == 0) { 655eda14cbcSMatt Macy error = dmu_objset_from_ds(ds, &os); 656eda14cbcSMatt Macy if (error == 0) { 657eda14cbcSMatt Macy zfsvfs = kmem_zalloc(sizeof (zfsvfs_t), KM_SLEEP); 658eda14cbcSMatt Macy error = zfsvfs_create_impl(&zfvp, zfsvfs, os); 659eda14cbcSMatt Macy if (error == 0) { 660eda14cbcSMatt Macy error = zfs_userspace_one(zfvp, type, domain, 661eda14cbcSMatt Macy rid, &value); 662eda14cbcSMatt Macy zfsvfs_free(zfvp); 663eda14cbcSMatt Macy } 664eda14cbcSMatt Macy } 665eda14cbcSMatt Macy if (domain != NULL) 666eda14cbcSMatt Macy kmem_strfree(domain); 667eda14cbcSMatt Macy } 668eda14cbcSMatt Macy dsl_dataset_rele(ds, FTAG); 669eda14cbcSMatt Macy 670eda14cbcSMatt Macy if ((value == 0) && ((type == ZFS_PROP_USERQUOTA) || 671eda14cbcSMatt Macy (type == ZFS_PROP_GROUPQUOTA))) 672eda14cbcSMatt Macy error = SET_ERROR(ENOENT); 673eda14cbcSMatt Macy if (error != 0) { 674eda14cbcSMatt Macy return (zcp_handle_error(state, dataset_name, 675eda14cbcSMatt Macy prop_name, error)); 676eda14cbcSMatt Macy } 677eda14cbcSMatt Macy 678eda14cbcSMatt Macy (void) lua_pushnumber(state, value); 679eda14cbcSMatt Macy (void) lua_pushstring(state, dataset_name); 680eda14cbcSMatt Macy return (2); 681eda14cbcSMatt Macy } 682eda14cbcSMatt Macy #endif 683eda14cbcSMatt Macy 684eda14cbcSMatt Macy /* 685eda14cbcSMatt Macy * Determines the name of the snapshot referenced in the written property 686eda14cbcSMatt Macy * name. Returns snapshot name in snap_name, a buffer that must be at least 687eda14cbcSMatt Macy * as large as ZFS_MAX_DATASET_NAME_LEN 688eda14cbcSMatt Macy */ 689eda14cbcSMatt Macy static void 690eda14cbcSMatt Macy parse_written_prop(const char *dataset_name, const char *prop_name, 691eda14cbcSMatt Macy char *snap_name) 692eda14cbcSMatt Macy { 693eda14cbcSMatt Macy ASSERT(zfs_prop_written(prop_name)); 694eda14cbcSMatt Macy const char *name = prop_name + ZFS_WRITTEN_PROP_PREFIX_LEN; 695eda14cbcSMatt Macy if (strchr(name, '@') == NULL) { 696eda14cbcSMatt Macy (void) snprintf(snap_name, ZFS_MAX_DATASET_NAME_LEN, "%s@%s", 697eda14cbcSMatt Macy dataset_name, name); 698eda14cbcSMatt Macy } else { 699eda14cbcSMatt Macy (void) strlcpy(snap_name, name, ZFS_MAX_DATASET_NAME_LEN); 700eda14cbcSMatt Macy } 701eda14cbcSMatt Macy } 702eda14cbcSMatt Macy 703eda14cbcSMatt Macy /* 704eda14cbcSMatt Macy * Look up written@ property for given dataset. On success 705eda14cbcSMatt Macy * push the value and the setpoint. If error is fatal, we will 706eda14cbcSMatt Macy * longjmp, otherwise push nothing. 707eda14cbcSMatt Macy */ 708eda14cbcSMatt Macy static int 709eda14cbcSMatt Macy zcp_get_written_prop(lua_State *state, dsl_pool_t *dp, 710eda14cbcSMatt Macy const char *dataset_name, const char *prop_name) 711eda14cbcSMatt Macy { 712eda14cbcSMatt Macy char snap_name[ZFS_MAX_DATASET_NAME_LEN]; 713eda14cbcSMatt Macy uint64_t used, comp, uncomp; 714eda14cbcSMatt Macy dsl_dataset_t *old; 715eda14cbcSMatt Macy int error = 0; 716eda14cbcSMatt Macy 717eda14cbcSMatt Macy parse_written_prop(dataset_name, prop_name, snap_name); 718eda14cbcSMatt Macy dsl_dataset_t *new = zcp_dataset_hold(state, dp, dataset_name, FTAG); 719eda14cbcSMatt Macy if (new == NULL) 720eda14cbcSMatt Macy return (1); /* not reached; zcp_dataset_hold() longjmp'd */ 721eda14cbcSMatt Macy 722eda14cbcSMatt Macy error = dsl_dataset_hold(dp, snap_name, FTAG, &old); 723eda14cbcSMatt Macy if (error != 0) { 724eda14cbcSMatt Macy dsl_dataset_rele(new, FTAG); 725eda14cbcSMatt Macy return (zcp_dataset_hold_error(state, dp, snap_name, 726eda14cbcSMatt Macy error)); 727eda14cbcSMatt Macy } 728eda14cbcSMatt Macy error = dsl_dataset_space_written(old, new, 729eda14cbcSMatt Macy &used, &comp, &uncomp); 730eda14cbcSMatt Macy 731eda14cbcSMatt Macy dsl_dataset_rele(old, FTAG); 732eda14cbcSMatt Macy dsl_dataset_rele(new, FTAG); 733eda14cbcSMatt Macy 734eda14cbcSMatt Macy if (error != 0) { 735eda14cbcSMatt Macy return (zcp_handle_error(state, dataset_name, 736eda14cbcSMatt Macy snap_name, error)); 737eda14cbcSMatt Macy } 738eda14cbcSMatt Macy (void) lua_pushnumber(state, used); 739eda14cbcSMatt Macy (void) lua_pushstring(state, dataset_name); 740eda14cbcSMatt Macy return (2); 741eda14cbcSMatt Macy } 742eda14cbcSMatt Macy 743eda14cbcSMatt Macy static int zcp_get_prop(lua_State *state); 744e92ffd9bSMartin Matuska static const zcp_lib_info_t zcp_get_prop_info = { 745eda14cbcSMatt Macy .name = "get_prop", 746eda14cbcSMatt Macy .func = zcp_get_prop, 747eda14cbcSMatt Macy .pargs = { 748eda14cbcSMatt Macy { .za_name = "dataset", .za_lua_type = LUA_TSTRING }, 749eda14cbcSMatt Macy { .za_name = "property", .za_lua_type = LUA_TSTRING }, 750eda14cbcSMatt Macy {NULL, 0} 751eda14cbcSMatt Macy }, 752eda14cbcSMatt Macy .kwargs = { 753eda14cbcSMatt Macy {NULL, 0} 754eda14cbcSMatt Macy } 755eda14cbcSMatt Macy }; 756eda14cbcSMatt Macy 757eda14cbcSMatt Macy static int 758eda14cbcSMatt Macy zcp_get_prop(lua_State *state) 759eda14cbcSMatt Macy { 760eda14cbcSMatt Macy const char *dataset_name; 761eda14cbcSMatt Macy const char *property_name; 762eda14cbcSMatt Macy dsl_pool_t *dp = zcp_run_info(state)->zri_pool; 763e92ffd9bSMartin Matuska const zcp_lib_info_t *libinfo = &zcp_get_prop_info; 764eda14cbcSMatt Macy 765eda14cbcSMatt Macy zcp_parse_args(state, libinfo->name, libinfo->pargs, libinfo->kwargs); 766eda14cbcSMatt Macy 767eda14cbcSMatt Macy dataset_name = lua_tostring(state, 1); 768eda14cbcSMatt Macy property_name = lua_tostring(state, 2); 769eda14cbcSMatt Macy 770eda14cbcSMatt Macy /* User defined property */ 771eda14cbcSMatt Macy if (zfs_prop_user(property_name)) { 772eda14cbcSMatt Macy return (zcp_get_user_prop(state, dp, 773eda14cbcSMatt Macy dataset_name, property_name)); 774eda14cbcSMatt Macy } 775eda14cbcSMatt Macy /* userspace property */ 776eda14cbcSMatt Macy if (zfs_prop_userquota(property_name)) { 777eda14cbcSMatt Macy #ifdef _KERNEL 778eda14cbcSMatt Macy return (zcp_get_userquota_prop(state, dp, 779eda14cbcSMatt Macy dataset_name, property_name)); 780eda14cbcSMatt Macy #else 781eda14cbcSMatt Macy return (luaL_error(state, 782eda14cbcSMatt Macy "user quota properties only supported in kernel mode", 783eda14cbcSMatt Macy property_name)); 784eda14cbcSMatt Macy #endif 785eda14cbcSMatt Macy } 786eda14cbcSMatt Macy /* written@ property */ 787eda14cbcSMatt Macy if (zfs_prop_written(property_name)) { 788eda14cbcSMatt Macy return (zcp_get_written_prop(state, dp, 789eda14cbcSMatt Macy dataset_name, property_name)); 790eda14cbcSMatt Macy } 791eda14cbcSMatt Macy 792eda14cbcSMatt Macy zfs_prop_t zfs_prop = zfs_name_to_prop(property_name); 793eda14cbcSMatt Macy /* Valid system property */ 794eda14cbcSMatt Macy if (zfs_prop != ZPROP_INVAL) { 795eda14cbcSMatt Macy return (zcp_get_system_prop(state, dp, dataset_name, 796eda14cbcSMatt Macy zfs_prop)); 797eda14cbcSMatt Macy } 798eda14cbcSMatt Macy 799eda14cbcSMatt Macy /* Invalid property name */ 800eda14cbcSMatt Macy return (luaL_error(state, 801eda14cbcSMatt Macy "'%s' is not a valid property", property_name)); 802eda14cbcSMatt Macy } 803eda14cbcSMatt Macy 804eda14cbcSMatt Macy int 805eda14cbcSMatt Macy zcp_load_get_lib(lua_State *state) 806eda14cbcSMatt Macy { 807eda14cbcSMatt Macy lua_pushcclosure(state, zcp_get_prop_info.func, 0); 808eda14cbcSMatt Macy lua_setfield(state, -2, zcp_get_prop_info.name); 809eda14cbcSMatt Macy 810eda14cbcSMatt Macy return (1); 811eda14cbcSMatt Macy } 812