xref: /illumos-gate/usr/src/uts/common/fs/zfs/zfs_znode.c (revision c3d26abc9ee97b4f60233556aadeb57e0bd30bb9)
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.
24*c3d26abcSMatthew Ahrens  * Copyright (c) 2014 Integros [integros.com]
25fa9e4066Sahrens  */
26fa9e4066Sahrens 
2775c76197Speteh /* Portions Copyright 2007 Jeremy Teo */
2875c76197Speteh 
2955434c77Sek #ifdef _KERNEL
30fa9e4066Sahrens #include <sys/types.h>
31fa9e4066Sahrens #include <sys/param.h>
32fa9e4066Sahrens #include <sys/time.h>
33fa9e4066Sahrens #include <sys/systm.h>
34fa9e4066Sahrens #include <sys/sysmacros.h>
35fa9e4066Sahrens #include <sys/resource.h>
36fa9e4066Sahrens #include <sys/mntent.h>
3772fc53bcSmarks #include <sys/mkdev.h>
38de8267e0Stimh #include <sys/u8_textprep.h>
39ab04eb8eStimh #include <sys/dsl_dataset.h>
40fa9e4066Sahrens #include <sys/vfs.h>
41aa59c4cbSrsb #include <sys/vfs_opreg.h>
42fa9e4066Sahrens #include <sys/vnode.h>
43fa9e4066Sahrens #include <sys/file.h>
44fa9e4066Sahrens #include <sys/kmem.h>
45fa9e4066Sahrens #include <sys/errno.h>
46fa9e4066Sahrens #include <sys/unistd.h>
47fa9e4066Sahrens #include <sys/mode.h>
48fa9e4066Sahrens #include <sys/atomic.h>
49fa9e4066Sahrens #include <vm/pvn.h>
50fa9e4066Sahrens #include "fs/fs_subr.h"
51fa9e4066Sahrens #include <sys/zfs_dir.h>
52fa9e4066Sahrens #include <sys/zfs_acl.h>
53fa9e4066Sahrens #include <sys/zfs_ioctl.h>
54104e2ed7Sperrin #include <sys/zfs_rlock.h>
55da6c28aaSamw #include <sys/zfs_fuid.h>
560a586ceaSMark Shellenbaum #include <sys/dnode.h>
57fa9e4066Sahrens #include <sys/fs/zfs.h>
58da6c28aaSamw #include <sys/kidmap.h>
5955434c77Sek #endif /* _KERNEL */
6055434c77Sek 
6155434c77Sek #include <sys/dmu.h>
62b5152584SMatthew Ahrens #include <sys/dmu_objset.h>
6355434c77Sek #include <sys/refcount.h>
6455434c77Sek #include <sys/stat.h>
6555434c77Sek #include <sys/zap.h>
6655434c77Sek #include <sys/zfs_znode.h>
670a586ceaSMark Shellenbaum #include <sys/sa.h>
680a586ceaSMark Shellenbaum #include <sys/zfs_sa.h>
6999d5e173STim Haley #include <sys/zfs_stat.h>
70fa9e4066Sahrens 
71de8267e0Stimh #include "zfs_prop.h"
720a586ceaSMark Shellenbaum #include "zfs_comutil.h"
73de8267e0Stimh 
74b5fca8f8Stomee /*
75b5fca8f8Stomee  * Define ZNODE_STATS to turn on statistic gathering. By default, it is only
76b5fca8f8Stomee  * turned on when DEBUG is also defined.
77b5fca8f8Stomee  */
78b5fca8f8Stomee #ifdef	DEBUG
79b5fca8f8Stomee #define	ZNODE_STATS
80b5fca8f8Stomee #endif	/* DEBUG */
81b5fca8f8Stomee 
82b5fca8f8Stomee #ifdef	ZNODE_STATS
83b5fca8f8Stomee #define	ZNODE_STAT_ADD(stat)			((stat)++)
84b5fca8f8Stomee #else
85b5fca8f8Stomee #define	ZNODE_STAT_ADD(stat)			/* nothing */
86b5fca8f8Stomee #endif	/* ZNODE_STATS */
87b5fca8f8Stomee 
8855434c77Sek /*
8955434c77Sek  * Functions needed for userland (ie: libzpool) are not put under
9055434c77Sek  * #ifdef_KERNEL; the rest of the functions have dependencies
9155434c77Sek  * (such as VFS logic) that will not compile easily in userland.
9255434c77Sek  */
9355434c77Sek #ifdef _KERNEL
944e9583b2STom Erickson /*
954e9583b2STom Erickson  * Needed to close a small window in zfs_znode_move() that allows the zfsvfs to
964e9583b2STom Erickson  * be freed before it can be safely accessed.
974e9583b2STom Erickson  */
984e9583b2STom Erickson krwlock_t zfsvfs_lock;
994e9583b2STom Erickson 
100b5fca8f8Stomee static kmem_cache_t *znode_cache = NULL;
101fa9e4066Sahrens 
102fa9e4066Sahrens /*ARGSUSED*/
103fa9e4066Sahrens static void
104874395d5Smaybee znode_evict_error(dmu_buf_t *dbuf, void *user_ptr)
105fa9e4066Sahrens {
106874395d5Smaybee 	/*
107874395d5Smaybee 	 * We should never drop all dbuf refs without first clearing
108874395d5Smaybee 	 * the eviction callback.
109874395d5Smaybee 	 */
110874395d5Smaybee 	panic("evicting znode %p\n", user_ptr);
111fa9e4066Sahrens }
112fa9e4066Sahrens 
113fa9e4066Sahrens /*ARGSUSED*/
114fa9e4066Sahrens static int
115b5fca8f8Stomee zfs_znode_cache_constructor(void *buf, void *arg, int kmflags)
116fa9e4066Sahrens {
117fa9e4066Sahrens 	znode_t *zp = buf;
118fa9e4066Sahrens 
119b5fca8f8Stomee 	ASSERT(!POINTER_IS_VALID(zp->z_zfsvfs));
120b5fca8f8Stomee 
121b5fca8f8Stomee 	zp->z_vnode = vn_alloc(kmflags);
122b5fca8f8Stomee 	if (zp->z_vnode == NULL) {
123b5fca8f8Stomee 		return (-1);
124b5fca8f8Stomee 	}
125b5fca8f8Stomee 	ZTOV(zp)->v_data = zp;
126b5fca8f8Stomee 
127b5fca8f8Stomee 	list_link_init(&zp->z_link_node);
128b5fca8f8Stomee 
129fa9e4066Sahrens 	mutex_init(&zp->z_lock, NULL, MUTEX_DEFAULT, NULL);
130104e2ed7Sperrin 	rw_init(&zp->z_parent_lock, NULL, RW_DEFAULT, NULL);
131af2c4821Smaybee 	rw_init(&zp->z_name_lock, NULL, RW_DEFAULT, NULL);
132fa9e4066Sahrens 	mutex_init(&zp->z_acl_lock, NULL, MUTEX_DEFAULT, NULL);
133104e2ed7Sperrin 
134104e2ed7Sperrin 	mutex_init(&zp->z_range_lock, NULL, MUTEX_DEFAULT, NULL);
135104e2ed7Sperrin 	avl_create(&zp->z_range_avl, zfs_range_compare,
136104e2ed7Sperrin 	    sizeof (rl_t), offsetof(rl_t, r_node));
137104e2ed7Sperrin 
138b5fca8f8Stomee 	zp->z_dirlocks = NULL;
139d47621a4STim Haley 	zp->z_acl_cached = NULL;
140744947dcSTom Erickson 	zp->z_moved = 0;
141fa9e4066Sahrens 	return (0);
142fa9e4066Sahrens }
143fa9e4066Sahrens 
144fa9e4066Sahrens /*ARGSUSED*/
145fa9e4066Sahrens static void
146b5fca8f8Stomee zfs_znode_cache_destructor(void *buf, void *arg)
147fa9e4066Sahrens {
148fa9e4066Sahrens 	znode_t *zp = buf;
149fa9e4066Sahrens 
150b5fca8f8Stomee 	ASSERT(!POINTER_IS_VALID(zp->z_zfsvfs));
151b5fca8f8Stomee 	ASSERT(ZTOV(zp)->v_data == zp);
152b5fca8f8Stomee 	vn_free(ZTOV(zp));
153b5fca8f8Stomee 	ASSERT(!list_link_active(&zp->z_link_node));
154fa9e4066Sahrens 	mutex_destroy(&zp->z_lock);
155104e2ed7Sperrin 	rw_destroy(&zp->z_parent_lock);
156af2c4821Smaybee 	rw_destroy(&zp->z_name_lock);
157fa9e4066Sahrens 	mutex_destroy(&zp->z_acl_lock);
158104e2ed7Sperrin 	avl_destroy(&zp->z_range_avl);
159c25056deSgw 	mutex_destroy(&zp->z_range_lock);
160fa9e4066Sahrens 
161b5fca8f8Stomee 	ASSERT(zp->z_dirlocks == NULL);
1624929fd5eSTim Haley 	ASSERT(zp->z_acl_cached == NULL);
163b5fca8f8Stomee }
164b5fca8f8Stomee 
165b5fca8f8Stomee #ifdef	ZNODE_STATS
166b5fca8f8Stomee static struct {
167b5fca8f8Stomee 	uint64_t zms_zfsvfs_invalid;
1684e9583b2STom Erickson 	uint64_t zms_zfsvfs_recheck1;
169b5fca8f8Stomee 	uint64_t zms_zfsvfs_unmounted;
1704e9583b2STom Erickson 	uint64_t zms_zfsvfs_recheck2;
171a66b2b35STom Erickson 	uint64_t zms_obj_held;
172b5fca8f8Stomee 	uint64_t zms_vnode_locked;
173a66b2b35STom Erickson 	uint64_t zms_not_only_dnlc;
174b5fca8f8Stomee } znode_move_stats;
175b5fca8f8Stomee #endif	/* ZNODE_STATS */
176b5fca8f8Stomee 
177b5fca8f8Stomee static void
178b5fca8f8Stomee zfs_znode_move_impl(znode_t *ozp, znode_t *nzp)
179b5fca8f8Stomee {
180b5fca8f8Stomee 	vnode_t *vp;
181b5fca8f8Stomee 
182b5fca8f8Stomee 	/* Copy fields. */
183b5fca8f8Stomee 	nzp->z_zfsvfs = ozp->z_zfsvfs;
184b5fca8f8Stomee 
185b5fca8f8Stomee 	/* Swap vnodes. */
186b5fca8f8Stomee 	vp = nzp->z_vnode;
187b5fca8f8Stomee 	nzp->z_vnode = ozp->z_vnode;
188b5fca8f8Stomee 	ozp->z_vnode = vp; /* let destructor free the overwritten vnode */
189b5fca8f8Stomee 	ZTOV(ozp)->v_data = ozp;
190b5fca8f8Stomee 	ZTOV(nzp)->v_data = nzp;
191b5fca8f8Stomee 
192b5fca8f8Stomee 	nzp->z_id = ozp->z_id;
193b5fca8f8Stomee 	ASSERT(ozp->z_dirlocks == NULL); /* znode not in use */
194b5fca8f8Stomee 	ASSERT(avl_numnodes(&ozp->z_range_avl) == 0);
195b5fca8f8Stomee 	nzp->z_unlinked = ozp->z_unlinked;
196b5fca8f8Stomee 	nzp->z_atime_dirty = ozp->z_atime_dirty;
197b5fca8f8Stomee 	nzp->z_zn_prefetch = ozp->z_zn_prefetch;
198b5fca8f8Stomee 	nzp->z_blksz = ozp->z_blksz;
199b5fca8f8Stomee 	nzp->z_seq = ozp->z_seq;
200b5fca8f8Stomee 	nzp->z_mapcnt = ozp->z_mapcnt;
201b5fca8f8Stomee 	nzp->z_gen = ozp->z_gen;
202b5fca8f8Stomee 	nzp->z_sync_cnt = ozp->z_sync_cnt;
2030a586ceaSMark Shellenbaum 	nzp->z_is_sa = ozp->z_is_sa;
2040a586ceaSMark Shellenbaum 	nzp->z_sa_hdl = ozp->z_sa_hdl;
2050a586ceaSMark Shellenbaum 	bcopy(ozp->z_atime, nzp->z_atime, sizeof (uint64_t) * 2);
2060a586ceaSMark Shellenbaum 	nzp->z_links = ozp->z_links;
2070a586ceaSMark Shellenbaum 	nzp->z_size = ozp->z_size;
2080a586ceaSMark Shellenbaum 	nzp->z_pflags = ozp->z_pflags;
2090a586ceaSMark Shellenbaum 	nzp->z_uid = ozp->z_uid;
2100a586ceaSMark Shellenbaum 	nzp->z_gid = ozp->z_gid;
2110a586ceaSMark Shellenbaum 	nzp->z_mode = ozp->z_mode;
212d98a6232SMark Shellenbaum 
213d98a6232SMark Shellenbaum 	/*
2146638ae1dSMark Shellenbaum 	 * Since this is just an idle znode and kmem is already dealing with
2156638ae1dSMark Shellenbaum 	 * memory pressure, release any cached ACL.
216d98a6232SMark Shellenbaum 	 */
217d98a6232SMark Shellenbaum 	if (ozp->z_acl_cached) {
218d98a6232SMark Shellenbaum 		zfs_acl_free(ozp->z_acl_cached);
219d98a6232SMark Shellenbaum 		ozp->z_acl_cached = NULL;
220d98a6232SMark Shellenbaum 	}
221b5fca8f8Stomee 
2220a586ceaSMark Shellenbaum 	sa_set_userp(nzp->z_sa_hdl, nzp);
223b5fca8f8Stomee 
224b5fca8f8Stomee 	/*
225b5fca8f8Stomee 	 * Invalidate the original znode by clearing fields that provide a
226b5fca8f8Stomee 	 * pointer back to the znode. Set the low bit of the vfs pointer to
227b5fca8f8Stomee 	 * ensure that zfs_znode_move() recognizes the znode as invalid in any
228b5fca8f8Stomee 	 * subsequent callback.
229b5fca8f8Stomee 	 */
2300a586ceaSMark Shellenbaum 	ozp->z_sa_hdl = NULL;
231b5fca8f8Stomee 	POINTER_INVALIDATE(&ozp->z_zfsvfs);
232744947dcSTom Erickson 
233744947dcSTom Erickson 	/*
234744947dcSTom Erickson 	 * Mark the znode.
235744947dcSTom Erickson 	 */
236744947dcSTom Erickson 	nzp->z_moved = 1;
237744947dcSTom Erickson 	ozp->z_moved = (uint8_t)-1;
238b5fca8f8Stomee }
239b5fca8f8Stomee 
240b5fca8f8Stomee /*ARGSUSED*/
241b5fca8f8Stomee static kmem_cbrc_t
242b5fca8f8Stomee zfs_znode_move(void *buf, void *newbuf, size_t size, void *arg)
243b5fca8f8Stomee {
244b5fca8f8Stomee 	znode_t *ozp = buf, *nzp = newbuf;
245b5fca8f8Stomee 	zfsvfs_t *zfsvfs;
246b5fca8f8Stomee 	vnode_t *vp;
247b5fca8f8Stomee 
248b5fca8f8Stomee 	/*
249b5fca8f8Stomee 	 * The znode is on the file system's list of known znodes if the vfs
250b5fca8f8Stomee 	 * pointer is valid. We set the low bit of the vfs pointer when freeing
251b5fca8f8Stomee 	 * the znode to invalidate it, and the memory patterns written by kmem
252b5fca8f8Stomee 	 * (baddcafe and deadbeef) set at least one of the two low bits. A newly
253b5fca8f8Stomee 	 * created znode sets the vfs pointer last of all to indicate that the
254b5fca8f8Stomee 	 * znode is known and in a valid state to be moved by this function.
255b5fca8f8Stomee 	 */
256b5fca8f8Stomee 	zfsvfs = ozp->z_zfsvfs;
257b5fca8f8Stomee 	if (!POINTER_IS_VALID(zfsvfs)) {
258b5fca8f8Stomee 		ZNODE_STAT_ADD(znode_move_stats.zms_zfsvfs_invalid);
259b5fca8f8Stomee 		return (KMEM_CBRC_DONT_KNOW);
260b5fca8f8Stomee 	}
261b5fca8f8Stomee 
262b5fca8f8Stomee 	/*
2634e9583b2STom Erickson 	 * Close a small window in which it's possible that the filesystem could
2644e9583b2STom Erickson 	 * be unmounted and freed, and zfsvfs, though valid in the previous
2654e9583b2STom Erickson 	 * statement, could point to unrelated memory by the time we try to
2664e9583b2STom Erickson 	 * prevent the filesystem from being unmounted.
2674e9583b2STom Erickson 	 */
2684e9583b2STom Erickson 	rw_enter(&zfsvfs_lock, RW_WRITER);
2694e9583b2STom Erickson 	if (zfsvfs != ozp->z_zfsvfs) {
2704e9583b2STom Erickson 		rw_exit(&zfsvfs_lock);
2714e9583b2STom Erickson 		ZNODE_STAT_ADD(znode_move_stats.zms_zfsvfs_recheck1);
2724e9583b2STom Erickson 		return (KMEM_CBRC_DONT_KNOW);
2734e9583b2STom Erickson 	}
2744e9583b2STom Erickson 
2754e9583b2STom Erickson 	/*
2764e9583b2STom Erickson 	 * If the znode is still valid, then so is the file system. We know that
2774e9583b2STom Erickson 	 * no valid file system can be freed while we hold zfsvfs_lock, so we
2784e9583b2STom Erickson 	 * can safely ensure that the filesystem is not and will not be
2794e9583b2STom Erickson 	 * unmounted. The next statement is equivalent to ZFS_ENTER().
280b5fca8f8Stomee 	 */
281c9030f6cSAlexander Motin 	rrm_enter(&zfsvfs->z_teardown_lock, RW_READER, FTAG);
28214843421SMatthew Ahrens 	if (zfsvfs->z_unmounted) {
28314843421SMatthew Ahrens 		ZFS_EXIT(zfsvfs);
2844e9583b2STom Erickson 		rw_exit(&zfsvfs_lock);
285b5fca8f8Stomee 		ZNODE_STAT_ADD(znode_move_stats.zms_zfsvfs_unmounted);
286b5fca8f8Stomee 		return (KMEM_CBRC_DONT_KNOW);
287b5fca8f8Stomee 	}
2884e9583b2STom Erickson 	rw_exit(&zfsvfs_lock);
289b5fca8f8Stomee 
290b5fca8f8Stomee 	mutex_enter(&zfsvfs->z_znodes_lock);
291b5fca8f8Stomee 	/*
292b5fca8f8Stomee 	 * Recheck the vfs pointer in case the znode was removed just before
293b5fca8f8Stomee 	 * acquiring the lock.
294b5fca8f8Stomee 	 */
295b5fca8f8Stomee 	if (zfsvfs != ozp->z_zfsvfs) {
296b5fca8f8Stomee 		mutex_exit(&zfsvfs->z_znodes_lock);
297b5fca8f8Stomee 		ZFS_EXIT(zfsvfs);
2984e9583b2STom Erickson 		ZNODE_STAT_ADD(znode_move_stats.zms_zfsvfs_recheck2);
299b5fca8f8Stomee 		return (KMEM_CBRC_DONT_KNOW);
300b5fca8f8Stomee 	}
301b5fca8f8Stomee 
302b5fca8f8Stomee 	/*
303b5fca8f8Stomee 	 * At this point we know that as long as we hold z_znodes_lock, the
304b5fca8f8Stomee 	 * znode cannot be freed and fields within the znode can be safely
305a66b2b35STom Erickson 	 * accessed. Now, prevent a race with zfs_zget().
306b5fca8f8Stomee 	 */
307a66b2b35STom Erickson 	if (ZFS_OBJ_HOLD_TRYENTER(zfsvfs, ozp->z_id) == 0) {
308a66b2b35STom Erickson 		mutex_exit(&zfsvfs->z_znodes_lock);
309a66b2b35STom Erickson 		ZFS_EXIT(zfsvfs);
310a66b2b35STom Erickson 		ZNODE_STAT_ADD(znode_move_stats.zms_obj_held);
311a66b2b35STom Erickson 		return (KMEM_CBRC_LATER);
312a66b2b35STom Erickson 	}
313a66b2b35STom Erickson 
314b5fca8f8Stomee 	vp = ZTOV(ozp);
315b5fca8f8Stomee 	if (mutex_tryenter(&vp->v_lock) == 0) {
316a66b2b35STom Erickson 		ZFS_OBJ_HOLD_EXIT(zfsvfs, ozp->z_id);
317b5fca8f8Stomee 		mutex_exit(&zfsvfs->z_znodes_lock);
318b5fca8f8Stomee 		ZFS_EXIT(zfsvfs);
319b5fca8f8Stomee 		ZNODE_STAT_ADD(znode_move_stats.zms_vnode_locked);
320b5fca8f8Stomee 		return (KMEM_CBRC_LATER);
321b5fca8f8Stomee 	}
322a66b2b35STom Erickson 
323b5fca8f8Stomee 	/* Only move znodes that are referenced _only_ by the DNLC. */
324b5fca8f8Stomee 	if (vp->v_count != 1 || !vn_in_dnlc(vp)) {
325b5fca8f8Stomee 		mutex_exit(&vp->v_lock);
326a66b2b35STom Erickson 		ZFS_OBJ_HOLD_EXIT(zfsvfs, ozp->z_id);
327b5fca8f8Stomee 		mutex_exit(&zfsvfs->z_znodes_lock);
328b5fca8f8Stomee 		ZFS_EXIT(zfsvfs);
329a66b2b35STom Erickson 		ZNODE_STAT_ADD(znode_move_stats.zms_not_only_dnlc);
330b5fca8f8Stomee 		return (KMEM_CBRC_LATER);
331b5fca8f8Stomee 	}
332b5fca8f8Stomee 
333b5fca8f8Stomee 	/*
334b5fca8f8Stomee 	 * The znode is known and in a valid state to move. We're holding the
335b5fca8f8Stomee 	 * locks needed to execute the critical section.
336b5fca8f8Stomee 	 */
337b5fca8f8Stomee 	zfs_znode_move_impl(ozp, nzp);
338b5fca8f8Stomee 	mutex_exit(&vp->v_lock);
339a66b2b35STom Erickson 	ZFS_OBJ_HOLD_EXIT(zfsvfs, ozp->z_id);
340b5fca8f8Stomee 
341b5fca8f8Stomee 	list_link_replace(&ozp->z_link_node, &nzp->z_link_node);
342b5fca8f8Stomee 	mutex_exit(&zfsvfs->z_znodes_lock);
343b5fca8f8Stomee 	ZFS_EXIT(zfsvfs);
344b5fca8f8Stomee 
345b5fca8f8Stomee 	return (KMEM_CBRC_YES);
346fa9e4066Sahrens }
347fa9e4066Sahrens 
348fa9e4066Sahrens void
349fa9e4066Sahrens zfs_znode_init(void)
350fa9e4066Sahrens {
351fa9e4066Sahrens 	/*
352fa9e4066Sahrens 	 * Initialize zcache
353fa9e4066Sahrens 	 */
3544e9583b2STom Erickson 	rw_init(&zfsvfs_lock, NULL, RW_DEFAULT, NULL);
355fa9e4066Sahrens 	ASSERT(znode_cache == NULL);
356fa9e4066Sahrens 	znode_cache = kmem_cache_create("zfs_znode_cache",
357fa9e4066Sahrens 	    sizeof (znode_t), 0, zfs_znode_cache_constructor,
358fa9e4066Sahrens 	    zfs_znode_cache_destructor, NULL, NULL, NULL, 0);
359b5fca8f8Stomee 	kmem_cache_set_move(znode_cache, zfs_znode_move);
360fa9e4066Sahrens }
361fa9e4066Sahrens 
362fa9e4066Sahrens void
363fa9e4066Sahrens zfs_znode_fini(void)
364fa9e4066Sahrens {
365fa9e4066Sahrens 	/*
366fa9e4066Sahrens 	 * Cleanup vfs & vnode ops
367fa9e4066Sahrens 	 */
368fa9e4066Sahrens 	zfs_remove_op_tables();
369fa9e4066Sahrens 
370fa9e4066Sahrens 	/*
371fa9e4066Sahrens 	 * Cleanup zcache
372fa9e4066Sahrens 	 */
373fa9e4066Sahrens 	if (znode_cache)
374fa9e4066Sahrens 		kmem_cache_destroy(znode_cache);
375fa9e4066Sahrens 	znode_cache = NULL;
3764e9583b2STom Erickson 	rw_destroy(&zfsvfs_lock);
377fa9e4066Sahrens }
378fa9e4066Sahrens 
379fa9e4066Sahrens struct vnodeops *zfs_dvnodeops;
380fa9e4066Sahrens struct vnodeops *zfs_fvnodeops;
381fa9e4066Sahrens struct vnodeops *zfs_symvnodeops;
382fa9e4066Sahrens struct vnodeops *zfs_xdvnodeops;
383fa9e4066Sahrens struct vnodeops *zfs_evnodeops;
384743a77edSAlan Wright struct vnodeops *zfs_sharevnodeops;
385fa9e4066Sahrens 
386fa9e4066Sahrens void
387fa9e4066Sahrens zfs_remove_op_tables()
388fa9e4066Sahrens {
389fa9e4066Sahrens 	/*
390fa9e4066Sahrens 	 * Remove vfs ops
391fa9e4066Sahrens 	 */
392fa9e4066Sahrens 	ASSERT(zfsfstype);
393fa9e4066Sahrens 	(void) vfs_freevfsops_by_type(zfsfstype);
394fa9e4066Sahrens 	zfsfstype = 0;
395fa9e4066Sahrens 
396fa9e4066Sahrens 	/*
397fa9e4066Sahrens 	 * Remove vnode ops
398fa9e4066Sahrens 	 */
399fa9e4066Sahrens 	if (zfs_dvnodeops)
400fa9e4066Sahrens 		vn_freevnodeops(zfs_dvnodeops);
401fa9e4066Sahrens 	if (zfs_fvnodeops)
402fa9e4066Sahrens 		vn_freevnodeops(zfs_fvnodeops);
403fa9e4066Sahrens 	if (zfs_symvnodeops)
404fa9e4066Sahrens 		vn_freevnodeops(zfs_symvnodeops);
405fa9e4066Sahrens 	if (zfs_xdvnodeops)
406fa9e4066Sahrens 		vn_freevnodeops(zfs_xdvnodeops);
407fa9e4066Sahrens 	if (zfs_evnodeops)
408fa9e4066Sahrens 		vn_freevnodeops(zfs_evnodeops);
409743a77edSAlan Wright 	if (zfs_sharevnodeops)
410743a77edSAlan Wright 		vn_freevnodeops(zfs_sharevnodeops);
411fa9e4066Sahrens 
412fa9e4066Sahrens 	zfs_dvnodeops = NULL;
413fa9e4066Sahrens 	zfs_fvnodeops = NULL;
414fa9e4066Sahrens 	zfs_symvnodeops = NULL;
415fa9e4066Sahrens 	zfs_xdvnodeops = NULL;
416fa9e4066Sahrens 	zfs_evnodeops = NULL;
417743a77edSAlan Wright 	zfs_sharevnodeops = NULL;
418fa9e4066Sahrens }
419fa9e4066Sahrens 
420fa9e4066Sahrens extern const fs_operation_def_t zfs_dvnodeops_template[];
421fa9e4066Sahrens extern const fs_operation_def_t zfs_fvnodeops_template[];
422fa9e4066Sahrens extern const fs_operation_def_t zfs_xdvnodeops_template[];
423fa9e4066Sahrens extern const fs_operation_def_t zfs_symvnodeops_template[];
424fa9e4066Sahrens extern const fs_operation_def_t zfs_evnodeops_template[];
425743a77edSAlan Wright extern const fs_operation_def_t zfs_sharevnodeops_template[];
426fa9e4066Sahrens 
427fa9e4066Sahrens int
428fa9e4066Sahrens zfs_create_op_tables()
429fa9e4066Sahrens {
430fa9e4066Sahrens 	int error;
431fa9e4066Sahrens 
432fa9e4066Sahrens 	/*
433fa9e4066Sahrens 	 * zfs_dvnodeops can be set if mod_remove() calls mod_installfs()
434fa9e4066Sahrens 	 * due to a failure to remove the the 2nd modlinkage (zfs_modldrv).
435fa9e4066Sahrens 	 * In this case we just return as the ops vectors are already set up.
436fa9e4066Sahrens 	 */
437fa9e4066Sahrens 	if (zfs_dvnodeops)
438fa9e4066Sahrens 		return (0);
439fa9e4066Sahrens 
440fa9e4066Sahrens 	error = vn_make_ops(MNTTYPE_ZFS, zfs_dvnodeops_template,
441fa9e4066Sahrens 	    &zfs_dvnodeops);
442fa9e4066Sahrens 	if (error)
443fa9e4066Sahrens 		return (error);
444fa9e4066Sahrens 
445fa9e4066Sahrens 	error = vn_make_ops(MNTTYPE_ZFS, zfs_fvnodeops_template,
446fa9e4066Sahrens 	    &zfs_fvnodeops);
447fa9e4066Sahrens 	if (error)
448fa9e4066Sahrens 		return (error);
449fa9e4066Sahrens 
450fa9e4066Sahrens 	error = vn_make_ops(MNTTYPE_ZFS, zfs_symvnodeops_template,
451fa9e4066Sahrens 	    &zfs_symvnodeops);
452fa9e4066Sahrens 	if (error)
453fa9e4066Sahrens 		return (error);
454fa9e4066Sahrens 
455fa9e4066Sahrens 	error = vn_make_ops(MNTTYPE_ZFS, zfs_xdvnodeops_template,
456fa9e4066Sahrens 	    &zfs_xdvnodeops);
457fa9e4066Sahrens 	if (error)
458fa9e4066Sahrens 		return (error);
459fa9e4066Sahrens 
460fa9e4066Sahrens 	error = vn_make_ops(MNTTYPE_ZFS, zfs_evnodeops_template,
461fa9e4066Sahrens 	    &zfs_evnodeops);
462743a77edSAlan Wright 	if (error)
463743a77edSAlan Wright 		return (error);
464743a77edSAlan Wright 
465743a77edSAlan Wright 	error = vn_make_ops(MNTTYPE_ZFS, zfs_sharevnodeops_template,
466743a77edSAlan Wright 	    &zfs_sharevnodeops);
467743a77edSAlan Wright 
468743a77edSAlan Wright 	return (error);
469743a77edSAlan Wright }
470743a77edSAlan Wright 
4719e1320c0SMark Shellenbaum int
472743a77edSAlan Wright zfs_create_share_dir(zfsvfs_t *zfsvfs, dmu_tx_t *tx)
473743a77edSAlan Wright {
47489459e17SMark Shellenbaum 	zfs_acl_ids_t acl_ids;
475743a77edSAlan Wright 	vattr_t vattr;
476743a77edSAlan Wright 	znode_t *sharezp;
477743a77edSAlan Wright 	vnode_t *vp;
478743a77edSAlan Wright 	znode_t *zp;
479743a77edSAlan Wright 	int error;
480743a77edSAlan Wright 
481743a77edSAlan Wright 	vattr.va_mask = AT_MODE|AT_UID|AT_GID|AT_TYPE;
482743a77edSAlan Wright 	vattr.va_type = VDIR;
483743a77edSAlan Wright 	vattr.va_mode = S_IFDIR|0555;
484743a77edSAlan Wright 	vattr.va_uid = crgetuid(kcred);
485743a77edSAlan Wright 	vattr.va_gid = crgetgid(kcred);
486743a77edSAlan Wright 
487743a77edSAlan Wright 	sharezp = kmem_cache_alloc(znode_cache, KM_SLEEP);
488744947dcSTom Erickson 	ASSERT(!POINTER_IS_VALID(sharezp->z_zfsvfs));
489744947dcSTom Erickson 	sharezp->z_moved = 0;
490743a77edSAlan Wright 	sharezp->z_unlinked = 0;
491743a77edSAlan Wright 	sharezp->z_atime_dirty = 0;
492743a77edSAlan Wright 	sharezp->z_zfsvfs = zfsvfs;
4930a586ceaSMark Shellenbaum 	sharezp->z_is_sa = zfsvfs->z_use_sa;
494743a77edSAlan Wright 
495743a77edSAlan Wright 	vp = ZTOV(sharezp);
496743a77edSAlan Wright 	vn_reinit(vp);
497743a77edSAlan Wright 	vp->v_type = VDIR;
498743a77edSAlan Wright 
49989459e17SMark Shellenbaum 	VERIFY(0 == zfs_acl_ids_create(sharezp, IS_ROOT_NODE, &vattr,
50089459e17SMark Shellenbaum 	    kcred, NULL, &acl_ids));
5010a586ceaSMark Shellenbaum 	zfs_mknode(sharezp, &vattr, tx, kcred, IS_ROOT_NODE, &zp, &acl_ids);
502743a77edSAlan Wright 	ASSERT3P(zp, ==, sharezp);
503743a77edSAlan Wright 	ASSERT(!vn_in_dnlc(ZTOV(sharezp))); /* not valid to move */
504743a77edSAlan Wright 	POINTER_INVALIDATE(&sharezp->z_zfsvfs);
505743a77edSAlan Wright 	error = zap_add(zfsvfs->z_os, MASTER_NODE_OBJ,
506743a77edSAlan Wright 	    ZFS_SHARES_DIR, 8, 1, &sharezp->z_id, tx);
507743a77edSAlan Wright 	zfsvfs->z_shares_dir = sharezp->z_id;
508743a77edSAlan Wright 
50989459e17SMark Shellenbaum 	zfs_acl_ids_free(&acl_ids);
510743a77edSAlan Wright 	ZTOV(sharezp)->v_count = 0;
5110a586ceaSMark Shellenbaum 	sa_handle_destroy(sharezp->z_sa_hdl);
512743a77edSAlan Wright 	kmem_cache_free(znode_cache, sharezp);
513fa9e4066Sahrens 
514fa9e4066Sahrens 	return (error);
515fa9e4066Sahrens }
516fa9e4066Sahrens 
51772fc53bcSmarks /*
51872fc53bcSmarks  * define a couple of values we need available
51972fc53bcSmarks  * for both 64 and 32 bit environments.
52072fc53bcSmarks  */
52172fc53bcSmarks #ifndef NBITSMINOR64
52272fc53bcSmarks #define	NBITSMINOR64	32
52372fc53bcSmarks #endif
52472fc53bcSmarks #ifndef MAXMAJ64
52572fc53bcSmarks #define	MAXMAJ64	0xffffffffUL
52672fc53bcSmarks #endif
52772fc53bcSmarks #ifndef	MAXMIN64
52872fc53bcSmarks #define	MAXMIN64	0xffffffffUL
52972fc53bcSmarks #endif
53072fc53bcSmarks 
53172fc53bcSmarks /*
53272fc53bcSmarks  * Create special expldev for ZFS private use.
53372fc53bcSmarks  * Can't use standard expldev since it doesn't do
53472fc53bcSmarks  * what we want.  The standard expldev() takes a
53572fc53bcSmarks  * dev32_t in LP64 and expands it to a long dev_t.
53672fc53bcSmarks  * We need an interface that takes a dev32_t in ILP32
53772fc53bcSmarks  * and expands it to a long dev_t.
53872fc53bcSmarks  */
53972fc53bcSmarks static uint64_t
54072fc53bcSmarks zfs_expldev(dev_t dev)
54172fc53bcSmarks {
54272fc53bcSmarks #ifndef _LP64
54372fc53bcSmarks 	major_t major = (major_t)dev >> NBITSMINOR32 & MAXMAJ32;
54472fc53bcSmarks 	return (((uint64_t)major << NBITSMINOR64) |
54572fc53bcSmarks 	    ((minor_t)dev & MAXMIN32));
54672fc53bcSmarks #else
54772fc53bcSmarks 	return (dev);
54872fc53bcSmarks #endif
54972fc53bcSmarks }
55072fc53bcSmarks 
55172fc53bcSmarks /*
55272fc53bcSmarks  * Special cmpldev for ZFS private use.
55372fc53bcSmarks  * Can't use standard cmpldev since it takes
55472fc53bcSmarks  * a long dev_t and compresses it to dev32_t in
55572fc53bcSmarks  * LP64.  We need to do a compaction of a long dev_t
55672fc53bcSmarks  * to a dev32_t in ILP32.
55772fc53bcSmarks  */
55872fc53bcSmarks dev_t
55972fc53bcSmarks zfs_cmpldev(uint64_t dev)
56072fc53bcSmarks {
56172fc53bcSmarks #ifndef _LP64
56272fc53bcSmarks 	minor_t minor = (minor_t)dev & MAXMIN64;
56372fc53bcSmarks 	major_t major = (major_t)(dev >> NBITSMINOR64) & MAXMAJ64;
56472fc53bcSmarks 
56572fc53bcSmarks 	if (major > MAXMAJ32 || minor > MAXMIN32)
56672fc53bcSmarks 		return (NODEV32);
56772fc53bcSmarks 
56872fc53bcSmarks 	return (((dev32_t)major << NBITSMINOR32) | minor);
56972fc53bcSmarks #else
57072fc53bcSmarks 	return (dev);
57172fc53bcSmarks #endif
57272fc53bcSmarks }
57372fc53bcSmarks 
5744ccbb6e7Sahrens static void
5750a586ceaSMark Shellenbaum zfs_znode_sa_init(zfsvfs_t *zfsvfs, znode_t *zp,
5760a586ceaSMark Shellenbaum     dmu_buf_t *db, dmu_object_type_t obj_type, sa_handle_t *sa_hdl)
5774ccbb6e7Sahrens {
578b5fca8f8Stomee 	ASSERT(!POINTER_IS_VALID(zp->z_zfsvfs) || (zfsvfs == zp->z_zfsvfs));
579b5fca8f8Stomee 	ASSERT(MUTEX_HELD(ZFS_OBJ_MUTEX(zfsvfs, zp->z_id)));
5804ccbb6e7Sahrens 
5814ccbb6e7Sahrens 	mutex_enter(&zp->z_lock);
5824ccbb6e7Sahrens 
5830a586ceaSMark Shellenbaum 	ASSERT(zp->z_sa_hdl == NULL);
5846638ae1dSMark Shellenbaum 	ASSERT(zp->z_acl_cached == NULL);
5850a586ceaSMark Shellenbaum 	if (sa_hdl == NULL) {
5860a586ceaSMark Shellenbaum 		VERIFY(0 == sa_handle_get_from_db(zfsvfs->z_os, db, zp,
5870a586ceaSMark Shellenbaum 		    SA_HDL_SHARED, &zp->z_sa_hdl));
5880a586ceaSMark Shellenbaum 	} else {
5890a586ceaSMark Shellenbaum 		zp->z_sa_hdl = sa_hdl;
5900a586ceaSMark Shellenbaum 		sa_set_userp(sa_hdl, zp);
5910a586ceaSMark Shellenbaum 	}
5924ccbb6e7Sahrens 
5930a586ceaSMark Shellenbaum 	zp->z_is_sa = (obj_type == DMU_OT_SA) ? B_TRUE : B_FALSE;
5944ccbb6e7Sahrens 
5954ccbb6e7Sahrens 	/*
5964ccbb6e7Sahrens 	 * Slap on VROOT if we are the root znode
5974ccbb6e7Sahrens 	 */
5984ccbb6e7Sahrens 	if (zp->z_id == zfsvfs->z_root)
5994ccbb6e7Sahrens 		ZTOV(zp)->v_flag |= VROOT;
6004ccbb6e7Sahrens 
6014ccbb6e7Sahrens 	mutex_exit(&zp->z_lock);
6024ccbb6e7Sahrens 	vn_exists(ZTOV(zp));
6034ccbb6e7Sahrens }
6044ccbb6e7Sahrens 
605874395d5Smaybee void
6064ccbb6e7Sahrens zfs_znode_dmu_fini(znode_t *zp)
6074ccbb6e7Sahrens {
608b5fca8f8Stomee 	ASSERT(MUTEX_HELD(ZFS_OBJ_MUTEX(zp->z_zfsvfs, zp->z_id)) ||
609b5fca8f8Stomee 	    zp->z_unlinked ||
610874395d5Smaybee 	    RW_WRITE_HELD(&zp->z_zfsvfs->z_teardown_inactive_lock));
6110a586ceaSMark Shellenbaum 
6120a586ceaSMark Shellenbaum 	sa_handle_destroy(zp->z_sa_hdl);
6130a586ceaSMark Shellenbaum 	zp->z_sa_hdl = NULL;
6144ccbb6e7Sahrens }
6154ccbb6e7Sahrens 
616fa9e4066Sahrens /*
617fa9e4066Sahrens  * Construct a new znode/vnode and intialize.
618fa9e4066Sahrens  *
619fa9e4066Sahrens  * This does not do a call to dmu_set_user() that is
620fa9e4066Sahrens  * up to the caller to do, in case you don't want to
621fa9e4066Sahrens  * return the znode
622fa9e4066Sahrens  */
623ea8dc4b6Seschrock static znode_t *
6240a586ceaSMark Shellenbaum zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
6250a586ceaSMark Shellenbaum     dmu_object_type_t obj_type, sa_handle_t *hdl)
626fa9e4066Sahrens {
627fa9e4066Sahrens 	znode_t	*zp;
628fa9e4066Sahrens 	vnode_t *vp;
6290a586ceaSMark Shellenbaum 	uint64_t mode;
6300a586ceaSMark Shellenbaum 	uint64_t parent;
6310a586ceaSMark Shellenbaum 	sa_bulk_attr_t bulk[9];
6320a586ceaSMark Shellenbaum 	int count = 0;
633fa9e4066Sahrens 
634fa9e4066Sahrens 	zp = kmem_cache_alloc(znode_cache, KM_SLEEP);
635fa9e4066Sahrens 
636fa9e4066Sahrens 	ASSERT(zp->z_dirlocks == NULL);
637b5fca8f8Stomee 	ASSERT(!POINTER_IS_VALID(zp->z_zfsvfs));
638744947dcSTom Erickson 	zp->z_moved = 0;
639fa9e4066Sahrens 
640b5fca8f8Stomee 	/*
641b5fca8f8Stomee 	 * Defer setting z_zfsvfs until the znode is ready to be a candidate for
642b5fca8f8Stomee 	 * the zfs_znode_move() callback.
643b5fca8f8Stomee 	 */
6440a586ceaSMark Shellenbaum 	zp->z_sa_hdl = NULL;
645893a6d32Sahrens 	zp->z_unlinked = 0;
646fa9e4066Sahrens 	zp->z_atime_dirty = 0;
647fa9e4066Sahrens 	zp->z_mapcnt = 0;
6484ccbb6e7Sahrens 	zp->z_id = db->db_object;
649fa9e4066Sahrens 	zp->z_blksz = blksz;
650fa9e4066Sahrens 	zp->z_seq = 0x7A4653;
65167bd71c6Sperrin 	zp->z_sync_cnt = 0;
6524ccbb6e7Sahrens 
6534ccbb6e7Sahrens 	vp = ZTOV(zp);
6544ccbb6e7Sahrens 	vn_reinit(vp);
6554ccbb6e7Sahrens 
6560a586ceaSMark Shellenbaum 	zfs_znode_sa_init(zfsvfs, zp, db, obj_type, hdl);
6570a586ceaSMark Shellenbaum 
6580a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zfsvfs), NULL, &mode, 8);
6590a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GEN(zfsvfs), NULL, &zp->z_gen, 8);
6600a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(zfsvfs), NULL,
6610a586ceaSMark Shellenbaum 	    &zp->z_size, 8);
6620a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_LINKS(zfsvfs), NULL,
6630a586ceaSMark Shellenbaum 	    &zp->z_links, 8);
6640a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), NULL,
6650a586ceaSMark Shellenbaum 	    &zp->z_pflags, 8);
6660a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_PARENT(zfsvfs), NULL, &parent, 8);
6670a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ATIME(zfsvfs), NULL,
6680a586ceaSMark Shellenbaum 	    &zp->z_atime, 16);
6690a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_UID(zfsvfs), NULL,
670f1696b23SMark Shellenbaum 	    &zp->z_uid, 8);
6710a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GID(zfsvfs), NULL,
672f1696b23SMark Shellenbaum 	    &zp->z_gid, 8);
6730a586ceaSMark Shellenbaum 
6740a586ceaSMark Shellenbaum 	if (sa_bulk_lookup(zp->z_sa_hdl, bulk, count) != 0 || zp->z_gen == 0) {
6750a586ceaSMark Shellenbaum 		if (hdl == NULL)
6760a586ceaSMark Shellenbaum 			sa_handle_destroy(zp->z_sa_hdl);
6770a586ceaSMark Shellenbaum 		kmem_cache_free(znode_cache, zp);
6780a586ceaSMark Shellenbaum 		return (NULL);
6790a586ceaSMark Shellenbaum 	}
680fa9e4066Sahrens 
6810a586ceaSMark Shellenbaum 	zp->z_mode = mode;
682fa9e4066Sahrens 	vp->v_vfsp = zfsvfs->z_parent->z_vfs;
6830a586ceaSMark Shellenbaum 
6840a586ceaSMark Shellenbaum 	vp->v_type = IFTOVT((mode_t)mode);
685fa9e4066Sahrens 
686fa9e4066Sahrens 	switch (vp->v_type) {
687fa9e4066Sahrens 	case VDIR:
6880a586ceaSMark Shellenbaum 		if (zp->z_pflags & ZFS_XATTR) {
689fa9e4066Sahrens 			vn_setops(vp, zfs_xdvnodeops);
690fa9e4066Sahrens 			vp->v_flag |= V_XATTRDIR;
6914ccbb6e7Sahrens 		} else {
692fa9e4066Sahrens 			vn_setops(vp, zfs_dvnodeops);
6934ccbb6e7Sahrens 		}
6947f6e3e7dSperrin 		zp->z_zn_prefetch = B_TRUE; /* z_prefetch default is enabled */
695fa9e4066Sahrens 		break;
696fa9e4066Sahrens 	case VBLK:
697fa9e4066Sahrens 	case VCHR:
6980a586ceaSMark Shellenbaum 		{
6990a586ceaSMark Shellenbaum 			uint64_t rdev;
7000a586ceaSMark Shellenbaum 			VERIFY(sa_lookup(zp->z_sa_hdl, SA_ZPL_RDEV(zfsvfs),
7010a586ceaSMark Shellenbaum 			    &rdev, sizeof (rdev)) == 0);
7020a586ceaSMark Shellenbaum 
7030a586ceaSMark Shellenbaum 			vp->v_rdev = zfs_cmpldev(rdev);
7040a586ceaSMark Shellenbaum 		}
705fa9e4066Sahrens 		/*FALLTHROUGH*/
706fa9e4066Sahrens 	case VFIFO:
707fa9e4066Sahrens 	case VSOCK:
708fa9e4066Sahrens 	case VDOOR:
709fa9e4066Sahrens 		vn_setops(vp, zfs_fvnodeops);
710fa9e4066Sahrens 		break;
711fa9e4066Sahrens 	case VREG:
712fa9e4066Sahrens 		vp->v_flag |= VMODSORT;
7130a586ceaSMark Shellenbaum 		if (parent == zfsvfs->z_shares_dir) {
714f1696b23SMark Shellenbaum 			ASSERT(zp->z_uid == 0 && zp->z_gid == 0);
715743a77edSAlan Wright 			vn_setops(vp, zfs_sharevnodeops);
7160a586ceaSMark Shellenbaum 		} else {
717743a77edSAlan Wright 			vn_setops(vp, zfs_fvnodeops);
7180a586ceaSMark Shellenbaum 		}
719fa9e4066Sahrens 		break;
720fa9e4066Sahrens 	case VLNK:
721fa9e4066Sahrens 		vn_setops(vp, zfs_symvnodeops);
722fa9e4066Sahrens 		break;
723fa9e4066Sahrens 	default:
724fa9e4066Sahrens 		vn_setops(vp, zfs_evnodeops);
725fa9e4066Sahrens 		break;
726fa9e4066Sahrens 	}
727fa9e4066Sahrens 
728b5fca8f8Stomee 	mutex_enter(&zfsvfs->z_znodes_lock);
729b5fca8f8Stomee 	list_insert_tail(&zfsvfs->z_all_znodes, zp);
730b5fca8f8Stomee 	membar_producer();
731b5fca8f8Stomee 	/*
732b5fca8f8Stomee 	 * Everything else must be valid before assigning z_zfsvfs makes the
733b5fca8f8Stomee 	 * znode eligible for zfs_znode_move().
734b5fca8f8Stomee 	 */
735b5fca8f8Stomee 	zp->z_zfsvfs = zfsvfs;
736b5fca8f8Stomee 	mutex_exit(&zfsvfs->z_znodes_lock);
737b5fca8f8Stomee 
738874395d5Smaybee 	VFS_HOLD(zfsvfs->z_vfs);
739fa9e4066Sahrens 	return (zp);
740fa9e4066Sahrens }
741fa9e4066Sahrens 
7420a586ceaSMark Shellenbaum static uint64_t empty_xattr;
7430a586ceaSMark Shellenbaum static uint64_t pad[4];
7440a586ceaSMark Shellenbaum static zfs_acl_phys_t acl_phys;
745fa9e4066Sahrens /*
746fa9e4066Sahrens  * Create a new DMU object to hold a zfs znode.
747fa9e4066Sahrens  *
748fa9e4066Sahrens  *	IN:	dzp	- parent directory for new znode
749fa9e4066Sahrens  *		vap	- file attributes for new znode
750fa9e4066Sahrens  *		tx	- dmu transaction id for zap operations
751fa9e4066Sahrens  *		cr	- credentials of caller
752fa9e4066Sahrens  *		flag	- flags:
753fa9e4066Sahrens  *			  IS_ROOT_NODE	- new object will be root
754fa9e4066Sahrens  *			  IS_XATTR	- new object is an attribute
755da6c28aaSamw  *		bonuslen - length of bonus buffer
756da6c28aaSamw  *		setaclp  - File/Dir initial ACL
757da6c28aaSamw  *		fuidp	 - Tracks fuid allocation.
758fa9e4066Sahrens  *
7594ccbb6e7Sahrens  *	OUT:	zpp	- allocated znode
760fa9e4066Sahrens  *
761fa9e4066Sahrens  */
762fa9e4066Sahrens void
7634ccbb6e7Sahrens zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr,
7640a586ceaSMark Shellenbaum     uint_t flag, znode_t **zpp, zfs_acl_ids_t *acl_ids)
765fa9e4066Sahrens {
7660a586ceaSMark Shellenbaum 	uint64_t	crtime[2], atime[2], mtime[2], ctime[2];
7670a586ceaSMark Shellenbaum 	uint64_t	mode, size, links, parent, pflags;
768744947dcSTom Erickson 	uint64_t	dzp_pflags = 0;
7690a586ceaSMark Shellenbaum 	uint64_t	rdev = 0;
770fa9e4066Sahrens 	zfsvfs_t	*zfsvfs = dzp->z_zfsvfs;
7710a586ceaSMark Shellenbaum 	dmu_buf_t	*db;
772fa9e4066Sahrens 	timestruc_t	now;
7734ccbb6e7Sahrens 	uint64_t	gen, obj;
7740a586ceaSMark Shellenbaum 	int		bonuslen;
7750a586ceaSMark Shellenbaum 	sa_handle_t	*sa_hdl;
7760a586ceaSMark Shellenbaum 	dmu_object_type_t obj_type;
7770a586ceaSMark Shellenbaum 	sa_bulk_attr_t	sa_attrs[ZPL_END];
7780a586ceaSMark Shellenbaum 	int		cnt = 0;
7790a586ceaSMark Shellenbaum 	zfs_acl_locator_cb_t locate = { 0 };
780fa9e4066Sahrens 
781fa9e4066Sahrens 	ASSERT(vap && (vap->va_mask & (AT_TYPE|AT_MODE)) == (AT_TYPE|AT_MODE));
782fa9e4066Sahrens 
7831209a471SNeil Perrin 	if (zfsvfs->z_replay) {
7844ccbb6e7Sahrens 		obj = vap->va_nodeid;
785fa9e4066Sahrens 		now = vap->va_ctime;		/* see zfs_replay_create() */
786fa9e4066Sahrens 		gen = vap->va_nblocks;		/* ditto */
787fa9e4066Sahrens 	} else {
7884ccbb6e7Sahrens 		obj = 0;
789fa9e4066Sahrens 		gethrestime(&now);
790fa9e4066Sahrens 		gen = dmu_tx_get_txg(tx);
791fa9e4066Sahrens 	}
792fa9e4066Sahrens 
7930a586ceaSMark Shellenbaum 	obj_type = zfsvfs->z_use_sa ? DMU_OT_SA : DMU_OT_ZNODE;
7940a586ceaSMark Shellenbaum 	bonuslen = (obj_type == DMU_OT_SA) ?
7950a586ceaSMark Shellenbaum 	    DN_MAX_BONUSLEN : ZFS_OLD_ZNODE_PHYS_SIZE;
7960a586ceaSMark Shellenbaum 
797fa9e4066Sahrens 	/*
798fa9e4066Sahrens 	 * Create a new DMU object.
799fa9e4066Sahrens 	 */
800ea8dc4b6Seschrock 	/*
801ea8dc4b6Seschrock 	 * There's currently no mechanism for pre-reading the blocks that will
802744947dcSTom Erickson 	 * be needed to allocate a new object, so we accept the small chance
803ea8dc4b6Seschrock 	 * that there will be an i/o error and we will fail one of the
804ea8dc4b6Seschrock 	 * assertions below.
805ea8dc4b6Seschrock 	 */
806fa9e4066Sahrens 	if (vap->va_type == VDIR) {
8074a1f0cc9SMark Shellenbaum 		if (zfsvfs->z_replay) {
80843466aaeSMax Grossman 			VERIFY0(zap_create_claim_norm(zfsvfs->z_os, obj,
809da6c28aaSamw 			    zfsvfs->z_norm, DMU_OT_DIRECTORY_CONTENTS,
81043466aaeSMax Grossman 			    obj_type, bonuslen, tx));
811fa9e4066Sahrens 		} else {
8124ccbb6e7Sahrens 			obj = zap_create_norm(zfsvfs->z_os,
813da6c28aaSamw 			    zfsvfs->z_norm, DMU_OT_DIRECTORY_CONTENTS,
8140a586ceaSMark Shellenbaum 			    obj_type, bonuslen, tx);
815fa9e4066Sahrens 		}
816fa9e4066Sahrens 	} else {
8174a1f0cc9SMark Shellenbaum 		if (zfsvfs->z_replay) {
81843466aaeSMax Grossman 			VERIFY0(dmu_object_claim(zfsvfs->z_os, obj,
819fa9e4066Sahrens 			    DMU_OT_PLAIN_FILE_CONTENTS, 0,
82043466aaeSMax Grossman 			    obj_type, bonuslen, tx));
821fa9e4066Sahrens 		} else {
8224ccbb6e7Sahrens 			obj = dmu_object_alloc(zfsvfs->z_os,
823fa9e4066Sahrens 			    DMU_OT_PLAIN_FILE_CONTENTS, 0,
8240a586ceaSMark Shellenbaum 			    obj_type, bonuslen, tx);
825fa9e4066Sahrens 		}
826fa9e4066Sahrens 	}
82759e7834dSMark Shellenbaum 
82859e7834dSMark Shellenbaum 	ZFS_OBJ_HOLD_ENTER(zfsvfs, obj);
8290a586ceaSMark Shellenbaum 	VERIFY(0 == sa_buf_hold(zfsvfs->z_os, obj, NULL, &db));
830fa9e4066Sahrens 
831fa9e4066Sahrens 	/*
832fa9e4066Sahrens 	 * If this is the root, fix up the half-initialized parent pointer
833fa9e4066Sahrens 	 * to reference the just-allocated physical data area.
834fa9e4066Sahrens 	 */
835fa9e4066Sahrens 	if (flag & IS_ROOT_NODE) {
8364ccbb6e7Sahrens 		dzp->z_id = obj;
8370a586ceaSMark Shellenbaum 	} else {
8380a586ceaSMark Shellenbaum 		dzp_pflags = dzp->z_pflags;
839fa9e4066Sahrens 	}
840fa9e4066Sahrens 
841fa9e4066Sahrens 	/*
842fa9e4066Sahrens 	 * If parent is an xattr, so am I.
843fa9e4066Sahrens 	 */
8440a586ceaSMark Shellenbaum 	if (dzp_pflags & ZFS_XATTR) {
845fa9e4066Sahrens 		flag |= IS_XATTR;
846fa9e4066Sahrens 	}
847fa9e4066Sahrens 
848da6c28aaSamw 	if (zfsvfs->z_use_fuids)
8490a586ceaSMark Shellenbaum 		pflags = ZFS_ARCHIVE | ZFS_AV_MODIFIED;
8500a586ceaSMark Shellenbaum 	else
8510a586ceaSMark Shellenbaum 		pflags = 0;
852da6c28aaSamw 
853fa9e4066Sahrens 	if (vap->va_type == VDIR) {
8540a586ceaSMark Shellenbaum 		size = 2;		/* contents ("." and "..") */
8550a586ceaSMark Shellenbaum 		links = (flag & (IS_ROOT_NODE | IS_XATTR)) ? 2 : 1;
8560a586ceaSMark Shellenbaum 	} else {
8570a586ceaSMark Shellenbaum 		size = links = 0;
8580a586ceaSMark Shellenbaum 	}
8590a586ceaSMark Shellenbaum 
8600a586ceaSMark Shellenbaum 	if (vap->va_type == VBLK || vap->va_type == VCHR) {
8610a586ceaSMark Shellenbaum 		rdev = zfs_expldev(vap->va_rdev);
862fa9e4066Sahrens 	}
863fa9e4066Sahrens 
8640a586ceaSMark Shellenbaum 	parent = dzp->z_id;
8650a586ceaSMark Shellenbaum 	mode = acl_ids->z_mode;
866fa9e4066Sahrens 	if (flag & IS_XATTR)
8670a586ceaSMark Shellenbaum 		pflags |= ZFS_XATTR;
868fa9e4066Sahrens 
8690a586ceaSMark Shellenbaum 	/*
8700a586ceaSMark Shellenbaum 	 * No execs denied will be deterimed when zfs_mode_compute() is called.
8710a586ceaSMark Shellenbaum 	 */
8720a586ceaSMark Shellenbaum 	pflags |= acl_ids->z_aclp->z_hints &
8730a586ceaSMark Shellenbaum 	    (ZFS_ACL_TRIVIAL|ZFS_INHERIT_ACE|ZFS_ACL_AUTO_INHERIT|
8740a586ceaSMark Shellenbaum 	    ZFS_ACL_DEFAULTED|ZFS_ACL_PROTECTED);
875fa9e4066Sahrens 
8760a586ceaSMark Shellenbaum 	ZFS_TIME_ENCODE(&now, crtime);
8770a586ceaSMark Shellenbaum 	ZFS_TIME_ENCODE(&now, ctime);
878fa9e4066Sahrens 
879fa9e4066Sahrens 	if (vap->va_mask & AT_ATIME) {
8800a586ceaSMark Shellenbaum 		ZFS_TIME_ENCODE(&vap->va_atime, atime);
881fa9e4066Sahrens 	} else {
8820a586ceaSMark Shellenbaum 		ZFS_TIME_ENCODE(&now, atime);
883fa9e4066Sahrens 	}
884fa9e4066Sahrens 
885fa9e4066Sahrens 	if (vap->va_mask & AT_MTIME) {
8860a586ceaSMark Shellenbaum 		ZFS_TIME_ENCODE(&vap->va_mtime, mtime);
8870a586ceaSMark Shellenbaum 	} else {
8880a586ceaSMark Shellenbaum 		ZFS_TIME_ENCODE(&now, mtime);
8890a586ceaSMark Shellenbaum 	}
8900a586ceaSMark Shellenbaum 
8910a586ceaSMark Shellenbaum 	/* Now add in all of the "SA" attributes */
8920a586ceaSMark Shellenbaum 	VERIFY(0 == sa_handle_get_from_db(zfsvfs->z_os, db, NULL, SA_HDL_SHARED,
8930a586ceaSMark Shellenbaum 	    &sa_hdl));
8940a586ceaSMark Shellenbaum 
8950a586ceaSMark Shellenbaum 	/*
8960a586ceaSMark Shellenbaum 	 * Setup the array of attributes to be replaced/set on the new file
8970a586ceaSMark Shellenbaum 	 *
8980a586ceaSMark Shellenbaum 	 * order for  DMU_OT_ZNODE is critical since it needs to be constructed
8990a586ceaSMark Shellenbaum 	 * in the old znode_phys_t format.  Don't change this ordering
9000a586ceaSMark Shellenbaum 	 */
9010a586ceaSMark Shellenbaum 
9020a586ceaSMark Shellenbaum 	if (obj_type == DMU_OT_ZNODE) {
9030a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_ATIME(zfsvfs),
9040a586ceaSMark Shellenbaum 		    NULL, &atime, 16);
9050a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_MTIME(zfsvfs),
9060a586ceaSMark Shellenbaum 		    NULL, &mtime, 16);
9070a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_CTIME(zfsvfs),
9080a586ceaSMark Shellenbaum 		    NULL, &ctime, 16);
9090a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_CRTIME(zfsvfs),
9100a586ceaSMark Shellenbaum 		    NULL, &crtime, 16);
9110a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_GEN(zfsvfs),
9120a586ceaSMark Shellenbaum 		    NULL, &gen, 8);
9130a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_MODE(zfsvfs),
9140a586ceaSMark Shellenbaum 		    NULL, &mode, 8);
9150a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_SIZE(zfsvfs),
9160a586ceaSMark Shellenbaum 		    NULL, &size, 8);
9170a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_PARENT(zfsvfs),
9180a586ceaSMark Shellenbaum 		    NULL, &parent, 8);
919fa9e4066Sahrens 	} else {
9200a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_MODE(zfsvfs),
9210a586ceaSMark Shellenbaum 		    NULL, &mode, 8);
9220a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_SIZE(zfsvfs),
9230a586ceaSMark Shellenbaum 		    NULL, &size, 8);
9240a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_GEN(zfsvfs),
9250a586ceaSMark Shellenbaum 		    NULL, &gen, 8);
9260a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_UID(zfsvfs), NULL,
9270a586ceaSMark Shellenbaum 		    &acl_ids->z_fuid, 8);
9280a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_GID(zfsvfs), NULL,
9290a586ceaSMark Shellenbaum 		    &acl_ids->z_fgid, 8);
9300a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_PARENT(zfsvfs),
9310a586ceaSMark Shellenbaum 		    NULL, &parent, 8);
9320a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_FLAGS(zfsvfs),
9330a586ceaSMark Shellenbaum 		    NULL, &pflags, 8);
9340a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_ATIME(zfsvfs),
9350a586ceaSMark Shellenbaum 		    NULL, &atime, 16);
9360a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_MTIME(zfsvfs),
9370a586ceaSMark Shellenbaum 		    NULL, &mtime, 16);
9380a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_CTIME(zfsvfs),
9390a586ceaSMark Shellenbaum 		    NULL, &ctime, 16);
9400a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_CRTIME(zfsvfs),
9410a586ceaSMark Shellenbaum 		    NULL, &crtime, 16);
9420a586ceaSMark Shellenbaum 	}
9430a586ceaSMark Shellenbaum 
9440a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_LINKS(zfsvfs), NULL, &links, 8);
9450a586ceaSMark Shellenbaum 
9460a586ceaSMark Shellenbaum 	if (obj_type == DMU_OT_ZNODE) {
9470a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_XATTR(zfsvfs), NULL,
9480a586ceaSMark Shellenbaum 		    &empty_xattr, 8);
9490a586ceaSMark Shellenbaum 	}
9500a586ceaSMark Shellenbaum 	if (obj_type == DMU_OT_ZNODE ||
9510a586ceaSMark Shellenbaum 	    (vap->va_type == VBLK || vap->va_type == VCHR)) {
9520a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_RDEV(zfsvfs),
9530a586ceaSMark Shellenbaum 		    NULL, &rdev, 8);
9540a586ceaSMark Shellenbaum 
955fa9e4066Sahrens 	}
9560a586ceaSMark Shellenbaum 	if (obj_type == DMU_OT_ZNODE) {
9570a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_FLAGS(zfsvfs),
9580a586ceaSMark Shellenbaum 		    NULL, &pflags, 8);
9590a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_UID(zfsvfs), NULL,
9600a586ceaSMark Shellenbaum 		    &acl_ids->z_fuid, 8);
9610a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_GID(zfsvfs), NULL,
9620a586ceaSMark Shellenbaum 		    &acl_ids->z_fgid, 8);
9630a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_PAD(zfsvfs), NULL, pad,
9640a586ceaSMark Shellenbaum 		    sizeof (uint64_t) * 4);
9650a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_ZNODE_ACL(zfsvfs), NULL,
9660a586ceaSMark Shellenbaum 		    &acl_phys, sizeof (zfs_acl_phys_t));
9670a586ceaSMark Shellenbaum 	} else if (acl_ids->z_aclp->z_version >= ZFS_ACL_VERSION_FUID) {
9680a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_DACL_COUNT(zfsvfs), NULL,
9690a586ceaSMark Shellenbaum 		    &acl_ids->z_aclp->z_acl_count, 8);
9700a586ceaSMark Shellenbaum 		locate.cb_aclp = acl_ids->z_aclp;
9710a586ceaSMark Shellenbaum 		SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_DACL_ACES(zfsvfs),
9720a586ceaSMark Shellenbaum 		    zfs_acl_data_locator, &locate,
9730a586ceaSMark Shellenbaum 		    acl_ids->z_aclp->z_acl_bytes);
97427dd1e87SMark Shellenbaum 		mode = zfs_mode_compute(mode, acl_ids->z_aclp, &pflags,
97527dd1e87SMark Shellenbaum 		    acl_ids->z_fuid, acl_ids->z_fgid);
9760a586ceaSMark Shellenbaum 	}
9770a586ceaSMark Shellenbaum 
9780a586ceaSMark Shellenbaum 	VERIFY(sa_replace_all_by_template(sa_hdl, sa_attrs, cnt, tx) == 0);
9790a586ceaSMark Shellenbaum 
980874395d5Smaybee 	if (!(flag & IS_ROOT_NODE)) {
9810a586ceaSMark Shellenbaum 		*zpp = zfs_znode_alloc(zfsvfs, db, 0, obj_type, sa_hdl);
9820a586ceaSMark Shellenbaum 		ASSERT(*zpp != NULL);
983874395d5Smaybee 	} else {
984874395d5Smaybee 		/*
985874395d5Smaybee 		 * If we are creating the root node, the "parent" we
986874395d5Smaybee 		 * passed in is the znode for the root.
987874395d5Smaybee 		 */
988874395d5Smaybee 		*zpp = dzp;
9890a586ceaSMark Shellenbaum 
9900a586ceaSMark Shellenbaum 		(*zpp)->z_sa_hdl = sa_hdl;
991874395d5Smaybee 	}
9920a586ceaSMark Shellenbaum 
9930a586ceaSMark Shellenbaum 	(*zpp)->z_pflags = pflags;
9940a586ceaSMark Shellenbaum 	(*zpp)->z_mode = mode;
99559e7834dSMark Shellenbaum 
9968f2529deSMark Shellenbaum 	if (vap->va_mask & AT_XVATTR)
9978f2529deSMark Shellenbaum 		zfs_xvattr_set(*zpp, (xvattr_t *)vap, tx);
9988f2529deSMark Shellenbaum 
9990a586ceaSMark Shellenbaum 	if (obj_type == DMU_OT_ZNODE ||
10000a586ceaSMark Shellenbaum 	    acl_ids->z_aclp->z_version < ZFS_ACL_VERSION_FUID) {
100143466aaeSMax Grossman 		VERIFY0(zfs_aclset_common(*zpp, acl_ids->z_aclp, cr, tx));
10020a586ceaSMark Shellenbaum 	}
100359e7834dSMark Shellenbaum 	ZFS_OBJ_HOLD_EXIT(zfsvfs, obj);
1004fa9e4066Sahrens }
1005fa9e4066Sahrens 
10060a586ceaSMark Shellenbaum /*
1007f7170741SWill Andrews  * Update in-core attributes.  It is assumed the caller will be doing an
1008f7170741SWill Andrews  * sa_bulk_update to push the changes out.
10090a586ceaSMark Shellenbaum  */
1010da6c28aaSamw void
10110a586ceaSMark Shellenbaum zfs_xvattr_set(znode_t *zp, xvattr_t *xvap, dmu_tx_t *tx)
1012da6c28aaSamw {
1013da6c28aaSamw 	xoptattr_t *xoap;
1014da6c28aaSamw 
1015da6c28aaSamw 	xoap = xva_getxoptattr(xvap);
1016da6c28aaSamw 	ASSERT(xoap);
1017da6c28aaSamw 
1018da6c28aaSamw 	if (XVA_ISSET_REQ(xvap, XAT_CREATETIME)) {
10190a586ceaSMark Shellenbaum 		uint64_t times[2];
10200a586ceaSMark Shellenbaum 		ZFS_TIME_ENCODE(&xoap->xoa_createtime, times);
10210a586ceaSMark Shellenbaum 		(void) sa_update(zp->z_sa_hdl, SA_ZPL_CRTIME(zp->z_zfsvfs),
10220a586ceaSMark Shellenbaum 		    &times, sizeof (times), tx);
1023da6c28aaSamw 		XVA_SET_RTN(xvap, XAT_CREATETIME);
1024da6c28aaSamw 	}
1025da6c28aaSamw 	if (XVA_ISSET_REQ(xvap, XAT_READONLY)) {
10260a586ceaSMark Shellenbaum 		ZFS_ATTR_SET(zp, ZFS_READONLY, xoap->xoa_readonly,
10270a586ceaSMark Shellenbaum 		    zp->z_pflags, tx);
1028da6c28aaSamw 		XVA_SET_RTN(xvap, XAT_READONLY);
1029da6c28aaSamw 	}
1030da6c28aaSamw 	if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) {
10310a586ceaSMark Shellenbaum 		ZFS_ATTR_SET(zp, ZFS_HIDDEN, xoap->xoa_hidden,
10320a586ceaSMark Shellenbaum 		    zp->z_pflags, tx);
1033da6c28aaSamw 		XVA_SET_RTN(xvap, XAT_HIDDEN);
1034da6c28aaSamw 	}
1035da6c28aaSamw 	if (XVA_ISSET_REQ(xvap, XAT_SYSTEM)) {
10360a586ceaSMark Shellenbaum 		ZFS_ATTR_SET(zp, ZFS_SYSTEM, xoap->xoa_system,
10370a586ceaSMark Shellenbaum 		    zp->z_pflags, tx);
1038da6c28aaSamw 		XVA_SET_RTN(xvap, XAT_SYSTEM);
1039da6c28aaSamw 	}
1040da6c28aaSamw 	if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE)) {
10410a586ceaSMark Shellenbaum 		ZFS_ATTR_SET(zp, ZFS_ARCHIVE, xoap->xoa_archive,
10420a586ceaSMark Shellenbaum 		    zp->z_pflags, tx);
1043da6c28aaSamw 		XVA_SET_RTN(xvap, XAT_ARCHIVE);
1044da6c28aaSamw 	}
1045da6c28aaSamw 	if (XVA_ISSET_REQ(xvap, XAT_IMMUTABLE)) {
10460a586ceaSMark Shellenbaum 		ZFS_ATTR_SET(zp, ZFS_IMMUTABLE, xoap->xoa_immutable,
10470a586ceaSMark Shellenbaum 		    zp->z_pflags, tx);
1048da6c28aaSamw 		XVA_SET_RTN(xvap, XAT_IMMUTABLE);
1049da6c28aaSamw 	}
1050da6c28aaSamw 	if (XVA_ISSET_REQ(xvap, XAT_NOUNLINK)) {
10510a586ceaSMark Shellenbaum 		ZFS_ATTR_SET(zp, ZFS_NOUNLINK, xoap->xoa_nounlink,
10520a586ceaSMark Shellenbaum 		    zp->z_pflags, tx);
1053da6c28aaSamw 		XVA_SET_RTN(xvap, XAT_NOUNLINK);
1054da6c28aaSamw 	}
1055da6c28aaSamw 	if (XVA_ISSET_REQ(xvap, XAT_APPENDONLY)) {
10560a586ceaSMark Shellenbaum 		ZFS_ATTR_SET(zp, ZFS_APPENDONLY, xoap->xoa_appendonly,
10570a586ceaSMark Shellenbaum 		    zp->z_pflags, tx);
1058da6c28aaSamw 		XVA_SET_RTN(xvap, XAT_APPENDONLY);
1059da6c28aaSamw 	}
1060da6c28aaSamw 	if (XVA_ISSET_REQ(xvap, XAT_NODUMP)) {
10610a586ceaSMark Shellenbaum 		ZFS_ATTR_SET(zp, ZFS_NODUMP, xoap->xoa_nodump,
10620a586ceaSMark Shellenbaum 		    zp->z_pflags, tx);
1063da6c28aaSamw 		XVA_SET_RTN(xvap, XAT_NODUMP);
1064da6c28aaSamw 	}
1065da6c28aaSamw 	if (XVA_ISSET_REQ(xvap, XAT_OPAQUE)) {
10660a586ceaSMark Shellenbaum 		ZFS_ATTR_SET(zp, ZFS_OPAQUE, xoap->xoa_opaque,
10670a586ceaSMark Shellenbaum 		    zp->z_pflags, tx);
1068da6c28aaSamw 		XVA_SET_RTN(xvap, XAT_OPAQUE);
1069da6c28aaSamw 	}
1070da6c28aaSamw 	if (XVA_ISSET_REQ(xvap, XAT_AV_QUARANTINED)) {
1071da6c28aaSamw 		ZFS_ATTR_SET(zp, ZFS_AV_QUARANTINED,
10720a586ceaSMark Shellenbaum 		    xoap->xoa_av_quarantined, zp->z_pflags, tx);
1073da6c28aaSamw 		XVA_SET_RTN(xvap, XAT_AV_QUARANTINED);
1074da6c28aaSamw 	}
1075da6c28aaSamw 	if (XVA_ISSET_REQ(xvap, XAT_AV_MODIFIED)) {
10760a586ceaSMark Shellenbaum 		ZFS_ATTR_SET(zp, ZFS_AV_MODIFIED, xoap->xoa_av_modified,
10770a586ceaSMark Shellenbaum 		    zp->z_pflags, tx);
1078da6c28aaSamw 		XVA_SET_RTN(xvap, XAT_AV_MODIFIED);
1079da6c28aaSamw 	}
1080da6c28aaSamw 	if (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP)) {
10810a586ceaSMark Shellenbaum 		zfs_sa_set_scanstamp(zp, xvap, tx);
1082da6c28aaSamw 		XVA_SET_RTN(xvap, XAT_AV_SCANSTAMP);
1083da6c28aaSamw 	}
10847a286c47SDai Ngo 	if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) {
10850a586ceaSMark Shellenbaum 		ZFS_ATTR_SET(zp, ZFS_REPARSE, xoap->xoa_reparse,
10860a586ceaSMark Shellenbaum 		    zp->z_pflags, tx);
10877a286c47SDai Ngo 		XVA_SET_RTN(xvap, XAT_REPARSE);
10887a286c47SDai Ngo 	}
1089fd9ee8b5Sjoyce mcintosh 	if (XVA_ISSET_REQ(xvap, XAT_OFFLINE)) {
1090fd9ee8b5Sjoyce mcintosh 		ZFS_ATTR_SET(zp, ZFS_OFFLINE, xoap->xoa_offline,
1091fd9ee8b5Sjoyce mcintosh 		    zp->z_pflags, tx);
1092fd9ee8b5Sjoyce mcintosh 		XVA_SET_RTN(xvap, XAT_OFFLINE);
1093fd9ee8b5Sjoyce mcintosh 	}
1094fd9ee8b5Sjoyce mcintosh 	if (XVA_ISSET_REQ(xvap, XAT_SPARSE)) {
1095fd9ee8b5Sjoyce mcintosh 		ZFS_ATTR_SET(zp, ZFS_SPARSE, xoap->xoa_sparse,
1096fd9ee8b5Sjoyce mcintosh 		    zp->z_pflags, tx);
1097fd9ee8b5Sjoyce mcintosh 		XVA_SET_RTN(xvap, XAT_SPARSE);
1098fd9ee8b5Sjoyce mcintosh 	}
1099da6c28aaSamw }
1100da6c28aaSamw 
1101fa9e4066Sahrens int
1102fa9e4066Sahrens zfs_zget(zfsvfs_t *zfsvfs, uint64_t obj_num, znode_t **zpp)
1103fa9e4066Sahrens {
1104fa9e4066Sahrens 	dmu_object_info_t doi;
1105fa9e4066Sahrens 	dmu_buf_t	*db;
1106fa9e4066Sahrens 	znode_t		*zp;
1107ea8dc4b6Seschrock 	int err;
11080a586ceaSMark Shellenbaum 	sa_handle_t	*hdl;
1109fa9e4066Sahrens 
1110fa9e4066Sahrens 	*zpp = NULL;
1111fa9e4066Sahrens 
1112fa9e4066Sahrens 	ZFS_OBJ_HOLD_ENTER(zfsvfs, obj_num);
1113fa9e4066Sahrens 
11140a586ceaSMark Shellenbaum 	err = sa_buf_hold(zfsvfs->z_os, obj_num, NULL, &db);
1115ea8dc4b6Seschrock 	if (err) {
1116fa9e4066Sahrens 		ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
1117ea8dc4b6Seschrock 		return (err);
1118fa9e4066Sahrens 	}
1119fa9e4066Sahrens 
1120fa9e4066Sahrens 	dmu_object_info_from_db(db, &doi);
11210a586ceaSMark Shellenbaum 	if (doi.doi_bonus_type != DMU_OT_SA &&
11220a586ceaSMark Shellenbaum 	    (doi.doi_bonus_type != DMU_OT_ZNODE ||
11230a586ceaSMark Shellenbaum 	    (doi.doi_bonus_type == DMU_OT_ZNODE &&
11240a586ceaSMark Shellenbaum 	    doi.doi_bonus_size < sizeof (znode_phys_t)))) {
11250a586ceaSMark Shellenbaum 		sa_buf_rele(db, NULL);
1126fa9e4066Sahrens 		ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
1127be6fd75aSMatthew Ahrens 		return (SET_ERROR(EINVAL));
1128fa9e4066Sahrens 	}
1129fa9e4066Sahrens 
11300a586ceaSMark Shellenbaum 	hdl = dmu_buf_get_user(db);
11310a586ceaSMark Shellenbaum 	if (hdl != NULL) {
11320a586ceaSMark Shellenbaum 		zp  = sa_get_userdata(hdl);
11330a586ceaSMark Shellenbaum 
1134fa9e4066Sahrens 
11354ccbb6e7Sahrens 		/*
11360a586ceaSMark Shellenbaum 		 * Since "SA" does immediate eviction we
11370a586ceaSMark Shellenbaum 		 * should never find a sa handle that doesn't
11380a586ceaSMark Shellenbaum 		 * know about the znode.
11394ccbb6e7Sahrens 		 */
11400a586ceaSMark Shellenbaum 
11410a586ceaSMark Shellenbaum 		ASSERT3P(zp, !=, NULL);
11420a586ceaSMark Shellenbaum 
11430a586ceaSMark Shellenbaum 		mutex_enter(&zp->z_lock);
1144fa9e4066Sahrens 		ASSERT3U(zp->z_id, ==, obj_num);
1145893a6d32Sahrens 		if (zp->z_unlinked) {
1146be6fd75aSMatthew Ahrens 			err = SET_ERROR(ENOENT);
1147fa9e4066Sahrens 		} else {
11484ccbb6e7Sahrens 			VN_HOLD(ZTOV(zp));
11494ccbb6e7Sahrens 			*zpp = zp;
11504ccbb6e7Sahrens 			err = 0;
1151fa9e4066Sahrens 		}
1152fa9e4066Sahrens 		mutex_exit(&zp->z_lock);
1153eaef6a96SRichard Yao 		sa_buf_rele(db, NULL);
1154ea8dc4b6Seschrock 		ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
11554ccbb6e7Sahrens 		return (err);
1156fa9e4066Sahrens 	}
1157fa9e4066Sahrens 
1158fa9e4066Sahrens 	/*
1159fa9e4066Sahrens 	 * Not found create new znode/vnode
116059e7834dSMark Shellenbaum 	 * but only if file exists.
116159e7834dSMark Shellenbaum 	 *
116259e7834dSMark Shellenbaum 	 * There is a small window where zfs_vget() could
116359e7834dSMark Shellenbaum 	 * find this object while a file create is still in
11640a586ceaSMark Shellenbaum 	 * progress.  This is checked for in zfs_znode_alloc()
11650a586ceaSMark Shellenbaum 	 *
11660a586ceaSMark Shellenbaum 	 * if zfs_znode_alloc() fails it will drop the hold on the
11670a586ceaSMark Shellenbaum 	 * bonus buffer.
1168fa9e4066Sahrens 	 */
11690a586ceaSMark Shellenbaum 	zp = zfs_znode_alloc(zfsvfs, db, doi.doi_data_block_size,
11700a586ceaSMark Shellenbaum 	    doi.doi_bonus_type, NULL);
11710a586ceaSMark Shellenbaum 	if (zp == NULL) {
1172be6fd75aSMatthew Ahrens 		err = SET_ERROR(ENOENT);
11730a586ceaSMark Shellenbaum 	} else {
11740a586ceaSMark Shellenbaum 		*zpp = zp;
117559e7834dSMark Shellenbaum 	}
1176ea8dc4b6Seschrock 	ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
117759e7834dSMark Shellenbaum 	return (err);
1178fa9e4066Sahrens }
1179fa9e4066Sahrens 
1180f18faf3fSek int
1181f18faf3fSek zfs_rezget(znode_t *zp)
1182f18faf3fSek {
1183f18faf3fSek 	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
1184f18faf3fSek 	dmu_object_info_t doi;
1185f18faf3fSek 	dmu_buf_t *db;
1186f18faf3fSek 	uint64_t obj_num = zp->z_id;
11870a586ceaSMark Shellenbaum 	uint64_t mode;
11880a586ceaSMark Shellenbaum 	sa_bulk_attr_t bulk[8];
1189f18faf3fSek 	int err;
11900a586ceaSMark Shellenbaum 	int count = 0;
11910a586ceaSMark Shellenbaum 	uint64_t gen;
1192f18faf3fSek 
1193f18faf3fSek 	ZFS_OBJ_HOLD_ENTER(zfsvfs, obj_num);
1194f18faf3fSek 
11950a586ceaSMark Shellenbaum 	mutex_enter(&zp->z_acl_lock);
11960a586ceaSMark Shellenbaum 	if (zp->z_acl_cached) {
11970a586ceaSMark Shellenbaum 		zfs_acl_free(zp->z_acl_cached);
11980a586ceaSMark Shellenbaum 		zp->z_acl_cached = NULL;
11990a586ceaSMark Shellenbaum 	}
12000a586ceaSMark Shellenbaum 
12010a586ceaSMark Shellenbaum 	mutex_exit(&zp->z_acl_lock);
12020a586ceaSMark Shellenbaum 	ASSERT(zp->z_sa_hdl == NULL);
12030a586ceaSMark Shellenbaum 	err = sa_buf_hold(zfsvfs->z_os, obj_num, NULL, &db);
1204f18faf3fSek 	if (err) {
1205f18faf3fSek 		ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
1206f18faf3fSek 		return (err);
1207f18faf3fSek 	}
1208f18faf3fSek 
1209f18faf3fSek 	dmu_object_info_from_db(db, &doi);
12100a586ceaSMark Shellenbaum 	if (doi.doi_bonus_type != DMU_OT_SA &&
12110a586ceaSMark Shellenbaum 	    (doi.doi_bonus_type != DMU_OT_ZNODE ||
12120a586ceaSMark Shellenbaum 	    (doi.doi_bonus_type == DMU_OT_ZNODE &&
12130a586ceaSMark Shellenbaum 	    doi.doi_bonus_size < sizeof (znode_phys_t)))) {
12140a586ceaSMark Shellenbaum 		sa_buf_rele(db, NULL);
1215f18faf3fSek 		ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
1216be6fd75aSMatthew Ahrens 		return (SET_ERROR(EINVAL));
1217f18faf3fSek 	}
1218f18faf3fSek 
12190a586ceaSMark Shellenbaum 	zfs_znode_sa_init(zfsvfs, zp, db, doi.doi_bonus_type, NULL);
12200a586ceaSMark Shellenbaum 
12210a586ceaSMark Shellenbaum 	/* reload cached values */
12220a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GEN(zfsvfs), NULL,
12230a586ceaSMark Shellenbaum 	    &gen, sizeof (gen));
12240a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(zfsvfs), NULL,
12250a586ceaSMark Shellenbaum 	    &zp->z_size, sizeof (zp->z_size));
12260a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_LINKS(zfsvfs), NULL,
12270a586ceaSMark Shellenbaum 	    &zp->z_links, sizeof (zp->z_links));
12280a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), NULL,
12290a586ceaSMark Shellenbaum 	    &zp->z_pflags, sizeof (zp->z_pflags));
12300a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ATIME(zfsvfs), NULL,
12310a586ceaSMark Shellenbaum 	    &zp->z_atime, sizeof (zp->z_atime));
12320a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_UID(zfsvfs), NULL,
1233f1696b23SMark Shellenbaum 	    &zp->z_uid, sizeof (zp->z_uid));
12340a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GID(zfsvfs), NULL,
1235f1696b23SMark Shellenbaum 	    &zp->z_gid, sizeof (zp->z_gid));
12360a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zfsvfs), NULL,
12370a586ceaSMark Shellenbaum 	    &mode, sizeof (mode));
12380a586ceaSMark Shellenbaum 
12390a586ceaSMark Shellenbaum 	if (sa_bulk_lookup(zp->z_sa_hdl, bulk, count)) {
12400a586ceaSMark Shellenbaum 		zfs_znode_dmu_fini(zp);
1241f18faf3fSek 		ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
1242be6fd75aSMatthew Ahrens 		return (SET_ERROR(EIO));
1243f18faf3fSek 	}
1244f18faf3fSek 
12451412a1a2SMark Shellenbaum 	zp->z_mode = mode;
12461412a1a2SMark Shellenbaum 
12470a586ceaSMark Shellenbaum 	if (gen != zp->z_gen) {
12480a586ceaSMark Shellenbaum 		zfs_znode_dmu_fini(zp);
12490a586ceaSMark Shellenbaum 		ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
1250be6fd75aSMatthew Ahrens 		return (SET_ERROR(EIO));
12516638ae1dSMark Shellenbaum 	}
12526638ae1dSMark Shellenbaum 
12530a586ceaSMark Shellenbaum 	zp->z_unlinked = (zp->z_links == 0);
12546166ad1cSek 	zp->z_blksz = doi.doi_data_block_size;
1255f18faf3fSek 
1256f18faf3fSek 	ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
1257f18faf3fSek 
1258f18faf3fSek 	return (0);
1259f18faf3fSek }
1260f18faf3fSek 
1261fa9e4066Sahrens void
1262fa9e4066Sahrens zfs_znode_delete(znode_t *zp, dmu_tx_t *tx)
1263fa9e4066Sahrens {
1264fa9e4066Sahrens 	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
1265cdb0ab79Smaybee 	objset_t *os = zfsvfs->z_os;
12664ccbb6e7Sahrens 	uint64_t obj = zp->z_id;
12671412a1a2SMark Shellenbaum 	uint64_t acl_obj = zfs_external_acl(zp);
1268fa9e4066Sahrens 
12694ccbb6e7Sahrens 	ZFS_OBJ_HOLD_ENTER(zfsvfs, obj);
12701412a1a2SMark Shellenbaum 	if (acl_obj) {
12711412a1a2SMark Shellenbaum 		VERIFY(!zp->z_is_sa);
1272cdb0ab79Smaybee 		VERIFY(0 == dmu_object_free(os, acl_obj, tx));
12731412a1a2SMark Shellenbaum 	}
1274cdb0ab79Smaybee 	VERIFY(0 == dmu_object_free(os, obj, tx));
12754ccbb6e7Sahrens 	zfs_znode_dmu_fini(zp);
12764ccbb6e7Sahrens 	ZFS_OBJ_HOLD_EXIT(zfsvfs, obj);
1277874395d5Smaybee 	zfs_znode_free(zp);
1278fa9e4066Sahrens }
1279fa9e4066Sahrens 
1280fa9e4066Sahrens void
1281fa9e4066Sahrens zfs_zinactive(znode_t *zp)
1282fa9e4066Sahrens {
1283fa9e4066Sahrens 	vnode_t	*vp = ZTOV(zp);
1284fa9e4066Sahrens 	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
1285fa9e4066Sahrens 	uint64_t z_id = zp->z_id;
1286fa9e4066Sahrens 
12870a586ceaSMark Shellenbaum 	ASSERT(zp->z_sa_hdl);
1288fa9e4066Sahrens 
1289fa9e4066Sahrens 	/*
1290fa9e4066Sahrens 	 * Don't allow a zfs_zget() while were trying to release this znode
1291fa9e4066Sahrens 	 */
1292fa9e4066Sahrens 	ZFS_OBJ_HOLD_ENTER(zfsvfs, z_id);
1293fa9e4066Sahrens 
1294fa9e4066Sahrens 	mutex_enter(&zp->z_lock);
1295fa9e4066Sahrens 	mutex_enter(&vp->v_lock);
1296fa9e4066Sahrens 	vp->v_count--;
1297fa9e4066Sahrens 	if (vp->v_count > 0 || vn_has_cached_data(vp)) {
1298fa9e4066Sahrens 		/*
1299fa9e4066Sahrens 		 * If the hold count is greater than zero, somebody has
1300fa9e4066Sahrens 		 * obtained a new reference on this znode while we were
1301fa9e4066Sahrens 		 * processing it here, so we are done.  If we still have
1302fa9e4066Sahrens 		 * mapped pages then we are also done, since we don't
1303fa9e4066Sahrens 		 * want to inactivate the znode until the pages get pushed.
1304fa9e4066Sahrens 		 *
1305fa9e4066Sahrens 		 * XXX - if vn_has_cached_data(vp) is true, but count == 0,
1306fa9e4066Sahrens 		 * this seems like it would leave the znode hanging with
1307fa9e4066Sahrens 		 * no chance to go inactive...
1308fa9e4066Sahrens 		 */
1309fa9e4066Sahrens 		mutex_exit(&vp->v_lock);
1310fa9e4066Sahrens 		mutex_exit(&zp->z_lock);
1311fa9e4066Sahrens 		ZFS_OBJ_HOLD_EXIT(zfsvfs, z_id);
1312fa9e4066Sahrens 		return;
1313fa9e4066Sahrens 	}
1314fa9e4066Sahrens 	mutex_exit(&vp->v_lock);
1315fa9e4066Sahrens 
1316fa9e4066Sahrens 	/*
1317fa9e4066Sahrens 	 * If this was the last reference to a file with no links,
1318fa9e4066Sahrens 	 * remove the file from the file system.
1319fa9e4066Sahrens 	 */
1320893a6d32Sahrens 	if (zp->z_unlinked) {
1321fa9e4066Sahrens 		mutex_exit(&zp->z_lock);
1322fa9e4066Sahrens 		ZFS_OBJ_HOLD_EXIT(zfsvfs, z_id);
1323893a6d32Sahrens 		zfs_rmnode(zp);
1324fa9e4066Sahrens 		return;
1325fa9e4066Sahrens 	}
13260a586ceaSMark Shellenbaum 
1327fa9e4066Sahrens 	mutex_exit(&zp->z_lock);
13284ccbb6e7Sahrens 	zfs_znode_dmu_fini(zp);
1329fa9e4066Sahrens 	ZFS_OBJ_HOLD_EXIT(zfsvfs, z_id);
1330874395d5Smaybee 	zfs_znode_free(zp);
1331fa9e4066Sahrens }
1332fa9e4066Sahrens 
1333fa9e4066Sahrens void
1334fa9e4066Sahrens zfs_znode_free(znode_t *zp)
1335fa9e4066Sahrens {
1336fa9e4066Sahrens 	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
1337fa9e4066Sahrens 
1338874395d5Smaybee 	vn_invalid(ZTOV(zp));
1339874395d5Smaybee 
1340b5fca8f8Stomee 	ASSERT(ZTOV(zp)->v_count == 0);
1341b5fca8f8Stomee 
1342fa9e4066Sahrens 	mutex_enter(&zfsvfs->z_znodes_lock);
1343b5fca8f8Stomee 	POINTER_INVALIDATE(&zp->z_zfsvfs);
1344fa9e4066Sahrens 	list_remove(&zfsvfs->z_all_znodes, zp);
1345fa9e4066Sahrens 	mutex_exit(&zfsvfs->z_znodes_lock);
1346fa9e4066Sahrens 
1347d47621a4STim Haley 	if (zp->z_acl_cached) {
1348d47621a4STim Haley 		zfs_acl_free(zp->z_acl_cached);
1349d47621a4STim Haley 		zp->z_acl_cached = NULL;
1350d47621a4STim Haley 	}
1351d47621a4STim Haley 
1352fa9e4066Sahrens 	kmem_cache_free(znode_cache, zp);
1353874395d5Smaybee 
1354874395d5Smaybee 	VFS_RELE(zfsvfs->z_vfs);
1355fa9e4066Sahrens }
1356fa9e4066Sahrens 
1357fa9e4066Sahrens void
13580a586ceaSMark Shellenbaum zfs_tstamp_update_setup(znode_t *zp, uint_t flag, uint64_t mtime[2],
13590a586ceaSMark Shellenbaum     uint64_t ctime[2], boolean_t have_tx)
1360fa9e4066Sahrens {
1361fa9e4066Sahrens 	timestruc_t	now;
1362fa9e4066Sahrens 
1363fa9e4066Sahrens 	gethrestime(&now);
1364fa9e4066Sahrens 
13650a586ceaSMark Shellenbaum 	if (have_tx) {	/* will sa_bulk_update happen really soon? */
1366fa9e4066Sahrens 		zp->z_atime_dirty = 0;
1367fa9e4066Sahrens 		zp->z_seq++;
1368fa9e4066Sahrens 	} else {
1369fa9e4066Sahrens 		zp->z_atime_dirty = 1;
1370fa9e4066Sahrens 	}
1371fa9e4066Sahrens 
13720a586ceaSMark Shellenbaum 	if (flag & AT_ATIME) {
13730a586ceaSMark Shellenbaum 		ZFS_TIME_ENCODE(&now, zp->z_atime);
13740a586ceaSMark Shellenbaum 	}
1375fa9e4066Sahrens 
1376da6c28aaSamw 	if (flag & AT_MTIME) {
13770a586ceaSMark Shellenbaum 		ZFS_TIME_ENCODE(&now, mtime);
13780a586ceaSMark Shellenbaum 		if (zp->z_zfsvfs->z_use_fuids) {
13790a586ceaSMark Shellenbaum 			zp->z_pflags |= (ZFS_ARCHIVE |
13800a586ceaSMark Shellenbaum 			    ZFS_AV_MODIFIED);
13810a586ceaSMark Shellenbaum 		}
1382da6c28aaSamw 	}
1383fa9e4066Sahrens 
1384da6c28aaSamw 	if (flag & AT_CTIME) {
13850a586ceaSMark Shellenbaum 		ZFS_TIME_ENCODE(&now, ctime);
1386da6c28aaSamw 		if (zp->z_zfsvfs->z_use_fuids)
13870a586ceaSMark Shellenbaum 			zp->z_pflags |= ZFS_ARCHIVE;
1388da6c28aaSamw 	}
1389fa9e4066Sahrens }
1390fa9e4066Sahrens 
1391fa9e4066Sahrens /*
1392104e2ed7Sperrin  * Grow the block size for a file.
1393fa9e4066Sahrens  *
1394fa9e4066Sahrens  *	IN:	zp	- znode of file to free data in.
1395fa9e4066Sahrens  *		size	- requested block size
1396fa9e4066Sahrens  *		tx	- open transaction.
1397fa9e4066Sahrens  *
1398fa9e4066Sahrens  * NOTE: this function assumes that the znode is write locked.
1399fa9e4066Sahrens  */
1400104e2ed7Sperrin void
1401fa9e4066Sahrens zfs_grow_blocksize(znode_t *zp, uint64_t size, dmu_tx_t *tx)
1402fa9e4066Sahrens {
1403fa9e4066Sahrens 	int		error;
1404fa9e4066Sahrens 	u_longlong_t	dummy;
1405fa9e4066Sahrens 
1406fa9e4066Sahrens 	if (size <= zp->z_blksz)
1407104e2ed7Sperrin 		return;
1408fa9e4066Sahrens 	/*
1409fa9e4066Sahrens 	 * If the file size is already greater than the current blocksize,
1410fa9e4066Sahrens 	 * we will not grow.  If there is more than one block in a file,
1411fa9e4066Sahrens 	 * the blocksize cannot change.
1412fa9e4066Sahrens 	 */
14130a586ceaSMark Shellenbaum 	if (zp->z_blksz && zp->z_size > zp->z_blksz)
1414104e2ed7Sperrin 		return;
1415fa9e4066Sahrens 
1416fa9e4066Sahrens 	error = dmu_object_set_blocksize(zp->z_zfsvfs->z_os, zp->z_id,
1417fa9e4066Sahrens 	    size, 0, tx);
14180a586ceaSMark Shellenbaum 
1419fa9e4066Sahrens 	if (error == ENOTSUP)
1420104e2ed7Sperrin 		return;
1421fb09f5aaSMadhav Suresh 	ASSERT0(error);
1422fa9e4066Sahrens 
1423fa9e4066Sahrens 	/* What blocksize did we actually get? */
14240a586ceaSMark Shellenbaum 	dmu_object_size_from_db(sa_get_db(zp->z_sa_hdl), &zp->z_blksz, &dummy);
1425fa9e4066Sahrens }
1426fa9e4066Sahrens 
1427fa9e4066Sahrens /*
1428fa9e4066Sahrens  * This is a dummy interface used when pvn_vplist_dirty() should *not*
1429fa9e4066Sahrens  * be calling back into the fs for a putpage().  E.g.: when truncating
1430fa9e4066Sahrens  * a file, the pages being "thrown away* don't need to be written out.
1431fa9e4066Sahrens  */
1432fa9e4066Sahrens /* ARGSUSED */
1433fa9e4066Sahrens static int
1434fa9e4066Sahrens zfs_no_putpage(vnode_t *vp, page_t *pp, u_offset_t *offp, size_t *lenp,
1435fa9e4066Sahrens     int flags, cred_t *cr)
1436fa9e4066Sahrens {
1437fa9e4066Sahrens 	ASSERT(0);
1438fa9e4066Sahrens 	return (0);
1439fa9e4066Sahrens }
1440fa9e4066Sahrens 
1441fa9e4066Sahrens /*
1442cdb0ab79Smaybee  * Increase the file length
1443fa9e4066Sahrens  *
1444fa9e4066Sahrens  *	IN:	zp	- znode of file to free data in.
1445cdb0ab79Smaybee  *		end	- new end-of-file
1446fa9e4066Sahrens  *
14474bb73804SMatthew Ahrens  *	RETURN:	0 on success, error code on failure
1448fa9e4066Sahrens  */
1449cdb0ab79Smaybee static int
1450cdb0ab79Smaybee zfs_extend(znode_t *zp, uint64_t end)
1451fa9e4066Sahrens {
14525730cc9aSmaybee 	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
1453cdb0ab79Smaybee 	dmu_tx_t *tx;
14545730cc9aSmaybee 	rl_t *rl;
1455cdb0ab79Smaybee 	uint64_t newblksz;
1456104e2ed7Sperrin 	int error;
1457fa9e4066Sahrens 
14585730cc9aSmaybee 	/*
1459cdb0ab79Smaybee 	 * We will change zp_size, lock the whole file.
14605730cc9aSmaybee 	 */
1461cdb0ab79Smaybee 	rl = zfs_range_lock(zp, 0, UINT64_MAX, RL_WRITER);
14625730cc9aSmaybee 
1463fa9e4066Sahrens 	/*
1464fa9e4066Sahrens 	 * Nothing to do if file already at desired length.
1465fa9e4066Sahrens 	 */
14660a586ceaSMark Shellenbaum 	if (end <= zp->z_size) {
1467c5c6ffa0Smaybee 		zfs_range_unlock(rl);
1468fa9e4066Sahrens 		return (0);
1469fa9e4066Sahrens 	}
14705730cc9aSmaybee 	tx = dmu_tx_create(zfsvfs->z_os);
14710a586ceaSMark Shellenbaum 	dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE);
14720a586ceaSMark Shellenbaum 	zfs_sa_upgrade_txholds(tx, zp);
1473cdb0ab79Smaybee 	if (end > zp->z_blksz &&
14745730cc9aSmaybee 	    (!ISP2(zp->z_blksz) || zp->z_blksz < zfsvfs->z_max_blksz)) {
1475fa9e4066Sahrens 		/*
1476fa9e4066Sahrens 		 * We are growing the file past the current block size.
1477fa9e4066Sahrens 		 */
1478fa9e4066Sahrens 		if (zp->z_blksz > zp->z_zfsvfs->z_max_blksz) {
1479b5152584SMatthew Ahrens 			/*
1480b5152584SMatthew Ahrens 			 * File's blocksize is already larger than the
1481b5152584SMatthew Ahrens 			 * "recordsize" property.  Only let it grow to
1482b5152584SMatthew Ahrens 			 * the next power of 2.
1483b5152584SMatthew Ahrens 			 */
1484fa9e4066Sahrens 			ASSERT(!ISP2(zp->z_blksz));
1485b5152584SMatthew Ahrens 			newblksz = MIN(end, 1 << highbit64(zp->z_blksz));
1486fa9e4066Sahrens 		} else {
1487cdb0ab79Smaybee 			newblksz = MIN(end, zp->z_zfsvfs->z_max_blksz);
1488fa9e4066Sahrens 		}
1489cdb0ab79Smaybee 		dmu_tx_hold_write(tx, zp->z_id, 0, newblksz);
1490cdb0ab79Smaybee 	} else {
1491cdb0ab79Smaybee 		newblksz = 0;
14925730cc9aSmaybee 	}
14935730cc9aSmaybee 
1494e722410cSMatthew Ahrens 	error = dmu_tx_assign(tx, TXG_WAIT);
14955730cc9aSmaybee 	if (error) {
14965730cc9aSmaybee 		dmu_tx_abort(tx);
1497c5c6ffa0Smaybee 		zfs_range_unlock(rl);
14985730cc9aSmaybee 		return (error);
1499fa9e4066Sahrens 	}
15005730cc9aSmaybee 
1501cdb0ab79Smaybee 	if (newblksz)
1502cdb0ab79Smaybee 		zfs_grow_blocksize(zp, newblksz, tx);
15035730cc9aSmaybee 
15040a586ceaSMark Shellenbaum 	zp->z_size = end;
15050a586ceaSMark Shellenbaum 
15060a586ceaSMark Shellenbaum 	VERIFY(0 == sa_update(zp->z_sa_hdl, SA_ZPL_SIZE(zp->z_zfsvfs),
15070a586ceaSMark Shellenbaum 	    &zp->z_size, sizeof (zp->z_size), tx));
15085730cc9aSmaybee 
1509cdb0ab79Smaybee 	zfs_range_unlock(rl);
15105730cc9aSmaybee 
1511cdb0ab79Smaybee 	dmu_tx_commit(tx);
15125730cc9aSmaybee 
1513cdb0ab79Smaybee 	return (0);
1514cdb0ab79Smaybee }
1515cdb0ab79Smaybee 
1516cdb0ab79Smaybee /*
1517cdb0ab79Smaybee  * Free space in a file.
1518cdb0ab79Smaybee  *
1519cdb0ab79Smaybee  *	IN:	zp	- znode of file to free data in.
1520cdb0ab79Smaybee  *		off	- start of section to free.
1521cdb0ab79Smaybee  *		len	- length of section to free.
1522cdb0ab79Smaybee  *
15234bb73804SMatthew Ahrens  *	RETURN:	0 on success, error code on failure
1524cdb0ab79Smaybee  */
1525cdb0ab79Smaybee static int
1526cdb0ab79Smaybee zfs_free_range(znode_t *zp, uint64_t off, uint64_t len)
1527cdb0ab79Smaybee {
1528cdb0ab79Smaybee 	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
1529cdb0ab79Smaybee 	rl_t *rl;
1530cdb0ab79Smaybee 	int error;
1531cdb0ab79Smaybee 
1532cdb0ab79Smaybee 	/*
1533cdb0ab79Smaybee 	 * Lock the range being freed.
1534cdb0ab79Smaybee 	 */
1535cdb0ab79Smaybee 	rl = zfs_range_lock(zp, off, len, RL_WRITER);
1536cdb0ab79Smaybee 
1537cdb0ab79Smaybee 	/*
1538cdb0ab79Smaybee 	 * Nothing to do if file already at desired length.
1539cdb0ab79Smaybee 	 */
15400a586ceaSMark Shellenbaum 	if (off >= zp->z_size) {
1541cdb0ab79Smaybee 		zfs_range_unlock(rl);
1542cdb0ab79Smaybee 		return (0);
15435730cc9aSmaybee 	}
15445730cc9aSmaybee 
15450a586ceaSMark Shellenbaum 	if (off + len > zp->z_size)
15460a586ceaSMark Shellenbaum 		len = zp->z_size - off;
1547cdb0ab79Smaybee 
1548cdb0ab79Smaybee 	error = dmu_free_long_range(zfsvfs->z_os, zp->z_id, off, len);
1549cdb0ab79Smaybee 
1550c5c6ffa0Smaybee 	zfs_range_unlock(rl);
15515730cc9aSmaybee 
1552cdb0ab79Smaybee 	return (error);
1553cdb0ab79Smaybee }
1554cdb0ab79Smaybee 
1555cdb0ab79Smaybee /*
1556cdb0ab79Smaybee  * Truncate a file
1557cdb0ab79Smaybee  *
1558cdb0ab79Smaybee  *	IN:	zp	- znode of file to free data in.
1559cdb0ab79Smaybee  *		end	- new end-of-file.
1560cdb0ab79Smaybee  *
15614bb73804SMatthew Ahrens  *	RETURN:	0 on success, error code on failure
1562cdb0ab79Smaybee  */
1563cdb0ab79Smaybee static int
1564cdb0ab79Smaybee zfs_trunc(znode_t *zp, uint64_t end)
1565cdb0ab79Smaybee {
1566cdb0ab79Smaybee 	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
1567cdb0ab79Smaybee 	vnode_t *vp = ZTOV(zp);
1568cdb0ab79Smaybee 	dmu_tx_t *tx;
1569cdb0ab79Smaybee 	rl_t *rl;
1570cdb0ab79Smaybee 	int error;
1571fd9ee8b5Sjoyce mcintosh 	sa_bulk_attr_t bulk[2];
1572fd9ee8b5Sjoyce mcintosh 	int count = 0;
1573cdb0ab79Smaybee 
1574cdb0ab79Smaybee 	/*
1575cdb0ab79Smaybee 	 * We will change zp_size, lock the whole file.
1576cdb0ab79Smaybee 	 */
1577cdb0ab79Smaybee 	rl = zfs_range_lock(zp, 0, UINT64_MAX, RL_WRITER);
1578cdb0ab79Smaybee 
1579cdb0ab79Smaybee 	/*
1580cdb0ab79Smaybee 	 * Nothing to do if file already at desired length.
1581cdb0ab79Smaybee 	 */
15820a586ceaSMark Shellenbaum 	if (end >= zp->z_size) {
1583cdb0ab79Smaybee 		zfs_range_unlock(rl);
1584cdb0ab79Smaybee 		return (0);
1585cdb0ab79Smaybee 	}
1586cdb0ab79Smaybee 
1587cdb0ab79Smaybee 	error = dmu_free_long_range(zfsvfs->z_os, zp->z_id, end,  -1);
1588cdb0ab79Smaybee 	if (error) {
1589cdb0ab79Smaybee 		zfs_range_unlock(rl);
1590cdb0ab79Smaybee 		return (error);
1591cdb0ab79Smaybee 	}
1592cdb0ab79Smaybee 	tx = dmu_tx_create(zfsvfs->z_os);
15930a586ceaSMark Shellenbaum 	dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE);
15940a586ceaSMark Shellenbaum 	zfs_sa_upgrade_txholds(tx, zp);
15954bb73804SMatthew Ahrens 	dmu_tx_mark_netfree(tx);
1596e722410cSMatthew Ahrens 	error = dmu_tx_assign(tx, TXG_WAIT);
1597cdb0ab79Smaybee 	if (error) {
1598cdb0ab79Smaybee 		dmu_tx_abort(tx);
1599cdb0ab79Smaybee 		zfs_range_unlock(rl);
1600cdb0ab79Smaybee 		return (error);
1601cdb0ab79Smaybee 	}
1602cdb0ab79Smaybee 
16030a586ceaSMark Shellenbaum 	zp->z_size = end;
1604fd9ee8b5Sjoyce mcintosh 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(zfsvfs),
1605fd9ee8b5Sjoyce mcintosh 	    NULL, &zp->z_size, sizeof (zp->z_size));
16060a586ceaSMark Shellenbaum 
1607fd9ee8b5Sjoyce mcintosh 	if (end == 0) {
1608fd9ee8b5Sjoyce mcintosh 		zp->z_pflags &= ~ZFS_SPARSE;
1609fd9ee8b5Sjoyce mcintosh 		SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs),
1610fd9ee8b5Sjoyce mcintosh 		    NULL, &zp->z_pflags, 8);
1611fd9ee8b5Sjoyce mcintosh 	}
1612fd9ee8b5Sjoyce mcintosh 	VERIFY(sa_bulk_update(zp->z_sa_hdl, bulk, count, tx) == 0);
1613cdb0ab79Smaybee 
16145730cc9aSmaybee 	dmu_tx_commit(tx);
16155730cc9aSmaybee 
1616fa9e4066Sahrens 	/*
16175730cc9aSmaybee 	 * Clear any mapped pages in the truncated region.  This has to
16185730cc9aSmaybee 	 * happen outside of the transaction to avoid the possibility of
16195730cc9aSmaybee 	 * a deadlock with someone trying to push a page that we are
16205730cc9aSmaybee 	 * about to invalidate.
1621fa9e4066Sahrens 	 */
1622cdb0ab79Smaybee 	if (vn_has_cached_data(vp)) {
1623fa9e4066Sahrens 		page_t *pp;
1624cdb0ab79Smaybee 		uint64_t start = end & PAGEMASK;
1625cdb0ab79Smaybee 		int poff = end & PAGEOFFSET;
1626fa9e4066Sahrens 
16275730cc9aSmaybee 		if (poff != 0 && (pp = page_lookup(vp, start, SE_SHARED))) {
1628fa9e4066Sahrens 			/*
1629fa9e4066Sahrens 			 * We need to zero a partial page.
1630fa9e4066Sahrens 			 */
16315730cc9aSmaybee 			pagezero(pp, poff, PAGESIZE - poff);
1632fa9e4066Sahrens 			start += PAGESIZE;
1633fa9e4066Sahrens 			page_unlock(pp);
1634fa9e4066Sahrens 		}
1635fa9e4066Sahrens 		error = pvn_vplist_dirty(vp, start, zfs_no_putpage,
16365730cc9aSmaybee 		    B_INVAL | B_TRUNC, NULL);
1637fa9e4066Sahrens 		ASSERT(error == 0);
1638fa9e4066Sahrens 	}
1639ac05c741SMark Maybee 
1640ac05c741SMark Maybee 	zfs_range_unlock(rl);
1641fa9e4066Sahrens 
1642fa9e4066Sahrens 	return (0);
1643fa9e4066Sahrens }
1644fa9e4066Sahrens 
1645cdb0ab79Smaybee /*
1646cdb0ab79Smaybee  * Free space in a file
1647cdb0ab79Smaybee  *
1648cdb0ab79Smaybee  *	IN:	zp	- znode of file to free data in.
1649cdb0ab79Smaybee  *		off	- start of range
1650cdb0ab79Smaybee  *		len	- end of range (0 => EOF)
1651cdb0ab79Smaybee  *		flag	- current file open mode flags.
1652cdb0ab79Smaybee  *		log	- TRUE if this action should be logged
1653cdb0ab79Smaybee  *
16544bb73804SMatthew Ahrens  *	RETURN:	0 on success, error code on failure
1655cdb0ab79Smaybee  */
1656cdb0ab79Smaybee int
1657cdb0ab79Smaybee zfs_freesp(znode_t *zp, uint64_t off, uint64_t len, int flag, boolean_t log)
1658cdb0ab79Smaybee {
1659cdb0ab79Smaybee 	vnode_t *vp = ZTOV(zp);
1660cdb0ab79Smaybee 	dmu_tx_t *tx;
1661cdb0ab79Smaybee 	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
1662cdb0ab79Smaybee 	zilog_t *zilog = zfsvfs->z_log;
16630a586ceaSMark Shellenbaum 	uint64_t mode;
16640a586ceaSMark Shellenbaum 	uint64_t mtime[2], ctime[2];
1665db9986c7SMark Shellenbaum 	sa_bulk_attr_t bulk[3];
16660a586ceaSMark Shellenbaum 	int count = 0;
1667cdb0ab79Smaybee 	int error;
1668cdb0ab79Smaybee 
16690a586ceaSMark Shellenbaum 	if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_MODE(zfsvfs), &mode,
16700a586ceaSMark Shellenbaum 	    sizeof (mode))) != 0)
16710a586ceaSMark Shellenbaum 		return (error);
16720a586ceaSMark Shellenbaum 
16730a586ceaSMark Shellenbaum 	if (off > zp->z_size) {
1674cdb0ab79Smaybee 		error =  zfs_extend(zp, off+len);
1675cdb0ab79Smaybee 		if (error == 0 && log)
1676cdb0ab79Smaybee 			goto log;
1677cdb0ab79Smaybee 		else
1678cdb0ab79Smaybee 			return (error);
1679cdb0ab79Smaybee 	}
1680cdb0ab79Smaybee 
1681cdb0ab79Smaybee 	/*
1682cdb0ab79Smaybee 	 * Check for any locks in the region to be freed.
1683cdb0ab79Smaybee 	 */
16840a586ceaSMark Shellenbaum 
16850a586ceaSMark Shellenbaum 	if (MANDLOCK(vp, (mode_t)mode)) {
16860a586ceaSMark Shellenbaum 		uint64_t length = (len ? len : zp->z_size - off);
1687cdb0ab79Smaybee 		if (error = chklock(vp, FWRITE, off, length, flag, NULL))
1688cdb0ab79Smaybee 			return (error);
1689cdb0ab79Smaybee 	}
1690cdb0ab79Smaybee 
1691cdb0ab79Smaybee 	if (len == 0) {
1692cdb0ab79Smaybee 		error = zfs_trunc(zp, off);
1693cdb0ab79Smaybee 	} else {
1694cdb0ab79Smaybee 		if ((error = zfs_free_range(zp, off, len)) == 0 &&
16950a586ceaSMark Shellenbaum 		    off + len > zp->z_size)
1696cdb0ab79Smaybee 			error = zfs_extend(zp, off+len);
1697cdb0ab79Smaybee 	}
1698cdb0ab79Smaybee 	if (error || !log)
1699cdb0ab79Smaybee 		return (error);
1700cdb0ab79Smaybee log:
1701cdb0ab79Smaybee 	tx = dmu_tx_create(zfsvfs->z_os);
17020a586ceaSMark Shellenbaum 	dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE);
17030a586ceaSMark Shellenbaum 	zfs_sa_upgrade_txholds(tx, zp);
1704e722410cSMatthew Ahrens 	error = dmu_tx_assign(tx, TXG_WAIT);
1705cdb0ab79Smaybee 	if (error) {
1706cdb0ab79Smaybee 		dmu_tx_abort(tx);
1707cdb0ab79Smaybee 		return (error);
1708cdb0ab79Smaybee 	}
1709cdb0ab79Smaybee 
17100a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zfsvfs), NULL, mtime, 16);
17110a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL, ctime, 16);
1712db9986c7SMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs),
1713db9986c7SMark Shellenbaum 	    NULL, &zp->z_pflags, 8);
17140a586ceaSMark Shellenbaum 	zfs_tstamp_update_setup(zp, CONTENT_MODIFIED, mtime, ctime, B_TRUE);
17150a586ceaSMark Shellenbaum 	error = sa_bulk_update(zp->z_sa_hdl, bulk, count, tx);
17160a586ceaSMark Shellenbaum 	ASSERT(error == 0);
17170a586ceaSMark Shellenbaum 
1718cdb0ab79Smaybee 	zfs_log_truncate(zilog, tx, TX_TRUNCATE, zp, off, len);
1719cdb0ab79Smaybee 
1720cdb0ab79Smaybee 	dmu_tx_commit(tx);
1721cdb0ab79Smaybee 	return (0);
1722cdb0ab79Smaybee }
1723cdb0ab79Smaybee 
1724fa9e4066Sahrens void
1725de8267e0Stimh zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx)
1726fa9e4066Sahrens {
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;
1734c701fde6SGleb Smirnoff 	zfsvfs_t	*zfsvfs;
1735fa9e4066Sahrens 	vnode_t		*vp;
1736fa9e4066Sahrens 	vattr_t		vattr;
17374ccbb6e7Sahrens 	znode_t		*zp;
173889459e17SMark Shellenbaum 	zfs_acl_ids_t	acl_ids;
1739fa9e4066Sahrens 
1740fa9e4066Sahrens 	/*
1741fa9e4066Sahrens 	 * First attempt to create master node.
1742fa9e4066Sahrens 	 */
1743ea8dc4b6Seschrock 	/*
1744ea8dc4b6Seschrock 	 * In an empty objset, there are no blocks to read and thus
1745ea8dc4b6Seschrock 	 * there can be no i/o errors (which we assert below).
1746ea8dc4b6Seschrock 	 */
1747fa9e4066Sahrens 	moid = MASTER_NODE_OBJ;
1748fa9e4066Sahrens 	error = zap_create_claim(os, moid, DMU_OT_MASTER_NODE,
1749fa9e4066Sahrens 	    DMU_OT_NONE, 0, tx);
1750fa9e4066Sahrens 	ASSERT(error == 0);
1751fa9e4066Sahrens 
1752fa9e4066Sahrens 	/*
1753fa9e4066Sahrens 	 * Set starting attributes.
1754fa9e4066Sahrens 	 */
17550a586ceaSMark Shellenbaum 	version = zfs_zpl_version_map(spa_version(dmu_objset_spa(os)));
1756de8267e0Stimh 	elem = NULL;
1757de8267e0Stimh 	while ((elem = nvlist_next_nvpair(zplprops, elem)) != NULL) {
1758de8267e0Stimh 		/* For the moment we expect all zpl props to be uint64_ts */
1759de8267e0Stimh 		uint64_t val;
1760de8267e0Stimh 		char *name;
1761de8267e0Stimh 
1762de8267e0Stimh 		ASSERT(nvpair_type(elem) == DATA_TYPE_UINT64);
1763b3d911cbStimh 		VERIFY(nvpair_value_uint64(elem, &val) == 0);
1764de8267e0Stimh 		name = nvpair_name(elem);
1765de8267e0Stimh 		if (strcmp(name, zfs_prop_to_name(ZFS_PROP_VERSION)) == 0) {
176614843421SMatthew Ahrens 			if (val < version)
176714843421SMatthew Ahrens 				version = val;
1768de8267e0Stimh 		} else {
1769de8267e0Stimh 			error = zap_update(os, moid, name, 8, 1, &val, tx);
1770de8267e0Stimh 		}
1771de8267e0Stimh 		ASSERT(error == 0);
1772de8267e0Stimh 		if (strcmp(name, zfs_prop_to_name(ZFS_PROP_NORMALIZE)) == 0)
1773de8267e0Stimh 			norm = val;
1774de8267e0Stimh 		else if (strcmp(name, zfs_prop_to_name(ZFS_PROP_CASE)) == 0)
1775de8267e0Stimh 			sense = val;
1776de8267e0Stimh 	}
1777de8267e0Stimh 	ASSERT(version != 0);
177814843421SMatthew Ahrens 	error = zap_update(os, moid, ZPL_VERSION_STR, 8, 1, &version, tx);
1779fa9e4066Sahrens 
17800a586ceaSMark Shellenbaum 	/*
17810a586ceaSMark Shellenbaum 	 * Create zap object used for SA attribute registration
17820a586ceaSMark Shellenbaum 	 */
17830a586ceaSMark Shellenbaum 
17840a586ceaSMark Shellenbaum 	if (version >= ZPL_VERSION_SA) {
17850a586ceaSMark Shellenbaum 		sa_obj = zap_create(os, DMU_OT_SA_MASTER_NODE,
17860a586ceaSMark Shellenbaum 		    DMU_OT_NONE, 0, tx);
17870a586ceaSMark Shellenbaum 		error = zap_add(os, moid, ZFS_SA_ATTRS, 8, 1, &sa_obj, tx);
17880a586ceaSMark Shellenbaum 		ASSERT(error == 0);
17890a586ceaSMark Shellenbaum 	} else {
17900a586ceaSMark Shellenbaum 		sa_obj = 0;
17910a586ceaSMark Shellenbaum 	}
1792fa9e4066Sahrens 	/*
1793fa9e4066Sahrens 	 * Create a delete queue.
1794fa9e4066Sahrens 	 */
179514843421SMatthew Ahrens 	obj = zap_create(os, DMU_OT_UNLINKED_SET, DMU_OT_NONE, 0, tx);
1796fa9e4066Sahrens 
179714843421SMatthew Ahrens 	error = zap_add(os, moid, ZFS_UNLINKED_SET, 8, 1, &obj, tx);
1798fa9e4066Sahrens 	ASSERT(error == 0);
1799fa9e4066Sahrens 
1800fa9e4066Sahrens 	/*
1801fa9e4066Sahrens 	 * Create root znode.  Create minimal znode/vnode/zfsvfs
1802fa9e4066Sahrens 	 * to allow zfs_mknode to work.
1803fa9e4066Sahrens 	 */
1804fa9e4066Sahrens 	vattr.va_mask = AT_MODE|AT_UID|AT_GID|AT_TYPE;
1805fa9e4066Sahrens 	vattr.va_type = VDIR;
1806fa9e4066Sahrens 	vattr.va_mode = S_IFDIR|0755;
1807ecd6cf80Smarks 	vattr.va_uid = crgetuid(cr);
1808ecd6cf80Smarks 	vattr.va_gid = crgetgid(cr);
1809fa9e4066Sahrens 
1810fa9e4066Sahrens 	rootzp = kmem_cache_alloc(znode_cache, KM_SLEEP);
1811744947dcSTom Erickson 	ASSERT(!POINTER_IS_VALID(rootzp->z_zfsvfs));
1812744947dcSTom Erickson 	rootzp->z_moved = 0;
1813893a6d32Sahrens 	rootzp->z_unlinked = 0;
1814fa9e4066Sahrens 	rootzp->z_atime_dirty = 0;
18150a586ceaSMark Shellenbaum 	rootzp->z_is_sa = USE_SA(version, os);
1816fa9e4066Sahrens 
1817fa9e4066Sahrens 	vp = ZTOV(rootzp);
1818fa9e4066Sahrens 	vn_reinit(vp);
1819fa9e4066Sahrens 	vp->v_type = VDIR;
1820fa9e4066Sahrens 
1821c701fde6SGleb Smirnoff 	zfsvfs = kmem_zalloc(sizeof (zfsvfs_t), KM_SLEEP);
1822c701fde6SGleb Smirnoff 	zfsvfs->z_os = os;
1823c701fde6SGleb Smirnoff 	zfsvfs->z_parent = zfsvfs;
1824c701fde6SGleb Smirnoff 	zfsvfs->z_version = version;
1825c701fde6SGleb Smirnoff 	zfsvfs->z_use_fuids = USE_FUIDS(version, os);
1826c701fde6SGleb Smirnoff 	zfsvfs->z_use_sa = USE_SA(version, os);
1827c701fde6SGleb Smirnoff 	zfsvfs->z_norm = norm;
18280a586ceaSMark Shellenbaum 
18291d8ccc7bSMark Shellenbaum 	error = sa_setup(os, sa_obj, zfs_attr_table, ZPL_END,
1830c701fde6SGleb Smirnoff 	    &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)
1839c701fde6SGleb Smirnoff 		zfsvfs->z_norm |= U8_TEXTPREP_TOUPPER;
1840fa9e4066Sahrens 
1841c701fde6SGleb Smirnoff 	mutex_init(&zfsvfs->z_znodes_lock, NULL, MUTEX_DEFAULT, NULL);
1842c701fde6SGleb Smirnoff 	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++)
1846c701fde6SGleb Smirnoff 		mutex_init(&zfsvfs->z_hold_mtx[i], NULL, MUTEX_DEFAULT, NULL);
184759e7834dSMark Shellenbaum 
1848c701fde6SGleb Smirnoff 	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 
1867c701fde6SGleb Smirnoff 	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++)
1872c701fde6SGleb Smirnoff 		mutex_destroy(&zfsvfs->z_hold_mtx[i]);
1873c701fde6SGleb Smirnoff 	kmem_free(zfsvfs, sizeof (zfsvfs_t));
1874fa9e4066Sahrens }
187555434c77Sek 
1876da6c28aaSamw #endif /* _KERNEL */
18770a586ceaSMark Shellenbaum 
187855434c77Sek static int
187999d5e173STim Haley zfs_sa_setup(objset_t *osp, sa_attr_type_t **sa_table)
188099d5e173STim Haley {
188199d5e173STim Haley 	uint64_t sa_obj = 0;
188299d5e173STim Haley 	int error;
188399d5e173STim Haley 
188499d5e173STim Haley 	error = zap_lookup(osp, MASTER_NODE_OBJ, ZFS_SA_ATTRS, 8, 1, &sa_obj);
188599d5e173STim Haley 	if (error != 0 && error != ENOENT)
188699d5e173STim Haley 		return (error);
188799d5e173STim Haley 
188899d5e173STim Haley 	error = sa_setup(osp, sa_obj, zfs_attr_table, ZPL_END, sa_table);
188999d5e173STim Haley 	return (error);
189099d5e173STim Haley }
189199d5e173STim Haley 
189299d5e173STim Haley static int
189399d5e173STim Haley zfs_grab_sa_handle(objset_t *osp, uint64_t obj, sa_handle_t **hdlp,
1894163eb7ffSTim Haley     dmu_buf_t **db, void *tag)
189555434c77Sek {
189655434c77Sek 	dmu_object_info_t doi;
189755434c77Sek 	int error;
18980a586ceaSMark Shellenbaum 
1899163eb7ffSTim Haley 	if ((error = sa_buf_hold(osp, obj, tag, db)) != 0)
190055434c77Sek 		return (error);
190155434c77Sek 
190299d5e173STim Haley 	dmu_object_info_from_db(*db, &doi);
19030a586ceaSMark Shellenbaum 	if ((doi.doi_bonus_type != DMU_OT_SA &&
19040a586ceaSMark Shellenbaum 	    doi.doi_bonus_type != DMU_OT_ZNODE) ||
19050a586ceaSMark Shellenbaum 	    doi.doi_bonus_type == DMU_OT_ZNODE &&
190655434c77Sek 	    doi.doi_bonus_size < sizeof (znode_phys_t)) {
1907163eb7ffSTim Haley 		sa_buf_rele(*db, tag);
1908be6fd75aSMatthew Ahrens 		return (SET_ERROR(ENOTSUP));
190955434c77Sek 	}
191055434c77Sek 
191199d5e173STim Haley 	error = sa_handle_get(osp, obj, NULL, SA_HDL_PRIVATE, hdlp);
191299d5e173STim Haley 	if (error != 0) {
1913163eb7ffSTim Haley 		sa_buf_rele(*db, tag);
19140a586ceaSMark Shellenbaum 		return (error);
19150a586ceaSMark Shellenbaum 	}
19160a586ceaSMark Shellenbaum 
191799d5e173STim Haley 	return (0);
191899d5e173STim Haley }
191999d5e173STim Haley 
192099d5e173STim Haley void
1921163eb7ffSTim Haley zfs_release_sa_handle(sa_handle_t *hdl, dmu_buf_t *db, void *tag)
192299d5e173STim Haley {
192399d5e173STim Haley 	sa_handle_destroy(hdl);
1924163eb7ffSTim Haley 	sa_buf_rele(db, tag);
192599d5e173STim Haley }
192699d5e173STim Haley 
192799d5e173STim Haley /*
192899d5e173STim Haley  * Given an object number, return its parent object number and whether
192999d5e173STim Haley  * or not the object is an extended attribute directory.
193099d5e173STim Haley  */
193199d5e173STim Haley static int
19321ce39b5fSJeremy Jones zfs_obj_to_pobj(objset_t *osp, sa_handle_t *hdl, sa_attr_type_t *sa_table,
19331ce39b5fSJeremy Jones     uint64_t *pobjp, int *is_xattrdir)
193499d5e173STim Haley {
193599d5e173STim Haley 	uint64_t parent;
193699d5e173STim Haley 	uint64_t pflags;
193799d5e173STim Haley 	uint64_t mode;
19381ce39b5fSJeremy Jones 	uint64_t parent_mode;
193999d5e173STim Haley 	sa_bulk_attr_t bulk[3];
19401ce39b5fSJeremy Jones 	sa_handle_t *sa_hdl;
19411ce39b5fSJeremy Jones 	dmu_buf_t *sa_db;
194299d5e173STim Haley 	int count = 0;
194399d5e173STim Haley 	int error;
194499d5e173STim Haley 
194599d5e173STim Haley 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_PARENT], NULL,
194699d5e173STim Haley 	    &parent, sizeof (parent));
19470a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_FLAGS], NULL,
194899d5e173STim Haley 	    &pflags, sizeof (pflags));
19490a586ceaSMark Shellenbaum 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_MODE], NULL,
195099d5e173STim Haley 	    &mode, sizeof (mode));
19510a586ceaSMark Shellenbaum 
195299d5e173STim Haley 	if ((error = sa_bulk_lookup(hdl, bulk, count)) != 0)
19530a586ceaSMark Shellenbaum 		return (error);
195499d5e173STim Haley 
19551ce39b5fSJeremy Jones 	/*
19561ce39b5fSJeremy Jones 	 * When a link is removed its parent pointer is not changed and will
19571ce39b5fSJeremy Jones 	 * be invalid.  There are two cases where a link is removed but the
19581ce39b5fSJeremy Jones 	 * file stays around, when it goes to the delete queue and when there
19591ce39b5fSJeremy Jones 	 * are additional links.
19601ce39b5fSJeremy Jones 	 */
19611ce39b5fSJeremy Jones 	error = zfs_grab_sa_handle(osp, parent, &sa_hdl, &sa_db, FTAG);
19621ce39b5fSJeremy Jones 	if (error != 0)
19631ce39b5fSJeremy Jones 		return (error);
19641ce39b5fSJeremy Jones 
19651ce39b5fSJeremy Jones 	error = sa_lookup(sa_hdl, ZPL_MODE, &parent_mode, sizeof (parent_mode));
19661ce39b5fSJeremy Jones 	zfs_release_sa_handle(sa_hdl, sa_db, FTAG);
19671ce39b5fSJeremy Jones 	if (error != 0)
19681ce39b5fSJeremy Jones 		return (error);
19691ce39b5fSJeremy Jones 
19700a586ceaSMark Shellenbaum 	*is_xattrdir = ((pflags & ZFS_XATTR) != 0) && S_ISDIR(mode);
197155434c77Sek 
19721ce39b5fSJeremy Jones 	/*
19731ce39b5fSJeremy Jones 	 * Extended attributes can be applied to files, directories, etc.
19741ce39b5fSJeremy Jones 	 * Otherwise the parent must be a directory.
19751ce39b5fSJeremy Jones 	 */
19761ce39b5fSJeremy Jones 	if (!*is_xattrdir && !S_ISDIR(parent_mode))
1977be6fd75aSMatthew Ahrens 		return (SET_ERROR(EINVAL));
19781ce39b5fSJeremy Jones 
19791ce39b5fSJeremy Jones 	*pobjp = parent;
19801ce39b5fSJeremy Jones 
198155434c77Sek 	return (0);
198255434c77Sek }
198355434c77Sek 
198499d5e173STim Haley /*
198599d5e173STim Haley  * Given an object number, return some zpl level statistics
198699d5e173STim Haley  */
198799d5e173STim Haley static int
198899d5e173STim Haley zfs_obj_to_stats_impl(sa_handle_t *hdl, sa_attr_type_t *sa_table,
198999d5e173STim Haley     zfs_stat_t *sb)
199055434c77Sek {
199199d5e173STim Haley 	sa_bulk_attr_t bulk[4];
199299d5e173STim Haley 	int count = 0;
199399d5e173STim Haley 
199499d5e173STim Haley 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_MODE], NULL,
199599d5e173STim Haley 	    &sb->zs_mode, sizeof (sb->zs_mode));
199699d5e173STim Haley 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_GEN], NULL,
199799d5e173STim Haley 	    &sb->zs_gen, sizeof (sb->zs_gen));
199899d5e173STim Haley 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_LINKS], NULL,
199999d5e173STim Haley 	    &sb->zs_links, sizeof (sb->zs_links));
200099d5e173STim Haley 	SA_ADD_BULK_ATTR(bulk, count, sa_table[ZPL_CTIME], NULL,
200199d5e173STim Haley 	    &sb->zs_ctime, sizeof (sb->zs_ctime));
200299d5e173STim Haley 
200399d5e173STim Haley 	return (sa_bulk_lookup(hdl, bulk, count));
200499d5e173STim Haley }
200599d5e173STim Haley 
200699d5e173STim Haley static int
200799d5e173STim Haley zfs_obj_to_path_impl(objset_t *osp, uint64_t obj, sa_handle_t *hdl,
200899d5e173STim Haley     sa_attr_type_t *sa_table, char *buf, int len)
200999d5e173STim Haley {
201099d5e173STim Haley 	sa_handle_t *sa_hdl;
201199d5e173STim Haley 	sa_handle_t *prevhdl = NULL;
201299d5e173STim Haley 	dmu_buf_t *prevdb = NULL;
201399d5e173STim Haley 	dmu_buf_t *sa_db = NULL;
201455434c77Sek 	char *path = buf + len - 1;
201555434c77Sek 	int error;
201655434c77Sek 
201755434c77Sek 	*path = '\0';
201899d5e173STim Haley 	sa_hdl = hdl;
20190a586ceaSMark Shellenbaum 
202055434c77Sek 	for (;;) {
202155434c77Sek 		uint64_t pobj;
202255434c77Sek 		char component[MAXNAMELEN + 2];
202355434c77Sek 		size_t complen;
202455434c77Sek 		int is_xattrdir;
202555434c77Sek 
202699d5e173STim Haley 		if (prevdb)
2027163eb7ffSTim Haley 			zfs_release_sa_handle(prevhdl, prevdb, FTAG);
202899d5e173STim Haley 
20291ce39b5fSJeremy Jones 		if ((error = zfs_obj_to_pobj(osp, sa_hdl, sa_table, &pobj,
203099d5e173STim Haley 		    &is_xattrdir)) != 0)
203155434c77Sek 			break;
203255434c77Sek 
203355434c77Sek 		if (pobj == obj) {
203455434c77Sek 			if (path[0] != '/')
203555434c77Sek 				*--path = '/';
203655434c77Sek 			break;
203755434c77Sek 		}
203855434c77Sek 
203955434c77Sek 		component[0] = '/';
204055434c77Sek 		if (is_xattrdir) {
204155434c77Sek 			(void) sprintf(component + 1, "<xattrdir>");
204255434c77Sek 		} else {
2043e7437265Sahrens 			error = zap_value_search(osp, pobj, obj,
2044e7437265Sahrens 			    ZFS_DIRENT_OBJ(-1ULL), component + 1);
204555434c77Sek 			if (error != 0)
204655434c77Sek 				break;
204755434c77Sek 		}
204855434c77Sek 
204955434c77Sek 		complen = strlen(component);
205055434c77Sek 		path -= complen;
205155434c77Sek 		ASSERT(path >= buf);
205255434c77Sek 		bcopy(component, path, complen);
205355434c77Sek 		obj = pobj;
205499d5e173STim Haley 
205599d5e173STim Haley 		if (sa_hdl != hdl) {
205699d5e173STim Haley 			prevhdl = sa_hdl;
205799d5e173STim Haley 			prevdb = sa_db;
205899d5e173STim Haley 		}
2059163eb7ffSTim Haley 		error = zfs_grab_sa_handle(osp, obj, &sa_hdl, &sa_db, FTAG);
206099d5e173STim Haley 		if (error != 0) {
206199d5e173STim Haley 			sa_hdl = prevhdl;
206299d5e173STim Haley 			sa_db = prevdb;
206399d5e173STim Haley 			break;
206499d5e173STim Haley 		}
206599d5e173STim Haley 	}
206699d5e173STim Haley 
206799d5e173STim Haley 	if (sa_hdl != NULL && sa_hdl != hdl) {
206899d5e173STim Haley 		ASSERT(sa_db != NULL);
2069163eb7ffSTim Haley 		zfs_release_sa_handle(sa_hdl, sa_db, FTAG);
207055434c77Sek 	}
207155434c77Sek 
207255434c77Sek 	if (error == 0)
207355434c77Sek 		(void) memmove(buf, path, buf + len - path);
20740a586ceaSMark Shellenbaum 
207555434c77Sek 	return (error);
207655434c77Sek }
207799d5e173STim Haley 
207899d5e173STim Haley int
207999d5e173STim Haley zfs_obj_to_path(objset_t *osp, uint64_t obj, char *buf, int len)
208099d5e173STim Haley {
208199d5e173STim Haley 	sa_attr_type_t *sa_table;
208299d5e173STim Haley 	sa_handle_t *hdl;
208399d5e173STim Haley 	dmu_buf_t *db;
208499d5e173STim Haley 	int error;
208599d5e173STim Haley 
208699d5e173STim Haley 	error = zfs_sa_setup(osp, &sa_table);
208799d5e173STim Haley 	if (error != 0)
208899d5e173STim Haley 		return (error);
208999d5e173STim Haley 
2090163eb7ffSTim Haley 	error = zfs_grab_sa_handle(osp, obj, &hdl, &db, FTAG);
209199d5e173STim Haley 	if (error != 0)
209299d5e173STim Haley 		return (error);
209399d5e173STim Haley 
209499d5e173STim Haley 	error = zfs_obj_to_path_impl(osp, obj, hdl, sa_table, buf, len);
209599d5e173STim Haley 
2096163eb7ffSTim Haley 	zfs_release_sa_handle(hdl, db, FTAG);
209799d5e173STim Haley 	return (error);
209899d5e173STim Haley }
209999d5e173STim Haley 
210099d5e173STim Haley int
210199d5e173STim Haley zfs_obj_to_stats(objset_t *osp, uint64_t obj, zfs_stat_t *sb,
210299d5e173STim Haley     char *buf, int len)
210399d5e173STim Haley {
210499d5e173STim Haley 	char *path = buf + len - 1;
210599d5e173STim Haley 	sa_attr_type_t *sa_table;
210699d5e173STim Haley 	sa_handle_t *hdl;
210799d5e173STim Haley 	dmu_buf_t *db;
210899d5e173STim Haley 	int error;
210999d5e173STim Haley 
211099d5e173STim Haley 	*path = '\0';
211199d5e173STim Haley 
211299d5e173STim Haley 	error = zfs_sa_setup(osp, &sa_table);
211399d5e173STim Haley 	if (error != 0)
211499d5e173STim Haley 		return (error);
211599d5e173STim Haley 
2116163eb7ffSTim Haley 	error = zfs_grab_sa_handle(osp, obj, &hdl, &db, FTAG);
211799d5e173STim Haley 	if (error != 0)
211899d5e173STim Haley 		return (error);
211999d5e173STim Haley 
212099d5e173STim Haley 	error = zfs_obj_to_stats_impl(hdl, sa_table, sb);
212199d5e173STim Haley 	if (error != 0) {
2122163eb7ffSTim Haley 		zfs_release_sa_handle(hdl, db, FTAG);
212399d5e173STim Haley 		return (error);
212499d5e173STim Haley 	}
212599d5e173STim Haley 
212699d5e173STim Haley 	error = zfs_obj_to_path_impl(osp, obj, hdl, sa_table, buf, len);
212799d5e173STim Haley 
2128163eb7ffSTim Haley 	zfs_release_sa_handle(hdl, db, FTAG);
212999d5e173STim Haley 	return (error);
213099d5e173STim Haley }
2131