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