xref: /freebsd-src/sys/contrib/openzfs/module/zfs/zfs_znode.c (revision 7a7741af18d6c8a804cc643cb7ecda9d730c6aa6)
1*7a7741afSMartin Matuska /*
2*7a7741afSMartin Matuska  * CDDL HEADER START
3*7a7741afSMartin Matuska  *
4*7a7741afSMartin Matuska  * The contents of this file are subject to the terms of the
5*7a7741afSMartin Matuska  * Common Development and Distribution License (the "License").
6*7a7741afSMartin Matuska  * You may not use this file except in compliance with the License.
7*7a7741afSMartin Matuska  *
8*7a7741afSMartin Matuska  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*7a7741afSMartin Matuska  * or https://opensource.org/licenses/CDDL-1.0.
10*7a7741afSMartin Matuska  * See the License for the specific language governing permissions
11*7a7741afSMartin Matuska  * and limitations under the License.
12*7a7741afSMartin Matuska  *
13*7a7741afSMartin Matuska  * When distributing Covered Code, include this CDDL HEADER in each
14*7a7741afSMartin Matuska  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*7a7741afSMartin Matuska  * If applicable, add the following below this CDDL HEADER, with the
16*7a7741afSMartin Matuska  * fields enclosed by brackets "[]" replaced with your own identifying
17*7a7741afSMartin Matuska  * information: Portions Copyright [yyyy] [name of copyright owner]
18*7a7741afSMartin Matuska  *
19*7a7741afSMartin Matuska  * CDDL HEADER END
20*7a7741afSMartin Matuska  */
21*7a7741afSMartin Matuska /*
22*7a7741afSMartin Matuska  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23*7a7741afSMartin Matuska  * Copyright (c) 2012, 2018 by Delphix. All rights reserved.
24*7a7741afSMartin Matuska  * Copyright (c) 2014 Integros [integros.com]
25*7a7741afSMartin Matuska  */
26*7a7741afSMartin Matuska 
27*7a7741afSMartin Matuska /* Portions Copyright 2007 Jeremy Teo */
28*7a7741afSMartin Matuska /* Portions Copyright 2011 Martin Matuska <mm@FreeBSD.org> */
29*7a7741afSMartin Matuska 
30*7a7741afSMartin Matuska #include <sys/dmu.h>
31*7a7741afSMartin Matuska #include <sys/dmu_objset.h>
32*7a7741afSMartin Matuska #include <sys/dmu_tx.h>
33*7a7741afSMartin Matuska #include <sys/zfs_refcount.h>
34*7a7741afSMartin Matuska #include <sys/stat.h>
35*7a7741afSMartin Matuska #include <sys/zap.h>
36*7a7741afSMartin Matuska #include <sys/zfs_znode.h>
37*7a7741afSMartin Matuska #include <sys/sa.h>
38*7a7741afSMartin Matuska #include <sys/zfs_sa.h>
39*7a7741afSMartin Matuska #include <sys/zfs_stat.h>
40*7a7741afSMartin Matuska 
41*7a7741afSMartin Matuska #include "zfs_prop.h"
42*7a7741afSMartin Matuska #include "zfs_comutil.h"
43*7a7741afSMartin Matuska 
44*7a7741afSMartin Matuska static int
45*7a7741afSMartin Matuska zfs_sa_setup(objset_t *osp, sa_attr_type_t **sa_table)
46*7a7741afSMartin Matuska {
47*7a7741afSMartin Matuska 	uint64_t sa_obj = 0;
48*7a7741afSMartin Matuska 	int error;
49*7a7741afSMartin Matuska 
50*7a7741afSMartin Matuska 	error = zap_lookup(osp, MASTER_NODE_OBJ, ZFS_SA_ATTRS, 8, 1, &sa_obj);
51*7a7741afSMartin Matuska 	if (error != 0 && error != ENOENT)
52*7a7741afSMartin Matuska 		return (error);
53*7a7741afSMartin Matuska 
54*7a7741afSMartin Matuska 	error = sa_setup(osp, sa_obj, zfs_attr_table, ZPL_END, sa_table);
55*7a7741afSMartin Matuska 	return (error);
56*7a7741afSMartin Matuska }
57*7a7741afSMartin Matuska 
58*7a7741afSMartin Matuska static int
59*7a7741afSMartin Matuska zfs_grab_sa_handle(objset_t *osp, uint64_t obj, sa_handle_t **hdlp,
60*7a7741afSMartin Matuska     dmu_buf_t **db, const void *tag)
61*7a7741afSMartin Matuska {
62*7a7741afSMartin Matuska 	dmu_object_info_t doi;
63*7a7741afSMartin Matuska 	int error;
64*7a7741afSMartin Matuska 
65*7a7741afSMartin Matuska 	if ((error = sa_buf_hold(osp, obj, tag, db)) != 0)
66*7a7741afSMartin Matuska 		return (error);
67*7a7741afSMartin Matuska 
68*7a7741afSMartin Matuska 	dmu_object_info_from_db(*db, &doi);
69*7a7741afSMartin Matuska 	if ((doi.doi_bonus_type != DMU_OT_SA &&
70*7a7741afSMartin Matuska 	    doi.doi_bonus_type != DMU_OT_ZNODE) ||
71*7a7741afSMartin Matuska 	    (doi.doi_bonus_type == DMU_OT_ZNODE &&
72*7a7741afSMartin Matuska 	    doi.doi_bonus_size < sizeof (znode_phys_t))) {
73*7a7741afSMartin Matuska 		sa_buf_rele(*db, tag);
74*7a7741afSMartin Matuska 		return (SET_ERROR(ENOTSUP));
75*7a7741afSMartin Matuska 	}
76*7a7741afSMartin Matuska 
77*7a7741afSMartin Matuska 	error = sa_handle_get(osp, obj, NULL, SA_HDL_PRIVATE, hdlp);
78*7a7741afSMartin Matuska 	if (error != 0) {
79*7a7741afSMartin Matuska 		sa_buf_rele(*db, tag);
80*7a7741afSMartin Matuska 		return (error);
81*7a7741afSMartin Matuska 	}
82*7a7741afSMartin Matuska 
83*7a7741afSMartin Matuska 	return (0);
84*7a7741afSMartin Matuska }
85*7a7741afSMartin Matuska 
86*7a7741afSMartin Matuska static void
87*7a7741afSMartin Matuska zfs_release_sa_handle(sa_handle_t *hdl, dmu_buf_t *db, const void *tag)
88*7a7741afSMartin Matuska {
89*7a7741afSMartin Matuska 	sa_handle_destroy(hdl);
90*7a7741afSMartin Matuska 	sa_buf_rele(db, tag);
91*7a7741afSMartin Matuska }
92*7a7741afSMartin Matuska 
93*7a7741afSMartin Matuska /*
94*7a7741afSMartin Matuska  * Given an object number, return its parent object number and whether
95*7a7741afSMartin Matuska  * or not the object is an extended attribute directory.
96*7a7741afSMartin Matuska  */
97*7a7741afSMartin Matuska int
98*7a7741afSMartin Matuska zfs_obj_to_pobj(objset_t *osp, sa_handle_t *hdl, sa_attr_type_t *sa_table,
99*7a7741afSMartin Matuska     uint64_t *pobjp, int *is_xattrdir)
100*7a7741afSMartin Matuska {
101*7a7741afSMartin Matuska 	uint64_t parent;
102*7a7741afSMartin Matuska 	uint64_t pflags;
103*7a7741afSMartin Matuska 	uint64_t mode;
104*7a7741afSMartin Matuska 	uint64_t parent_mode;
105*7a7741afSMartin Matuska 	sa_bulk_attr_t bulk[3];
106*7a7741afSMartin Matuska 	sa_handle_t *sa_hdl;
107*7a7741afSMartin Matuska 	dmu_buf_t *sa_db;
108*7a7741afSMartin Matuska 	int count = 0;
109*7a7741afSMartin Matuska 	int error;
110*7a7741afSMartin Matuska 
111*7a7741afSMartin Matuska 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_PARENT], NULL,
112*7a7741afSMartin Matuska 	    &parent, sizeof (parent));
113*7a7741afSMartin Matuska 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_FLAGS], NULL,
114*7a7741afSMartin Matuska 	    &pflags, sizeof (pflags));
115*7a7741afSMartin Matuska 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_MODE], NULL,
116*7a7741afSMartin Matuska 	    &mode, sizeof (mode));
117*7a7741afSMartin Matuska 
118*7a7741afSMartin Matuska 	if ((error = sa_bulk_lookup(hdl, bulk, count)) != 0)
119*7a7741afSMartin Matuska 		return (error);
120*7a7741afSMartin Matuska 
121*7a7741afSMartin Matuska 	/*
122*7a7741afSMartin Matuska 	 * When a link is removed its parent pointer is not changed and will
123*7a7741afSMartin Matuska 	 * be invalid.  There are two cases where a link is removed but the
124*7a7741afSMartin Matuska 	 * file stays around, when it goes to the delete queue and when there
125*7a7741afSMartin Matuska 	 * are additional links.
126*7a7741afSMartin Matuska 	 */
127*7a7741afSMartin Matuska 	error = zfs_grab_sa_handle(osp, parent, &sa_hdl, &sa_db, FTAG);
128*7a7741afSMartin Matuska 	if (error != 0)
129*7a7741afSMartin Matuska 		return (error);
130*7a7741afSMartin Matuska 
131*7a7741afSMartin Matuska 	error = sa_lookup(sa_hdl, ZPL_MODE, &parent_mode, sizeof (parent_mode));
132*7a7741afSMartin Matuska 	zfs_release_sa_handle(sa_hdl, sa_db, FTAG);
133*7a7741afSMartin Matuska 	if (error != 0)
134*7a7741afSMartin Matuska 		return (error);
135*7a7741afSMartin Matuska 
136*7a7741afSMartin Matuska 	*is_xattrdir = ((pflags & ZFS_XATTR) != 0) && S_ISDIR(mode);
137*7a7741afSMartin Matuska 
138*7a7741afSMartin Matuska 	/*
139*7a7741afSMartin Matuska 	 * Extended attributes can be applied to files, directories, etc.
140*7a7741afSMartin Matuska 	 * Otherwise the parent must be a directory.
141*7a7741afSMartin Matuska 	 */
142*7a7741afSMartin Matuska 	if (!*is_xattrdir && !S_ISDIR(parent_mode))
143*7a7741afSMartin Matuska 		return (SET_ERROR(EINVAL));
144*7a7741afSMartin Matuska 
145*7a7741afSMartin Matuska 	*pobjp = parent;
146*7a7741afSMartin Matuska 
147*7a7741afSMartin Matuska 	return (0);
148*7a7741afSMartin Matuska }
149*7a7741afSMartin Matuska 
150*7a7741afSMartin Matuska /*
151*7a7741afSMartin Matuska  * Given an object number, return some zpl level statistics
152*7a7741afSMartin Matuska  */
153*7a7741afSMartin Matuska static int
154*7a7741afSMartin Matuska zfs_obj_to_stats_impl(sa_handle_t *hdl, sa_attr_type_t *sa_table,
155*7a7741afSMartin Matuska     zfs_stat_t *sb)
156*7a7741afSMartin Matuska {
157*7a7741afSMartin Matuska 	sa_bulk_attr_t bulk[4];
158*7a7741afSMartin Matuska 	int count = 0;
159*7a7741afSMartin Matuska 
160*7a7741afSMartin Matuska 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_MODE], NULL,
161*7a7741afSMartin Matuska 	    &sb->zs_mode, sizeof (sb->zs_mode));
162*7a7741afSMartin Matuska 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_GEN], NULL,
163*7a7741afSMartin Matuska 	    &sb->zs_gen, sizeof (sb->zs_gen));
164*7a7741afSMartin Matuska 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_LINKS], NULL,
165*7a7741afSMartin Matuska 	    &sb->zs_links, sizeof (sb->zs_links));
166*7a7741afSMartin Matuska 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_CTIME], NULL,
167*7a7741afSMartin Matuska 	    &sb->zs_ctime, sizeof (sb->zs_ctime));
168*7a7741afSMartin Matuska 
169*7a7741afSMartin Matuska 	return (sa_bulk_lookup(hdl, bulk, count));
170*7a7741afSMartin Matuska }
171*7a7741afSMartin Matuska 
172*7a7741afSMartin Matuska static int
173*7a7741afSMartin Matuska zfs_obj_to_path_impl(objset_t *osp, uint64_t obj, sa_handle_t *hdl,
174*7a7741afSMartin Matuska     sa_attr_type_t *sa_table, char *buf, int len)
175*7a7741afSMartin Matuska {
176*7a7741afSMartin Matuska 	sa_handle_t *sa_hdl;
177*7a7741afSMartin Matuska 	sa_handle_t *prevhdl = NULL;
178*7a7741afSMartin Matuska 	dmu_buf_t *prevdb = NULL;
179*7a7741afSMartin Matuska 	dmu_buf_t *sa_db = NULL;
180*7a7741afSMartin Matuska 	char *path = buf + len - 1;
181*7a7741afSMartin Matuska 	char *comp_buf;
182*7a7741afSMartin Matuska 	int error;
183*7a7741afSMartin Matuska 
184*7a7741afSMartin Matuska 	*path = '\0';
185*7a7741afSMartin Matuska 	sa_hdl = hdl;
186*7a7741afSMartin Matuska 
187*7a7741afSMartin Matuska 	uint64_t deleteq_obj;
188*7a7741afSMartin Matuska 	VERIFY0(zap_lookup(osp, MASTER_NODE_OBJ,
189*7a7741afSMartin Matuska 	    ZFS_UNLINKED_SET, sizeof (uint64_t), 1, &deleteq_obj));
190*7a7741afSMartin Matuska 	error = zap_lookup_int(osp, deleteq_obj, obj);
191*7a7741afSMartin Matuska 	if (error == 0) {
192*7a7741afSMartin Matuska 		return (ESTALE);
193*7a7741afSMartin Matuska 	} else if (error != ENOENT) {
194*7a7741afSMartin Matuska 		return (error);
195*7a7741afSMartin Matuska 	}
196*7a7741afSMartin Matuska 
197*7a7741afSMartin Matuska 	comp_buf = kmem_alloc(ZAP_MAXNAMELEN_NEW + 2, KM_SLEEP);
198*7a7741afSMartin Matuska 	for (;;) {
199*7a7741afSMartin Matuska 		uint64_t pobj = 0;
200*7a7741afSMartin Matuska 		char *component = comp_buf;
201*7a7741afSMartin Matuska 		size_t complen;
202*7a7741afSMartin Matuska 		int is_xattrdir = 0;
203*7a7741afSMartin Matuska 
204*7a7741afSMartin Matuska 		if (prevdb) {
205*7a7741afSMartin Matuska 			ASSERT3P(prevhdl, !=, NULL);
206*7a7741afSMartin Matuska 			zfs_release_sa_handle(prevhdl, prevdb, FTAG);
207*7a7741afSMartin Matuska 		}
208*7a7741afSMartin Matuska 
209*7a7741afSMartin Matuska 		if ((error = zfs_obj_to_pobj(osp, sa_hdl, sa_table, &pobj,
210*7a7741afSMartin Matuska 		    &is_xattrdir)) != 0)
211*7a7741afSMartin Matuska 			break;
212*7a7741afSMartin Matuska 
213*7a7741afSMartin Matuska 		if (pobj == obj) {
214*7a7741afSMartin Matuska 			if (path[0] != '/')
215*7a7741afSMartin Matuska 				*--path = '/';
216*7a7741afSMartin Matuska 			break;
217*7a7741afSMartin Matuska 		}
218*7a7741afSMartin Matuska 
219*7a7741afSMartin Matuska 		component[0] = '/';
220*7a7741afSMartin Matuska 		if (is_xattrdir) {
221*7a7741afSMartin Matuska 			strcpy(component + 1, "<xattrdir>");
222*7a7741afSMartin Matuska 		} else {
223*7a7741afSMartin Matuska 			error = zap_value_search(osp, pobj, obj,
224*7a7741afSMartin Matuska 			    ZFS_DIRENT_OBJ(-1ULL), component + 1,
225*7a7741afSMartin Matuska 			    ZAP_MAXNAMELEN_NEW);
226*7a7741afSMartin Matuska 			if (error != 0)
227*7a7741afSMartin Matuska 				break;
228*7a7741afSMartin Matuska 		}
229*7a7741afSMartin Matuska 
230*7a7741afSMartin Matuska 		complen = strlen(component);
231*7a7741afSMartin Matuska 		path -= complen;
232*7a7741afSMartin Matuska 		ASSERT3P(path, >=, buf);
233*7a7741afSMartin Matuska 		memcpy(path, component, complen);
234*7a7741afSMartin Matuska 		obj = pobj;
235*7a7741afSMartin Matuska 
236*7a7741afSMartin Matuska 		if (sa_hdl != hdl) {
237*7a7741afSMartin Matuska 			prevhdl = sa_hdl;
238*7a7741afSMartin Matuska 			prevdb = sa_db;
239*7a7741afSMartin Matuska 		}
240*7a7741afSMartin Matuska 		error = zfs_grab_sa_handle(osp, obj, &sa_hdl, &sa_db, FTAG);
241*7a7741afSMartin Matuska 		if (error != 0) {
242*7a7741afSMartin Matuska 			sa_hdl = prevhdl;
243*7a7741afSMartin Matuska 			sa_db = prevdb;
244*7a7741afSMartin Matuska 			break;
245*7a7741afSMartin Matuska 		}
246*7a7741afSMartin Matuska 	}
247*7a7741afSMartin Matuska 
248*7a7741afSMartin Matuska 	if (sa_hdl != NULL && sa_hdl != hdl) {
249*7a7741afSMartin Matuska 		ASSERT3P(sa_db, !=, NULL);
250*7a7741afSMartin Matuska 		zfs_release_sa_handle(sa_hdl, sa_db, FTAG);
251*7a7741afSMartin Matuska 	}
252*7a7741afSMartin Matuska 
253*7a7741afSMartin Matuska 	if (error == 0)
254*7a7741afSMartin Matuska 		(void) memmove(buf, path, buf + len - path);
255*7a7741afSMartin Matuska 
256*7a7741afSMartin Matuska 	kmem_free(comp_buf, ZAP_MAXNAMELEN_NEW +2);
257*7a7741afSMartin Matuska 	return (error);
258*7a7741afSMartin Matuska }
259*7a7741afSMartin Matuska 
260*7a7741afSMartin Matuska int
261*7a7741afSMartin Matuska zfs_obj_to_path(objset_t *osp, uint64_t obj, char *buf, int len)
262*7a7741afSMartin Matuska {
263*7a7741afSMartin Matuska 	sa_attr_type_t *sa_table;
264*7a7741afSMartin Matuska 	sa_handle_t *hdl;
265*7a7741afSMartin Matuska 	dmu_buf_t *db;
266*7a7741afSMartin Matuska 	int error;
267*7a7741afSMartin Matuska 
268*7a7741afSMartin Matuska 	error = zfs_sa_setup(osp, &sa_table);
269*7a7741afSMartin Matuska 	if (error != 0)
270*7a7741afSMartin Matuska 		return (error);
271*7a7741afSMartin Matuska 
272*7a7741afSMartin Matuska 	error = zfs_grab_sa_handle(osp, obj, &hdl, &db, FTAG);
273*7a7741afSMartin Matuska 	if (error != 0)
274*7a7741afSMartin Matuska 		return (error);
275*7a7741afSMartin Matuska 
276*7a7741afSMartin Matuska 	error = zfs_obj_to_path_impl(osp, obj, hdl, sa_table, buf, len);
277*7a7741afSMartin Matuska 
278*7a7741afSMartin Matuska 	zfs_release_sa_handle(hdl, db, FTAG);
279*7a7741afSMartin Matuska 	return (error);
280*7a7741afSMartin Matuska }
281*7a7741afSMartin Matuska 
282*7a7741afSMartin Matuska int
283*7a7741afSMartin Matuska zfs_obj_to_stats(objset_t *osp, uint64_t obj, zfs_stat_t *sb,
284*7a7741afSMartin Matuska     char *buf, int len)
285*7a7741afSMartin Matuska {
286*7a7741afSMartin Matuska 	char *path = buf + len - 1;
287*7a7741afSMartin Matuska 	sa_attr_type_t *sa_table;
288*7a7741afSMartin Matuska 	sa_handle_t *hdl;
289*7a7741afSMartin Matuska 	dmu_buf_t *db;
290*7a7741afSMartin Matuska 	int error;
291*7a7741afSMartin Matuska 
292*7a7741afSMartin Matuska 	*path = '\0';
293*7a7741afSMartin Matuska 
294*7a7741afSMartin Matuska 	error = zfs_sa_setup(osp, &sa_table);
295*7a7741afSMartin Matuska 	if (error != 0)
296*7a7741afSMartin Matuska 		return (error);
297*7a7741afSMartin Matuska 
298*7a7741afSMartin Matuska 	error = zfs_grab_sa_handle(osp, obj, &hdl, &db, FTAG);
299*7a7741afSMartin Matuska 	if (error != 0)
300*7a7741afSMartin Matuska 		return (error);
301*7a7741afSMartin Matuska 
302*7a7741afSMartin Matuska 	error = zfs_obj_to_stats_impl(hdl, sa_table, sb);
303*7a7741afSMartin Matuska 	if (error != 0) {
304*7a7741afSMartin Matuska 		zfs_release_sa_handle(hdl, db, FTAG);
305*7a7741afSMartin Matuska 		return (error);
306*7a7741afSMartin Matuska 	}
307*7a7741afSMartin Matuska 
308*7a7741afSMartin Matuska 	error = zfs_obj_to_path_impl(osp, obj, hdl, sa_table, buf, len);
309*7a7741afSMartin Matuska 
310*7a7741afSMartin Matuska 	zfs_release_sa_handle(hdl, db, FTAG);
311*7a7741afSMartin Matuska 	return (error);
312*7a7741afSMartin Matuska }
313*7a7741afSMartin Matuska 
314*7a7741afSMartin Matuska /*
315*7a7741afSMartin Matuska  * Read a property stored within the master node.
316*7a7741afSMartin Matuska  */
317*7a7741afSMartin Matuska int
318*7a7741afSMartin Matuska zfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value)
319*7a7741afSMartin Matuska {
320*7a7741afSMartin Matuska 	uint64_t *cached_copy = NULL;
321*7a7741afSMartin Matuska 
322*7a7741afSMartin Matuska 	/*
323*7a7741afSMartin Matuska 	 * Figure out where in the objset_t the cached copy would live, if it
324*7a7741afSMartin Matuska 	 * is available for the requested property.
325*7a7741afSMartin Matuska 	 */
326*7a7741afSMartin Matuska 	if (os != NULL) {
327*7a7741afSMartin Matuska 		switch (prop) {
328*7a7741afSMartin Matuska 		case ZFS_PROP_VERSION:
329*7a7741afSMartin Matuska 			cached_copy = &os->os_version;
330*7a7741afSMartin Matuska 			break;
331*7a7741afSMartin Matuska 		case ZFS_PROP_NORMALIZE:
332*7a7741afSMartin Matuska 			cached_copy = &os->os_normalization;
333*7a7741afSMartin Matuska 			break;
334*7a7741afSMartin Matuska 		case ZFS_PROP_UTF8ONLY:
335*7a7741afSMartin Matuska 			cached_copy = &os->os_utf8only;
336*7a7741afSMartin Matuska 			break;
337*7a7741afSMartin Matuska 		case ZFS_PROP_CASE:
338*7a7741afSMartin Matuska 			cached_copy = &os->os_casesensitivity;
339*7a7741afSMartin Matuska 			break;
340*7a7741afSMartin Matuska 		default:
341*7a7741afSMartin Matuska 			break;
342*7a7741afSMartin Matuska 		}
343*7a7741afSMartin Matuska 	}
344*7a7741afSMartin Matuska 	if (cached_copy != NULL && *cached_copy != OBJSET_PROP_UNINITIALIZED) {
345*7a7741afSMartin Matuska 		*value = *cached_copy;
346*7a7741afSMartin Matuska 		return (0);
347*7a7741afSMartin Matuska 	}
348*7a7741afSMartin Matuska 
349*7a7741afSMartin Matuska 	/*
350*7a7741afSMartin Matuska 	 * If the property wasn't cached, look up the file system's value for
351*7a7741afSMartin Matuska 	 * the property. For the version property, we look up a slightly
352*7a7741afSMartin Matuska 	 * different string.
353*7a7741afSMartin Matuska 	 */
354*7a7741afSMartin Matuska 	const char *pname;
355*7a7741afSMartin Matuska 	int error = ENOENT;
356*7a7741afSMartin Matuska 	if (prop == ZFS_PROP_VERSION)
357*7a7741afSMartin Matuska 		pname = ZPL_VERSION_STR;
358*7a7741afSMartin Matuska 	else
359*7a7741afSMartin Matuska 		pname = zfs_prop_to_name(prop);
360*7a7741afSMartin Matuska 
361*7a7741afSMartin Matuska 	if (os != NULL) {
362*7a7741afSMartin Matuska 		ASSERT3U(os->os_phys->os_type, ==, DMU_OST_ZFS);
363*7a7741afSMartin Matuska 		error = zap_lookup(os, MASTER_NODE_OBJ, pname, 8, 1, value);
364*7a7741afSMartin Matuska 	}
365*7a7741afSMartin Matuska 
366*7a7741afSMartin Matuska 	if (error == ENOENT) {
367*7a7741afSMartin Matuska 		/* No value set, use the default value */
368*7a7741afSMartin Matuska 		switch (prop) {
369*7a7741afSMartin Matuska 		case ZFS_PROP_VERSION:
370*7a7741afSMartin Matuska 			*value = ZPL_VERSION;
371*7a7741afSMartin Matuska 			break;
372*7a7741afSMartin Matuska 		case ZFS_PROP_NORMALIZE:
373*7a7741afSMartin Matuska 		case ZFS_PROP_UTF8ONLY:
374*7a7741afSMartin Matuska 			*value = 0;
375*7a7741afSMartin Matuska 			break;
376*7a7741afSMartin Matuska 		case ZFS_PROP_CASE:
377*7a7741afSMartin Matuska 			*value = ZFS_CASE_SENSITIVE;
378*7a7741afSMartin Matuska 			break;
379*7a7741afSMartin Matuska 		case ZFS_PROP_ACLTYPE:
380*7a7741afSMartin Matuska #ifdef __FreeBSD__
381*7a7741afSMartin Matuska 			*value = ZFS_ACLTYPE_NFSV4;
382*7a7741afSMartin Matuska #else
383*7a7741afSMartin Matuska 			*value = ZFS_ACLTYPE_OFF;
384*7a7741afSMartin Matuska #endif
385*7a7741afSMartin Matuska 			break;
386*7a7741afSMartin Matuska 		default:
387*7a7741afSMartin Matuska 			return (error);
388*7a7741afSMartin Matuska 		}
389*7a7741afSMartin Matuska 		error = 0;
390*7a7741afSMartin Matuska 	}
391*7a7741afSMartin Matuska 
392*7a7741afSMartin Matuska 	/*
393*7a7741afSMartin Matuska 	 * If one of the methods for getting the property value above worked,
394*7a7741afSMartin Matuska 	 * copy it into the objset_t's cache.
395*7a7741afSMartin Matuska 	 */
396*7a7741afSMartin Matuska 	if (error == 0 && cached_copy != NULL) {
397*7a7741afSMartin Matuska 		*cached_copy = *value;
398*7a7741afSMartin Matuska 	}
399*7a7741afSMartin Matuska 
400*7a7741afSMartin Matuska 	return (error);
401*7a7741afSMartin Matuska }
402