xref: /illumos-gate/usr/src/uts/common/fs/zfs/zfs_znode.c (revision b515258426fed6c7311fd3f1dea697cfbd4085c6)
1fa9e4066Sahrens /*
2fa9e4066Sahrens  * CDDL HEADER START
3fa9e4066Sahrens  *
4fa9e4066Sahrens  * The contents of this file are subject to the terms of the
5ea8dc4b6Seschrock  * Common Development and Distribution License (the "License").
6ea8dc4b6Seschrock  * You may not use this file except in compliance with the License.
7fa9e4066Sahrens  *
8fa9e4066Sahrens  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fa9e4066Sahrens  * or http://www.opensolaris.org/os/licensing.
10fa9e4066Sahrens  * See the License for the specific language governing permissions
11fa9e4066Sahrens  * and limitations under the License.
12fa9e4066Sahrens  *
13fa9e4066Sahrens  * When distributing Covered Code, include this CDDL HEADER in each
14fa9e4066Sahrens  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fa9e4066Sahrens  * If applicable, add the following below this CDDL HEADER, with the
16fa9e4066Sahrens  * fields enclosed by brackets "[]" replaced with your own identifying
17fa9e4066Sahrens  * information: Portions Copyright [yyyy] [name of copyright owner]
18fa9e4066Sahrens  *
19fa9e4066Sahrens  * CDDL HEADER END
20fa9e4066Sahrens  */
21fa9e4066Sahrens /*
228f2529deSMark Shellenbaum  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
234bb73804SMatthew Ahrens  * Copyright (c) 2012, 2014 by Delphix. All rights reserved.
24fa9e4066Sahrens  */
25fa9e4066Sahrens 
2675c76197Speteh /* Portions Copyright 2007 Jeremy Teo */
2775c76197Speteh 
2855434c77Sek #ifdef _KERNEL
29fa9e4066Sahrens #include <sys/types.h>
30fa9e4066Sahrens #include <sys/param.h>
31fa9e4066Sahrens #include <sys/time.h>
32fa9e4066Sahrens #include <sys/systm.h>
33fa9e4066Sahrens #include <sys/sysmacros.h>
34fa9e4066Sahrens #include <sys/resource.h>
35fa9e4066Sahrens #include <sys/mntent.h>
3672fc53bcSmarks #include <sys/mkdev.h>
37de8267e0Stimh #include <sys/u8_textprep.h>
38ab04eb8eStimh #include <sys/dsl_dataset.h>
39fa9e4066Sahrens #include <sys/vfs.h>
40aa59c4cbSrsb #include <sys/vfs_opreg.h>
41fa9e4066Sahrens #include <sys/vnode.h>
42fa9e4066Sahrens #include <sys/file.h>
43fa9e4066Sahrens #include <sys/kmem.h>
44fa9e4066Sahrens #include <sys/errno.h>
45fa9e4066Sahrens #include <sys/unistd.h>
46fa9e4066Sahrens #include <sys/mode.h>
47fa9e4066Sahrens #include <sys/atomic.h>
48fa9e4066Sahrens #include <vm/pvn.h>
49fa9e4066Sahrens #include "fs/fs_subr.h"
50fa9e4066Sahrens #include <sys/zfs_dir.h>
51fa9e4066Sahrens #include <sys/zfs_acl.h>
52fa9e4066Sahrens #include <sys/zfs_ioctl.h>
53104e2ed7Sperrin #include <sys/zfs_rlock.h>
54da6c28aaSamw #include <sys/zfs_fuid.h>
550a586ceaSMark Shellenbaum #include <sys/dnode.h>
56fa9e4066Sahrens #include <sys/fs/zfs.h>
57da6c28aaSamw #include <sys/kidmap.h>
5855434c77Sek #endif /* _KERNEL */
5955434c77Sek 
6055434c77Sek #include <sys/dmu.h>
61*b5152584SMatthew Ahrens #include <sys/dmu_objset.h>
6255434c77Sek #include <sys/refcount.h>
6355434c77Sek #include <sys/stat.h>
6455434c77Sek #include <sys/zap.h>
6555434c77Sek #include <sys/zfs_znode.h>
660a586ceaSMark Shellenbaum #include <sys/sa.h>
670a586ceaSMark Shellenbaum #include <sys/zfs_sa.h>
6899d5e173STim Haley #include <sys/zfs_stat.h>
69fa9e4066Sahrens 
70de8267e0Stimh #include "zfs_prop.h"
710a586ceaSMark Shellenbaum #include "zfs_comutil.h"
72de8267e0Stimh 
73b5fca8f8Stomee /*
74b5fca8f8Stomee  * Define ZNODE_STATS to turn on statistic gathering. By default, it is only
75b5fca8f8Stomee  * turned on when DEBUG is also defined.
76b5fca8f8Stomee  */
77b5fca8f8Stomee #ifdef	DEBUG
78b5fca8f8Stomee #define	ZNODE_STATS
79b5fca8f8Stomee #endif	/* DEBUG */
80b5fca8f8Stomee 
81b5fca8f8Stomee #ifdef	ZNODE_STATS
82b5fca8f8Stomee #define	ZNODE_STAT_ADD(stat)			((stat)++)
83b5fca8f8Stomee #else
84b5fca8f8Stomee #define	ZNODE_STAT_ADD(stat)			/* nothing */
85b5fca8f8Stomee #endif	/* ZNODE_STATS */
86b5fca8f8Stomee 
8755434c77Sek /*
8855434c77Sek  * Functions needed for userland (ie: libzpool) are not put under
8955434c77Sek  * #ifdef_KERNEL; the rest of the functions have dependencies
9055434c77Sek  * (such as VFS logic) that will not compile easily in userland.
9155434c77Sek  */
9255434c77Sek #ifdef _KERNEL
934e9583b2STom Erickson /*
944e9583b2STom Erickson  * Needed to close a small window in zfs_znode_move() that allows the zfsvfs to
954e9583b2STom Erickson  * be freed before it can be safely accessed.
964e9583b2STom Erickson  */
974e9583b2STom Erickson krwlock_t zfsvfs_lock;
984e9583b2STom Erickson 
99b5fca8f8Stomee static kmem_cache_t *znode_cache = NULL;
100fa9e4066Sahrens 
101fa9e4066Sahrens /*ARGSUSED*/
102fa9e4066Sahrens static void
103874395d5Smaybee znode_evict_error(dmu_buf_t *dbuf, void *user_ptr)
104fa9e4066Sahrens {
105874395d5Smaybee 	/*
106874395d5Smaybee 	 * We should never drop all dbuf refs without first clearing
107874395d5Smaybee 	 * the eviction callback.
108874395d5Smaybee 	 */
109874395d5Smaybee 	panic("evicting znode %p\n", user_ptr);
110fa9e4066Sahrens }
111fa9e4066Sahrens 
112fa9e4066Sahrens /*ARGSUSED*/
113fa9e4066Sahrens static int
114b5fca8f8Stomee zfs_znode_cache_constructor(void *buf, void *arg, int kmflags)
115fa9e4066Sahrens {
116fa9e4066Sahrens 	znode_t *zp = buf;
117fa9e4066Sahrens 
118b5fca8f8Stomee 	ASSERT(!POINTER_IS_VALID(zp->z_zfsvfs));
119b5fca8f8Stomee 
120b5fca8f8Stomee 	zp->z_vnode = vn_alloc(kmflags);
121b5fca8f8Stomee 	if (zp->z_vnode == NULL) {
122b5fca8f8Stomee 		return (-1);
123b5fca8f8Stomee 	}
124b5fca8f8Stomee 	ZTOV(zp)->v_data = zp;
125b5fca8f8Stomee 
126b5fca8f8Stomee 	list_link_init(&zp->z_link_node);
127b5fca8f8Stomee 
128fa9e4066Sahrens 	mutex_init(&zp->z_lock, NULL, MUTEX_DEFAULT, NULL);
129104e2ed7Sperrin 	rw_init(&zp->z_parent_lock, NULL, RW_DEFAULT, NULL);
130af2c4821Smaybee 	rw_init(&zp->z_name_lock, NULL, RW_DEFAULT, NULL);
131fa9e4066Sahrens 	mutex_init(&zp->z_acl_lock, NULL, MUTEX_DEFAULT, NULL);
132104e2ed7Sperrin 
133104e2ed7Sperrin 	mutex_init(&zp->z_range_lock, NULL, MUTEX_DEFAULT, NULL);
134104e2ed7Sperrin 	avl_create(&zp->z_range_avl, zfs_range_compare,
135104e2ed7Sperrin 	    sizeof (rl_t), offsetof(rl_t, r_node));
136104e2ed7Sperrin 
137b5fca8f8Stomee 	zp->z_dirlocks = NULL;
138d47621a4STim Haley 	zp->z_acl_cached = NULL;
139744947dcSTom Erickson 	zp->z_moved = 0;
140fa9e4066Sahrens 	return (0);
141fa9e4066Sahrens }
142fa9e4066Sahrens 
143fa9e4066Sahrens /*ARGSUSED*/
144fa9e4066Sahrens static void
145b5fca8f8Stomee zfs_znode_cache_destructor(void *buf, void *arg)
146fa9e4066Sahrens {
147fa9e4066Sahrens 	znode_t *zp = buf;
148fa9e4066Sahrens 
149b5fca8f8Stomee 	ASSERT(!POINTER_IS_VALID(zp->z_zfsvfs));
150b5fca8f8Stomee 	ASSERT(ZTOV(zp)->v_data == zp);
151b5fca8f8Stomee 	vn_free(ZTOV(zp));
152b5fca8f8Stomee 	ASSERT(!list_link_active(&zp->z_link_node));
153fa9e4066Sahrens 	mutex_destroy(&zp->z_lock);
154104e2ed7Sperrin 	rw_destroy(&zp->z_parent_lock);
155af2c4821Smaybee 	rw_destroy(&zp->z_name_lock);
156fa9e4066Sahrens 	mutex_destroy(&zp->z_acl_lock);
157104e2ed7Sperrin 	avl_destroy(&zp->z_range_avl);
158c25056deSgw 	mutex_destroy(&zp->z_range_lock);
159fa9e4066Sahrens 
160b5fca8f8Stomee 	ASSERT(zp->z_dirlocks == NULL);
1614929fd5eSTim Haley 	ASSERT(zp->z_acl_cached == NULL);
162b5fca8f8Stomee }
163b5fca8f8Stomee 
164b5fca8f8Stomee #ifdef	ZNODE_STATS
165b5fca8f8Stomee static struct {
166b5fca8f8Stomee 	uint64_t zms_zfsvfs_invalid;
1674e9583b2STom Erickson 	uint64_t zms_zfsvfs_recheck1;
168b5fca8f8Stomee 	uint64_t zms_zfsvfs_unmounted;
1694e9583b2STom Erickson 	uint64_t zms_zfsvfs_recheck2;
170a66b2b35STom Erickson 	uint64_t zms_obj_held;
171b5fca8f8Stomee 	uint64_t zms_vnode_locked;
172a66b2b35STom Erickson 	uint64_t zms_not_only_dnlc;
173b5fca8f8Stomee } znode_move_stats;
174b5fca8f8Stomee #endif	/* ZNODE_STATS */
175b5fca8f8Stomee 
176b5fca8f8Stomee static void
177b5fca8f8Stomee zfs_znode_move_impl(znode_t *ozp, znode_t *nzp)
178b5fca8f8Stomee {
179b5fca8f8Stomee 	vnode_t *vp;
180b5fca8f8Stomee 
181b5fca8f8Stomee 	/* Copy fields. */
182b5fca8f8Stomee 	nzp->z_zfsvfs = ozp->z_zfsvfs;
183b5fca8f8Stomee 
184b5fca8f8Stomee 	/* Swap vnodes. */
185b5fca8f8Stomee 	vp = nzp->z_vnode;
186b5fca8f8Stomee 	nzp->z_vnode = ozp->z_vnode;
187b5fca8f8Stomee 	ozp->z_vnode = vp; /* let destructor free the overwritten vnode */
188b5fca8f8Stomee 	ZTOV(ozp)->v_data = ozp;
189b5fca8f8Stomee 	ZTOV(nzp)->v_data = nzp;
190b5fca8f8Stomee 
191b5fca8f8Stomee 	nzp->z_id = ozp->z_id;
192b5fca8f8Stomee 	ASSERT(ozp->z_dirlocks == NULL); /* znode not in use */
193b5fca8f8Stomee 	ASSERT(avl_numnodes(&ozp->z_range_avl) == 0);
194b5fca8f8Stomee 	nzp->z_unlinked = ozp->z_unlinked;
195b5fca8f8Stomee 	nzp->z_atime_dirty = ozp->z_atime_dirty;
196b5fca8f8Stomee 	nzp->z_zn_prefetch = ozp->z_zn_prefetch;
197b5fca8f8Stomee 	nzp->z_blksz = ozp->z_blksz;
198b5fca8f8Stomee 	nzp->z_seq = ozp->z_seq;
199b5fca8f8Stomee 	nzp->z_mapcnt = ozp->z_mapcnt;
200b5fca8f8Stomee 	nzp->z_gen = ozp->z_gen;
201b5fca8f8Stomee 	nzp->z_sync_cnt = ozp->z_sync_cnt;
2020a586ceaSMark Shellenbaum 	nzp->z_is_sa = ozp->z_is_sa;
2030a586ceaSMark Shellenbaum 	nzp->z_sa_hdl = ozp->z_sa_hdl;
2040a586ceaSMark Shellenbaum 	bcopy(ozp->z_atime, nzp->z_atime, sizeof (uint64_t) * 2);
2050a586ceaSMark Shellenbaum 	nzp->z_links = ozp->z_links;
2060a586ceaSMark Shellenbaum 	nzp->z_size = ozp->z_size;
2070a586ceaSMark Shellenbaum 	nzp->z_pflags = ozp->z_pflags;
2080a586ceaSMark Shellenbaum 	nzp->z_uid = ozp->z_uid;
2090a586ceaSMark Shellenbaum 	nzp->z_gid = ozp->z_gid;
2100a586ceaSMark Shellenbaum 	nzp->z_mode = ozp->z_mode;
211d98a6232SMark Shellenbaum 
212d98a6232SMark Shellenbaum 	/*
2136638ae1dSMark Shellenbaum 	 * Since this is just an idle znode and kmem is already dealing with
2146638ae1dSMark Shellenbaum 	 * memory pressure, release any cached ACL.
215d98a6232SMark Shellenbaum 	 */
216d98a6232SMark Shellenbaum 	if (ozp->z_acl_cached) {
217d98a6232SMark Shellenbaum 		zfs_acl_free(ozp->z_acl_cached);
218d98a6232SMark Shellenbaum 		ozp->z_acl_cached = NULL;
219d98a6232SMark Shellenbaum 	}
220b5fca8f8Stomee 
2210a586ceaSMark Shellenbaum 	sa_set_userp(nzp->z_sa_hdl, nzp);
222b5fca8f8Stomee 
223b5fca8f8Stomee 	/*
224b5fca8f8Stomee 	 * Invalidate the original znode by clearing fields that provide a
225b5fca8f8Stomee 	 * pointer back to the znode. Set the low bit of the vfs pointer to
226b5fca8f8Stomee 	 * ensure that zfs_znode_move() recognizes the znode as invalid in any
227b5fca8f8Stomee 	 * subsequent callback.
228b5fca8f8Stomee 	 */
2290a586ceaSMark Shellenbaum 	ozp->z_sa_hdl = NULL;
230b5fca8f8Stomee 	POINTER_INVALIDATE(&ozp->z_zfsvfs);
231744947dcSTom Erickson 
232744947dcSTom Erickson 	/*
233744947dcSTom Erickson 	 * Mark the znode.
234744947dcSTom Erickson 	 */
235744947dcSTom Erickson 	nzp->z_moved = 1;
236744947dcSTom Erickson 	ozp->z_moved = (uint8_t)-1;
237b5fca8f8Stomee }
238b5fca8f8Stomee 
239b5fca8f8Stomee /*ARGSUSED*/
240b5fca8f8Stomee static kmem_cbrc_t
241b5fca8f8Stomee zfs_znode_move(void *buf, void *newbuf, size_t size, void *arg)
242b5fca8f8Stomee {
243b5fca8f8Stomee 	znode_t *ozp = buf, *nzp = newbuf;
244b5fca8f8Stomee 	zfsvfs_t *zfsvfs;
245b5fca8f8Stomee 	vnode_t *vp;
246b5fca8f8Stomee 
247b5fca8f8Stomee 	/*
248b5fca8f8Stomee 	 * The znode is on the file system's list of known znodes if the vfs
249b5fca8f8Stomee 	 * pointer is valid. We set the low bit of the vfs pointer when freeing
250b5fca8f8Stomee 	 * the znode to invalidate it, and the memory patterns written by kmem
251b5fca8f8Stomee 	 * (baddcafe and deadbeef) set at least one of the two low bits. A newly
252b5fca8f8Stomee 	 * created znode sets the vfs pointer last of all to indicate that the
253b5fca8f8Stomee 	 * znode is known and in a valid state to be moved by this function.
254b5fca8f8Stomee 	 */
255b5fca8f8Stomee 	zfsvfs = ozp->z_zfsvfs;
256b5fca8f8Stomee 	if (!POINTER_IS_VALID(zfsvfs)) {
257b5fca8f8Stomee 		ZNODE_STAT_ADD(znode_move_stats.zms_zfsvfs_invalid);
258b5fca8f8Stomee 		return (KMEM_CBRC_DONT_KNOW);
259b5fca8f8Stomee 	}
260b5fca8f8Stomee 
261b5fca8f8Stomee 	/*
2624e9583b2STom Erickson 	 * Close a small window in which it's possible that the filesystem could
2634e9583b2STom Erickson 	 * be unmounted and freed, and zfsvfs, though valid in the previous
2644e9583b2STom Erickson 	 * statement, could point to unrelated memory by the time we try to
2654e9583b2STom Erickson 	 * prevent the filesystem from being unmounted.
2664e9583b2STom Erickson 	 */
2674e9583b2STom Erickson 	rw_enter(&zfsvfs_lock, RW_WRITER);
2684e9583b2STom Erickson 	if (zfsvfs != ozp->z_zfsvfs) {
2694e9583b2STom Erickson 		rw_exit(&zfsvfs_lock);
2704e9583b2STom Erickson 		ZNODE_STAT_ADD(znode_move_stats.zms_zfsvfs_recheck1);
2714e9583b2STom Erickson 		return (KMEM_CBRC_DONT_KNOW);
2724e9583b2STom Erickson 	}
2734e9583b2STom Erickson 
2744e9583b2STom Erickson 	/*
2754e9583b2STom Erickson 	 * If the znode is still valid, then so is the file system. We know that
2764e9583b2STom Erickson 	 * no valid file system can be freed while we hold zfsvfs_lock, so we
2774e9583b2STom Erickson 	 * can safely ensure that the filesystem is not and will not be
2784e9583b2STom Erickson 	 * unmounted. The next statement is equivalent to ZFS_ENTER().
279b5fca8f8Stomee 	 */
280c9030f6cSAlexander Motin 	rrm_enter(&zfsvfs->z_teardown_lock, RW_READER, FTAG);
28114843421SMatthew Ahrens 	if (zfsvfs->z_unmounted) {
28214843421SMatthew Ahrens 		ZFS_EXIT(zfsvfs);
2834e9583b2STom Erickson 		rw_exit(&zfsvfs_lock);
284b5fca8f8Stomee 		ZNODE_STAT_ADD(znode_move_stats.zms_zfsvfs_unmounted);
285b5fca8f8Stomee 		return (KMEM_CBRC_DONT_KNOW);
286b5fca8f8Stomee 	}
2874e9583b2STom Erickson 	rw_exit(&zfsvfs_lock);
288b5fca8f8Stomee 
289b5fca8f8Stomee 	mutex_enter(&zfsvfs->z_znodes_lock);
290b5fca8f8Stomee 	/*
291b5fca8f8Stomee 	 * Recheck the vfs pointer in case the znode was removed just before
292b5fca8f8Stomee 	 * acquiring the lock.
293b5fca8f8Stomee 	 */
294b5fca8f8Stomee 	if (zfsvfs != ozp->z_zfsvfs) {
295b5fca8f8Stomee 		mutex_exit(&zfsvfs->z_znodes_lock);
296b5fca8f8Stomee 		ZFS_EXIT(zfsvfs);
2974e9583b2STom Erickson 		ZNODE_STAT_ADD(znode_move_stats.zms_zfsvfs_recheck2);
298b5fca8f8Stomee 		return (KMEM_CBRC_DONT_KNOW);
299b5fca8f8Stomee 	}
300b5fca8f8Stomee 
301b5fca8f8Stomee 	/*
302b5fca8f8Stomee 	 * At this point we know that as long as we hold z_znodes_lock, the
303b5fca8f8Stomee 	 * znode cannot be freed and fields within the znode can be safely
304a66b2b35STom Erickson 	 * accessed. Now, prevent a race with zfs_zget().
305b5fca8f8Stomee 	 */
306a66b2b35STom Erickson 	if (ZFS_OBJ_HOLD_TRYENTER(zfsvfs, ozp->z_id) == 0) {
307a66b2b35STom Erickson 		mutex_exit(&zfsvfs->z_znodes_lock);
308a66b2b35STom Erickson 		ZFS_EXIT(zfsvfs);
309a66b2b35STom Erickson 		ZNODE_STAT_ADD(znode_move_stats.zms_obj_held);
310a66b2b35STom Erickson 		return (KMEM_CBRC_LATER);
311a66b2b35STom Erickson 	}
312a66b2b35STom Erickson 
313b5fca8f8Stomee 	vp = ZTOV(ozp);
314b5fca8f8Stomee 	if (mutex_tryenter(&vp->v_lock) == 0) {
315a66b2b35STom Erickson 		ZFS_OBJ_HOLD_EXIT(zfsvfs, ozp->z_id);
316b5fca8f8Stomee 		mutex_exit(&zfsvfs->z_znodes_lock);
317b5fca8f8Stomee 		ZFS_EXIT(zfsvfs);
318b5fca8f8Stomee 		ZNODE_STAT_ADD(znode_move_stats.zms_vnode_locked);
319b5fca8f8Stomee 		return (KMEM_CBRC_LATER);
320b5fca8f8Stomee 	}
321a66b2b35STom Erickson 
322b5fca8f8Stomee 	/* Only move znodes that are referenced _only_ by the DNLC. */
323b5fca8f8Stomee 	if (vp->v_count != 1 || !vn_in_dnlc(vp)) {
324b5fca8f8Stomee 		mutex_exit(&vp->v_lock);
325a66b2b35STom Erickson 		ZFS_OBJ_HOLD_EXIT(zfsvfs, ozp->z_id);
326b5fca8f8Stomee 		mutex_exit(&zfsvfs->z_znodes_lock);
327b5fca8f8Stomee 		ZFS_EXIT(zfsvfs);
328a66b2b35STom Erickson 		ZNODE_STAT_ADD(znode_move_stats.zms_not_only_dnlc);
329b5fca8f8Stomee 		return (KMEM_CBRC_LATER);
330b5fca8f8Stomee 	}
331b5fca8f8Stomee 
332b5fca8f8Stomee 	/*
333b5fca8f8Stomee 	 * The znode is known and in a valid state to move. We're holding the
334b5fca8f8Stomee 	 * locks needed to execute the critical section.
335b5fca8f8Stomee 	 */
336b5fca8f8Stomee 	zfs_znode_move_impl(ozp, nzp);
337b5fca8f8Stomee 	mutex_exit(&vp->v_lock);
338a66b2b35STom Erickson 	ZFS_OBJ_HOLD_EXIT(zfsvfs, ozp->z_id);
339b5fca8f8Stomee 
340b5fca8f8Stomee 	list_link_replace(&ozp->z_link_node, &nzp->z_link_node);
341b5fca8f8Stomee 	mutex_exit(&zfsvfs->z_znodes_lock);
342b5fca8f8Stomee 	ZFS_EXIT(zfsvfs);
343b5fca8f8Stomee 
344b5fca8f8Stomee 	return (KMEM_CBRC_YES);
345fa9e4066Sahrens }
346fa9e4066Sahrens 
347fa9e4066Sahrens void
348fa9e4066Sahrens zfs_znode_init(void)
349fa9e4066Sahrens {
350fa9e4066Sahrens 	/*
351fa9e4066Sahrens 	 * Initialize zcache
352fa9e4066Sahrens 	 */
3534e9583b2STom Erickson 	rw_init(&zfsvfs_lock, NULL, RW_DEFAULT, NULL);
354fa9e4066Sahrens 	ASSERT(znode_cache == NULL);
355fa9e4066Sahrens 	znode_cache = kmem_cache_create("zfs_znode_cache",
356fa9e4066Sahrens 	    sizeof (znode_t), 0, zfs_znode_cache_constructor,
357fa9e4066Sahrens 	    zfs_znode_cache_destructor, NULL, NULL, NULL, 0);
358b5fca8f8Stomee 	kmem_cache_set_move(znode_cache, zfs_znode_move);
359fa9e4066Sahrens }
360fa9e4066Sahrens 
361fa9e4066Sahrens void
362fa9e4066Sahrens zfs_znode_fini(void)
363fa9e4066Sahrens {
364fa9e4066Sahrens 	/*
365fa9e4066Sahrens 	 * Cleanup vfs & vnode ops
366fa9e4066Sahrens 	 */
367fa9e4066Sahrens 	zfs_remove_op_tables();
368fa9e4066Sahrens 
369fa9e4066Sahrens 	/*
370fa9e4066Sahrens 	 * Cleanup zcache
371fa9e4066Sahrens 	 */
372fa9e4066Sahrens 	if (znode_cache)
373fa9e4066Sahrens 		kmem_cache_destroy(znode_cache);
374fa9e4066Sahrens 	znode_cache = NULL;
3754e9583b2STom Erickson 	rw_destroy(&zfsvfs_lock);
376fa9e4066Sahrens }
377fa9e4066Sahrens 
378fa9e4066Sahrens struct vnodeops *zfs_dvnodeops;
379fa9e4066Sahrens struct vnodeops *zfs_fvnodeops;
380fa9e4066Sahrens struct vnodeops *zfs_symvnodeops;
381fa9e4066Sahrens struct vnodeops *zfs_xdvnodeops;
382fa9e4066Sahrens struct vnodeops *zfs_evnodeops;
383743a77edSAlan Wright struct vnodeops *zfs_sharevnodeops;
384fa9e4066Sahrens 
385fa9e4066Sahrens void
386fa9e4066Sahrens zfs_remove_op_tables()
387fa9e4066Sahrens {
388fa9e4066Sahrens 	/*
389fa9e4066Sahrens 	 * Remove vfs ops
390fa9e4066Sahrens 	 */
391fa9e4066Sahrens 	ASSERT(zfsfstype);
392fa9e4066Sahrens 	(void) vfs_freevfsops_by_type(zfsfstype);
393fa9e4066Sahrens 	zfsfstype = 0;
394fa9e4066Sahrens 
395fa9e4066Sahrens 	/*
396fa9e4066Sahrens 	 * Remove vnode ops
397fa9e4066Sahrens 	 */
398fa9e4066Sahrens 	if (zfs_dvnodeops)
399fa9e4066Sahrens 		vn_freevnodeops(zfs_dvnodeops);
400fa9e4066Sahrens 	if (zfs_fvnodeops)
401fa9e4066Sahrens 		vn_freevnodeops(zfs_fvnodeops);
402fa9e4066Sahrens 	if (zfs_symvnodeops)
403fa9e4066Sahrens 		vn_freevnodeops(zfs_symvnodeops);
404fa9e4066Sahrens 	if (zfs_xdvnodeops)
405fa9e4066Sahrens 		vn_freevnodeops(zfs_xdvnodeops);
406fa9e4066Sahrens 	if (zfs_evnodeops)
407fa9e4066Sahrens 		vn_freevnodeops(zfs_evnodeops);
408743a77edSAlan Wright 	if (zfs_sharevnodeops)
409743a77edSAlan Wright 		vn_freevnodeops(zfs_sharevnodeops);
410fa9e4066Sahrens 
411fa9e4066Sahrens 	zfs_dvnodeops = NULL;
412fa9e4066Sahrens 	zfs_fvnodeops = NULL;
413fa9e4066Sahrens 	zfs_symvnodeops = NULL;
414fa9e4066Sahrens 	zfs_xdvnodeops = NULL;
415fa9e4066Sahrens 	zfs_evnodeops = NULL;
416743a77edSAlan Wright 	zfs_sharevnodeops = NULL;
417fa9e4066Sahrens }
418fa9e4066Sahrens 
419fa9e4066Sahrens extern const fs_operation_def_t zfs_dvnodeops_template[];
420fa9e4066Sahrens extern const fs_operation_def_t zfs_fvnodeops_template[];
421fa9e4066Sahrens extern const fs_operation_def_t zfs_xdvnodeops_template[];
422fa9e4066Sahrens extern const fs_operation_def_t zfs_symvnodeops_template[];
423fa9e4066Sahrens extern const fs_operation_def_t zfs_evnodeops_template[];
424743a77edSAlan Wright extern const fs_operation_def_t zfs_sharevnodeops_template[];
425fa9e4066Sahrens 
426fa9e4066Sahrens int
427fa9e4066Sahrens zfs_create_op_tables()
428fa9e4066Sahrens {
429fa9e4066Sahrens 	int error;
430fa9e4066Sahrens 
431fa9e4066Sahrens 	/*
432fa9e4066Sahrens 	 * zfs_dvnodeops can be set if mod_remove() calls mod_installfs()
433fa9e4066Sahrens 	 * due to a failure to remove the the 2nd modlinkage (zfs_modldrv).
434fa9e4066Sahrens 	 * In this case we just return as the ops vectors are already set up.
435fa9e4066Sahrens 	 */
436fa9e4066Sahrens 	if (zfs_dvnodeops)
437fa9e4066Sahrens 		return (0);
438fa9e4066Sahrens 
439fa9e4066Sahrens 	error = vn_make_ops(MNTTYPE_ZFS, zfs_dvnodeops_template,
440fa9e4066Sahrens 	    &zfs_dvnodeops);
441fa9e4066Sahrens 	if (error)
442fa9e4066Sahrens 		return (error);
443fa9e4066Sahrens 
444fa9e4066Sahrens 	error = vn_make_ops(MNTTYPE_ZFS, zfs_fvnodeops_template,
445fa9e4066Sahrens 	    &zfs_fvnodeops);
446fa9e4066Sahrens 	if (error)
447fa9e4066Sahrens 		return (error);
448fa9e4066Sahrens 
449fa9e4066Sahrens 	error = vn_make_ops(MNTTYPE_ZFS, zfs_symvnodeops_template,
450fa9e4066Sahrens 	    &zfs_symvnodeops);
451fa9e4066Sahrens 	if (error)
452fa9e4066Sahrens 		return (error);
453fa9e4066Sahrens 
454fa9e4066Sahrens 	error = vn_make_ops(MNTTYPE_ZFS, zfs_xdvnodeops_template,
455fa9e4066Sahrens 	    &zfs_xdvnodeops);
456fa9e4066Sahrens 	if (error)
457fa9e4066Sahrens 		return (error);
458fa9e4066Sahrens 
459fa9e4066Sahrens 	error = vn_make_ops(MNTTYPE_ZFS, zfs_evnodeops_template,
460fa9e4066Sahrens 	    &zfs_evnodeops);
461743a77edSAlan Wright 	if (error)
462743a77edSAlan Wright 		return (error);
463743a77edSAlan Wright 
464743a77edSAlan Wright 	error = vn_make_ops(MNTTYPE_ZFS, zfs_sharevnodeops_template,
465743a77edSAlan Wright 	    &zfs_sharevnodeops);
466743a77edSAlan Wright 
467743a77edSAlan Wright 	return (error);
468743a77edSAlan Wright }
469743a77edSAlan Wright 
4709e1320c0SMark Shellenbaum int
471743a77edSAlan Wright zfs_create_share_dir(zfsvfs_t *zfsvfs, dmu_tx_t *tx)
472743a77edSAlan Wright {
47389459e17SMark Shellenbaum 	zfs_acl_ids_t acl_ids;
474743a77edSAlan Wright 	vattr_t vattr;
475743a77edSAlan Wright 	znode_t *sharezp;
476743a77edSAlan Wright 	vnode_t *vp;
477743a77edSAlan Wright 	znode_t *zp;
478743a77edSAlan Wright 	int error;
479743a77edSAlan Wright 
480743a77edSAlan Wright 	vattr.va_mask = AT_MODE|AT_UID|AT_GID|AT_TYPE;
481743a77edSAlan Wright 	vattr.va_type = VDIR;
482743a77edSAlan Wright 	vattr.va_mode = S_IFDIR|0555;
483743a77edSAlan Wright 	vattr.va_uid = crgetuid(kcred);
484743a77edSAlan Wright 	vattr.va_gid = crgetgid(kcred);
485743a77edSAlan Wright 
486743a77edSAlan Wright 	sharezp = kmem_cache_alloc(znode_cache, KM_SLEEP);
487744947dcSTom Erickson 	ASSERT(!POINTER_IS_VALID(sharezp->z_zfsvfs));
488744947dcSTom Erickson 	sharezp->z_moved = 0;
489743a77edSAlan Wright 	sharezp->z_unlinked = 0;
490743a77edSAlan Wright 	sharezp->z_atime_dirty = 0;
491743a77edSAlan Wright 	sharezp->z_zfsvfs = zfsvfs;
4920a586ceaSMark Shellenbaum 	sharezp->z_is_sa = zfsvfs->z_use_sa;
493743a77edSAlan Wright 
494743a77edSAlan Wright 	vp = ZTOV(sharezp);
495743a77edSAlan Wright 	vn_reinit(vp);
496743a77edSAlan Wright 	vp->v_type = VDIR;
497743a77edSAlan Wright 
49889459e17SMark Shellenbaum 	VERIFY(0 == zfs_acl_ids_create(sharezp, IS_ROOT_NODE, &vattr,
49989459e17SMark Shellenbaum 	    kcred, NULL, &acl_ids));
5000a586ceaSMark Shellenbaum 	zfs_mknode(sharezp, &vattr, tx, kcred, IS_ROOT_NODE, &zp, &acl_ids);
501743a77edSAlan Wright 	ASSERT3P(zp, ==, sharezp);
502743a77edSAlan Wright 	ASSERT(!vn_in_dnlc(ZTOV(sharezp))); /* not valid to move */
503743a77edSAlan Wright 	POINTER_INVALIDATE(&sharezp->z_zfsvfs);
504743a77edSAlan Wright 	error = zap_add(zfsvfs->z_os, MASTER_NODE_OBJ,
505743a77edSAlan Wright 	    ZFS_SHARES_DIR, 8, 1, &sharezp->z_id, tx);
506743a77edSAlan Wright 	zfsvfs->z_shares_dir = sharezp->z_id;
507743a77edSAlan Wright 
50889459e17SMark Shellenbaum 	zfs_acl_ids_free(&acl_ids);
509743a77edSAlan Wright 	ZTOV(sharezp)->v_count = 0;
5100a586ceaSMark Shellenbaum 	sa_handle_destroy(sharezp->z_sa_hdl);
511743a77edSAlan Wright 	kmem_cache_free(znode_cache, sharezp);
512fa9e4066Sahrens 
513fa9e4066Sahrens 	return (error);
514fa9e4066Sahrens }
515fa9e4066Sahrens 
51672fc53bcSmarks /*
51772fc53bcSmarks  * define a couple of values we need available
51872fc53bcSmarks  * for both 64 and 32 bit environments.
51972fc53bcSmarks  */
52072fc53bcSmarks #ifndef NBITSMINOR64
52172fc53bcSmarks #define	NBITSMINOR64	32
52272fc53bcSmarks #endif
52372fc53bcSmarks #ifndef MAXMAJ64
52472fc53bcSmarks #define	MAXMAJ64	0xffffffffUL
52572fc53bcSmarks #endif
52672fc53bcSmarks #ifndef	MAXMIN64
52772fc53bcSmarks #define	MAXMIN64	0xffffffffUL
52872fc53bcSmarks #endif
52972fc53bcSmarks 
53072fc53bcSmarks /*
53172fc53bcSmarks  * Create special expldev for ZFS private use.
53272fc53bcSmarks  * Can't use standard expldev since it doesn't do
53372fc53bcSmarks  * what we want.  The standard expldev() takes a
53472fc53bcSmarks  * dev32_t in LP64 and expands it to a long dev_t.
53572fc53bcSmarks  * We need an interface that takes a dev32_t in ILP32
53672fc53bcSmarks  * and expands it to a long dev_t.
53772fc53bcSmarks  */
53872fc53bcSmarks static uint64_t
53972fc53bcSmarks zfs_expldev(dev_t dev)
54072fc53bcSmarks {
54172fc53bcSmarks #ifndef _LP64
54272fc53bcSmarks 	major_t major = (major_t)dev >> NBITSMINOR32 & MAXMAJ32;
54372fc53bcSmarks 	return (((uint64_t)major << NBITSMINOR64) |
54472fc53bcSmarks 	    ((minor_t)dev & MAXMIN32));
54572fc53bcSmarks #else
54672fc53bcSmarks 	return (dev);
54772fc53bcSmarks #endif
54872fc53bcSmarks }
54972fc53bcSmarks 
55072fc53bcSmarks /*
55172fc53bcSmarks  * Special cmpldev for ZFS private use.
55272fc53bcSmarks  * Can't use standard cmpldev since it takes
55372fc53bcSmarks  * a long dev_t and compresses it to dev32_t in
55472fc53bcSmarks  * LP64.  We need to do a compaction of a long dev_t
55572fc53bcSmarks  * to a dev32_t in ILP32.
55672fc53bcSmarks  */
55772fc53bcSmarks dev_t
55872fc53bcSmarks zfs_cmpldev(uint64_t dev)
55972fc53bcSmarks {
56072fc53bcSmarks #ifndef _LP64
56172fc53bcSmarks 	minor_t minor = (minor_t)dev & MAXMIN64;
56272fc53bcSmarks 	major_t major = (major_t)(dev >> NBITSMINOR64) & MAXMAJ64;
56372fc53bcSmarks 
56472fc53bcSmarks 	if (major > MAXMAJ32 || minor > MAXMIN32)
56572fc53bcSmarks 		return (NODEV32);
56672fc53bcSmarks 
56772fc53bcSmarks 	return (((dev32_t)major << NBITSMINOR32) | minor);
56872fc53bcSmarks #else
56972fc53bcSmarks 	return (dev);
57072fc53bcSmarks #endif
57172fc53bcSmarks }
57272fc53bcSmarks 
5734ccbb6e7Sahrens static void
5740a586ceaSMark Shellenbaum zfs_znode_sa_init(zfsvfs_t *zfsvfs, znode_t *zp,
5750a586ceaSMark Shellenbaum     dmu_buf_t *db, dmu_object_type_t obj_type, sa_handle_t *sa_hdl)
5764ccbb6e7Sahrens {
577b5fca8f8Stomee 	ASSERT(!POINTER_IS_VALID(zp->z_zfsvfs) || (zfsvfs == zp->z_zfsvfs));
578b5fca8f8Stomee 	ASSERT(MUTEX_HELD(ZFS_OBJ_MUTEX(zfsvfs, zp->z_id)));
5794ccbb6e7Sahrens 
5804ccbb6e7Sahrens 	mutex_enter(&zp->z_lock);
5814ccbb6e7Sahrens 
5820a586ceaSMark Shellenbaum 	ASSERT(zp->z_sa_hdl == NULL);
5836638ae1dSMark Shellenbaum 	ASSERT(zp->z_acl_cached == NULL);
5840a586ceaSMark Shellenbaum 	if (sa_hdl == NULL) {
5850a586ceaSMark Shellenbaum 		VERIFY(0 == sa_handle_get_from_db(zfsvfs->z_os, db, zp,
5860a586ceaSMark Shellenbaum 		    SA_HDL_SHARED, &zp->z_sa_hdl));
5870a586ceaSMark Shellenbaum 	} else {
5880a586ceaSMark Shellenbaum 		zp->z_sa_hdl = sa_hdl;
5890a586ceaSMark Shellenbaum 		sa_set_userp(sa_hdl, zp);
5900a586ceaSMark Shellenbaum 	}
5914ccbb6e7Sahrens 
5920a586ceaSMark Shellenbaum 	zp->z_is_sa = (obj_type == DMU_OT_SA) ? B_TRUE : B_FALSE;
5934ccbb6e7Sahrens 
5944ccbb6e7Sahrens 	/*
5954ccbb6e7Sahrens 	 * Slap on VROOT if we are the root znode
5964ccbb6e7Sahrens 	 */
5974ccbb6e7Sahrens 	if (zp->z_id == zfsvfs->z_root)
5984ccbb6e7Sahrens 		ZTOV(zp)->v_flag |= VROOT;
5994ccbb6e7Sahrens 
6004ccbb6e7Sahrens 	mutex_exit(&zp->z_lock);
6014ccbb6e7Sahrens 	vn_exists(ZTOV(zp));
6024ccbb6e7Sahrens }
6034ccbb6e7Sahrens 
604874395d5Smaybee void
6054ccbb6e7Sahrens zfs_znode_dmu_fini(znode_t *zp)
6064ccbb6e7Sahrens {
607b5fca8f8Stomee 	ASSERT(MUTEX_HELD(ZFS_OBJ_MUTEX(zp->z_zfsvfs, zp->z_id)) ||
608b5fca8f8Stomee 	    zp->z_unlinked ||
609874395d5Smaybee 	    RW_WRITE_HELD(&zp->z_zfsvfs->z_teardown_inactive_lock));
6100a586ceaSMark Shellenbaum 
6110a586ceaSMark Shellenbaum 	sa_handle_destroy(zp->z_sa_hdl);
6120a586ceaSMark Shellenbaum 	zp->z_sa_hdl = NULL;
6134ccbb6e7Sahrens }
6144ccbb6e7Sahrens 
615fa9e4066Sahrens /*
616fa9e4066Sahrens  * Construct a new znode/vnode and intialize.
617fa9e4066Sahrens  *
618fa9e4066Sahrens  * This does not do a call to dmu_set_user() that is
619fa9e4066Sahrens  * up to the caller to do, in case you don't want to
620fa9e4066Sahrens  * return the znode
621fa9e4066Sahrens  */
622ea8dc4b6Seschrock static znode_t *
6230a586ceaSMark Shellenbaum zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
6240a586ceaSMark Shellenbaum     dmu_object_type_t obj_type, sa_handle_t *hdl)
625fa9e4066Sahrens {
626fa9e4066Sahrens 	znode_t	*zp;
627fa9e4066Sahrens 	vnode_t *vp;
6280a586ceaSMark Shellenbaum 	uint64_t mode;
6290a586ceaSMark Shellenbaum 	uint64_t parent;
6300a586ceaSMark Shellenbaum 	sa_bulk_attr_t bulk[9];
6310a586ceaSMark Shellenbaum 	int count = 0;
632fa9e4066Sahrens 
633fa9e4066Sahrens 	zp = kmem_cache_alloc(znode_cache, KM_SLEEP);
634fa9e4066Sahrens 
635fa9e4066Sahrens 	ASSERT(zp->z_dirlocks == NULL);
636b5fca8f8Stomee 	ASSERT(!POINTER_IS_VALID(zp->z_zfsvfs));
637744947dcSTom Erickson 	zp->z_moved = 0;
638fa9e4066Sahrens 
639b5fca8f8Stomee 	/*
640b5fca8f8Stomee 	 * Defer setting z_zfsvfs until the znode is ready to be a candidate for
641b5fca8f8Stomee 	 * the zfs_znode_move() callback.
642b5fca8f8Stomee 	 */
6430a586ceaSMark Shellenbaum 	zp->z_sa_hdl = NULL;
644893a6d32Sahrens 	zp->z_unlinked = 0;
645fa9e4066Sahrens 	zp->z_atime_dirty = 0;
646fa9e4066Sahrens 	zp->z_mapcnt = 0;
6474ccbb6e7Sahrens 	zp->z_id = db->db_object;
648fa9e4066Sahrens 	zp->z_blksz = blksz;
649fa9e4066Sahrens 	zp->z_seq = 0x7A4653;
65067bd71c6Sperrin 	zp->z_sync_cnt = 0;
6514ccbb6e7Sahrens 
6524ccbb6e7Sahrens 	vp = ZTOV(zp);
6534ccbb6e7Sahrens 	vn_reinit(vp);
6544ccbb6e7Sahrens 
6550a586ceaSMark Shellenbaum 	zfs_znode_sa_init(zfsvfs, zp, db, obj_type, hdl);
6560a586ceaSMark Shellenbaum 
6570a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zfsvfs), NULL, &mode, 8);
6580a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GEN(zfsvfs), NULL, &zp->z_gen, 8);
6590a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(zfsvfs), NULL,
6600a586ceaSMark Shellenbaum 	    &zp->z_size, 8);
6610a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_LINKS(zfsvfs), NULL,
6620a586ceaSMark Shellenbaum 	    &zp->z_links, 8);
6630a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), NULL,
6640a586ceaSMark Shellenbaum 	    &zp->z_pflags, 8);
6650a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_PARENT(zfsvfs), NULL, &parent, 8);
6660a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ATIME(zfsvfs), NULL,
6670a586ceaSMark Shellenbaum 	    &zp->z_atime, 16);
6680a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_UID(zfsvfs), NULL,
669f1696b23SMark Shellenbaum 	    &zp->z_uid, 8);
6700a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GID(zfsvfs), NULL,
671f1696b23SMark Shellenbaum 	    &zp->z_gid, 8);
6720a586ceaSMark Shellenbaum 
6730a586ceaSMark Shellenbaum 	if (sa_bulk_lookup(zp->z_sa_hdl, bulk, count) != 0 || zp->z_gen == 0) {
6740a586ceaSMark Shellenbaum 		if (hdl == NULL)
6750a586ceaSMark Shellenbaum 			sa_handle_destroy(zp->z_sa_hdl);
6760a586ceaSMark Shellenbaum 		kmem_cache_free(znode_cache, zp);
6770a586ceaSMark Shellenbaum 		return (NULL);
6780a586ceaSMark Shellenbaum 	}
679fa9e4066Sahrens 
6800a586ceaSMark Shellenbaum 	zp->z_mode = mode;
681fa9e4066Sahrens 	vp->v_vfsp = zfsvfs->z_parent->z_vfs;
6820a586ceaSMark Shellenbaum 
6830a586ceaSMark Shellenbaum 	vp->v_type = IFTOVT((mode_t)mode);
684fa9e4066Sahrens 
685fa9e4066Sahrens 	switch (vp->v_type) {
686fa9e4066Sahrens 	case VDIR:
6870a586ceaSMark Shellenbaum 		if (zp->z_pflags & ZFS_XATTR) {
688fa9e4066Sahrens 			vn_setops(vp, zfs_xdvnodeops);
689fa9e4066Sahrens 			vp->v_flag |= V_XATTRDIR;
6904ccbb6e7Sahrens 		} else {
691fa9e4066Sahrens 			vn_setops(vp, zfs_dvnodeops);
6924ccbb6e7Sahrens 		}
6937f6e3e7dSperrin 		zp->z_zn_prefetch = B_TRUE; /* z_prefetch default is enabled */
694fa9e4066Sahrens 		break;
695fa9e4066Sahrens 	case VBLK:
696fa9e4066Sahrens 	case VCHR:
6970a586ceaSMark Shellenbaum 		{
6980a586ceaSMark Shellenbaum 			uint64_t rdev;
6990a586ceaSMark Shellenbaum 			VERIFY(sa_lookup(zp->z_sa_hdl, SA_ZPL_RDEV(zfsvfs),
7000a586ceaSMark Shellenbaum 			    &rdev, sizeof (rdev)) == 0);
7010a586ceaSMark Shellenbaum 
7020a586ceaSMark Shellenbaum 			vp->v_rdev = zfs_cmpldev(rdev);
7030a586ceaSMark Shellenbaum 		}
704fa9e4066Sahrens 		/*FALLTHROUGH*/
705fa9e4066Sahrens 	case VFIFO:
706fa9e4066Sahrens 	case VSOCK:
707fa9e4066Sahrens 	case VDOOR:
708fa9e4066Sahrens 		vn_setops(vp, zfs_fvnodeops);
709fa9e4066Sahrens 		break;
710fa9e4066Sahrens 	case VREG:
711fa9e4066Sahrens 		vp->v_flag |= VMODSORT;
7120a586ceaSMark Shellenbaum 		if (parent == zfsvfs->z_shares_dir) {
713f1696b23SMark Shellenbaum 			ASSERT(zp->z_uid == 0 && zp->z_gid == 0);
714743a77edSAlan Wright 			vn_setops(vp, zfs_sharevnodeops);
7150a586ceaSMark Shellenbaum 		} else {
716743a77edSAlan Wright 			vn_setops(vp, zfs_fvnodeops);
7170a586ceaSMark Shellenbaum 		}
718fa9e4066Sahrens 		break;
719fa9e4066Sahrens 	case VLNK:
720fa9e4066Sahrens 		vn_setops(vp, zfs_symvnodeops);
721fa9e4066Sahrens 		break;
722fa9e4066Sahrens 	default:
723fa9e4066Sahrens 		vn_setops(vp, zfs_evnodeops);
724fa9e4066Sahrens 		break;
725fa9e4066Sahrens 	}
726fa9e4066Sahrens 
727b5fca8f8Stomee 	mutex_enter(&zfsvfs->z_znodes_lock);
728b5fca8f8Stomee 	list_insert_tail(&zfsvfs->z_all_znodes, zp);
729b5fca8f8Stomee 	membar_producer();
730b5fca8f8Stomee 	/*
731b5fca8f8Stomee 	 * Everything else must be valid before assigning z_zfsvfs makes the
732b5fca8f8Stomee 	 * znode eligible for zfs_znode_move().
733b5fca8f8Stomee 	 */
734b5fca8f8Stomee 	zp->z_zfsvfs = zfsvfs;
735b5fca8f8Stomee 	mutex_exit(&zfsvfs->z_znodes_lock);
736b5fca8f8Stomee 
737874395d5Smaybee 	VFS_HOLD(zfsvfs->z_vfs);
738fa9e4066Sahrens 	return (zp);
739fa9e4066Sahrens }
740fa9e4066Sahrens 
7410a586ceaSMark Shellenbaum static uint64_t empty_xattr;
7420a586ceaSMark Shellenbaum static uint64_t pad[4];
7430a586ceaSMark Shellenbaum static zfs_acl_phys_t acl_phys;
744fa9e4066Sahrens /*
745fa9e4066Sahrens  * Create a new DMU object to hold a zfs znode.
746fa9e4066Sahrens  *
747fa9e4066Sahrens  *	IN:	dzp	- parent directory for new znode
748fa9e4066Sahrens  *		vap	- file attributes for new znode
749fa9e4066Sahrens  *		tx	- dmu transaction id for zap operations
750fa9e4066Sahrens  *		cr	- credentials of caller
751fa9e4066Sahrens  *		flag	- flags:
752fa9e4066Sahrens  *			  IS_ROOT_NODE	- new object will be root
753fa9e4066Sahrens  *			  IS_XATTR	- new object is an attribute
754da6c28aaSamw  *		bonuslen - length of bonus buffer
755da6c28aaSamw  *		setaclp  - File/Dir initial ACL
756da6c28aaSamw  *		fuidp	 - Tracks fuid allocation.
757fa9e4066Sahrens  *
7584ccbb6e7Sahrens  *	OUT:	zpp	- allocated znode
759fa9e4066Sahrens  *
760fa9e4066Sahrens  */
761fa9e4066Sahrens void
7624ccbb6e7Sahrens zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr,
7630a586ceaSMark Shellenbaum     uint_t flag, znode_t **zpp, zfs_acl_ids_t *acl_ids)
764fa9e4066Sahrens {
7650a586ceaSMark Shellenbaum 	uint64_t	crtime[2], atime[2], mtime[2], ctime[2];
7660a586ceaSMark Shellenbaum 	uint64_t	mode, size, links, parent, pflags;
767744947dcSTom Erickson 	uint64_t	dzp_pflags = 0;
7680a586ceaSMark Shellenbaum 	uint64_t	rdev = 0;
769fa9e4066Sahrens 	zfsvfs_t	*zfsvfs = dzp->z_zfsvfs;
7700a586ceaSMark Shellenbaum 	dmu_buf_t	*db;
771fa9e4066Sahrens 	timestruc_t	now;
7724ccbb6e7Sahrens 	uint64_t	gen, obj;
7730a586ceaSMark Shellenbaum 	int		bonuslen;
7740a586ceaSMark Shellenbaum 	sa_handle_t	*sa_hdl;
7750a586ceaSMark Shellenbaum 	dmu_object_type_t obj_type;
7760a586ceaSMark Shellenbaum 	sa_bulk_attr_t	sa_attrs[ZPL_END];
7770a586ceaSMark Shellenbaum 	int		cnt = 0;
7780a586ceaSMark Shellenbaum 	zfs_acl_locator_cb_t locate = { 0 };
779fa9e4066Sahrens 
780fa9e4066Sahrens 	ASSERT(vap && (vap->va_mask & (AT_TYPE|AT_MODE)) == (AT_TYPE|AT_MODE));
781fa9e4066Sahrens 
7821209a471SNeil Perrin 	if (zfsvfs->z_replay) {
7834ccbb6e7Sahrens 		obj = vap->va_nodeid;
784fa9e4066Sahrens 		now = vap->va_ctime;		/* see zfs_replay_create() */
785fa9e4066Sahrens 		gen = vap->va_nblocks;		/* ditto */
786fa9e4066Sahrens 	} else {
7874ccbb6e7Sahrens 		obj = 0;
788fa9e4066Sahrens 		gethrestime(&now);
789fa9e4066Sahrens 		gen = dmu_tx_get_txg(tx);
790fa9e4066Sahrens 	}
791fa9e4066Sahrens 
7920a586ceaSMark Shellenbaum 	obj_type = zfsvfs->z_use_sa ? DMU_OT_SA : DMU_OT_ZNODE;
7930a586ceaSMark Shellenbaum 	bonuslen = (obj_type == DMU_OT_SA) ?
7940a586ceaSMark Shellenbaum 	    DN_MAX_BONUSLEN : ZFS_OLD_ZNODE_PHYS_SIZE;
7950a586ceaSMark Shellenbaum 
796fa9e4066Sahrens 	/*
797fa9e4066Sahrens 	 * Create a new DMU object.
798fa9e4066Sahrens 	 */
799ea8dc4b6Seschrock 	/*
800ea8dc4b6Seschrock 	 * There's currently no mechanism for pre-reading the blocks that will
801744947dcSTom Erickson 	 * be needed to allocate a new object, so we accept the small chance
802ea8dc4b6Seschrock 	 * that there will be an i/o error and we will fail one of the
803ea8dc4b6Seschrock 	 * assertions below.
804ea8dc4b6Seschrock 	 */
805fa9e4066Sahrens 	if (vap->va_type == VDIR) {
8064a1f0cc9SMark Shellenbaum 		if (zfsvfs->z_replay) {
80743466aaeSMax Grossman 			VERIFY0(zap_create_claim_norm(zfsvfs->z_os, obj,
808da6c28aaSamw 			    zfsvfs->z_norm, DMU_OT_DIRECTORY_CONTENTS,
80943466aaeSMax Grossman 			    obj_type, bonuslen, tx));
810fa9e4066Sahrens 		} else {
8114ccbb6e7Sahrens 			obj = zap_create_norm(zfsvfs->z_os,
812da6c28aaSamw 			    zfsvfs->z_norm, DMU_OT_DIRECTORY_CONTENTS,
8130a586ceaSMark Shellenbaum 			    obj_type, bonuslen, tx);
814fa9e4066Sahrens 		}
815fa9e4066Sahrens 	} else {
8164a1f0cc9SMark Shellenbaum 		if (zfsvfs->z_replay) {
81743466aaeSMax Grossman 			VERIFY0(dmu_object_claim(zfsvfs->z_os, obj,
818fa9e4066Sahrens 			    DMU_OT_PLAIN_FILE_CONTENTS, 0,
81943466aaeSMax Grossman 			    obj_type, bonuslen, tx));
820fa9e4066Sahrens 		} else {
8214ccbb6e7Sahrens 			obj = dmu_object_alloc(zfsvfs->z_os,
822fa9e4066Sahrens 			    DMU_OT_PLAIN_FILE_CONTENTS, 0,
8230a586ceaSMark Shellenbaum 			    obj_type, bonuslen, tx);
824fa9e4066Sahrens 		}
825fa9e4066Sahrens 	}
82659e7834dSMark Shellenbaum 
82759e7834dSMark Shellenbaum 	ZFS_OBJ_HOLD_ENTER(zfsvfs, obj);
8280a586ceaSMark Shellenbaum 	VERIFY(0 == sa_buf_hold(zfsvfs->z_os, obj, NULL, &db));
829fa9e4066Sahrens 
830fa9e4066Sahrens 	/*
831fa9e4066Sahrens 	 * If this is the root, fix up the half-initialized parent pointer
832fa9e4066Sahrens 	 * to reference the just-allocated physical data area.
833fa9e4066Sahrens 	 */
834fa9e4066Sahrens 	if (flag & IS_ROOT_NODE) {
8354ccbb6e7Sahrens 		dzp->z_id = obj;
8360a586ceaSMark Shellenbaum 	} else {
8370a586ceaSMark Shellenbaum 		dzp_pflags = dzp->z_pflags;
838fa9e4066Sahrens 	}
839fa9e4066Sahrens 
840fa9e4066Sahrens 	/*
841fa9e4066Sahrens 	 * If parent is an xattr, so am I.
842fa9e4066Sahrens 	 */
8430a586ceaSMark Shellenbaum 	if (dzp_pflags & ZFS_XATTR) {
844fa9e4066Sahrens 		flag |= IS_XATTR;
845fa9e4066Sahrens 	}
846fa9e4066Sahrens 
847da6c28aaSamw 	if (zfsvfs->z_use_fuids)
8480a586ceaSMark Shellenbaum 		pflags = ZFS_ARCHIVE | ZFS_AV_MODIFIED;
8490a586ceaSMark Shellenbaum 	else
8500a586ceaSMark Shellenbaum 		pflags = 0;
851da6c28aaSamw 
852fa9e4066Sahrens 	if (vap->va_type == VDIR) {
8530a586ceaSMark Shellenbaum 		size = 2;		/* contents ("." and "..") */
8540a586ceaSMark Shellenbaum 		links = (flag & (IS_ROOT_NODE | IS_XATTR)) ? 2 : 1;
8550a586ceaSMark Shellenbaum 	} else {
8560a586ceaSMark Shellenbaum 		size = links = 0;
8570a586ceaSMark Shellenbaum 	}
8580a586ceaSMark Shellenbaum 
8590a586ceaSMark Shellenbaum 	if (vap->va_type == VBLK || vap->va_type == VCHR) {
8600a586ceaSMark Shellenbaum 		rdev = zfs_expldev(vap->va_rdev);
861fa9e4066Sahrens 	}
862fa9e4066Sahrens 
8630a586ceaSMark Shellenbaum 	parent = dzp->z_id;
8640a586ceaSMark Shellenbaum 	mode = acl_ids->z_mode;
865fa9e4066Sahrens 	if (flag & IS_XATTR)
8660a586ceaSMark Shellenbaum 		pflags |= ZFS_XATTR;
867fa9e4066Sahrens 
8680a586ceaSMark Shellenbaum 	/*
8690a586ceaSMark Shellenbaum 	 * No execs denied will be deterimed when zfs_mode_compute() is called.
8700a586ceaSMark Shellenbaum 	 */
8710a586ceaSMark Shellenbaum 	pflags |= acl_ids->z_aclp->z_hints &
8720a586ceaSMark Shellenbaum 	    (ZFS_ACL_TRIVIAL|ZFS_INHERIT_ACE|ZFS_ACL_AUTO_INHERIT|
8730a586ceaSMark Shellenbaum 	    ZFS_ACL_DEFAULTED|ZFS_ACL_PROTECTED);
874fa9e4066Sahrens 
8750a586ceaSMark Shellenbaum 	ZFS_TIME_ENCODE(&now, crtime);
8760a586ceaSMark Shellenbaum 	ZFS_TIME_ENCODE(&now, ctime);
877fa9e4066Sahrens 
878fa9e4066Sahrens 	if (vap->va_mask & AT_ATIME) {
8790a586ceaSMark Shellenbaum 		ZFS_TIME_ENCODE(&vap->va_atime, atime);
880fa9e4066Sahrens 	} else {
8810a586ceaSMark Shellenbaum 		ZFS_TIME_ENCODE(&now, atime);
882fa9e4066Sahrens 	}
883fa9e4066Sahrens 
884fa9e4066Sahrens 	if (vap->va_mask & AT_MTIME) {
8850a586ceaSMark Shellenbaum 		ZFS_TIME_ENCODE(&vap->va_mtime, mtime);
8860a586ceaSMark Shellenbaum 	} else {
8870a586ceaSMark Shellenbaum 		ZFS_TIME_ENCODE(&now, mtime);
8880a586ceaSMark Shellenbaum 	}
8890a586ceaSMark Shellenbaum 
8900a586ceaSMark Shellenbaum 	/* Now add in all of the "SA" attributes */
8910a586ceaSMark Shellenbaum 	VERIFY(0 == sa_handle_get_from_db(zfsvfs->z_os, db, NULL, SA_HDL_SHARED,
8920a586ceaSMark Shellenbaum 	    &sa_hdl));
8930a586ceaSMark Shellenbaum 
8940a586ceaSMark Shellenbaum 	/*
8950a586ceaSMark Shellenbaum 	 * Setup the array of attributes to be replaced/set on the new file
8960a586ceaSMark Shellenbaum 	 *
8970a586ceaSMark Shellenbaum 	 * order for  DMU_OT_ZNODE is critical since it needs to be constructed
8980a586ceaSMark Shellenbaum 	 * in the old znode_phys_t format.  Don't change this ordering
8990a586ceaSMark Shellenbaum 	 */
9000a586ceaSMark Shellenbaum 
9010a586ceaSMark Shellenbaum 	if (obj_type == DMU_OT_ZNODE) {
9020a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_ATIME(zfsvfs),
9030a586ceaSMark Shellenbaum 		    NULL, &atime, 16);
9040a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_MTIME(zfsvfs),
9050a586ceaSMark Shellenbaum 		    NULL, &mtime, 16);
9060a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_CTIME(zfsvfs),
9070a586ceaSMark Shellenbaum 		    NULL, &ctime, 16);
9080a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_CRTIME(zfsvfs),
9090a586ceaSMark Shellenbaum 		    NULL, &crtime, 16);
9100a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_GEN(zfsvfs),
9110a586ceaSMark Shellenbaum 		    NULL, &gen, 8);
9120a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_MODE(zfsvfs),
9130a586ceaSMark Shellenbaum 		    NULL, &mode, 8);
9140a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_SIZE(zfsvfs),
9150a586ceaSMark Shellenbaum 		    NULL, &size, 8);
9160a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_PARENT(zfsvfs),
9170a586ceaSMark Shellenbaum 		    NULL, &parent, 8);
918fa9e4066Sahrens 	} else {
9190a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_MODE(zfsvfs),
9200a586ceaSMark Shellenbaum 		    NULL, &mode, 8);
9210a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_SIZE(zfsvfs),
9220a586ceaSMark Shellenbaum 		    NULL, &size, 8);
9230a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_GEN(zfsvfs),
9240a586ceaSMark Shellenbaum 		    NULL, &gen, 8);
9250a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_UID(zfsvfs), NULL,
9260a586ceaSMark Shellenbaum 		    &acl_ids->z_fuid, 8);
9270a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_GID(zfsvfs), NULL,
9280a586ceaSMark Shellenbaum 		    &acl_ids->z_fgid, 8);
9290a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_PARENT(zfsvfs),
9300a586ceaSMark Shellenbaum 		    NULL, &parent, 8);
9310a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_FLAGS(zfsvfs),
9320a586ceaSMark Shellenbaum 		    NULL, &pflags, 8);
9330a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_ATIME(zfsvfs),
9340a586ceaSMark Shellenbaum 		    NULL, &atime, 16);
9350a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_MTIME(zfsvfs),
9360a586ceaSMark Shellenbaum 		    NULL, &mtime, 16);
9370a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_CTIME(zfsvfs),
9380a586ceaSMark Shellenbaum 		    NULL, &ctime, 16);
9390a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_CRTIME(zfsvfs),
9400a586ceaSMark Shellenbaum 		    NULL, &crtime, 16);
9410a586ceaSMark Shellenbaum 	}
9420a586ceaSMark Shellenbaum 
9430a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_LINKS(zfsvfs), NULL, &links, 8);
9440a586ceaSMark Shellenbaum 
9450a586ceaSMark Shellenbaum 	if (obj_type == DMU_OT_ZNODE) {
9460a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_XATTR(zfsvfs), NULL,
9470a586ceaSMark Shellenbaum 		    &empty_xattr, 8);
9480a586ceaSMark Shellenbaum 	}
9490a586ceaSMark Shellenbaum 	if (obj_type == DMU_OT_ZNODE ||
9500a586ceaSMark Shellenbaum 	    (vap->va_type == VBLK || vap->va_type == VCHR)) {
9510a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_RDEV(zfsvfs),
9520a586ceaSMark Shellenbaum 		    NULL, &rdev, 8);
9530a586ceaSMark Shellenbaum 
954fa9e4066Sahrens 	}
9550a586ceaSMark Shellenbaum 	if (obj_type == DMU_OT_ZNODE) {
9560a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_FLAGS(zfsvfs),
9570a586ceaSMark Shellenbaum 		    NULL, &pflags, 8);
9580a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_UID(zfsvfs), NULL,
9590a586ceaSMark Shellenbaum 		    &acl_ids->z_fuid, 8);
9600a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_GID(zfsvfs), NULL,
9610a586ceaSMark Shellenbaum 		    &acl_ids->z_fgid, 8);
9620a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_PAD(zfsvfs), NULL, pad,
9630a586ceaSMark Shellenbaum 		    sizeof (uint64_t) * 4);
9640a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_ZNODE_ACL(zfsvfs), NULL,
9650a586ceaSMark Shellenbaum 		    &acl_phys, sizeof (zfs_acl_phys_t));
9660a586ceaSMark Shellenbaum 	} else if (acl_ids->z_aclp->z_version >= ZFS_ACL_VERSION_FUID) {
9670a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_DACL_COUNT(zfsvfs), NULL,
9680a586ceaSMark Shellenbaum 		    &acl_ids->z_aclp->z_acl_count, 8);
9690a586ceaSMark Shellenbaum 		locate.cb_aclp = acl_ids->z_aclp;
9700a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_DACL_ACES(zfsvfs),
9710a586ceaSMark Shellenbaum 		    zfs_acl_data_locator, &locate,
9720a586ceaSMark Shellenbaum 		    acl_ids->z_aclp->z_acl_bytes);
97327dd1e87SMark Shellenbaum 		mode = zfs_mode_compute(mode, acl_ids->z_aclp, &pflags,
97427dd1e87SMark Shellenbaum 		    acl_ids->z_fuid, acl_ids->z_fgid);
9750a586ceaSMark Shellenbaum 	}
9760a586ceaSMark Shellenbaum 
9770a586ceaSMark Shellenbaum 	VERIFY(sa_replace_all_by_template(sa_hdl, sa_attrs, cnt, tx) == 0);
9780a586ceaSMark Shellenbaum 
979874395d5Smaybee 	if (!(flag & IS_ROOT_NODE)) {
9800a586ceaSMark Shellenbaum 		*zpp = zfs_znode_alloc(zfsvfs, db, 0, obj_type, sa_hdl);
9810a586ceaSMark Shellenbaum 		ASSERT(*zpp != NULL);
982874395d5Smaybee 	} else {
983874395d5Smaybee 		/*
984874395d5Smaybee 		 * If we are creating the root node, the "parent" we
985874395d5Smaybee 		 * passed in is the znode for the root.
986874395d5Smaybee 		 */
987874395d5Smaybee 		*zpp = dzp;
9880a586ceaSMark Shellenbaum 
9890a586ceaSMark Shellenbaum 		(*zpp)->z_sa_hdl = sa_hdl;
990874395d5Smaybee 	}
9910a586ceaSMark Shellenbaum 
9920a586ceaSMark Shellenbaum 	(*zpp)->z_pflags = pflags;
9930a586ceaSMark Shellenbaum 	(*zpp)->z_mode = mode;
99459e7834dSMark Shellenbaum 
9958f2529deSMark Shellenbaum 	if (vap->va_mask & AT_XVATTR)
9968f2529deSMark Shellenbaum 		zfs_xvattr_set(*zpp, (xvattr_t *)vap, tx);
9978f2529deSMark Shellenbaum 
9980a586ceaSMark Shellenbaum 	if (obj_type == DMU_OT_ZNODE ||
9990a586ceaSMark Shellenbaum 	    acl_ids->z_aclp->z_version < ZFS_ACL_VERSION_FUID) {
100043466aaeSMax Grossman 		VERIFY0(zfs_aclset_common(*zpp, acl_ids->z_aclp, cr, tx));
10010a586ceaSMark Shellenbaum 	}
100259e7834dSMark Shellenbaum 	ZFS_OBJ_HOLD_EXIT(zfsvfs, obj);
1003fa9e4066Sahrens }
1004fa9e4066Sahrens 
10050a586ceaSMark Shellenbaum /*
1006f7170741SWill Andrews  * Update in-core attributes.  It is assumed the caller will be doing an
1007f7170741SWill Andrews  * sa_bulk_update to push the changes out.
10080a586ceaSMark Shellenbaum  */
1009da6c28aaSamw void
10100a586ceaSMark Shellenbaum zfs_xvattr_set(znode_t *zp, xvattr_t *xvap, dmu_tx_t *tx)
1011da6c28aaSamw {
1012da6c28aaSamw 	xoptattr_t *xoap;
1013da6c28aaSamw 
1014da6c28aaSamw 	xoap = xva_getxoptattr(xvap);
1015da6c28aaSamw 	ASSERT(xoap);
1016da6c28aaSamw 
1017da6c28aaSamw 	if (XVA_ISSET_REQ(xvap, XAT_CREATETIME)) {
10180a586ceaSMark Shellenbaum 		uint64_t times[2];
10190a586ceaSMark Shellenbaum 		ZFS_TIME_ENCODE(&xoap->xoa_createtime, times);
10200a586ceaSMark Shellenbaum 		(void) sa_update(zp->z_sa_hdl, SA_ZPL_CRTIME(zp->z_zfsvfs),
10210a586ceaSMark Shellenbaum 		    &times, sizeof (times), tx);
1022da6c28aaSamw 		XVA_SET_RTN(xvap, XAT_CREATETIME);
1023da6c28aaSamw 	}
1024da6c28aaSamw 	if (XVA_ISSET_REQ(xvap, XAT_READONLY)) {
10250a586ceaSMark Shellenbaum 		ZFS_ATTR_SET(zp, ZFS_READONLY, xoap->xoa_readonly,
10260a586ceaSMark Shellenbaum 		    zp->z_pflags, tx);
1027da6c28aaSamw 		XVA_SET_RTN(xvap, XAT_READONLY);
1028da6c28aaSamw 	}
1029da6c28aaSamw 	if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) {
10300a586ceaSMark Shellenbaum 		ZFS_ATTR_SET(zp, ZFS_HIDDEN, xoap->xoa_hidden,
10310a586ceaSMark Shellenbaum 		    zp->z_pflags, tx);
1032da6c28aaSamw 		XVA_SET_RTN(xvap, XAT_HIDDEN);
1033da6c28aaSamw 	}
1034da6c28aaSamw 	if (XVA_ISSET_REQ(xvap, XAT_SYSTEM)) {
10350a586ceaSMark Shellenbaum 		ZFS_ATTR_SET(zp, ZFS_SYSTEM, xoap->xoa_system,
10360a586ceaSMark Shellenbaum 		    zp->z_pflags, tx);
1037da6c28aaSamw 		XVA_SET_RTN(xvap, XAT_SYSTEM);
1038da6c28aaSamw 	}
1039da6c28aaSamw 	if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE)) {
10400a586ceaSMark Shellenbaum 		ZFS_ATTR_SET(zp, ZFS_ARCHIVE, xoap->xoa_archive,
10410a586ceaSMark Shellenbaum 		    zp->z_pflags, tx);
1042da6c28aaSamw 		XVA_SET_RTN(xvap, XAT_ARCHIVE);
1043da6c28aaSamw 	}
1044da6c28aaSamw 	if (XVA_ISSET_REQ(xvap, XAT_IMMUTABLE)) {
10450a586ceaSMark Shellenbaum 		ZFS_ATTR_SET(zp, ZFS_IMMUTABLE, xoap->xoa_immutable,
10460a586ceaSMark Shellenbaum 		    zp->z_pflags, tx);
1047da6c28aaSamw 		XVA_SET_RTN(xvap, XAT_IMMUTABLE);
1048da6c28aaSamw 	}
1049da6c28aaSamw 	if (XVA_ISSET_REQ(xvap, XAT_NOUNLINK)) {
10500a586ceaSMark Shellenbaum 		ZFS_ATTR_SET(zp, ZFS_NOUNLINK, xoap->xoa_nounlink,
10510a586ceaSMark Shellenbaum 		    zp->z_pflags, tx);
1052da6c28aaSamw 		XVA_SET_RTN(xvap, XAT_NOUNLINK);
1053da6c28aaSamw 	}
1054da6c28aaSamw 	if (XVA_ISSET_REQ(xvap, XAT_APPENDONLY)) {
10550a586ceaSMark Shellenbaum 		ZFS_ATTR_SET(zp, ZFS_APPENDONLY, xoap->xoa_appendonly,
10560a586ceaSMark Shellenbaum 		    zp->z_pflags, tx);
1057da6c28aaSamw 		XVA_SET_RTN(xvap, XAT_APPENDONLY);
1058da6c28aaSamw 	}
1059da6c28aaSamw 	if (XVA_ISSET_REQ(xvap, XAT_NODUMP)) {
10600a586ceaSMark Shellenbaum 		ZFS_ATTR_SET(zp, ZFS_NODUMP, xoap->xoa_nodump,
10610a586ceaSMark Shellenbaum 		    zp->z_pflags, tx);
1062da6c28aaSamw 		XVA_SET_RTN(xvap, XAT_NODUMP);
1063da6c28aaSamw 	}
1064da6c28aaSamw 	if (XVA_ISSET_REQ(xvap, XAT_OPAQUE)) {
10650a586ceaSMark Shellenbaum 		ZFS_ATTR_SET(zp, ZFS_OPAQUE, xoap->xoa_opaque,
10660a586ceaSMark Shellenbaum 		    zp->z_pflags, tx);
1067da6c28aaSamw 		XVA_SET_RTN(xvap, XAT_OPAQUE);
1068da6c28aaSamw 	}
1069da6c28aaSamw 	if (XVA_ISSET_REQ(xvap, XAT_AV_QUARANTINED)) {
1070da6c28aaSamw 		ZFS_ATTR_SET(zp, ZFS_AV_QUARANTINED,
10710a586ceaSMark Shellenbaum 		    xoap->xoa_av_quarantined, zp->z_pflags, tx);
1072da6c28aaSamw 		XVA_SET_RTN(xvap, XAT_AV_QUARANTINED);
1073da6c28aaSamw 	}
1074da6c28aaSamw 	if (XVA_ISSET_REQ(xvap, XAT_AV_MODIFIED)) {
10750a586ceaSMark Shellenbaum 		ZFS_ATTR_SET(zp, ZFS_AV_MODIFIED, xoap->xoa_av_modified,
10760a586ceaSMark Shellenbaum 		    zp->z_pflags, tx);
1077da6c28aaSamw 		XVA_SET_RTN(xvap, XAT_AV_MODIFIED);
1078da6c28aaSamw 	}
1079da6c28aaSamw 	if (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP)) {
10800a586ceaSMark Shellenbaum 		zfs_sa_set_scanstamp(zp, xvap, tx);
1081da6c28aaSamw 		XVA_SET_RTN(xvap, XAT_AV_SCANSTAMP);
1082da6c28aaSamw 	}
10837a286c47SDai Ngo 	if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) {
10840a586ceaSMark Shellenbaum 		ZFS_ATTR_SET(zp, ZFS_REPARSE, xoap->xoa_reparse,
10850a586ceaSMark Shellenbaum 		    zp->z_pflags, tx);
10867a286c47SDai Ngo 		XVA_SET_RTN(xvap, XAT_REPARSE);
10877a286c47SDai Ngo 	}
1088fd9ee8b5Sjoyce mcintosh 	if (XVA_ISSET_REQ(xvap, XAT_OFFLINE)) {
1089fd9ee8b5Sjoyce mcintosh 		ZFS_ATTR_SET(zp, ZFS_OFFLINE, xoap->xoa_offline,
1090fd9ee8b5Sjoyce mcintosh 		    zp->z_pflags, tx);
1091fd9ee8b5Sjoyce mcintosh 		XVA_SET_RTN(xvap, XAT_OFFLINE);
1092fd9ee8b5Sjoyce mcintosh 	}
1093fd9ee8b5Sjoyce mcintosh 	if (XVA_ISSET_REQ(xvap, XAT_SPARSE)) {
1094fd9ee8b5Sjoyce mcintosh 		ZFS_ATTR_SET(zp, ZFS_SPARSE, xoap->xoa_sparse,
1095fd9ee8b5Sjoyce mcintosh 		    zp->z_pflags, tx);
1096fd9ee8b5Sjoyce mcintosh 		XVA_SET_RTN(xvap, XAT_SPARSE);
1097fd9ee8b5Sjoyce mcintosh 	}
1098da6c28aaSamw }
1099da6c28aaSamw 
1100fa9e4066Sahrens int
1101fa9e4066Sahrens zfs_zget(zfsvfs_t *zfsvfs, uint64_t obj_num, znode_t **zpp)
1102fa9e4066Sahrens {
1103fa9e4066Sahrens 	dmu_object_info_t doi;
1104fa9e4066Sahrens 	dmu_buf_t	*db;
1105fa9e4066Sahrens 	znode_t		*zp;
1106ea8dc4b6Seschrock 	int err;
11070a586ceaSMark Shellenbaum 	sa_handle_t	*hdl;
1108fa9e4066Sahrens 
1109fa9e4066Sahrens 	*zpp = NULL;
1110fa9e4066Sahrens 
1111fa9e4066Sahrens 	ZFS_OBJ_HOLD_ENTER(zfsvfs, obj_num);
1112fa9e4066Sahrens 
11130a586ceaSMark Shellenbaum 	err = sa_buf_hold(zfsvfs->z_os, obj_num, NULL, &db);
1114ea8dc4b6Seschrock 	if (err) {
1115fa9e4066Sahrens 		ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
1116ea8dc4b6Seschrock 		return (err);
1117fa9e4066Sahrens 	}
1118fa9e4066Sahrens 
1119fa9e4066Sahrens 	dmu_object_info_from_db(db, &doi);
11200a586ceaSMark Shellenbaum 	if (doi.doi_bonus_type != DMU_OT_SA &&
11210a586ceaSMark Shellenbaum 	    (doi.doi_bonus_type != DMU_OT_ZNODE ||
11220a586ceaSMark Shellenbaum 	    (doi.doi_bonus_type == DMU_OT_ZNODE &&
11230a586ceaSMark Shellenbaum 	    doi.doi_bonus_size < sizeof (znode_phys_t)))) {
11240a586ceaSMark Shellenbaum 		sa_buf_rele(db, NULL);
1125fa9e4066Sahrens 		ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
1126be6fd75aSMatthew Ahrens 		return (SET_ERROR(EINVAL));
1127fa9e4066Sahrens 	}
1128fa9e4066Sahrens 
11290a586ceaSMark Shellenbaum 	hdl = dmu_buf_get_user(db);
11300a586ceaSMark Shellenbaum 	if (hdl != NULL) {
11310a586ceaSMark Shellenbaum 		zp  = sa_get_userdata(hdl);
11320a586ceaSMark Shellenbaum 
1133fa9e4066Sahrens 
11344ccbb6e7Sahrens 		/*
11350a586ceaSMark Shellenbaum 		 * Since "SA" does immediate eviction we
11360a586ceaSMark Shellenbaum 		 * should never find a sa handle that doesn't
11370a586ceaSMark Shellenbaum 		 * know about the znode.
11384ccbb6e7Sahrens 		 */
11390a586ceaSMark Shellenbaum 
11400a586ceaSMark Shellenbaum 		ASSERT3P(zp, !=, NULL);
11410a586ceaSMark Shellenbaum 
11420a586ceaSMark Shellenbaum 		mutex_enter(&zp->z_lock);
1143fa9e4066Sahrens 		ASSERT3U(zp->z_id, ==, obj_num);
1144893a6d32Sahrens 		if (zp->z_unlinked) {
1145be6fd75aSMatthew Ahrens 			err = SET_ERROR(ENOENT);
1146fa9e4066Sahrens 		} else {
11474ccbb6e7Sahrens 			VN_HOLD(ZTOV(zp));
11484ccbb6e7Sahrens 			*zpp = zp;
11494ccbb6e7Sahrens 			err = 0;
1150fa9e4066Sahrens 		}
11510a586ceaSMark Shellenbaum 		sa_buf_rele(db, NULL);
1152fa9e4066Sahrens 		mutex_exit(&zp->z_lock);
1153ea8dc4b6Seschrock 		ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
11544ccbb6e7Sahrens 		return (err);
1155fa9e4066Sahrens 	}
1156fa9e4066Sahrens 
1157fa9e4066Sahrens 	/*
1158fa9e4066Sahrens 	 * Not found create new znode/vnode
115959e7834dSMark Shellenbaum 	 * but only if file exists.
116059e7834dSMark Shellenbaum 	 *
116159e7834dSMark Shellenbaum 	 * There is a small window where zfs_vget() could
116259e7834dSMark Shellenbaum 	 * find this object while a file create is still in
11630a586ceaSMark Shellenbaum 	 * progress.  This is checked for in zfs_znode_alloc()
11640a586ceaSMark Shellenbaum 	 *
11650a586ceaSMark Shellenbaum 	 * if zfs_znode_alloc() fails it will drop the hold on the
11660a586ceaSMark Shellenbaum 	 * bonus buffer.
1167fa9e4066Sahrens 	 */
11680a586ceaSMark Shellenbaum 	zp = zfs_znode_alloc(zfsvfs, db, doi.doi_data_block_size,
11690a586ceaSMark Shellenbaum 	    doi.doi_bonus_type, NULL);
11700a586ceaSMark Shellenbaum 	if (zp == NULL) {
1171be6fd75aSMatthew Ahrens 		err = SET_ERROR(ENOENT);
11720a586ceaSMark Shellenbaum 	} else {
11730a586ceaSMark Shellenbaum 		*zpp = zp;
117459e7834dSMark Shellenbaum 	}
1175ea8dc4b6Seschrock 	ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
117659e7834dSMark Shellenbaum 	return (err);
1177fa9e4066Sahrens }
1178fa9e4066Sahrens 
1179f18faf3fSek int
1180f18faf3fSek zfs_rezget(znode_t *zp)
1181f18faf3fSek {
1182f18faf3fSek 	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
1183f18faf3fSek 	dmu_object_info_t doi;
1184f18faf3fSek 	dmu_buf_t *db;
1185f18faf3fSek 	uint64_t obj_num = zp->z_id;
11860a586ceaSMark Shellenbaum 	uint64_t mode;
11870a586ceaSMark Shellenbaum 	sa_bulk_attr_t bulk[8];
1188f18faf3fSek 	int err;
11890a586ceaSMark Shellenbaum 	int count = 0;
11900a586ceaSMark Shellenbaum 	uint64_t gen;
1191f18faf3fSek 
1192f18faf3fSek 	ZFS_OBJ_HOLD_ENTER(zfsvfs, obj_num);
1193f18faf3fSek 
11940a586ceaSMark Shellenbaum 	mutex_enter(&zp->z_acl_lock);
11950a586ceaSMark Shellenbaum 	if (zp->z_acl_cached) {
11960a586ceaSMark Shellenbaum 		zfs_acl_free(zp->z_acl_cached);
11970a586ceaSMark Shellenbaum 		zp->z_acl_cached = NULL;
11980a586ceaSMark Shellenbaum 	}
11990a586ceaSMark Shellenbaum 
12000a586ceaSMark Shellenbaum 	mutex_exit(&zp->z_acl_lock);
12010a586ceaSMark Shellenbaum 	ASSERT(zp->z_sa_hdl == NULL);
12020a586ceaSMark Shellenbaum 	err = sa_buf_hold(zfsvfs->z_os, obj_num, NULL, &db);
1203f18faf3fSek 	if (err) {
1204f18faf3fSek 		ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
1205f18faf3fSek 		return (err);
1206f18faf3fSek 	}
1207f18faf3fSek 
1208f18faf3fSek 	dmu_object_info_from_db(db, &doi);
12090a586ceaSMark Shellenbaum 	if (doi.doi_bonus_type != DMU_OT_SA &&
12100a586ceaSMark Shellenbaum 	    (doi.doi_bonus_type != DMU_OT_ZNODE ||
12110a586ceaSMark Shellenbaum 	    (doi.doi_bonus_type == DMU_OT_ZNODE &&
12120a586ceaSMark Shellenbaum 	    doi.doi_bonus_size < sizeof (znode_phys_t)))) {
12130a586ceaSMark Shellenbaum 		sa_buf_rele(db, NULL);
1214f18faf3fSek 		ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
1215be6fd75aSMatthew Ahrens 		return (SET_ERROR(EINVAL));
1216f18faf3fSek 	}
1217f18faf3fSek 
12180a586ceaSMark Shellenbaum 	zfs_znode_sa_init(zfsvfs, zp, db, doi.doi_bonus_type, NULL);
12190a586ceaSMark Shellenbaum 
12200a586ceaSMark Shellenbaum 	/* reload cached values */
12210a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GEN(zfsvfs), NULL,
12220a586ceaSMark Shellenbaum 	    &gen, sizeof (gen));
12230a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(zfsvfs), NULL,
12240a586ceaSMark Shellenbaum 	    &zp->z_size, sizeof (zp->z_size));
12250a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_LINKS(zfsvfs), NULL,
12260a586ceaSMark Shellenbaum 	    &zp->z_links, sizeof (zp->z_links));
12270a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), NULL,
12280a586ceaSMark Shellenbaum 	    &zp->z_pflags, sizeof (zp->z_pflags));
12290a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ATIME(zfsvfs), NULL,
12300a586ceaSMark Shellenbaum 	    &zp->z_atime, sizeof (zp->z_atime));
12310a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_UID(zfsvfs), NULL,
1232f1696b23SMark Shellenbaum 	    &zp->z_uid, sizeof (zp->z_uid));
12330a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GID(zfsvfs), NULL,
1234f1696b23SMark Shellenbaum 	    &zp->z_gid, sizeof (zp->z_gid));
12350a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zfsvfs), NULL,
12360a586ceaSMark Shellenbaum 	    &mode, sizeof (mode));
12370a586ceaSMark Shellenbaum 
12380a586ceaSMark Shellenbaum 	if (sa_bulk_lookup(zp->z_sa_hdl, bulk, count)) {
12390a586ceaSMark Shellenbaum 		zfs_znode_dmu_fini(zp);
1240f18faf3fSek 		ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
1241be6fd75aSMatthew Ahrens 		return (SET_ERROR(EIO));
1242f18faf3fSek 	}
1243f18faf3fSek 
12441412a1a2SMark Shellenbaum 	zp->z_mode = mode;
12451412a1a2SMark Shellenbaum 
12460a586ceaSMark Shellenbaum 	if (gen != zp->z_gen) {
12470a586ceaSMark Shellenbaum 		zfs_znode_dmu_fini(zp);
12480a586ceaSMark Shellenbaum 		ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
1249be6fd75aSMatthew Ahrens 		return (SET_ERROR(EIO));
12506638ae1dSMark Shellenbaum 	}
12516638ae1dSMark Shellenbaum 
12520a586ceaSMark Shellenbaum 	zp->z_unlinked = (zp->z_links == 0);
12536166ad1cSek 	zp->z_blksz = doi.doi_data_block_size;
1254f18faf3fSek 
1255f18faf3fSek 	ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
1256f18faf3fSek 
1257f18faf3fSek 	return (0);
1258f18faf3fSek }
1259f18faf3fSek 
1260fa9e4066Sahrens void
1261fa9e4066Sahrens zfs_znode_delete(znode_t *zp, dmu_tx_t *tx)
1262fa9e4066Sahrens {
1263fa9e4066Sahrens 	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
1264cdb0ab79Smaybee 	objset_t *os = zfsvfs->z_os;
12654ccbb6e7Sahrens 	uint64_t obj = zp->z_id;
12661412a1a2SMark Shellenbaum 	uint64_t acl_obj = zfs_external_acl(zp);
1267fa9e4066Sahrens 
12684ccbb6e7Sahrens 	ZFS_OBJ_HOLD_ENTER(zfsvfs, obj);
12691412a1a2SMark Shellenbaum 	if (acl_obj) {
12701412a1a2SMark Shellenbaum 		VERIFY(!zp->z_is_sa);
1271cdb0ab79Smaybee 		VERIFY(0 == dmu_object_free(os, acl_obj, tx));
12721412a1a2SMark Shellenbaum 	}
1273cdb0ab79Smaybee 	VERIFY(0 == dmu_object_free(os, obj, tx));
12744ccbb6e7Sahrens 	zfs_znode_dmu_fini(zp);
12754ccbb6e7Sahrens 	ZFS_OBJ_HOLD_EXIT(zfsvfs, obj);
1276874395d5Smaybee 	zfs_znode_free(zp);
1277fa9e4066Sahrens }
1278fa9e4066Sahrens 
1279fa9e4066Sahrens void
1280fa9e4066Sahrens zfs_zinactive(znode_t *zp)
1281fa9e4066Sahrens {
1282fa9e4066Sahrens 	vnode_t	*vp = ZTOV(zp);
1283fa9e4066Sahrens 	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
1284fa9e4066Sahrens 	uint64_t z_id = zp->z_id;
1285fa9e4066Sahrens 
12860a586ceaSMark Shellenbaum 	ASSERT(zp->z_sa_hdl);
1287fa9e4066Sahrens 
1288fa9e4066Sahrens 	/*
1289fa9e4066Sahrens 	 * Don't allow a zfs_zget() while were trying to release this znode
1290fa9e4066Sahrens 	 */
1291fa9e4066Sahrens 	ZFS_OBJ_HOLD_ENTER(zfsvfs, z_id);
1292fa9e4066Sahrens 
1293fa9e4066Sahrens 	mutex_enter(&zp->z_lock);
1294fa9e4066Sahrens 	mutex_enter(&vp->v_lock);
1295fa9e4066Sahrens 	vp->v_count--;
1296fa9e4066Sahrens 	if (vp->v_count > 0 || vn_has_cached_data(vp)) {
1297fa9e4066Sahrens 		/*
1298fa9e4066Sahrens 		 * If the hold count is greater than zero, somebody has
1299fa9e4066Sahrens 		 * obtained a new reference on this znode while we were
1300fa9e4066Sahrens 		 * processing it here, so we are done.  If we still have
1301fa9e4066Sahrens 		 * mapped pages then we are also done, since we don't
1302fa9e4066Sahrens 		 * want to inactivate the znode until the pages get pushed.
1303fa9e4066Sahrens 		 *
1304fa9e4066Sahrens 		 * XXX - if vn_has_cached_data(vp) is true, but count == 0,
1305fa9e4066Sahrens 		 * this seems like it would leave the znode hanging with
1306fa9e4066Sahrens 		 * no chance to go inactive...
1307fa9e4066Sahrens 		 */
1308fa9e4066Sahrens 		mutex_exit(&vp->v_lock);
1309fa9e4066Sahrens 		mutex_exit(&zp->z_lock);
1310fa9e4066Sahrens 		ZFS_OBJ_HOLD_EXIT(zfsvfs, z_id);
1311fa9e4066Sahrens 		return;
1312fa9e4066Sahrens 	}
1313fa9e4066Sahrens 	mutex_exit(&vp->v_lock);
1314fa9e4066Sahrens 
1315fa9e4066Sahrens 	/*
1316fa9e4066Sahrens 	 * If this was the last reference to a file with no links,
1317fa9e4066Sahrens 	 * remove the file from the file system.
1318fa9e4066Sahrens 	 */
1319893a6d32Sahrens 	if (zp->z_unlinked) {
1320fa9e4066Sahrens 		mutex_exit(&zp->z_lock);
1321fa9e4066Sahrens 		ZFS_OBJ_HOLD_EXIT(zfsvfs, z_id);
1322893a6d32Sahrens 		zfs_rmnode(zp);
1323fa9e4066Sahrens 		return;
1324fa9e4066Sahrens 	}
13250a586ceaSMark Shellenbaum 
1326fa9e4066Sahrens 	mutex_exit(&zp->z_lock);
13274ccbb6e7Sahrens 	zfs_znode_dmu_fini(zp);
1328fa9e4066Sahrens 	ZFS_OBJ_HOLD_EXIT(zfsvfs, z_id);
1329874395d5Smaybee 	zfs_znode_free(zp);
1330fa9e4066Sahrens }
1331fa9e4066Sahrens 
1332fa9e4066Sahrens void
1333fa9e4066Sahrens zfs_znode_free(znode_t *zp)
1334fa9e4066Sahrens {
1335fa9e4066Sahrens 	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
1336fa9e4066Sahrens 
1337874395d5Smaybee 	vn_invalid(ZTOV(zp));
1338874395d5Smaybee 
1339b5fca8f8Stomee 	ASSERT(ZTOV(zp)->v_count == 0);
1340b5fca8f8Stomee 
1341fa9e4066Sahrens 	mutex_enter(&zfsvfs->z_znodes_lock);
1342b5fca8f8Stomee 	POINTER_INVALIDATE(&zp->z_zfsvfs);
1343fa9e4066Sahrens 	list_remove(&zfsvfs->z_all_znodes, zp);
1344fa9e4066Sahrens 	mutex_exit(&zfsvfs->z_znodes_lock);
1345fa9e4066Sahrens 
1346d47621a4STim Haley 	if (zp->z_acl_cached) {
1347d47621a4STim Haley 		zfs_acl_free(zp->z_acl_cached);
1348d47621a4STim Haley 		zp->z_acl_cached = NULL;
1349d47621a4STim Haley 	}
1350d47621a4STim Haley 
1351fa9e4066Sahrens 	kmem_cache_free(znode_cache, zp);
1352874395d5Smaybee 
1353874395d5Smaybee 	VFS_RELE(zfsvfs->z_vfs);
1354fa9e4066Sahrens }
1355fa9e4066Sahrens 
1356fa9e4066Sahrens void
13570a586ceaSMark Shellenbaum zfs_tstamp_update_setup(znode_t *zp, uint_t flag, uint64_t mtime[2],
13580a586ceaSMark Shellenbaum     uint64_t ctime[2], boolean_t have_tx)
1359fa9e4066Sahrens {
1360fa9e4066Sahrens 	timestruc_t	now;
1361fa9e4066Sahrens 
1362fa9e4066Sahrens 	gethrestime(&now);
1363fa9e4066Sahrens 
13640a586ceaSMark Shellenbaum 	if (have_tx) {	/* will sa_bulk_update happen really soon? */
1365fa9e4066Sahrens 		zp->z_atime_dirty = 0;
1366fa9e4066Sahrens 		zp->z_seq++;
1367fa9e4066Sahrens 	} else {
1368fa9e4066Sahrens 		zp->z_atime_dirty = 1;
1369fa9e4066Sahrens 	}
1370fa9e4066Sahrens 
13710a586ceaSMark Shellenbaum 	if (flag & AT_ATIME) {
13720a586ceaSMark Shellenbaum 		ZFS_TIME_ENCODE(&now, zp->z_atime);
13730a586ceaSMark Shellenbaum 	}
1374fa9e4066Sahrens 
1375da6c28aaSamw 	if (flag & AT_MTIME) {
13760a586ceaSMark Shellenbaum 		ZFS_TIME_ENCODE(&now, mtime);
13770a586ceaSMark Shellenbaum 		if (zp->z_zfsvfs->z_use_fuids) {
13780a586ceaSMark Shellenbaum 			zp->z_pflags |= (ZFS_ARCHIVE |
13790a586ceaSMark Shellenbaum 			    ZFS_AV_MODIFIED);
13800a586ceaSMark Shellenbaum 		}
1381da6c28aaSamw 	}
1382fa9e4066Sahrens 
1383da6c28aaSamw 	if (flag & AT_CTIME) {
13840a586ceaSMark Shellenbaum 		ZFS_TIME_ENCODE(&now, ctime);
1385da6c28aaSamw 		if (zp->z_zfsvfs->z_use_fuids)
13860a586ceaSMark Shellenbaum 			zp->z_pflags |= ZFS_ARCHIVE;
1387da6c28aaSamw 	}
1388fa9e4066Sahrens }
1389fa9e4066Sahrens 
1390fa9e4066Sahrens /*
1391104e2ed7Sperrin  * Grow the block size for a file.
1392fa9e4066Sahrens  *
1393fa9e4066Sahrens  *	IN:	zp	- znode of file to free data in.
1394fa9e4066Sahrens  *		size	- requested block size
1395fa9e4066Sahrens  *		tx	- open transaction.
1396fa9e4066Sahrens  *
1397fa9e4066Sahrens  * NOTE: this function assumes that the znode is write locked.
1398fa9e4066Sahrens  */
1399104e2ed7Sperrin void
1400fa9e4066Sahrens zfs_grow_blocksize(znode_t *zp, uint64_t size, dmu_tx_t *tx)
1401fa9e4066Sahrens {
1402fa9e4066Sahrens 	int		error;
1403fa9e4066Sahrens 	u_longlong_t	dummy;
1404fa9e4066Sahrens 
1405fa9e4066Sahrens 	if (size <= zp->z_blksz)
1406104e2ed7Sperrin 		return;
1407fa9e4066Sahrens 	/*
1408fa9e4066Sahrens 	 * If the file size is already greater than the current blocksize,
1409fa9e4066Sahrens 	 * we will not grow.  If there is more than one block in a file,
1410fa9e4066Sahrens 	 * the blocksize cannot change.
1411fa9e4066Sahrens 	 */
14120a586ceaSMark Shellenbaum 	if (zp->z_blksz && zp->z_size > zp->z_blksz)
1413104e2ed7Sperrin 		return;
1414fa9e4066Sahrens 
1415fa9e4066Sahrens 	error = dmu_object_set_blocksize(zp->z_zfsvfs->z_os, zp->z_id,
1416fa9e4066Sahrens 	    size, 0, tx);
14170a586ceaSMark Shellenbaum 
1418fa9e4066Sahrens 	if (error == ENOTSUP)
1419104e2ed7Sperrin 		return;
1420fb09f5aaSMadhav Suresh 	ASSERT0(error);
1421fa9e4066Sahrens 
1422fa9e4066Sahrens 	/* What blocksize did we actually get? */
14230a586ceaSMark Shellenbaum 	dmu_object_size_from_db(sa_get_db(zp->z_sa_hdl), &zp->z_blksz, &dummy);
1424fa9e4066Sahrens }
1425fa9e4066Sahrens 
1426fa9e4066Sahrens /*
1427fa9e4066Sahrens  * This is a dummy interface used when pvn_vplist_dirty() should *not*
1428fa9e4066Sahrens  * be calling back into the fs for a putpage().  E.g.: when truncating
1429fa9e4066Sahrens  * a file, the pages being "thrown away* don't need to be written out.
1430fa9e4066Sahrens  */
1431fa9e4066Sahrens /* ARGSUSED */
1432fa9e4066Sahrens static int
1433fa9e4066Sahrens zfs_no_putpage(vnode_t *vp, page_t *pp, u_offset_t *offp, size_t *lenp,
1434fa9e4066Sahrens     int flags, cred_t *cr)
1435fa9e4066Sahrens {
1436fa9e4066Sahrens 	ASSERT(0);
1437fa9e4066Sahrens 	return (0);
1438fa9e4066Sahrens }
1439fa9e4066Sahrens 
1440fa9e4066Sahrens /*
1441cdb0ab79Smaybee  * Increase the file length
1442fa9e4066Sahrens  *
1443fa9e4066Sahrens  *	IN:	zp	- znode of file to free data in.
1444cdb0ab79Smaybee  *		end	- new end-of-file
1445fa9e4066Sahrens  *
14464bb73804SMatthew Ahrens  *	RETURN:	0 on success, error code on failure
1447fa9e4066Sahrens  */
1448cdb0ab79Smaybee static int
1449cdb0ab79Smaybee zfs_extend(znode_t *zp, uint64_t end)
1450fa9e4066Sahrens {
14515730cc9aSmaybee 	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
1452cdb0ab79Smaybee 	dmu_tx_t *tx;
14535730cc9aSmaybee 	rl_t *rl;
1454cdb0ab79Smaybee 	uint64_t newblksz;
1455104e2ed7Sperrin 	int error;
1456fa9e4066Sahrens 
14575730cc9aSmaybee 	/*
1458cdb0ab79Smaybee 	 * We will change zp_size, lock the whole file.
14595730cc9aSmaybee 	 */
1460cdb0ab79Smaybee 	rl = zfs_range_lock(zp, 0, UINT64_MAX, RL_WRITER);
14615730cc9aSmaybee 
1462fa9e4066Sahrens 	/*
1463fa9e4066Sahrens 	 * Nothing to do if file already at desired length.
1464fa9e4066Sahrens 	 */
14650a586ceaSMark Shellenbaum 	if (end <= zp->z_size) {
1466c5c6ffa0Smaybee 		zfs_range_unlock(rl);
1467fa9e4066Sahrens 		return (0);
1468fa9e4066Sahrens 	}
14695730cc9aSmaybee 	tx = dmu_tx_create(zfsvfs->z_os);
14700a586ceaSMark Shellenbaum 	dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE);
14710a586ceaSMark Shellenbaum 	zfs_sa_upgrade_txholds(tx, zp);
1472cdb0ab79Smaybee 	if (end > zp->z_blksz &&
14735730cc9aSmaybee 	    (!ISP2(zp->z_blksz) || zp->z_blksz < zfsvfs->z_max_blksz)) {
1474fa9e4066Sahrens 		/*
1475fa9e4066Sahrens 		 * We are growing the file past the current block size.
1476fa9e4066Sahrens 		 */
1477fa9e4066Sahrens 		if (zp->z_blksz > zp->z_zfsvfs->z_max_blksz) {
1478*b5152584SMatthew Ahrens 			/*
1479*b5152584SMatthew Ahrens 			 * File's blocksize is already larger than the
1480*b5152584SMatthew Ahrens 			 * "recordsize" property.  Only let it grow to
1481*b5152584SMatthew Ahrens 			 * the next power of 2.
1482*b5152584SMatthew Ahrens 			 */
1483fa9e4066Sahrens 			ASSERT(!ISP2(zp->z_blksz));
1484*b5152584SMatthew Ahrens 			newblksz = MIN(end, 1 << highbit64(zp->z_blksz));
1485fa9e4066Sahrens 		} else {
1486cdb0ab79Smaybee 			newblksz = MIN(end, zp->z_zfsvfs->z_max_blksz);
1487fa9e4066Sahrens 		}
1488cdb0ab79Smaybee 		dmu_tx_hold_write(tx, zp->z_id, 0, newblksz);
1489cdb0ab79Smaybee 	} else {
1490cdb0ab79Smaybee 		newblksz = 0;
14915730cc9aSmaybee 	}
14925730cc9aSmaybee 
1493e722410cSMatthew Ahrens 	error = dmu_tx_assign(tx, TXG_WAIT);
14945730cc9aSmaybee 	if (error) {
14955730cc9aSmaybee 		dmu_tx_abort(tx);
1496c5c6ffa0Smaybee 		zfs_range_unlock(rl);
14975730cc9aSmaybee 		return (error);
1498fa9e4066Sahrens 	}
14995730cc9aSmaybee 
1500cdb0ab79Smaybee 	if (newblksz)
1501cdb0ab79Smaybee 		zfs_grow_blocksize(zp, newblksz, tx);
15025730cc9aSmaybee 
15030a586ceaSMark Shellenbaum 	zp->z_size = end;
15040a586ceaSMark Shellenbaum 
15050a586ceaSMark Shellenbaum 	VERIFY(0 == sa_update(zp->z_sa_hdl, SA_ZPL_SIZE(zp->z_zfsvfs),
15060a586ceaSMark Shellenbaum 	    &zp->z_size, sizeof (zp->z_size), tx));
15075730cc9aSmaybee 
1508cdb0ab79Smaybee 	zfs_range_unlock(rl);
15095730cc9aSmaybee 
1510cdb0ab79Smaybee 	dmu_tx_commit(tx);
15115730cc9aSmaybee 
1512cdb0ab79Smaybee 	return (0);
1513cdb0ab79Smaybee }
1514cdb0ab79Smaybee 
1515cdb0ab79Smaybee /*
1516cdb0ab79Smaybee  * Free space in a file.
1517cdb0ab79Smaybee  *
1518cdb0ab79Smaybee  *	IN:	zp	- znode of file to free data in.
1519cdb0ab79Smaybee  *		off	- start of section to free.
1520cdb0ab79Smaybee  *		len	- length of section to free.
1521cdb0ab79Smaybee  *
15224bb73804SMatthew Ahrens  *	RETURN:	0 on success, error code on failure
1523cdb0ab79Smaybee  */
1524cdb0ab79Smaybee static int
1525cdb0ab79Smaybee zfs_free_range(znode_t *zp, uint64_t off, uint64_t len)
1526cdb0ab79Smaybee {
1527cdb0ab79Smaybee 	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
1528cdb0ab79Smaybee 	rl_t *rl;
1529cdb0ab79Smaybee 	int error;
1530cdb0ab79Smaybee 
1531cdb0ab79Smaybee 	/*
1532cdb0ab79Smaybee 	 * Lock the range being freed.
1533cdb0ab79Smaybee 	 */
1534cdb0ab79Smaybee 	rl = zfs_range_lock(zp, off, len, RL_WRITER);
1535cdb0ab79Smaybee 
1536cdb0ab79Smaybee 	/*
1537cdb0ab79Smaybee 	 * Nothing to do if file already at desired length.
1538cdb0ab79Smaybee 	 */
15390a586ceaSMark Shellenbaum 	if (off >= zp->z_size) {
1540cdb0ab79Smaybee 		zfs_range_unlock(rl);
1541cdb0ab79Smaybee 		return (0);
15425730cc9aSmaybee 	}
15435730cc9aSmaybee 
15440a586ceaSMark Shellenbaum 	if (off + len > zp->z_size)
15450a586ceaSMark Shellenbaum 		len = zp->z_size - off;
1546cdb0ab79Smaybee 
1547cdb0ab79Smaybee 	error = dmu_free_long_range(zfsvfs->z_os, zp->z_id, off, len);
1548cdb0ab79Smaybee 
1549c5c6ffa0Smaybee 	zfs_range_unlock(rl);
15505730cc9aSmaybee 
1551cdb0ab79Smaybee 	return (error);
1552cdb0ab79Smaybee }
1553cdb0ab79Smaybee 
1554cdb0ab79Smaybee /*
1555cdb0ab79Smaybee  * Truncate a file
1556cdb0ab79Smaybee  *
1557cdb0ab79Smaybee  *	IN:	zp	- znode of file to free data in.
1558cdb0ab79Smaybee  *		end	- new end-of-file.
1559cdb0ab79Smaybee  *
15604bb73804SMatthew Ahrens  *	RETURN:	0 on success, error code on failure
1561cdb0ab79Smaybee  */
1562cdb0ab79Smaybee static int
1563cdb0ab79Smaybee zfs_trunc(znode_t *zp, uint64_t end)
1564cdb0ab79Smaybee {
1565cdb0ab79Smaybee 	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
1566cdb0ab79Smaybee 	vnode_t *vp = ZTOV(zp);
1567cdb0ab79Smaybee 	dmu_tx_t *tx;
1568cdb0ab79Smaybee 	rl_t *rl;
1569cdb0ab79Smaybee 	int error;
1570fd9ee8b5Sjoyce mcintosh 	sa_bulk_attr_t bulk[2];
1571fd9ee8b5Sjoyce mcintosh 	int count = 0;
1572cdb0ab79Smaybee 
1573cdb0ab79Smaybee 	/*
1574cdb0ab79Smaybee 	 * We will change zp_size, lock the whole file.
1575cdb0ab79Smaybee 	 */
1576cdb0ab79Smaybee 	rl = zfs_range_lock(zp, 0, UINT64_MAX, RL_WRITER);
1577cdb0ab79Smaybee 
1578cdb0ab79Smaybee 	/*
1579cdb0ab79Smaybee 	 * Nothing to do if file already at desired length.
1580cdb0ab79Smaybee 	 */
15810a586ceaSMark Shellenbaum 	if (end >= zp->z_size) {
1582cdb0ab79Smaybee 		zfs_range_unlock(rl);
1583cdb0ab79Smaybee 		return (0);
1584cdb0ab79Smaybee 	}
1585cdb0ab79Smaybee 
1586cdb0ab79Smaybee 	error = dmu_free_long_range(zfsvfs->z_os, zp->z_id, end,  -1);
1587cdb0ab79Smaybee 	if (error) {
1588cdb0ab79Smaybee 		zfs_range_unlock(rl);
1589cdb0ab79Smaybee 		return (error);
1590cdb0ab79Smaybee 	}
1591cdb0ab79Smaybee 	tx = dmu_tx_create(zfsvfs->z_os);
15920a586ceaSMark Shellenbaum 	dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE);
15930a586ceaSMark Shellenbaum 	zfs_sa_upgrade_txholds(tx, zp);
15944bb73804SMatthew Ahrens 	dmu_tx_mark_netfree(tx);
1595e722410cSMatthew Ahrens 	error = dmu_tx_assign(tx, TXG_WAIT);
1596cdb0ab79Smaybee 	if (error) {
1597cdb0ab79Smaybee 		dmu_tx_abort(tx);
1598cdb0ab79Smaybee 		zfs_range_unlock(rl);
1599cdb0ab79Smaybee 		return (error);
1600cdb0ab79Smaybee 	}
1601cdb0ab79Smaybee 
16020a586ceaSMark Shellenbaum 	zp->z_size = end;
1603fd9ee8b5Sjoyce mcintosh 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(zfsvfs),
1604fd9ee8b5Sjoyce mcintosh 	    NULL, &zp->z_size, sizeof (zp->z_size));
16050a586ceaSMark Shellenbaum 
1606fd9ee8b5Sjoyce mcintosh 	if (end == 0) {
1607fd9ee8b5Sjoyce mcintosh 		zp->z_pflags &= ~ZFS_SPARSE;
1608fd9ee8b5Sjoyce mcintosh 		SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs),
1609fd9ee8b5Sjoyce mcintosh 		    NULL, &zp->z_pflags, 8);
1610fd9ee8b5Sjoyce mcintosh 	}
1611fd9ee8b5Sjoyce mcintosh 	VERIFY(sa_bulk_update(zp->z_sa_hdl, bulk, count, tx) == 0);
1612cdb0ab79Smaybee 
16135730cc9aSmaybee 	dmu_tx_commit(tx);
16145730cc9aSmaybee 
1615fa9e4066Sahrens 	/*
16165730cc9aSmaybee 	 * Clear any mapped pages in the truncated region.  This has to
16175730cc9aSmaybee 	 * happen outside of the transaction to avoid the possibility of
16185730cc9aSmaybee 	 * a deadlock with someone trying to push a page that we are
16195730cc9aSmaybee 	 * about to invalidate.
1620fa9e4066Sahrens 	 */
1621cdb0ab79Smaybee 	if (vn_has_cached_data(vp)) {
1622fa9e4066Sahrens 		page_t *pp;
1623cdb0ab79Smaybee 		uint64_t start = end & PAGEMASK;
1624cdb0ab79Smaybee 		int poff = end & PAGEOFFSET;
1625fa9e4066Sahrens 
16265730cc9aSmaybee 		if (poff != 0 && (pp = page_lookup(vp, start, SE_SHARED))) {
1627fa9e4066Sahrens 			/*
1628fa9e4066Sahrens 			 * We need to zero a partial page.
1629fa9e4066Sahrens 			 */
16305730cc9aSmaybee 			pagezero(pp, poff, PAGESIZE - poff);
1631fa9e4066Sahrens 			start += PAGESIZE;
1632fa9e4066Sahrens 			page_unlock(pp);
1633fa9e4066Sahrens 		}
1634fa9e4066Sahrens 		error = pvn_vplist_dirty(vp, start, zfs_no_putpage,
16355730cc9aSmaybee 		    B_INVAL | B_TRUNC, NULL);
1636fa9e4066Sahrens 		ASSERT(error == 0);
1637fa9e4066Sahrens 	}
1638ac05c741SMark Maybee 
1639ac05c741SMark Maybee 	zfs_range_unlock(rl);
1640fa9e4066Sahrens 
1641fa9e4066Sahrens 	return (0);
1642fa9e4066Sahrens }
1643fa9e4066Sahrens 
1644cdb0ab79Smaybee /*
1645cdb0ab79Smaybee  * Free space in a file
1646cdb0ab79Smaybee  *
1647cdb0ab79Smaybee  *	IN:	zp	- znode of file to free data in.
1648cdb0ab79Smaybee  *		off	- start of range
1649cdb0ab79Smaybee  *		len	- end of range (0 => EOF)
1650cdb0ab79Smaybee  *		flag	- current file open mode flags.
1651cdb0ab79Smaybee  *		log	- TRUE if this action should be logged
1652cdb0ab79Smaybee  *
16534bb73804SMatthew Ahrens  *	RETURN:	0 on success, error code on failure
1654cdb0ab79Smaybee  */
1655cdb0ab79Smaybee int
1656cdb0ab79Smaybee zfs_freesp(znode_t *zp, uint64_t off, uint64_t len, int flag, boolean_t log)
1657cdb0ab79Smaybee {
1658cdb0ab79Smaybee 	vnode_t *vp = ZTOV(zp);
1659cdb0ab79Smaybee 	dmu_tx_t *tx;
1660cdb0ab79Smaybee 	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
1661cdb0ab79Smaybee 	zilog_t *zilog = zfsvfs->z_log;
16620a586ceaSMark Shellenbaum 	uint64_t mode;
16630a586ceaSMark Shellenbaum 	uint64_t mtime[2], ctime[2];
1664db9986c7SMark Shellenbaum 	sa_bulk_attr_t bulk[3];
16650a586ceaSMark Shellenbaum 	int count = 0;
1666cdb0ab79Smaybee 	int error;
1667cdb0ab79Smaybee 
16680a586ceaSMark Shellenbaum 	if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_MODE(zfsvfs), &mode,
16690a586ceaSMark Shellenbaum 	    sizeof (mode))) != 0)
16700a586ceaSMark Shellenbaum 		return (error);
16710a586ceaSMark Shellenbaum 
16720a586ceaSMark Shellenbaum 	if (off > zp->z_size) {
1673cdb0ab79Smaybee 		error =  zfs_extend(zp, off+len);
1674cdb0ab79Smaybee 		if (error == 0 && log)
1675cdb0ab79Smaybee 			goto log;
1676cdb0ab79Smaybee 		else
1677cdb0ab79Smaybee 			return (error);
1678cdb0ab79Smaybee 	}
1679cdb0ab79Smaybee 
1680cdb0ab79Smaybee 	/*
1681cdb0ab79Smaybee 	 * Check for any locks in the region to be freed.
1682cdb0ab79Smaybee 	 */
16830a586ceaSMark Shellenbaum 
16840a586ceaSMark Shellenbaum 	if (MANDLOCK(vp, (mode_t)mode)) {
16850a586ceaSMark Shellenbaum 		uint64_t length = (len ? len : zp->z_size - off);
1686cdb0ab79Smaybee 		if (error = chklock(vp, FWRITE, off, length, flag, NULL))
1687cdb0ab79Smaybee 			return (error);
1688cdb0ab79Smaybee 	}
1689cdb0ab79Smaybee 
1690cdb0ab79Smaybee 	if (len == 0) {
1691cdb0ab79Smaybee 		error = zfs_trunc(zp, off);
1692cdb0ab79Smaybee 	} else {
1693cdb0ab79Smaybee 		if ((error = zfs_free_range(zp, off, len)) == 0 &&
16940a586ceaSMark Shellenbaum 		    off + len > zp->z_size)
1695cdb0ab79Smaybee 			error = zfs_extend(zp, off+len);
1696cdb0ab79Smaybee 	}
1697cdb0ab79Smaybee 	if (error || !log)
1698cdb0ab79Smaybee 		return (error);
1699cdb0ab79Smaybee log:
1700cdb0ab79Smaybee 	tx = dmu_tx_create(zfsvfs->z_os);
17010a586ceaSMark Shellenbaum 	dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE);
17020a586ceaSMark Shellenbaum 	zfs_sa_upgrade_txholds(tx, zp);
1703e722410cSMatthew Ahrens 	error = dmu_tx_assign(tx, TXG_WAIT);
1704cdb0ab79Smaybee 	if (error) {
1705cdb0ab79Smaybee 		dmu_tx_abort(tx);
1706cdb0ab79Smaybee 		return (error);
1707cdb0ab79Smaybee 	}
1708cdb0ab79Smaybee 
17090a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zfsvfs), NULL, mtime, 16);
17100a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL, ctime, 16);
1711db9986c7SMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs),
1712db9986c7SMark Shellenbaum 	    NULL, &zp->z_pflags, 8);
17130a586ceaSMark Shellenbaum 	zfs_tstamp_update_setup(zp, CONTENT_MODIFIED, mtime, ctime, B_TRUE);
17140a586ceaSMark Shellenbaum 	error = sa_bulk_update(zp->z_sa_hdl, bulk, count, tx);
17150a586ceaSMark Shellenbaum 	ASSERT(error == 0);
17160a586ceaSMark Shellenbaum 
1717cdb0ab79Smaybee 	zfs_log_truncate(zilog, tx, TX_TRUNCATE, zp, off, len);
1718cdb0ab79Smaybee 
1719cdb0ab79Smaybee 	dmu_tx_commit(tx);
1720cdb0ab79Smaybee 	return (0);
1721cdb0ab79Smaybee }
1722cdb0ab79Smaybee 
1723fa9e4066Sahrens void
1724de8267e0Stimh zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx)
1725fa9e4066Sahrens {
1726fa9e4066Sahrens 	zfsvfs_t	zfsvfs;
17270a586ceaSMark Shellenbaum 	uint64_t	moid, obj, sa_obj, version;
1728de8267e0Stimh 	uint64_t	sense = ZFS_CASE_SENSITIVE;
1729de8267e0Stimh 	uint64_t	norm = 0;
1730de8267e0Stimh 	nvpair_t	*elem;
1731fa9e4066Sahrens 	int		error;
173259e7834dSMark Shellenbaum 	int		i;
1733fa9e4066Sahrens 	znode_t		*rootzp = NULL;
1734fa9e4066Sahrens 	vnode_t		*vp;
1735fa9e4066Sahrens 	vattr_t		vattr;
17364ccbb6e7Sahrens 	znode_t		*zp;
173789459e17SMark Shellenbaum 	zfs_acl_ids_t	acl_ids;
1738fa9e4066Sahrens 
1739fa9e4066Sahrens 	/*
1740fa9e4066Sahrens 	 * First attempt to create master node.
1741fa9e4066Sahrens 	 */
1742ea8dc4b6Seschrock 	/*
1743ea8dc4b6Seschrock 	 * In an empty objset, there are no blocks to read and thus
1744ea8dc4b6Seschrock 	 * there can be no i/o errors (which we assert below).
1745ea8dc4b6Seschrock 	 */
1746fa9e4066Sahrens 	moid = MASTER_NODE_OBJ;
1747fa9e4066Sahrens 	error = zap_create_claim(os, moid, DMU_OT_MASTER_NODE,
1748fa9e4066Sahrens 	    DMU_OT_NONE, 0, tx);
1749fa9e4066Sahrens 	ASSERT(error == 0);
1750fa9e4066Sahrens 
1751fa9e4066Sahrens 	/*
1752fa9e4066Sahrens 	 * Set starting attributes.
1753fa9e4066Sahrens 	 */
17540a586ceaSMark Shellenbaum 	version = zfs_zpl_version_map(spa_version(dmu_objset_spa(os)));
1755de8267e0Stimh 	elem = NULL;
1756de8267e0Stimh 	while ((elem = nvlist_next_nvpair(zplprops, elem)) != NULL) {
1757de8267e0Stimh 		/* For the moment we expect all zpl props to be uint64_ts */
1758de8267e0Stimh 		uint64_t val;
1759de8267e0Stimh 		char *name;
1760de8267e0Stimh 
1761de8267e0Stimh 		ASSERT(nvpair_type(elem) == DATA_TYPE_UINT64);
1762b3d911cbStimh 		VERIFY(nvpair_value_uint64(elem, &val) == 0);
1763de8267e0Stimh 		name = nvpair_name(elem);
1764de8267e0Stimh 		if (strcmp(name, zfs_prop_to_name(ZFS_PROP_VERSION)) == 0) {
176514843421SMatthew Ahrens 			if (val < version)
176614843421SMatthew Ahrens 				version = val;
1767de8267e0Stimh 		} else {
1768de8267e0Stimh 			error = zap_update(os, moid, name, 8, 1, &val, tx);
1769de8267e0Stimh 		}
1770de8267e0Stimh 		ASSERT(error == 0);
1771de8267e0Stimh 		if (strcmp(name, zfs_prop_to_name(ZFS_PROP_NORMALIZE)) == 0)
1772de8267e0Stimh 			norm = val;
1773de8267e0Stimh 		else if (strcmp(name, zfs_prop_to_name(ZFS_PROP_CASE)) == 0)
1774de8267e0Stimh 			sense = val;
1775de8267e0Stimh 	}
1776de8267e0Stimh 	ASSERT(version != 0);
177714843421SMatthew Ahrens 	error = zap_update(os, moid, ZPL_VERSION_STR, 8, 1, &version, tx);
1778fa9e4066Sahrens 
17790a586ceaSMark Shellenbaum 	/*
17800a586ceaSMark Shellenbaum 	 * Create zap object used for SA attribute registration
17810a586ceaSMark Shellenbaum 	 */
17820a586ceaSMark Shellenbaum 
17830a586ceaSMark Shellenbaum 	if (version >= ZPL_VERSION_SA) {
17840a586ceaSMark Shellenbaum 		sa_obj = zap_create(os, DMU_OT_SA_MASTER_NODE,
17850a586ceaSMark Shellenbaum 		    DMU_OT_NONE, 0, tx);
17860a586ceaSMark Shellenbaum 		error = zap_add(os, moid, ZFS_SA_ATTRS, 8, 1, &sa_obj, tx);
17870a586ceaSMark Shellenbaum 		ASSERT(error == 0);
17880a586ceaSMark Shellenbaum 	} else {
17890a586ceaSMark Shellenbaum 		sa_obj = 0;
17900a586ceaSMark Shellenbaum 	}
1791fa9e4066Sahrens 	/*
1792fa9e4066Sahrens 	 * Create a delete queue.
1793fa9e4066Sahrens 	 */
179414843421SMatthew Ahrens 	obj = zap_create(os, DMU_OT_UNLINKED_SET, DMU_OT_NONE, 0, tx);
1795fa9e4066Sahrens 
179614843421SMatthew Ahrens 	error = zap_add(os, moid, ZFS_UNLINKED_SET, 8, 1, &obj, tx);
1797fa9e4066Sahrens 	ASSERT(error == 0);
1798fa9e4066Sahrens 
1799fa9e4066Sahrens 	/*
1800fa9e4066Sahrens 	 * Create root znode.  Create minimal znode/vnode/zfsvfs
1801fa9e4066Sahrens 	 * to allow zfs_mknode to work.
1802fa9e4066Sahrens 	 */
1803fa9e4066Sahrens 	vattr.va_mask = AT_MODE|AT_UID|AT_GID|AT_TYPE;
1804fa9e4066Sahrens 	vattr.va_type = VDIR;
1805fa9e4066Sahrens 	vattr.va_mode = S_IFDIR|0755;
1806ecd6cf80Smarks 	vattr.va_uid = crgetuid(cr);
1807ecd6cf80Smarks 	vattr.va_gid = crgetgid(cr);
1808fa9e4066Sahrens 
1809fa9e4066Sahrens 	rootzp = kmem_cache_alloc(znode_cache, KM_SLEEP);
1810744947dcSTom Erickson 	ASSERT(!POINTER_IS_VALID(rootzp->z_zfsvfs));
1811744947dcSTom Erickson 	rootzp->z_moved = 0;
1812893a6d32Sahrens 	rootzp->z_unlinked = 0;
1813fa9e4066Sahrens 	rootzp->z_atime_dirty = 0;
18140a586ceaSMark Shellenbaum 	rootzp->z_is_sa = USE_SA(version, os);
1815fa9e4066Sahrens 
1816fa9e4066Sahrens 	vp = ZTOV(rootzp);
1817fa9e4066Sahrens 	vn_reinit(vp);
1818fa9e4066Sahrens 	vp->v_type = VDIR;
1819fa9e4066Sahrens 
1820fa9e4066Sahrens 	bzero(&zfsvfs, sizeof (zfsvfs_t));
1821fa9e4066Sahrens 
1822fa9e4066Sahrens 	zfsvfs.z_os = os;
1823fa9e4066Sahrens 	zfsvfs.z_parent = &zfsvfs;
1824da6c28aaSamw 	zfsvfs.z_version = version;
1825da6c28aaSamw 	zfsvfs.z_use_fuids = USE_FUIDS(version, os);
18260a586ceaSMark Shellenbaum 	zfsvfs.z_use_sa = USE_SA(version, os);
1827da6c28aaSamw 	zfsvfs.z_norm = norm;
18280a586ceaSMark Shellenbaum 
18291d8ccc7bSMark Shellenbaum 	error = sa_setup(os, sa_obj, zfs_attr_table, ZPL_END,
18301d8ccc7bSMark Shellenbaum 	    &zfsvfs.z_attr_table);
18311d8ccc7bSMark Shellenbaum 
18321d8ccc7bSMark Shellenbaum 	ASSERT(error == 0);
18330a586ceaSMark Shellenbaum 
1834de8267e0Stimh 	/*
1835de8267e0Stimh 	 * Fold case on file systems that are always or sometimes case
1836de8267e0Stimh 	 * insensitive.
1837de8267e0Stimh 	 */
1838de8267e0Stimh 	if (sense == ZFS_CASE_INSENSITIVE || sense == ZFS_CASE_MIXED)
1839de8267e0Stimh 		zfsvfs.z_norm |= U8_TEXTPREP_TOUPPER;
1840fa9e4066Sahrens 
1841fa9e4066Sahrens 	mutex_init(&zfsvfs.z_znodes_lock, NULL, MUTEX_DEFAULT, NULL);
1842fa9e4066Sahrens 	list_create(&zfsvfs.z_all_znodes, sizeof (znode_t),
1843fa9e4066Sahrens 	    offsetof(znode_t, z_link_node));
1844fa9e4066Sahrens 
184559e7834dSMark Shellenbaum 	for (i = 0; i != ZFS_OBJ_MTX_SZ; i++)
184659e7834dSMark Shellenbaum 		mutex_init(&zfsvfs.z_hold_mtx[i], NULL, MUTEX_DEFAULT, NULL);
184759e7834dSMark Shellenbaum 
1848b5fca8f8Stomee 	rootzp->z_zfsvfs = &zfsvfs;
184989459e17SMark Shellenbaum 	VERIFY(0 == zfs_acl_ids_create(rootzp, IS_ROOT_NODE, &vattr,
185089459e17SMark Shellenbaum 	    cr, NULL, &acl_ids));
18510a586ceaSMark Shellenbaum 	zfs_mknode(rootzp, &vattr, tx, cr, IS_ROOT_NODE, &zp, &acl_ids);
1852874395d5Smaybee 	ASSERT3P(zp, ==, rootzp);
1853b5fca8f8Stomee 	ASSERT(!vn_in_dnlc(ZTOV(rootzp))); /* not valid to move */
18544ccbb6e7Sahrens 	error = zap_add(os, moid, ZFS_ROOT_OBJ, 8, 1, &rootzp->z_id, tx);
1855fa9e4066Sahrens 	ASSERT(error == 0);
185689459e17SMark Shellenbaum 	zfs_acl_ids_free(&acl_ids);
1857b5fca8f8Stomee 	POINTER_INVALIDATE(&rootzp->z_zfsvfs);
1858fa9e4066Sahrens 
1859fa9e4066Sahrens 	ZTOV(rootzp)->v_count = 0;
18600a586ceaSMark Shellenbaum 	sa_handle_destroy(rootzp->z_sa_hdl);
1861fa9e4066Sahrens 	kmem_cache_free(znode_cache, rootzp);
1862743a77edSAlan Wright 
1863743a77edSAlan Wright 	/*
1864743a77edSAlan Wright 	 * Create shares directory
1865743a77edSAlan Wright 	 */
1866743a77edSAlan Wright 
1867743a77edSAlan Wright 	error = zfs_create_share_dir(&zfsvfs, tx);
186889459e17SMark Shellenbaum 
1869743a77edSAlan Wright 	ASSERT(error == 0);
187059e7834dSMark Shellenbaum 
187159e7834dSMark Shellenbaum 	for (i = 0; i != ZFS_OBJ_MTX_SZ; i++)
187259e7834dSMark Shellenbaum 		mutex_destroy(&zfsvfs.z_hold_mtx[i]);
1873fa9e4066Sahrens }
187455434c77Sek 
1875da6c28aaSamw #endif /* _KERNEL */
18760a586ceaSMark Shellenbaum 
187755434c77Sek static int
187899d5e173STim Haley zfs_sa_setup(objset_t *osp, sa_attr_type_t **sa_table)
187999d5e173STim Haley {
188099d5e173STim Haley 	uint64_t sa_obj = 0;
188199d5e173STim Haley 	int error;
188299d5e173STim Haley 
188399d5e173STim Haley 	error = zap_lookup(osp, MASTER_NODE_OBJ, ZFS_SA_ATTRS, 8, 1, &sa_obj);
188499d5e173STim Haley 	if (error != 0 && error != ENOENT)
188599d5e173STim Haley 		return (error);
188699d5e173STim Haley 
188799d5e173STim Haley 	error = sa_setup(osp, sa_obj, zfs_attr_table, ZPL_END, sa_table);
188899d5e173STim Haley 	return (error);
188999d5e173STim Haley }
189099d5e173STim Haley 
189199d5e173STim Haley static int
189299d5e173STim Haley zfs_grab_sa_handle(objset_t *osp, uint64_t obj, sa_handle_t **hdlp,
1893163eb7ffSTim Haley     dmu_buf_t **db, void *tag)
189455434c77Sek {
189555434c77Sek 	dmu_object_info_t doi;
189655434c77Sek 	int error;
18970a586ceaSMark Shellenbaum 
1898163eb7ffSTim Haley 	if ((error = sa_buf_hold(osp, obj, tag, db)) != 0)
189955434c77Sek 		return (error);
190055434c77Sek 
190199d5e173STim Haley 	dmu_object_info_from_db(*db, &doi);
19020a586ceaSMark Shellenbaum 	if ((doi.doi_bonus_type != DMU_OT_SA &&
19030a586ceaSMark Shellenbaum 	    doi.doi_bonus_type != DMU_OT_ZNODE) ||
19040a586ceaSMark Shellenbaum 	    doi.doi_bonus_type == DMU_OT_ZNODE &&
190555434c77Sek 	    doi.doi_bonus_size < sizeof (znode_phys_t)) {
1906163eb7ffSTim Haley 		sa_buf_rele(*db, tag);
1907be6fd75aSMatthew Ahrens 		return (SET_ERROR(ENOTSUP));
190855434c77Sek 	}
190955434c77Sek 
191099d5e173STim Haley 	error = sa_handle_get(osp, obj, NULL, SA_HDL_PRIVATE, hdlp);
191199d5e173STim Haley 	if (error != 0) {
1912163eb7ffSTim Haley 		sa_buf_rele(*db, tag);
19130a586ceaSMark Shellenbaum 		return (error);
19140a586ceaSMark Shellenbaum 	}
19150a586ceaSMark Shellenbaum 
191699d5e173STim Haley 	return (0);
191799d5e173STim Haley }
191899d5e173STim Haley 
191999d5e173STim Haley void
1920163eb7ffSTim Haley zfs_release_sa_handle(sa_handle_t *hdl, dmu_buf_t *db, void *tag)
192199d5e173STim Haley {
192299d5e173STim Haley 	sa_handle_destroy(hdl);
1923163eb7ffSTim Haley 	sa_buf_rele(db, tag);
192499d5e173STim Haley }
192599d5e173STim Haley 
192699d5e173STim Haley /*
192799d5e173STim Haley  * Given an object number, return its parent object number and whether
192899d5e173STim Haley  * or not the object is an extended attribute directory.
192999d5e173STim Haley  */
193099d5e173STim Haley static int
19311ce39b5fSJeremy Jones zfs_obj_to_pobj(objset_t *osp, sa_handle_t *hdl, sa_attr_type_t *sa_table,
19321ce39b5fSJeremy Jones     uint64_t *pobjp, int *is_xattrdir)
193399d5e173STim Haley {
193499d5e173STim Haley 	uint64_t parent;
193599d5e173STim Haley 	uint64_t pflags;
193699d5e173STim Haley 	uint64_t mode;
19371ce39b5fSJeremy Jones 	uint64_t parent_mode;
193899d5e173STim Haley 	sa_bulk_attr_t bulk[3];
19391ce39b5fSJeremy Jones 	sa_handle_t *sa_hdl;
19401ce39b5fSJeremy Jones 	dmu_buf_t *sa_db;
194199d5e173STim Haley 	int count = 0;
194299d5e173STim Haley 	int error;
194399d5e173STim Haley 
194499d5e173STim Haley 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_PARENT], NULL,
194599d5e173STim Haley 	    &parent, sizeof (parent));
19460a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_FLAGS], NULL,
194799d5e173STim Haley 	    &pflags, sizeof (pflags));
19480a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_MODE], NULL,
194999d5e173STim Haley 	    &mode, sizeof (mode));
19500a586ceaSMark Shellenbaum 
195199d5e173STim Haley 	if ((error = sa_bulk_lookup(hdl, bulk, count)) != 0)
19520a586ceaSMark Shellenbaum 		return (error);
195399d5e173STim Haley 
19541ce39b5fSJeremy Jones 	/*
19551ce39b5fSJeremy Jones 	 * When a link is removed its parent pointer is not changed and will
19561ce39b5fSJeremy Jones 	 * be invalid.  There are two cases where a link is removed but the
19571ce39b5fSJeremy Jones 	 * file stays around, when it goes to the delete queue and when there
19581ce39b5fSJeremy Jones 	 * are additional links.
19591ce39b5fSJeremy Jones 	 */
19601ce39b5fSJeremy Jones 	error = zfs_grab_sa_handle(osp, parent, &sa_hdl, &sa_db, FTAG);
19611ce39b5fSJeremy Jones 	if (error != 0)
19621ce39b5fSJeremy Jones 		return (error);
19631ce39b5fSJeremy Jones 
19641ce39b5fSJeremy Jones 	error = sa_lookup(sa_hdl, ZPL_MODE, &parent_mode, sizeof (parent_mode));
19651ce39b5fSJeremy Jones 	zfs_release_sa_handle(sa_hdl, sa_db, FTAG);
19661ce39b5fSJeremy Jones 	if (error != 0)
19671ce39b5fSJeremy Jones 		return (error);
19681ce39b5fSJeremy Jones 
19690a586ceaSMark Shellenbaum 	*is_xattrdir = ((pflags & ZFS_XATTR) != 0) && S_ISDIR(mode);
197055434c77Sek 
19711ce39b5fSJeremy Jones 	/*
19721ce39b5fSJeremy Jones 	 * Extended attributes can be applied to files, directories, etc.
19731ce39b5fSJeremy Jones 	 * Otherwise the parent must be a directory.
19741ce39b5fSJeremy Jones 	 */
19751ce39b5fSJeremy Jones 	if (!*is_xattrdir && !S_ISDIR(parent_mode))
1976be6fd75aSMatthew Ahrens 		return (SET_ERROR(EINVAL));
19771ce39b5fSJeremy Jones 
19781ce39b5fSJeremy Jones 	*pobjp = parent;
19791ce39b5fSJeremy Jones 
198055434c77Sek 	return (0);
198155434c77Sek }
198255434c77Sek 
198399d5e173STim Haley /*
198499d5e173STim Haley  * Given an object number, return some zpl level statistics
198599d5e173STim Haley  */
198699d5e173STim Haley static int
198799d5e173STim Haley zfs_obj_to_stats_impl(sa_handle_t *hdl, sa_attr_type_t *sa_table,
198899d5e173STim Haley     zfs_stat_t *sb)
198955434c77Sek {
199099d5e173STim Haley 	sa_bulk_attr_t bulk[4];
199199d5e173STim Haley 	int count = 0;
199299d5e173STim Haley 
199399d5e173STim Haley 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_MODE], NULL,
199499d5e173STim Haley 	    &sb->zs_mode, sizeof (sb->zs_mode));
199599d5e173STim Haley 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_GEN], NULL,
199699d5e173STim Haley 	    &sb->zs_gen, sizeof (sb->zs_gen));
199799d5e173STim Haley 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_LINKS], NULL,
199899d5e173STim Haley 	    &sb->zs_links, sizeof (sb->zs_links));
199999d5e173STim Haley 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_CTIME], NULL,
200099d5e173STim Haley 	    &sb->zs_ctime, sizeof (sb->zs_ctime));
200199d5e173STim Haley 
200299d5e173STim Haley 	return (sa_bulk_lookup(hdl, bulk, count));
200399d5e173STim Haley }
200499d5e173STim Haley 
200599d5e173STim Haley static int
200699d5e173STim Haley zfs_obj_to_path_impl(objset_t *osp, uint64_t obj, sa_handle_t *hdl,
200799d5e173STim Haley     sa_attr_type_t *sa_table, char *buf, int len)
200899d5e173STim Haley {
200999d5e173STim Haley 	sa_handle_t *sa_hdl;
201099d5e173STim Haley 	sa_handle_t *prevhdl = NULL;
201199d5e173STim Haley 	dmu_buf_t *prevdb = NULL;
201299d5e173STim Haley 	dmu_buf_t *sa_db = NULL;
201355434c77Sek 	char *path = buf + len - 1;
201455434c77Sek 	int error;
201555434c77Sek 
201655434c77Sek 	*path = '\0';
201799d5e173STim Haley 	sa_hdl = hdl;
20180a586ceaSMark Shellenbaum 
201955434c77Sek 	for (;;) {
202055434c77Sek 		uint64_t pobj;
202155434c77Sek 		char component[MAXNAMELEN + 2];
202255434c77Sek 		size_t complen;
202355434c77Sek 		int is_xattrdir;
202455434c77Sek 
202599d5e173STim Haley 		if (prevdb)
2026163eb7ffSTim Haley 			zfs_release_sa_handle(prevhdl, prevdb, FTAG);
202799d5e173STim Haley 
20281ce39b5fSJeremy Jones 		if ((error = zfs_obj_to_pobj(osp, sa_hdl, sa_table, &pobj,
202999d5e173STim Haley 		    &is_xattrdir)) != 0)
203055434c77Sek 			break;
203155434c77Sek 
203255434c77Sek 		if (pobj == obj) {
203355434c77Sek 			if (path[0] != '/')
203455434c77Sek 				*--path = '/';
203555434c77Sek 			break;
203655434c77Sek 		}
203755434c77Sek 
203855434c77Sek 		component[0] = '/';
203955434c77Sek 		if (is_xattrdir) {
204055434c77Sek 			(void) sprintf(component + 1, "<xattrdir>");
204155434c77Sek 		} else {
2042e7437265Sahrens 			error = zap_value_search(osp, pobj, obj,
2043e7437265Sahrens 			    ZFS_DIRENT_OBJ(-1ULL), component + 1);
204455434c77Sek 			if (error != 0)
204555434c77Sek 				break;
204655434c77Sek 		}
204755434c77Sek 
204855434c77Sek 		complen = strlen(component);
204955434c77Sek 		path -= complen;
205055434c77Sek 		ASSERT(path >= buf);
205155434c77Sek 		bcopy(component, path, complen);
205255434c77Sek 		obj = pobj;
205399d5e173STim Haley 
205499d5e173STim Haley 		if (sa_hdl != hdl) {
205599d5e173STim Haley 			prevhdl = sa_hdl;
205699d5e173STim Haley 			prevdb = sa_db;
205799d5e173STim Haley 		}
2058163eb7ffSTim Haley 		error = zfs_grab_sa_handle(osp, obj, &sa_hdl, &sa_db, FTAG);
205999d5e173STim Haley 		if (error != 0) {
206099d5e173STim Haley 			sa_hdl = prevhdl;
206199d5e173STim Haley 			sa_db = prevdb;
206299d5e173STim Haley 			break;
206399d5e173STim Haley 		}
206499d5e173STim Haley 	}
206599d5e173STim Haley 
206699d5e173STim Haley 	if (sa_hdl != NULL && sa_hdl != hdl) {
206799d5e173STim Haley 		ASSERT(sa_db != NULL);
2068163eb7ffSTim Haley 		zfs_release_sa_handle(sa_hdl, sa_db, FTAG);
206955434c77Sek 	}
207055434c77Sek 
207155434c77Sek 	if (error == 0)
207255434c77Sek 		(void) memmove(buf, path, buf + len - path);
20730a586ceaSMark Shellenbaum 
207455434c77Sek 	return (error);
207555434c77Sek }
207699d5e173STim Haley 
207799d5e173STim Haley int
207899d5e173STim Haley zfs_obj_to_path(objset_t *osp, uint64_t obj, char *buf, int len)
207999d5e173STim Haley {
208099d5e173STim Haley 	sa_attr_type_t *sa_table;
208199d5e173STim Haley 	sa_handle_t *hdl;
208299d5e173STim Haley 	dmu_buf_t *db;
208399d5e173STim Haley 	int error;
208499d5e173STim Haley 
208599d5e173STim Haley 	error = zfs_sa_setup(osp, &sa_table);
208699d5e173STim Haley 	if (error != 0)
208799d5e173STim Haley 		return (error);
208899d5e173STim Haley 
2089163eb7ffSTim Haley 	error = zfs_grab_sa_handle(osp, obj, &hdl, &db, FTAG);
209099d5e173STim Haley 	if (error != 0)
209199d5e173STim Haley 		return (error);
209299d5e173STim Haley 
209399d5e173STim Haley 	error = zfs_obj_to_path_impl(osp, obj, hdl, sa_table, buf, len);
209499d5e173STim Haley 
2095163eb7ffSTim Haley 	zfs_release_sa_handle(hdl, db, FTAG);
209699d5e173STim Haley 	return (error);
209799d5e173STim Haley }
209899d5e173STim Haley 
209999d5e173STim Haley int
210099d5e173STim Haley zfs_obj_to_stats(objset_t *osp, uint64_t obj, zfs_stat_t *sb,
210199d5e173STim Haley     char *buf, int len)
210299d5e173STim Haley {
210399d5e173STim Haley 	char *path = buf + len - 1;
210499d5e173STim Haley 	sa_attr_type_t *sa_table;
210599d5e173STim Haley 	sa_handle_t *hdl;
210699d5e173STim Haley 	dmu_buf_t *db;
210799d5e173STim Haley 	int error;
210899d5e173STim Haley 
210999d5e173STim Haley 	*path = '\0';
211099d5e173STim Haley 
211199d5e173STim Haley 	error = zfs_sa_setup(osp, &sa_table);
211299d5e173STim Haley 	if (error != 0)
211399d5e173STim Haley 		return (error);
211499d5e173STim Haley 
2115163eb7ffSTim Haley 	error = zfs_grab_sa_handle(osp, obj, &hdl, &db, FTAG);
211699d5e173STim Haley 	if (error != 0)
211799d5e173STim Haley 		return (error);
211899d5e173STim Haley 
211999d5e173STim Haley 	error = zfs_obj_to_stats_impl(hdl, sa_table, sb);
212099d5e173STim Haley 	if (error != 0) {
2121163eb7ffSTim Haley 		zfs_release_sa_handle(hdl, db, FTAG);
212299d5e173STim Haley 		return (error);
212399d5e173STim Haley 	}
212499d5e173STim Haley 
212599d5e173STim Haley 	error = zfs_obj_to_path_impl(osp, obj, hdl, sa_table, buf, len);
212699d5e173STim Haley 
2127163eb7ffSTim Haley 	zfs_release_sa_handle(hdl, db, FTAG);
212899d5e173STim Haley 	return (error);
212999d5e173STim Haley }
2130