xref: /freebsd/sys/contrib/openzfs/module/zfs/zfs_znode.c (revision 071ab5a1f3cbfd29c8fbec27f7e619418adaf074)
161145dc2SMartin Matuska // SPDX-License-Identifier: CDDL-1.0
27a7741afSMartin Matuska /*
37a7741afSMartin Matuska  * CDDL HEADER START
47a7741afSMartin Matuska  *
57a7741afSMartin Matuska  * The contents of this file are subject to the terms of the
67a7741afSMartin Matuska  * Common Development and Distribution License (the "License").
77a7741afSMartin Matuska  * You may not use this file except in compliance with the License.
87a7741afSMartin Matuska  *
97a7741afSMartin Matuska  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107a7741afSMartin Matuska  * or https://opensource.org/licenses/CDDL-1.0.
117a7741afSMartin Matuska  * See the License for the specific language governing permissions
127a7741afSMartin Matuska  * and limitations under the License.
137a7741afSMartin Matuska  *
147a7741afSMartin Matuska  * When distributing Covered Code, include this CDDL HEADER in each
157a7741afSMartin Matuska  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167a7741afSMartin Matuska  * If applicable, add the following below this CDDL HEADER, with the
177a7741afSMartin Matuska  * fields enclosed by brackets "[]" replaced with your own identifying
187a7741afSMartin Matuska  * information: Portions Copyright [yyyy] [name of copyright owner]
197a7741afSMartin Matuska  *
207a7741afSMartin Matuska  * CDDL HEADER END
217a7741afSMartin Matuska  */
227a7741afSMartin Matuska /*
237a7741afSMartin Matuska  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
247a7741afSMartin Matuska  * Copyright (c) 2012, 2018 by Delphix. All rights reserved.
257a7741afSMartin Matuska  * Copyright (c) 2014 Integros [integros.com]
267a7741afSMartin Matuska  */
277a7741afSMartin Matuska 
287a7741afSMartin Matuska /* Portions Copyright 2007 Jeremy Teo */
297a7741afSMartin Matuska /* Portions Copyright 2011 Martin Matuska <mm@FreeBSD.org> */
307a7741afSMartin Matuska 
317a7741afSMartin Matuska #include <sys/dmu.h>
327a7741afSMartin Matuska #include <sys/dmu_objset.h>
337a7741afSMartin Matuska #include <sys/dmu_tx.h>
347a7741afSMartin Matuska #include <sys/zfs_refcount.h>
357a7741afSMartin Matuska #include <sys/stat.h>
367a7741afSMartin Matuska #include <sys/zap.h>
377a7741afSMartin Matuska #include <sys/zfs_znode.h>
387a7741afSMartin Matuska #include <sys/sa.h>
397a7741afSMartin Matuska #include <sys/zfs_sa.h>
407a7741afSMartin Matuska #include <sys/zfs_stat.h>
417a7741afSMartin Matuska 
427a7741afSMartin Matuska #include "zfs_prop.h"
437a7741afSMartin Matuska #include "zfs_comutil.h"
447a7741afSMartin Matuska 
457a7741afSMartin Matuska static int
zfs_sa_setup(objset_t * osp,sa_attr_type_t ** sa_table)467a7741afSMartin Matuska zfs_sa_setup(objset_t *osp, sa_attr_type_t **sa_table)
477a7741afSMartin Matuska {
487a7741afSMartin Matuska 	uint64_t sa_obj = 0;
497a7741afSMartin Matuska 	int error;
507a7741afSMartin Matuska 
517a7741afSMartin Matuska 	error = zap_lookup(osp, MASTER_NODE_OBJ, ZFS_SA_ATTRS, 8, 1, &sa_obj);
527a7741afSMartin Matuska 	if (error != 0 && error != ENOENT)
537a7741afSMartin Matuska 		return (error);
547a7741afSMartin Matuska 
557a7741afSMartin Matuska 	error = sa_setup(osp, sa_obj, zfs_attr_table, ZPL_END, sa_table);
567a7741afSMartin Matuska 	return (error);
577a7741afSMartin Matuska }
587a7741afSMartin Matuska 
597a7741afSMartin Matuska static int
zfs_grab_sa_handle(objset_t * osp,uint64_t obj,sa_handle_t ** hdlp,dmu_buf_t ** db,const void * tag)607a7741afSMartin Matuska zfs_grab_sa_handle(objset_t *osp, uint64_t obj, sa_handle_t **hdlp,
617a7741afSMartin Matuska     dmu_buf_t **db, const void *tag)
627a7741afSMartin Matuska {
637a7741afSMartin Matuska 	dmu_object_info_t doi;
647a7741afSMartin Matuska 	int error;
657a7741afSMartin Matuska 
667a7741afSMartin Matuska 	if ((error = sa_buf_hold(osp, obj, tag, db)) != 0)
677a7741afSMartin Matuska 		return (error);
687a7741afSMartin Matuska 
697a7741afSMartin Matuska 	dmu_object_info_from_db(*db, &doi);
707a7741afSMartin Matuska 	if ((doi.doi_bonus_type != DMU_OT_SA &&
717a7741afSMartin Matuska 	    doi.doi_bonus_type != DMU_OT_ZNODE) ||
727a7741afSMartin Matuska 	    (doi.doi_bonus_type == DMU_OT_ZNODE &&
737a7741afSMartin Matuska 	    doi.doi_bonus_size < sizeof (znode_phys_t))) {
747a7741afSMartin Matuska 		sa_buf_rele(*db, tag);
757a7741afSMartin Matuska 		return (SET_ERROR(ENOTSUP));
767a7741afSMartin Matuska 	}
777a7741afSMartin Matuska 
787a7741afSMartin Matuska 	error = sa_handle_get(osp, obj, NULL, SA_HDL_PRIVATE, hdlp);
797a7741afSMartin Matuska 	if (error != 0) {
807a7741afSMartin Matuska 		sa_buf_rele(*db, tag);
817a7741afSMartin Matuska 		return (error);
827a7741afSMartin Matuska 	}
837a7741afSMartin Matuska 
847a7741afSMartin Matuska 	return (0);
857a7741afSMartin Matuska }
867a7741afSMartin Matuska 
877a7741afSMartin Matuska static void
zfs_release_sa_handle(sa_handle_t * hdl,dmu_buf_t * db,const void * tag)887a7741afSMartin Matuska zfs_release_sa_handle(sa_handle_t *hdl, dmu_buf_t *db, const void *tag)
897a7741afSMartin Matuska {
907a7741afSMartin Matuska 	sa_handle_destroy(hdl);
917a7741afSMartin Matuska 	sa_buf_rele(db, tag);
927a7741afSMartin Matuska }
937a7741afSMartin Matuska 
947a7741afSMartin Matuska /*
957a7741afSMartin Matuska  * Given an object number, return its parent object number and whether
967a7741afSMartin Matuska  * or not the object is an extended attribute directory.
977a7741afSMartin Matuska  */
987a7741afSMartin Matuska int
zfs_obj_to_pobj(objset_t * osp,sa_handle_t * hdl,sa_attr_type_t * sa_table,uint64_t * pobjp,int * is_xattrdir)997a7741afSMartin Matuska zfs_obj_to_pobj(objset_t *osp, sa_handle_t *hdl, sa_attr_type_t *sa_table,
1007a7741afSMartin Matuska     uint64_t *pobjp, int *is_xattrdir)
1017a7741afSMartin Matuska {
1027a7741afSMartin Matuska 	uint64_t parent;
1037a7741afSMartin Matuska 	uint64_t pflags;
1047a7741afSMartin Matuska 	uint64_t mode;
1057a7741afSMartin Matuska 	uint64_t parent_mode;
1067a7741afSMartin Matuska 	sa_bulk_attr_t bulk[3];
1077a7741afSMartin Matuska 	sa_handle_t *sa_hdl;
1087a7741afSMartin Matuska 	dmu_buf_t *sa_db;
1097a7741afSMartin Matuska 	int count = 0;
1107a7741afSMartin Matuska 	int error;
1117a7741afSMartin Matuska 
1127a7741afSMartin Matuska 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_PARENT], NULL,
1137a7741afSMartin Matuska 	    &parent, sizeof (parent));
1147a7741afSMartin Matuska 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_FLAGS], NULL,
1157a7741afSMartin Matuska 	    &pflags, sizeof (pflags));
1167a7741afSMartin Matuska 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_MODE], NULL,
1177a7741afSMartin Matuska 	    &mode, sizeof (mode));
1187a7741afSMartin Matuska 
1197a7741afSMartin Matuska 	if ((error = sa_bulk_lookup(hdl, bulk, count)) != 0)
1207a7741afSMartin Matuska 		return (error);
1217a7741afSMartin Matuska 
1227a7741afSMartin Matuska 	/*
1237a7741afSMartin Matuska 	 * When a link is removed its parent pointer is not changed and will
1247a7741afSMartin Matuska 	 * be invalid.  There are two cases where a link is removed but the
1257a7741afSMartin Matuska 	 * file stays around, when it goes to the delete queue and when there
1267a7741afSMartin Matuska 	 * are additional links.
1277a7741afSMartin Matuska 	 */
1287a7741afSMartin Matuska 	error = zfs_grab_sa_handle(osp, parent, &sa_hdl, &sa_db, FTAG);
1297a7741afSMartin Matuska 	if (error != 0)
1307a7741afSMartin Matuska 		return (error);
1317a7741afSMartin Matuska 
1327a7741afSMartin Matuska 	error = sa_lookup(sa_hdl, ZPL_MODE, &parent_mode, sizeof (parent_mode));
1337a7741afSMartin Matuska 	zfs_release_sa_handle(sa_hdl, sa_db, FTAG);
1347a7741afSMartin Matuska 	if (error != 0)
1357a7741afSMartin Matuska 		return (error);
1367a7741afSMartin Matuska 
1377a7741afSMartin Matuska 	*is_xattrdir = ((pflags & ZFS_XATTR) != 0) && S_ISDIR(mode);
1387a7741afSMartin Matuska 
1397a7741afSMartin Matuska 	/*
1407a7741afSMartin Matuska 	 * Extended attributes can be applied to files, directories, etc.
1417a7741afSMartin Matuska 	 * Otherwise the parent must be a directory.
1427a7741afSMartin Matuska 	 */
1437a7741afSMartin Matuska 	if (!*is_xattrdir && !S_ISDIR(parent_mode))
1447a7741afSMartin Matuska 		return (SET_ERROR(EINVAL));
1457a7741afSMartin Matuska 
1467a7741afSMartin Matuska 	*pobjp = parent;
1477a7741afSMartin Matuska 
1487a7741afSMartin Matuska 	return (0);
1497a7741afSMartin Matuska }
1507a7741afSMartin Matuska 
1517a7741afSMartin Matuska /*
1527a7741afSMartin Matuska  * Given an object number, return some zpl level statistics
1537a7741afSMartin Matuska  */
1547a7741afSMartin Matuska static int
zfs_obj_to_stats_impl(sa_handle_t * hdl,sa_attr_type_t * sa_table,zfs_stat_t * sb)1557a7741afSMartin Matuska zfs_obj_to_stats_impl(sa_handle_t *hdl, sa_attr_type_t *sa_table,
1567a7741afSMartin Matuska     zfs_stat_t *sb)
1577a7741afSMartin Matuska {
1587a7741afSMartin Matuska 	sa_bulk_attr_t bulk[4];
1597a7741afSMartin Matuska 	int count = 0;
1607a7741afSMartin Matuska 
1617a7741afSMartin Matuska 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_MODE], NULL,
1627a7741afSMartin Matuska 	    &sb->zs_mode, sizeof (sb->zs_mode));
1637a7741afSMartin Matuska 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_GEN], NULL,
1647a7741afSMartin Matuska 	    &sb->zs_gen, sizeof (sb->zs_gen));
1657a7741afSMartin Matuska 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_LINKS], NULL,
1667a7741afSMartin Matuska 	    &sb->zs_links, sizeof (sb->zs_links));
1677a7741afSMartin Matuska 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_CTIME], NULL,
1687a7741afSMartin Matuska 	    &sb->zs_ctime, sizeof (sb->zs_ctime));
1697a7741afSMartin Matuska 
1707a7741afSMartin Matuska 	return (sa_bulk_lookup(hdl, bulk, count));
1717a7741afSMartin Matuska }
1727a7741afSMartin Matuska 
1737a7741afSMartin Matuska static int
zfs_obj_to_path_impl(objset_t * osp,uint64_t obj,sa_handle_t * hdl,sa_attr_type_t * sa_table,char * buf,int len)1747a7741afSMartin Matuska zfs_obj_to_path_impl(objset_t *osp, uint64_t obj, sa_handle_t *hdl,
1757a7741afSMartin Matuska     sa_attr_type_t *sa_table, char *buf, int len)
1767a7741afSMartin Matuska {
1777a7741afSMartin Matuska 	sa_handle_t *sa_hdl;
1787a7741afSMartin Matuska 	sa_handle_t *prevhdl = NULL;
1797a7741afSMartin Matuska 	dmu_buf_t *prevdb = NULL;
1807a7741afSMartin Matuska 	dmu_buf_t *sa_db = NULL;
1817a7741afSMartin Matuska 	char *path = buf + len - 1;
1827a7741afSMartin Matuska 	char *comp_buf;
1837a7741afSMartin Matuska 	int error;
1847a7741afSMartin Matuska 
1857a7741afSMartin Matuska 	*path = '\0';
1867a7741afSMartin Matuska 	sa_hdl = hdl;
1877a7741afSMartin Matuska 
1887a7741afSMartin Matuska 	uint64_t deleteq_obj;
1897a7741afSMartin Matuska 	VERIFY0(zap_lookup(osp, MASTER_NODE_OBJ,
1907a7741afSMartin Matuska 	    ZFS_UNLINKED_SET, sizeof (uint64_t), 1, &deleteq_obj));
1917a7741afSMartin Matuska 	error = zap_lookup_int(osp, deleteq_obj, obj);
1927a7741afSMartin Matuska 	if (error == 0) {
1937a7741afSMartin Matuska 		return (ESTALE);
1947a7741afSMartin Matuska 	} else if (error != ENOENT) {
1957a7741afSMartin Matuska 		return (error);
1967a7741afSMartin Matuska 	}
1977a7741afSMartin Matuska 
1987a7741afSMartin Matuska 	comp_buf = kmem_alloc(ZAP_MAXNAMELEN_NEW + 2, KM_SLEEP);
1997a7741afSMartin Matuska 	for (;;) {
2007a7741afSMartin Matuska 		uint64_t pobj = 0;
2017a7741afSMartin Matuska 		char *component = comp_buf;
2027a7741afSMartin Matuska 		size_t complen;
2037a7741afSMartin Matuska 		int is_xattrdir = 0;
2047a7741afSMartin Matuska 
2057a7741afSMartin Matuska 		if (prevdb) {
2067a7741afSMartin Matuska 			ASSERT3P(prevhdl, !=, NULL);
2077a7741afSMartin Matuska 			zfs_release_sa_handle(prevhdl, prevdb, FTAG);
2087a7741afSMartin Matuska 		}
2097a7741afSMartin Matuska 
2107a7741afSMartin Matuska 		if ((error = zfs_obj_to_pobj(osp, sa_hdl, sa_table, &pobj,
2117a7741afSMartin Matuska 		    &is_xattrdir)) != 0)
2127a7741afSMartin Matuska 			break;
2137a7741afSMartin Matuska 
2147a7741afSMartin Matuska 		if (pobj == obj) {
2157a7741afSMartin Matuska 			if (path[0] != '/')
2167a7741afSMartin Matuska 				*--path = '/';
2177a7741afSMartin Matuska 			break;
2187a7741afSMartin Matuska 		}
2197a7741afSMartin Matuska 
2207a7741afSMartin Matuska 		component[0] = '/';
2217a7741afSMartin Matuska 		if (is_xattrdir) {
2227a7741afSMartin Matuska 			strcpy(component + 1, "<xattrdir>");
2237a7741afSMartin Matuska 		} else {
2247a7741afSMartin Matuska 			error = zap_value_search(osp, pobj, obj,
2257a7741afSMartin Matuska 			    ZFS_DIRENT_OBJ(-1ULL), component + 1,
2267a7741afSMartin Matuska 			    ZAP_MAXNAMELEN_NEW);
2277a7741afSMartin Matuska 			if (error != 0)
2287a7741afSMartin Matuska 				break;
2297a7741afSMartin Matuska 		}
2307a7741afSMartin Matuska 
2317a7741afSMartin Matuska 		complen = strlen(component);
2327a7741afSMartin Matuska 		path -= complen;
2337a7741afSMartin Matuska 		ASSERT3P(path, >=, buf);
2347a7741afSMartin Matuska 		memcpy(path, component, complen);
2357a7741afSMartin Matuska 		obj = pobj;
2367a7741afSMartin Matuska 
2377a7741afSMartin Matuska 		if (sa_hdl != hdl) {
2387a7741afSMartin Matuska 			prevhdl = sa_hdl;
2397a7741afSMartin Matuska 			prevdb = sa_db;
2407a7741afSMartin Matuska 		}
2417a7741afSMartin Matuska 		error = zfs_grab_sa_handle(osp, obj, &sa_hdl, &sa_db, FTAG);
2427a7741afSMartin Matuska 		if (error != 0) {
2437a7741afSMartin Matuska 			sa_hdl = prevhdl;
2447a7741afSMartin Matuska 			sa_db = prevdb;
2457a7741afSMartin Matuska 			break;
2467a7741afSMartin Matuska 		}
2477a7741afSMartin Matuska 	}
2487a7741afSMartin Matuska 
2497a7741afSMartin Matuska 	if (sa_hdl != NULL && sa_hdl != hdl) {
2507a7741afSMartin Matuska 		ASSERT3P(sa_db, !=, NULL);
2517a7741afSMartin Matuska 		zfs_release_sa_handle(sa_hdl, sa_db, FTAG);
2527a7741afSMartin Matuska 	}
2537a7741afSMartin Matuska 
2547a7741afSMartin Matuska 	if (error == 0)
2557a7741afSMartin Matuska 		(void) memmove(buf, path, buf + len - path);
2567a7741afSMartin Matuska 
2577a7741afSMartin Matuska 	kmem_free(comp_buf, ZAP_MAXNAMELEN_NEW +2);
2587a7741afSMartin Matuska 	return (error);
2597a7741afSMartin Matuska }
2607a7741afSMartin Matuska 
2617a7741afSMartin Matuska int
zfs_obj_to_path(objset_t * osp,uint64_t obj,char * buf,int len)2627a7741afSMartin Matuska zfs_obj_to_path(objset_t *osp, uint64_t obj, char *buf, int len)
2637a7741afSMartin Matuska {
2647a7741afSMartin Matuska 	sa_attr_type_t *sa_table;
2657a7741afSMartin Matuska 	sa_handle_t *hdl;
2667a7741afSMartin Matuska 	dmu_buf_t *db;
2677a7741afSMartin Matuska 	int error;
2687a7741afSMartin Matuska 
2697a7741afSMartin Matuska 	error = zfs_sa_setup(osp, &sa_table);
2707a7741afSMartin Matuska 	if (error != 0)
2717a7741afSMartin Matuska 		return (error);
2727a7741afSMartin Matuska 
2737a7741afSMartin Matuska 	error = zfs_grab_sa_handle(osp, obj, &hdl, &db, FTAG);
2747a7741afSMartin Matuska 	if (error != 0)
2757a7741afSMartin Matuska 		return (error);
2767a7741afSMartin Matuska 
2777a7741afSMartin Matuska 	error = zfs_obj_to_path_impl(osp, obj, hdl, sa_table, buf, len);
2787a7741afSMartin Matuska 
2797a7741afSMartin Matuska 	zfs_release_sa_handle(hdl, db, FTAG);
2807a7741afSMartin Matuska 	return (error);
2817a7741afSMartin Matuska }
2827a7741afSMartin Matuska 
2837a7741afSMartin Matuska int
zfs_obj_to_stats(objset_t * osp,uint64_t obj,zfs_stat_t * sb,char * buf,int len)2847a7741afSMartin Matuska zfs_obj_to_stats(objset_t *osp, uint64_t obj, zfs_stat_t *sb,
2857a7741afSMartin Matuska     char *buf, int len)
2867a7741afSMartin Matuska {
2877a7741afSMartin Matuska 	char *path = buf + len - 1;
2887a7741afSMartin Matuska 	sa_attr_type_t *sa_table;
2897a7741afSMartin Matuska 	sa_handle_t *hdl;
2907a7741afSMartin Matuska 	dmu_buf_t *db;
2917a7741afSMartin Matuska 	int error;
2927a7741afSMartin Matuska 
2937a7741afSMartin Matuska 	*path = '\0';
2947a7741afSMartin Matuska 
2957a7741afSMartin Matuska 	error = zfs_sa_setup(osp, &sa_table);
2967a7741afSMartin Matuska 	if (error != 0)
2977a7741afSMartin Matuska 		return (error);
2987a7741afSMartin Matuska 
2997a7741afSMartin Matuska 	error = zfs_grab_sa_handle(osp, obj, &hdl, &db, FTAG);
3007a7741afSMartin Matuska 	if (error != 0)
3017a7741afSMartin Matuska 		return (error);
3027a7741afSMartin Matuska 
3037a7741afSMartin Matuska 	error = zfs_obj_to_stats_impl(hdl, sa_table, sb);
3047a7741afSMartin Matuska 	if (error != 0) {
3057a7741afSMartin Matuska 		zfs_release_sa_handle(hdl, db, FTAG);
3067a7741afSMartin Matuska 		return (error);
3077a7741afSMartin Matuska 	}
3087a7741afSMartin Matuska 
3097a7741afSMartin Matuska 	error = zfs_obj_to_path_impl(osp, obj, hdl, sa_table, buf, len);
3107a7741afSMartin Matuska 
3117a7741afSMartin Matuska 	zfs_release_sa_handle(hdl, db, FTAG);
3127a7741afSMartin Matuska 	return (error);
3137a7741afSMartin Matuska }
3147a7741afSMartin Matuska 
3157a7741afSMartin Matuska /*
3167a7741afSMartin Matuska  * Read a property stored within the master node.
3177a7741afSMartin Matuska  */
3187a7741afSMartin Matuska int
zfs_get_zplprop(objset_t * os,zfs_prop_t prop,uint64_t * value)3197a7741afSMartin Matuska zfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value)
3207a7741afSMartin Matuska {
3217a7741afSMartin Matuska 	uint64_t *cached_copy = NULL;
3227a7741afSMartin Matuska 
3237a7741afSMartin Matuska 	/*
3247a7741afSMartin Matuska 	 * Figure out where in the objset_t the cached copy would live, if it
3257a7741afSMartin Matuska 	 * is available for the requested property.
3267a7741afSMartin Matuska 	 */
3277a7741afSMartin Matuska 	if (os != NULL) {
3287a7741afSMartin Matuska 		switch (prop) {
3297a7741afSMartin Matuska 		case ZFS_PROP_VERSION:
3307a7741afSMartin Matuska 			cached_copy = &os->os_version;
3317a7741afSMartin Matuska 			break;
3327a7741afSMartin Matuska 		case ZFS_PROP_NORMALIZE:
3337a7741afSMartin Matuska 			cached_copy = &os->os_normalization;
3347a7741afSMartin Matuska 			break;
3357a7741afSMartin Matuska 		case ZFS_PROP_UTF8ONLY:
3367a7741afSMartin Matuska 			cached_copy = &os->os_utf8only;
3377a7741afSMartin Matuska 			break;
3387a7741afSMartin Matuska 		case ZFS_PROP_CASE:
3397a7741afSMartin Matuska 			cached_copy = &os->os_casesensitivity;
3407a7741afSMartin Matuska 			break;
3417a7741afSMartin Matuska 		default:
3427a7741afSMartin Matuska 			break;
3437a7741afSMartin Matuska 		}
3447a7741afSMartin Matuska 	}
3457a7741afSMartin Matuska 	if (cached_copy != NULL && *cached_copy != OBJSET_PROP_UNINITIALIZED) {
3467a7741afSMartin Matuska 		*value = *cached_copy;
3477a7741afSMartin Matuska 		return (0);
3487a7741afSMartin Matuska 	}
3497a7741afSMartin Matuska 
3507a7741afSMartin Matuska 	/*
3517a7741afSMartin Matuska 	 * If the property wasn't cached, look up the file system's value for
3527a7741afSMartin Matuska 	 * the property. For the version property, we look up a slightly
3537a7741afSMartin Matuska 	 * different string.
3547a7741afSMartin Matuska 	 */
3557a7741afSMartin Matuska 	const char *pname;
3567a7741afSMartin Matuska 	int error = ENOENT;
3577a7741afSMartin Matuska 	if (prop == ZFS_PROP_VERSION)
3587a7741afSMartin Matuska 		pname = ZPL_VERSION_STR;
3597a7741afSMartin Matuska 	else
3607a7741afSMartin Matuska 		pname = zfs_prop_to_name(prop);
3617a7741afSMartin Matuska 
3627a7741afSMartin Matuska 	if (os != NULL) {
3637a7741afSMartin Matuska 		ASSERT3U(os->os_phys->os_type, ==, DMU_OST_ZFS);
3647a7741afSMartin Matuska 		error = zap_lookup(os, MASTER_NODE_OBJ, pname, 8, 1, value);
3657a7741afSMartin Matuska 	}
3667a7741afSMartin Matuska 
3677a7741afSMartin Matuska 	if (error == ENOENT) {
3687a7741afSMartin Matuska 		/* No value set, use the default value */
3697a7741afSMartin Matuska 		switch (prop) {
3707a7741afSMartin Matuska 		case ZFS_PROP_VERSION:
3717a7741afSMartin Matuska 			*value = ZPL_VERSION;
3727a7741afSMartin Matuska 			break;
3737a7741afSMartin Matuska 		case ZFS_PROP_NORMALIZE:
3747a7741afSMartin Matuska 		case ZFS_PROP_UTF8ONLY:
3757a7741afSMartin Matuska 			*value = 0;
3767a7741afSMartin Matuska 			break;
3777a7741afSMartin Matuska 		case ZFS_PROP_CASE:
3787a7741afSMartin Matuska 			*value = ZFS_CASE_SENSITIVE;
3797a7741afSMartin Matuska 			break;
3807a7741afSMartin Matuska 		case ZFS_PROP_ACLTYPE:
3817a7741afSMartin Matuska #ifdef __FreeBSD__
3827a7741afSMartin Matuska 			*value = ZFS_ACLTYPE_NFSV4;
3837a7741afSMartin Matuska #else
3847a7741afSMartin Matuska 			*value = ZFS_ACLTYPE_OFF;
3857a7741afSMartin Matuska #endif
3867a7741afSMartin Matuska 			break;
387*071ab5a1SMartin Matuska 		case ZFS_PROP_DEFAULTUSERQUOTA:
388*071ab5a1SMartin Matuska 		case ZFS_PROP_DEFAULTGROUPQUOTA:
389*071ab5a1SMartin Matuska 		case ZFS_PROP_DEFAULTPROJECTQUOTA:
390*071ab5a1SMartin Matuska 		case ZFS_PROP_DEFAULTUSEROBJQUOTA:
391*071ab5a1SMartin Matuska 		case ZFS_PROP_DEFAULTGROUPOBJQUOTA:
392*071ab5a1SMartin Matuska 		case ZFS_PROP_DEFAULTPROJECTOBJQUOTA:
393*071ab5a1SMartin Matuska 			*value = 0;
394*071ab5a1SMartin Matuska 			return (0);
3957a7741afSMartin Matuska 		default:
3967a7741afSMartin Matuska 			return (error);
3977a7741afSMartin Matuska 		}
3987a7741afSMartin Matuska 		error = 0;
3997a7741afSMartin Matuska 	}
4007a7741afSMartin Matuska 
4017a7741afSMartin Matuska 	/*
4027a7741afSMartin Matuska 	 * If one of the methods for getting the property value above worked,
4037a7741afSMartin Matuska 	 * copy it into the objset_t's cache.
4047a7741afSMartin Matuska 	 */
4057a7741afSMartin Matuska 	if (error == 0 && cached_copy != NULL) {
4067a7741afSMartin Matuska 		*cached_copy = *value;
4077a7741afSMartin Matuska 	}
4087a7741afSMartin Matuska 
4097a7741afSMartin Matuska 	return (error);
4107a7741afSMartin Matuska }
411