zfs_vnops.c revision 169057
1168404Spjd/*
2168404Spjd * CDDL HEADER START
3168404Spjd *
4168404Spjd * The contents of this file are subject to the terms of the
5168404Spjd * Common Development and Distribution License (the "License").
6168404Spjd * You may not use this file except in compliance with the License.
7168404Spjd *
8168404Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9168404Spjd * or http://www.opensolaris.org/os/licensing.
10168404Spjd * See the License for the specific language governing permissions
11168404Spjd * and limitations under the License.
12168404Spjd *
13168404Spjd * When distributing Covered Code, include this CDDL HEADER in each
14168404Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15168404Spjd * If applicable, add the following below this CDDL HEADER, with the
16168404Spjd * fields enclosed by brackets "[]" replaced with your own identifying
17168404Spjd * information: Portions Copyright [yyyy] [name of copyright owner]
18168404Spjd *
19168404Spjd * CDDL HEADER END
20168404Spjd */
21168404Spjd/*
22168404Spjd * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23168404Spjd * Use is subject to license terms.
24168404Spjd */
25168404Spjd
26168404Spjd#pragma ident	"%Z%%M%	%I%	%E% SMI"
27168404Spjd
28168404Spjd#include <sys/types.h>
29168404Spjd#include <sys/param.h>
30168404Spjd#include <sys/time.h>
31168404Spjd#include <sys/systm.h>
32168404Spjd#include <sys/sysmacros.h>
33168404Spjd#include <sys/resource.h>
34168404Spjd#include <sys/vfs.h>
35168404Spjd#include <sys/vnode.h>
36168404Spjd#include <sys/file.h>
37168404Spjd#include <sys/stat.h>
38168404Spjd#include <sys/kmem.h>
39168404Spjd#include <sys/taskq.h>
40168404Spjd#include <sys/uio.h>
41168404Spjd#include <sys/atomic.h>
42168404Spjd#include <sys/namei.h>
43168404Spjd#include <sys/mman.h>
44168404Spjd#include <sys/cmn_err.h>
45168404Spjd#include <sys/errno.h>
46168404Spjd#include <sys/unistd.h>
47168404Spjd#include <sys/zfs_vfsops.h>
48168404Spjd#include <sys/zfs_dir.h>
49168404Spjd#include <sys/zfs_acl.h>
50168404Spjd#include <sys/zfs_ioctl.h>
51168404Spjd#include <sys/fs/zfs.h>
52168404Spjd#include <sys/dmu.h>
53168404Spjd#include <sys/spa.h>
54168404Spjd#include <sys/txg.h>
55168404Spjd#include <sys/dbuf.h>
56168404Spjd#include <sys/zap.h>
57168404Spjd#include <sys/dirent.h>
58168962Spjd#include <sys/policy.h>
59168962Spjd#include <sys/sunddi.h>
60168404Spjd#include <sys/filio.h>
61168404Spjd#include <sys/zfs_ctldir.h>
62168404Spjd#include <sys/dnlc.h>
63168404Spjd#include <sys/zfs_rlock.h>
64168404Spjd#include <sys/bio.h>
65168404Spjd#include <sys/buf.h>
66168404Spjd#include <sys/sf_buf.h>
67168404Spjd#include <sys/sched.h>
68168404Spjd
69168404Spjd/*
70168404Spjd * Programming rules.
71168404Spjd *
72168404Spjd * Each vnode op performs some logical unit of work.  To do this, the ZPL must
73168404Spjd * properly lock its in-core state, create a DMU transaction, do the work,
74168404Spjd * record this work in the intent log (ZIL), commit the DMU transaction,
75168404Spjd * and wait the the intent log to commit if it's is a synchronous operation.
76168404Spjd * Morover, the vnode ops must work in both normal and log replay context.
77168404Spjd * The ordering of events is important to avoid deadlocks and references
78168404Spjd * to freed memory.  The example below illustrates the following Big Rules:
79168404Spjd *
80168404Spjd *  (1) A check must be made in each zfs thread for a mounted file system.
81168404Spjd *	This is done avoiding races using ZFS_ENTER(zfsvfs).
82168404Spjd *	A ZFS_EXIT(zfsvfs) is needed before all returns.
83168404Spjd *
84168404Spjd *  (2)	VN_RELE() should always be the last thing except for zil_commit()
85168404Spjd *	(if necessary) and ZFS_EXIT(). This is for 3 reasons:
86168404Spjd *	First, if it's the last reference, the vnode/znode
87168404Spjd *	can be freed, so the zp may point to freed memory.  Second, the last
88168404Spjd *	reference will call zfs_zinactive(), which may induce a lot of work --
89168404Spjd *	pushing cached pages (which acquires range locks) and syncing out
90168404Spjd *	cached atime changes.  Third, zfs_zinactive() may require a new tx,
91168404Spjd *	which could deadlock the system if you were already holding one.
92168404Spjd *
93168404Spjd *  (3)	All range locks must be grabbed before calling dmu_tx_assign(),
94168404Spjd *	as they can span dmu_tx_assign() calls.
95168404Spjd *
96168404Spjd *  (4)	Always pass zfsvfs->z_assign as the second argument to dmu_tx_assign().
97168404Spjd *	In normal operation, this will be TXG_NOWAIT.  During ZIL replay,
98168404Spjd *	it will be a specific txg.  Either way, dmu_tx_assign() never blocks.
99168404Spjd *	This is critical because we don't want to block while holding locks.
100168404Spjd *	Note, in particular, that if a lock is sometimes acquired before
101168404Spjd *	the tx assigns, and sometimes after (e.g. z_lock), then failing to
102168404Spjd *	use a non-blocking assign can deadlock the system.  The scenario:
103168404Spjd *
104168404Spjd *	Thread A has grabbed a lock before calling dmu_tx_assign().
105168404Spjd *	Thread B is in an already-assigned tx, and blocks for this lock.
106168404Spjd *	Thread A calls dmu_tx_assign(TXG_WAIT) and blocks in txg_wait_open()
107168404Spjd *	forever, because the previous txg can't quiesce until B's tx commits.
108168404Spjd *
109168404Spjd *	If dmu_tx_assign() returns ERESTART and zfsvfs->z_assign is TXG_NOWAIT,
110168404Spjd *	then drop all locks, call dmu_tx_wait(), and try again.
111168404Spjd *
112168404Spjd *  (5)	If the operation succeeded, generate the intent log entry for it
113168404Spjd *	before dropping locks.  This ensures that the ordering of events
114168404Spjd *	in the intent log matches the order in which they actually occurred.
115168404Spjd *
116168404Spjd *  (6)	At the end of each vnode op, the DMU tx must always commit,
117168404Spjd *	regardless of whether there were any errors.
118168404Spjd *
119168404Spjd *  (7)	After dropping all locks, invoke zil_commit(zilog, seq, foid)
120168404Spjd *	to ensure that synchronous semantics are provided when necessary.
121168404Spjd *
122168404Spjd * In general, this is how things should be ordered in each vnode op:
123168404Spjd *
124168404Spjd *	ZFS_ENTER(zfsvfs);		// exit if unmounted
125168404Spjd * top:
126168404Spjd *	zfs_dirent_lock(&dl, ...)	// lock directory entry (may VN_HOLD())
127168404Spjd *	rw_enter(...);			// grab any other locks you need
128168404Spjd *	tx = dmu_tx_create(...);	// get DMU tx
129168404Spjd *	dmu_tx_hold_*();		// hold each object you might modify
130168404Spjd *	error = dmu_tx_assign(tx, zfsvfs->z_assign);	// try to assign
131168404Spjd *	if (error) {
132168404Spjd *		rw_exit(...);		// drop locks
133168404Spjd *		zfs_dirent_unlock(dl);	// unlock directory entry
134168404Spjd *		VN_RELE(...);		// release held vnodes
135168404Spjd *		if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) {
136168404Spjd *			dmu_tx_wait(tx);
137168404Spjd *			dmu_tx_abort(tx);
138168404Spjd *			goto top;
139168404Spjd *		}
140168404Spjd *		dmu_tx_abort(tx);	// abort DMU tx
141168404Spjd *		ZFS_EXIT(zfsvfs);	// finished in zfs
142168404Spjd *		return (error);		// really out of space
143168404Spjd *	}
144168404Spjd *	error = do_real_work();		// do whatever this VOP does
145168404Spjd *	if (error == 0)
146168404Spjd *		zfs_log_*(...);		// on success, make ZIL entry
147168404Spjd *	dmu_tx_commit(tx);		// commit DMU tx -- error or not
148168404Spjd *	rw_exit(...);			// drop locks
149168404Spjd *	zfs_dirent_unlock(dl);		// unlock directory entry
150168404Spjd *	VN_RELE(...);			// release held vnodes
151168404Spjd *	zil_commit(zilog, seq, foid);	// synchronous when necessary
152168404Spjd *	ZFS_EXIT(zfsvfs);		// finished in zfs
153168404Spjd *	return (error);			// done, report error
154168404Spjd */
155168404Spjd/* ARGSUSED */
156168404Spjdstatic int
157168962Spjdzfs_open(vnode_t **vpp, int flag, cred_t *cr)
158168404Spjd{
159168962Spjd	znode_t	*zp = VTOZ(*vpp);
160168404Spjd
161168404Spjd	/* Keep a count of the synchronous opens in the znode */
162168962Spjd	if (flag & (FSYNC | FDSYNC))
163168404Spjd		atomic_inc_32(&zp->z_sync_cnt);
164168404Spjd	return (0);
165168404Spjd}
166168404Spjd
167168404Spjd/* ARGSUSED */
168168404Spjdstatic int
169168962Spjdzfs_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr)
170168404Spjd{
171168962Spjd	znode_t	*zp = VTOZ(vp);
172168404Spjd
173168404Spjd	/* Decrement the synchronous opens in the znode */
174168962Spjd	if (flag & (FSYNC | FDSYNC))
175168404Spjd		atomic_dec_32(&zp->z_sync_cnt);
176168404Spjd
177168962Spjd	/*
178168962Spjd	 * Clean up any locks held by this process on the vp.
179168962Spjd	 */
180168962Spjd	cleanlocks(vp, ddi_get_pid(), 0);
181168962Spjd	cleanshares(vp, ddi_get_pid());
182168962Spjd
183168404Spjd	return (0);
184168404Spjd}
185168404Spjd
186168404Spjd/*
187168404Spjd * Lseek support for finding holes (cmd == _FIO_SEEK_HOLE) and
188168404Spjd * data (cmd == _FIO_SEEK_DATA). "off" is an in/out parameter.
189168404Spjd */
190168404Spjdstatic int
191168978Spjdzfs_holey(vnode_t *vp, u_long cmd, offset_t *off)
192168404Spjd{
193168404Spjd	znode_t	*zp = VTOZ(vp);
194168404Spjd	uint64_t noff = (uint64_t)*off; /* new offset */
195168404Spjd	uint64_t file_sz;
196168404Spjd	int error;
197168404Spjd	boolean_t hole;
198168404Spjd
199168404Spjd	file_sz = zp->z_phys->zp_size;
200168404Spjd	if (noff >= file_sz)  {
201168404Spjd		return (ENXIO);
202168404Spjd	}
203168404Spjd
204168962Spjd	if (cmd == _FIO_SEEK_HOLE)
205168404Spjd		hole = B_TRUE;
206168404Spjd	else
207168404Spjd		hole = B_FALSE;
208168404Spjd
209168404Spjd	error = dmu_offset_next(zp->z_zfsvfs->z_os, zp->z_id, hole, &noff);
210168404Spjd
211168404Spjd	/* end of file? */
212168404Spjd	if ((error == ESRCH) || (noff > file_sz)) {
213168404Spjd		/*
214168404Spjd		 * Handle the virtual hole at the end of file.
215168404Spjd		 */
216168404Spjd		if (hole) {
217168404Spjd			*off = file_sz;
218168404Spjd			return (0);
219168404Spjd		}
220168404Spjd		return (ENXIO);
221168404Spjd	}
222168404Spjd
223168404Spjd	if (noff < *off)
224168404Spjd		return (error);
225168404Spjd	*off = noff;
226168404Spjd	return (error);
227168404Spjd}
228168404Spjd
229168404Spjd/* ARGSUSED */
230168404Spjdstatic int
231168978Spjdzfs_ioctl(vnode_t *vp, u_long com, intptr_t data, int flag, cred_t *cred,
232168962Spjd    int *rvalp)
233168404Spjd{
234168962Spjd	offset_t off;
235168962Spjd	int error;
236168962Spjd	zfsvfs_t *zfsvfs;
237168404Spjd
238168404Spjd	switch (com) {
239168962Spjd	    case _FIOFFS:
240168962Spjd		return (0);
241168404Spjd
242168962Spjd		/*
243168962Spjd		 * The following two ioctls are used by bfu.  Faking out,
244168962Spjd		 * necessary to avoid bfu errors.
245168962Spjd		 */
246168962Spjd	    case _FIOGDIO:
247168962Spjd	    case _FIOSDIO:
248168962Spjd		return (0);
249168962Spjd
250168962Spjd	    case _FIO_SEEK_DATA:
251168962Spjd	    case _FIO_SEEK_HOLE:
252168962Spjd		if (ddi_copyin((void *)data, &off, sizeof (off), flag))
253168962Spjd			return (EFAULT);
254168962Spjd
255168404Spjd		zfsvfs = VTOZ(vp)->z_zfsvfs;
256168404Spjd		ZFS_ENTER(zfsvfs);
257168404Spjd
258168404Spjd		/* offset parameter is in/out */
259168404Spjd		error = zfs_holey(vp, com, &off);
260168404Spjd		ZFS_EXIT(zfsvfs);
261168404Spjd		if (error)
262168404Spjd			return (error);
263168962Spjd		if (ddi_copyout(&off, (void *)data, sizeof (off), flag))
264168962Spjd			return (EFAULT);
265168404Spjd		return (0);
266168404Spjd	}
267168404Spjd	return (ENOTTY);
268168404Spjd}
269168404Spjd
270168404Spjd/*
271168404Spjd * When a file is memory mapped, we must keep the IO data synchronized
272168404Spjd * between the DMU cache and the memory mapped pages.  What this means:
273168404Spjd *
274168404Spjd * On Write:	If we find a memory mapped page, we write to *both*
275168404Spjd *		the page and the dmu buffer.
276168404Spjd *
277168404Spjd * NOTE: We will always "break up" the IO into PAGESIZE uiomoves when
278168404Spjd *	the file is memory mapped.
279168404Spjd */
280168404Spjdstatic int
281168404Spjdmappedwrite(vnode_t *vp, int nbytes, uio_t *uio, dmu_tx_t *tx)
282168404Spjd{
283168404Spjd	znode_t *zp = VTOZ(vp);
284168404Spjd	objset_t *os = zp->z_zfsvfs->z_os;
285168404Spjd	vm_object_t obj;
286168404Spjd	vm_page_t m;
287168404Spjd	struct sf_buf *sf;
288168404Spjd	int64_t start, off;
289168404Spjd	int len = nbytes;
290168404Spjd	int error = 0;
291168404Spjd
292168404Spjd	ASSERT(vp->v_mount != NULL);
293168404Spjd	obj = vp->v_object;
294168404Spjd	ASSERT(obj != NULL);
295168404Spjd
296168404Spjd	start = uio->uio_loffset;
297168404Spjd	off = start & PAGEOFFSET;
298168404Spjd	VM_OBJECT_LOCK(obj);
299168404Spjd	for (start &= PAGEMASK; len > 0; start += PAGESIZE) {
300168404Spjd		uint64_t bytes = MIN(PAGESIZE - off, len);
301168404Spjd
302168404Spjdagain:
303168404Spjd		if ((m = vm_page_lookup(obj, OFF_TO_IDX(start))) != NULL &&
304168404Spjd		    vm_page_is_valid(m, (vm_offset_t)off, bytes)) {
305169057Spjd			uint64_t woff, dmubytes;
306168404Spjd			caddr_t va;
307168404Spjd
308168404Spjd			if (vm_page_sleep_if_busy(m, FALSE, "zfsmwb"))
309168404Spjd				goto again;
310169057Spjd			woff = uio->uio_loffset;
311169057Spjd			dmubytes = MIN(PAGESIZE,
312169057Spjd			    obj->un_pager.vnp.vnp_size - (woff - off));
313168404Spjd			vm_page_busy(m);
314169057Spjd			vm_page_lock_queues();
315169057Spjd			vm_page_undirty(m);
316169057Spjd			vm_page_unlock_queues();
317168404Spjd			VM_OBJECT_UNLOCK(obj);
318168404Spjd			sched_pin();
319168404Spjd			sf = sf_buf_alloc(m, SFB_CPUPRIVATE);
320168404Spjd			va = (caddr_t)sf_buf_kva(sf);
321169057Spjd			error = uiomove(va + off, bytes, UIO_WRITE, uio);
322169057Spjd			dmu_write(os, zp->z_id, woff - off, dmubytes, va, tx);
323168404Spjd			sf_buf_free(sf);
324168404Spjd			sched_unpin();
325168404Spjd			VM_OBJECT_LOCK(obj);
326168404Spjd			vm_page_wakeup(m);
327168404Spjd		} else {
328168404Spjd			VM_OBJECT_UNLOCK(obj);
329168404Spjd			error = dmu_write_uio(os, zp->z_id, uio, bytes, tx);
330168404Spjd			VM_OBJECT_LOCK(obj);
331168404Spjd		}
332168404Spjd		len -= bytes;
333168404Spjd		off = 0;
334168404Spjd		if (error)
335168404Spjd			break;
336168404Spjd	}
337168404Spjd	VM_OBJECT_UNLOCK(obj);
338168404Spjd	return (error);
339168404Spjd}
340168404Spjd
341168404Spjd/*
342168404Spjd * When a file is memory mapped, we must keep the IO data synchronized
343168404Spjd * between the DMU cache and the memory mapped pages.  What this means:
344168404Spjd *
345168404Spjd * On Read:	We "read" preferentially from memory mapped pages,
346168404Spjd *		else we default from the dmu buffer.
347168404Spjd *
348168404Spjd * NOTE: We will always "break up" the IO into PAGESIZE uiomoves when
349168404Spjd *	the file is memory mapped.
350168404Spjd */
351168404Spjdstatic int
352168404Spjdmappedread(vnode_t *vp, int nbytes, uio_t *uio)
353168404Spjd{
354168404Spjd	znode_t *zp = VTOZ(vp);
355168404Spjd	objset_t *os = zp->z_zfsvfs->z_os;
356168404Spjd	vm_object_t obj;
357168404Spjd	vm_page_t m;
358168404Spjd	struct sf_buf *sf;
359168404Spjd	int64_t start, off;
360168926Spjd	caddr_t va;
361168404Spjd	int len = nbytes;
362168404Spjd	int error = 0;
363168404Spjd
364168404Spjd	ASSERT(vp->v_mount != NULL);
365168404Spjd	obj = vp->v_object;
366168404Spjd	ASSERT(obj != NULL);
367168404Spjd
368168404Spjd	start = uio->uio_loffset;
369168404Spjd	off = start & PAGEOFFSET;
370168404Spjd	VM_OBJECT_LOCK(obj);
371168404Spjd	for (start &= PAGEMASK; len > 0; start += PAGESIZE) {
372168404Spjd		uint64_t bytes = MIN(PAGESIZE - off, len);
373168404Spjd
374168404Spjdagain:
375168404Spjd		if ((m = vm_page_lookup(obj, OFF_TO_IDX(start))) != NULL &&
376168404Spjd		    vm_page_is_valid(m, (vm_offset_t)off, bytes)) {
377168404Spjd			if (vm_page_sleep_if_busy(m, FALSE, "zfsmrb"))
378168404Spjd				goto again;
379168404Spjd			vm_page_busy(m);
380168404Spjd			VM_OBJECT_UNLOCK(obj);
381168404Spjd			sched_pin();
382168404Spjd			sf = sf_buf_alloc(m, SFB_CPUPRIVATE);
383168404Spjd			va = (caddr_t)sf_buf_kva(sf);
384168404Spjd			error = uiomove(va + off, bytes, UIO_READ, uio);
385168404Spjd			sf_buf_free(sf);
386168404Spjd			sched_unpin();
387168404Spjd			VM_OBJECT_LOCK(obj);
388168404Spjd			vm_page_wakeup(m);
389168926Spjd		} else if (m != NULL && uio->uio_segflg == UIO_NOCOPY) {
390168962Spjd			/*
391168962Spjd			 * The code below is here to make sendfile(2) work
392168962Spjd			 * correctly with ZFS. As pointed out by ups@
393168962Spjd			 * sendfile(2) should be changed to use VOP_GETPAGES(),
394168962Spjd			 * but it pessimize performance of sendfile/UFS, that's
395168962Spjd			 * why I handle this special case in ZFS code.
396168962Spjd			 */
397168926Spjd			if (vm_page_sleep_if_busy(m, FALSE, "zfsmrb"))
398168926Spjd				goto again;
399168926Spjd			vm_page_busy(m);
400168926Spjd			VM_OBJECT_UNLOCK(obj);
401168926Spjd			sched_pin();
402168926Spjd			sf = sf_buf_alloc(m, SFB_CPUPRIVATE);
403168926Spjd			va = (caddr_t)sf_buf_kva(sf);
404168926Spjd			error = dmu_read(os, zp->z_id, start + off, bytes,
405168926Spjd			    (void *)(va + off));
406168926Spjd			sf_buf_free(sf);
407168926Spjd			sched_unpin();
408168926Spjd			VM_OBJECT_LOCK(obj);
409168926Spjd			vm_page_wakeup(m);
410168926Spjd			uio->uio_resid -= bytes;
411168404Spjd		} else {
412168404Spjd			VM_OBJECT_UNLOCK(obj);
413168404Spjd			error = dmu_read_uio(os, zp->z_id, uio, bytes);
414168404Spjd			VM_OBJECT_LOCK(obj);
415168404Spjd		}
416168404Spjd		len -= bytes;
417168404Spjd		off = 0;
418168404Spjd		if (error)
419168404Spjd			break;
420168404Spjd	}
421168404Spjd	VM_OBJECT_UNLOCK(obj);
422168404Spjd	return (error);
423168404Spjd}
424168404Spjd
425168404Spjdoffset_t zfs_read_chunk_size = 1024 * 1024; /* Tunable */
426168404Spjd
427168404Spjd/*
428168404Spjd * Read bytes from specified file into supplied buffer.
429168404Spjd *
430168404Spjd *	IN:	vp	- vnode of file to be read from.
431168404Spjd *		uio	- structure supplying read location, range info,
432168404Spjd *			  and return buffer.
433168404Spjd *		ioflag	- SYNC flags; used to provide FRSYNC semantics.
434168404Spjd *		cr	- credentials of caller.
435168404Spjd *
436168404Spjd *	OUT:	uio	- updated offset and range, buffer filled.
437168404Spjd *
438168404Spjd *	RETURN:	0 if success
439168404Spjd *		error code if failure
440168404Spjd *
441168404Spjd * Side Effects:
442168404Spjd *	vp - atime updated if byte count > 0
443168404Spjd */
444168404Spjd/* ARGSUSED */
445168404Spjdstatic int
446168962Spjdzfs_read(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct)
447168404Spjd{
448168404Spjd	znode_t		*zp = VTOZ(vp);
449168404Spjd	zfsvfs_t	*zfsvfs = zp->z_zfsvfs;
450168404Spjd	objset_t	*os = zfsvfs->z_os;
451168404Spjd	ssize_t		n, nbytes;
452168404Spjd	int		error;
453168404Spjd	rl_t		*rl;
454168404Spjd
455168404Spjd	ZFS_ENTER(zfsvfs);
456168404Spjd
457168404Spjd	/*
458168404Spjd	 * Validate file offset
459168404Spjd	 */
460168404Spjd	if (uio->uio_loffset < (offset_t)0) {
461168404Spjd		ZFS_EXIT(zfsvfs);
462168404Spjd		return (EINVAL);
463168404Spjd	}
464168404Spjd
465168404Spjd	/*
466168404Spjd	 * Fasttrack empty reads
467168404Spjd	 */
468168404Spjd	if (uio->uio_resid == 0) {
469168404Spjd		ZFS_EXIT(zfsvfs);
470168404Spjd		return (0);
471168404Spjd	}
472168404Spjd
473168404Spjd	/*
474168962Spjd	 * Check for mandatory locks
475168962Spjd	 */
476168962Spjd	if (MANDMODE((mode_t)zp->z_phys->zp_mode)) {
477168962Spjd		if (error = chklock(vp, FREAD,
478168962Spjd		    uio->uio_loffset, uio->uio_resid, uio->uio_fmode, ct)) {
479168962Spjd			ZFS_EXIT(zfsvfs);
480168962Spjd			return (error);
481168962Spjd		}
482168962Spjd	}
483168962Spjd
484168962Spjd	/*
485168404Spjd	 * If we're in FRSYNC mode, sync out this znode before reading it.
486168404Spjd	 */
487168962Spjd	if (ioflag & FRSYNC)
488168404Spjd		zil_commit(zfsvfs->z_log, zp->z_last_itx, zp->z_id);
489168404Spjd
490168404Spjd	/*
491168404Spjd	 * Lock the range against changes.
492168404Spjd	 */
493168404Spjd	rl = zfs_range_lock(zp, uio->uio_loffset, uio->uio_resid, RL_READER);
494168404Spjd
495168404Spjd	/*
496168404Spjd	 * If we are reading past end-of-file we can skip
497168404Spjd	 * to the end; but we might still need to set atime.
498168404Spjd	 */
499168404Spjd	if (uio->uio_loffset >= zp->z_phys->zp_size) {
500168404Spjd		error = 0;
501168404Spjd		goto out;
502168404Spjd	}
503168404Spjd
504168404Spjd	ASSERT(uio->uio_loffset < zp->z_phys->zp_size);
505168404Spjd	n = MIN(uio->uio_resid, zp->z_phys->zp_size - uio->uio_loffset);
506168404Spjd
507168404Spjd	while (n > 0) {
508168404Spjd		nbytes = MIN(n, zfs_read_chunk_size -
509168404Spjd		    P2PHASE(uio->uio_loffset, zfs_read_chunk_size));
510168404Spjd
511168404Spjd		if (vn_has_cached_data(vp))
512168404Spjd			error = mappedread(vp, nbytes, uio);
513168404Spjd		else
514168404Spjd			error = dmu_read_uio(os, zp->z_id, uio, nbytes);
515168404Spjd		if (error)
516168404Spjd			break;
517168962Spjd
518168404Spjd		n -= nbytes;
519168404Spjd	}
520168404Spjd
521168404Spjdout:
522168404Spjd	zfs_range_unlock(rl);
523168404Spjd
524168404Spjd	ZFS_ACCESSTIME_STAMP(zfsvfs, zp);
525168404Spjd	ZFS_EXIT(zfsvfs);
526168404Spjd	return (error);
527168404Spjd}
528168404Spjd
529168404Spjd/*
530168404Spjd * Fault in the pages of the first n bytes specified by the uio structure.
531168404Spjd * 1 byte in each page is touched and the uio struct is unmodified.
532168404Spjd * Any error will exit this routine as this is only a best
533168404Spjd * attempt to get the pages resident. This is a copy of ufs_trans_touch().
534168404Spjd */
535168404Spjdstatic void
536168404Spjdzfs_prefault_write(ssize_t n, struct uio *uio)
537168404Spjd{
538168404Spjd	struct iovec *iov;
539168404Spjd	ulong_t cnt, incr;
540168404Spjd	caddr_t p;
541168404Spjd
542168404Spjd	if (uio->uio_segflg != UIO_USERSPACE)
543168404Spjd		return;
544168404Spjd
545168404Spjd	iov = uio->uio_iov;
546168404Spjd
547168404Spjd	while (n) {
548168404Spjd		cnt = MIN(iov->iov_len, n);
549168404Spjd		if (cnt == 0) {
550168404Spjd			/* empty iov entry */
551168404Spjd			iov++;
552168404Spjd			continue;
553168404Spjd		}
554168404Spjd		n -= cnt;
555168404Spjd		/*
556168404Spjd		 * touch each page in this segment.
557168404Spjd		 */
558168404Spjd		p = iov->iov_base;
559168404Spjd		while (cnt) {
560168404Spjd			if (fubyte(p) == -1)
561168404Spjd				return;
562168404Spjd			incr = MIN(cnt, PAGESIZE);
563168404Spjd			p += incr;
564168404Spjd			cnt -= incr;
565168404Spjd		}
566168404Spjd		/*
567168404Spjd		 * touch the last byte in case it straddles a page.
568168404Spjd		 */
569168404Spjd		p--;
570168404Spjd		if (fubyte(p) == -1)
571168404Spjd			return;
572168404Spjd		iov++;
573168404Spjd	}
574168404Spjd}
575168404Spjd
576168404Spjd/*
577168404Spjd * Write the bytes to a file.
578168404Spjd *
579168404Spjd *	IN:	vp	- vnode of file to be written to.
580168404Spjd *		uio	- structure supplying write location, range info,
581168404Spjd *			  and data buffer.
582168404Spjd *		ioflag	- IO_APPEND flag set if in append mode.
583168404Spjd *		cr	- credentials of caller.
584168404Spjd *
585168404Spjd *	OUT:	uio	- updated offset and range.
586168404Spjd *
587168404Spjd *	RETURN:	0 if success
588168404Spjd *		error code if failure
589168404Spjd *
590168404Spjd * Timestamps:
591168404Spjd *	vp - ctime|mtime updated if byte count > 0
592168404Spjd */
593168404Spjd/* ARGSUSED */
594168404Spjdstatic int
595168962Spjdzfs_write(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct)
596168404Spjd{
597168404Spjd	znode_t		*zp = VTOZ(vp);
598168962Spjd	rlim64_t	limit = MAXOFFSET_T;
599168404Spjd	ssize_t		start_resid = uio->uio_resid;
600168404Spjd	ssize_t		tx_bytes;
601168404Spjd	uint64_t	end_size;
602168404Spjd	dmu_tx_t	*tx;
603168404Spjd	zfsvfs_t	*zfsvfs = zp->z_zfsvfs;
604168404Spjd	zilog_t		*zilog = zfsvfs->z_log;
605168404Spjd	offset_t	woff;
606168404Spjd	ssize_t		n, nbytes;
607168404Spjd	rl_t		*rl;
608168404Spjd	int		max_blksz = zfsvfs->z_max_blksz;
609168404Spjd	int		error;
610168404Spjd
611168404Spjd	/*
612168404Spjd	 * Fasttrack empty write
613168404Spjd	 */
614168404Spjd	n = start_resid;
615168404Spjd	if (n == 0)
616168404Spjd		return (0);
617168404Spjd
618168962Spjd	if (limit == RLIM64_INFINITY || limit > MAXOFFSET_T)
619168962Spjd		limit = MAXOFFSET_T;
620168962Spjd
621168404Spjd	ZFS_ENTER(zfsvfs);
622168404Spjd
623168404Spjd	/*
624168404Spjd	 * Pre-fault the pages to ensure slow (eg NFS) pages
625168404Spjd	 * don't hold up txg.
626168404Spjd	 */
627168404Spjd	zfs_prefault_write(n, uio);
628168404Spjd
629168404Spjd	/*
630168404Spjd	 * If in append mode, set the io offset pointer to eof.
631168404Spjd	 */
632168404Spjd	if (ioflag & IO_APPEND) {
633168404Spjd		/*
634168404Spjd		 * Range lock for a file append:
635168404Spjd		 * The value for the start of range will be determined by
636168404Spjd		 * zfs_range_lock() (to guarantee append semantics).
637168404Spjd		 * If this write will cause the block size to increase,
638168404Spjd		 * zfs_range_lock() will lock the entire file, so we must
639168404Spjd		 * later reduce the range after we grow the block size.
640168404Spjd		 */
641168404Spjd		rl = zfs_range_lock(zp, 0, n, RL_APPEND);
642168404Spjd		if (rl->r_len == UINT64_MAX) {
643168404Spjd			/* overlocked, zp_size can't change */
644168404Spjd			woff = uio->uio_loffset = zp->z_phys->zp_size;
645168404Spjd		} else {
646168404Spjd			woff = uio->uio_loffset = rl->r_off;
647168404Spjd		}
648168404Spjd	} else {
649168404Spjd		woff = uio->uio_loffset;
650168404Spjd		/*
651168404Spjd		 * Validate file offset
652168404Spjd		 */
653168404Spjd		if (woff < 0) {
654168404Spjd			ZFS_EXIT(zfsvfs);
655168404Spjd			return (EINVAL);
656168404Spjd		}
657168404Spjd
658168404Spjd		/*
659168404Spjd		 * If we need to grow the block size then zfs_range_lock()
660168404Spjd		 * will lock a wider range than we request here.
661168404Spjd		 * Later after growing the block size we reduce the range.
662168404Spjd		 */
663168404Spjd		rl = zfs_range_lock(zp, woff, n, RL_WRITER);
664168404Spjd	}
665168404Spjd
666168962Spjd	if (woff >= limit) {
667168962Spjd		zfs_range_unlock(rl);
668168962Spjd		ZFS_EXIT(zfsvfs);
669168962Spjd		return (EFBIG);
670168962Spjd	}
671168962Spjd
672168962Spjd	if ((woff + n) > limit || woff > (limit - n))
673168962Spjd		n = limit - woff;
674168962Spjd
675168962Spjd	/*
676168962Spjd	 * Check for mandatory locks
677168962Spjd	 */
678168962Spjd	if (MANDMODE((mode_t)zp->z_phys->zp_mode) &&
679168962Spjd	    (error = chklock(vp, FWRITE, woff, n, uio->uio_fmode, ct)) != 0) {
680168962Spjd		zfs_range_unlock(rl);
681168962Spjd		ZFS_EXIT(zfsvfs);
682168962Spjd		return (error);
683168962Spjd	}
684168404Spjd	end_size = MAX(zp->z_phys->zp_size, woff + n);
685168404Spjd
686168404Spjd	/*
687168404Spjd	 * Write the file in reasonable size chunks.  Each chunk is written
688168404Spjd	 * in a separate transaction; this keeps the intent log records small
689168404Spjd	 * and allows us to do more fine-grained space accounting.
690168404Spjd	 */
691168404Spjd	while (n > 0) {
692168404Spjd		/*
693168404Spjd		 * Start a transaction.
694168404Spjd		 */
695168404Spjd		woff = uio->uio_loffset;
696168404Spjd		tx = dmu_tx_create(zfsvfs->z_os);
697168404Spjd		dmu_tx_hold_bonus(tx, zp->z_id);
698168404Spjd		dmu_tx_hold_write(tx, zp->z_id, woff, MIN(n, max_blksz));
699168404Spjd		error = dmu_tx_assign(tx, zfsvfs->z_assign);
700168404Spjd		if (error) {
701168404Spjd			if (error == ERESTART &&
702168404Spjd			    zfsvfs->z_assign == TXG_NOWAIT) {
703168404Spjd				dmu_tx_wait(tx);
704168404Spjd				dmu_tx_abort(tx);
705168404Spjd				continue;
706168404Spjd			}
707168404Spjd			dmu_tx_abort(tx);
708168404Spjd			break;
709168404Spjd		}
710168404Spjd
711168404Spjd		/*
712168404Spjd		 * If zfs_range_lock() over-locked we grow the blocksize
713168404Spjd		 * and then reduce the lock range.  This will only happen
714168404Spjd		 * on the first iteration since zfs_range_reduce() will
715168404Spjd		 * shrink down r_len to the appropriate size.
716168404Spjd		 */
717168404Spjd		if (rl->r_len == UINT64_MAX) {
718168404Spjd			uint64_t new_blksz;
719168404Spjd
720168404Spjd			if (zp->z_blksz > max_blksz) {
721168404Spjd				ASSERT(!ISP2(zp->z_blksz));
722168404Spjd				new_blksz = MIN(end_size, SPA_MAXBLOCKSIZE);
723168404Spjd			} else {
724168404Spjd				new_blksz = MIN(end_size, max_blksz);
725168404Spjd			}
726168404Spjd			zfs_grow_blocksize(zp, new_blksz, tx);
727168404Spjd			zfs_range_reduce(rl, woff, n);
728168404Spjd		}
729168404Spjd
730168404Spjd		/*
731168404Spjd		 * XXX - should we really limit each write to z_max_blksz?
732168404Spjd		 * Perhaps we should use SPA_MAXBLOCKSIZE chunks?
733168404Spjd		 */
734168404Spjd		nbytes = MIN(n, max_blksz - P2PHASE(woff, max_blksz));
735168404Spjd		rw_enter(&zp->z_map_lock, RW_READER);
736168404Spjd
737168404Spjd		if (woff + nbytes > zp->z_phys->zp_size)
738168404Spjd			vnode_pager_setsize(vp, woff + nbytes);
739168404Spjd
740168962Spjd		tx_bytes = uio->uio_resid;
741168404Spjd		if (vn_has_cached_data(vp)) {
742168404Spjd			rw_exit(&zp->z_map_lock);
743168404Spjd			error = mappedwrite(vp, nbytes, uio, tx);
744168404Spjd		} else {
745168404Spjd			error = dmu_write_uio(zfsvfs->z_os, zp->z_id,
746168404Spjd			    uio, nbytes, tx);
747168404Spjd			rw_exit(&zp->z_map_lock);
748168404Spjd		}
749168404Spjd		tx_bytes -= uio->uio_resid;
750168404Spjd
751168404Spjd		/*
752168404Spjd		 * If we made no progress, we're done.  If we made even
753168404Spjd		 * partial progress, update the znode and ZIL accordingly.
754168404Spjd		 */
755168404Spjd		if (tx_bytes == 0) {
756168404Spjd			dmu_tx_commit(tx);
757168404Spjd			ASSERT(error != 0);
758168404Spjd			break;
759168404Spjd		}
760168404Spjd
761168404Spjd		/*
762168404Spjd		 * Clear Set-UID/Set-GID bits on successful write if not
763168404Spjd		 * privileged and at least one of the excute bits is set.
764168404Spjd		 *
765168404Spjd		 * It would be nice to to this after all writes have
766168404Spjd		 * been done, but that would still expose the ISUID/ISGID
767168404Spjd		 * to another app after the partial write is committed.
768168404Spjd		 */
769168404Spjd		mutex_enter(&zp->z_acl_lock);
770168404Spjd		if ((zp->z_phys->zp_mode & (S_IXUSR | (S_IXUSR >> 3) |
771168404Spjd		    (S_IXUSR >> 6))) != 0 &&
772168404Spjd		    (zp->z_phys->zp_mode & (S_ISUID | S_ISGID)) != 0 &&
773168404Spjd		    secpolicy_vnode_setid_retain(cr,
774168404Spjd		    (zp->z_phys->zp_mode & S_ISUID) != 0 &&
775168404Spjd		    zp->z_phys->zp_uid == 0) != 0) {
776168404Spjd			    zp->z_phys->zp_mode &= ~(S_ISUID | S_ISGID);
777168404Spjd		}
778168404Spjd		mutex_exit(&zp->z_acl_lock);
779168404Spjd
780168404Spjd		/*
781168404Spjd		 * Update time stamp.  NOTE: This marks the bonus buffer as
782168404Spjd		 * dirty, so we don't have to do it again for zp_size.
783168404Spjd		 */
784168404Spjd		zfs_time_stamper(zp, CONTENT_MODIFIED, tx);
785168404Spjd
786168404Spjd		/*
787168404Spjd		 * Update the file size (zp_size) if it has changed;
788168404Spjd		 * account for possible concurrent updates.
789168404Spjd		 */
790168404Spjd		while ((end_size = zp->z_phys->zp_size) < uio->uio_loffset)
791168404Spjd			(void) atomic_cas_64(&zp->z_phys->zp_size, end_size,
792168404Spjd			    uio->uio_loffset);
793168404Spjd		zfs_log_write(zilog, tx, TX_WRITE, zp, woff, tx_bytes, ioflag);
794168404Spjd		dmu_tx_commit(tx);
795168404Spjd
796168404Spjd		if (error != 0)
797168404Spjd			break;
798168404Spjd		ASSERT(tx_bytes == nbytes);
799168404Spjd		n -= nbytes;
800168404Spjd	}
801168404Spjd
802168404Spjd	zfs_range_unlock(rl);
803168404Spjd
804168404Spjd	/*
805168404Spjd	 * If we're in replay mode, or we made no progress, return error.
806168404Spjd	 * Otherwise, it's at least a partial write, so it's successful.
807168404Spjd	 */
808168404Spjd	if (zfsvfs->z_assign >= TXG_INITIAL || uio->uio_resid == start_resid) {
809168404Spjd		ZFS_EXIT(zfsvfs);
810168404Spjd		return (error);
811168404Spjd	}
812168404Spjd
813168962Spjd	if (ioflag & (FSYNC | FDSYNC))
814168404Spjd		zil_commit(zilog, zp->z_last_itx, zp->z_id);
815168404Spjd
816168404Spjd	ZFS_EXIT(zfsvfs);
817168404Spjd	return (0);
818168404Spjd}
819168404Spjd
820168404Spjdvoid
821168404Spjdzfs_get_done(dmu_buf_t *db, void *vzgd)
822168404Spjd{
823168404Spjd	zgd_t *zgd = (zgd_t *)vzgd;
824168404Spjd	rl_t *rl = zgd->zgd_rl;
825168404Spjd	vnode_t *vp = ZTOV(rl->r_zp);
826168404Spjd	int vfslocked;
827168404Spjd
828168404Spjd	vfslocked = VFS_LOCK_GIANT(vp->v_vfsp);
829168404Spjd	dmu_buf_rele(db, vzgd);
830168404Spjd	zfs_range_unlock(rl);
831168404Spjd	VN_RELE(vp);
832168404Spjd	zil_add_vdev(zgd->zgd_zilog, DVA_GET_VDEV(BP_IDENTITY(zgd->zgd_bp)));
833168404Spjd	kmem_free(zgd, sizeof (zgd_t));
834168404Spjd	VFS_UNLOCK_GIANT(vfslocked);
835168404Spjd}
836168404Spjd
837168404Spjd/*
838168404Spjd * Get data to generate a TX_WRITE intent log record.
839168404Spjd */
840168404Spjdint
841168404Spjdzfs_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio)
842168404Spjd{
843168404Spjd	zfsvfs_t *zfsvfs = arg;
844168404Spjd	objset_t *os = zfsvfs->z_os;
845168404Spjd	znode_t *zp;
846168404Spjd	uint64_t off = lr->lr_offset;
847168404Spjd	dmu_buf_t *db;
848168404Spjd	rl_t *rl;
849168404Spjd	zgd_t *zgd;
850168404Spjd	int dlen = lr->lr_length;		/* length of user data */
851168404Spjd	int error = 0;
852168404Spjd
853168404Spjd	ASSERT(zio);
854168404Spjd	ASSERT(dlen != 0);
855168404Spjd
856168404Spjd	/*
857168404Spjd	 * Nothing to do if the file has been removed
858168404Spjd	 */
859168404Spjd	if (zfs_zget(zfsvfs, lr->lr_foid, &zp) != 0)
860168404Spjd		return (ENOENT);
861168404Spjd	if (zp->z_unlinked) {
862168404Spjd		VN_RELE(ZTOV(zp));
863168404Spjd		return (ENOENT);
864168404Spjd	}
865168404Spjd
866168404Spjd	/*
867168404Spjd	 * Write records come in two flavors: immediate and indirect.
868168404Spjd	 * For small writes it's cheaper to store the data with the
869168404Spjd	 * log record (immediate); for large writes it's cheaper to
870168404Spjd	 * sync the data and get a pointer to it (indirect) so that
871168404Spjd	 * we don't have to write the data twice.
872168404Spjd	 */
873168404Spjd	if (buf != NULL) { /* immediate write */
874168404Spjd		rl = zfs_range_lock(zp, off, dlen, RL_READER);
875168404Spjd		/* test for truncation needs to be done while range locked */
876168404Spjd		if (off >= zp->z_phys->zp_size) {
877168404Spjd			error = ENOENT;
878168404Spjd			goto out;
879168404Spjd		}
880168404Spjd		VERIFY(0 == dmu_read(os, lr->lr_foid, off, dlen, buf));
881168404Spjd	} else { /* indirect write */
882168404Spjd		uint64_t boff; /* block starting offset */
883168404Spjd
884168404Spjd		/*
885168404Spjd		 * Have to lock the whole block to ensure when it's
886168404Spjd		 * written out and it's checksum is being calculated
887168404Spjd		 * that no one can change the data. We need to re-check
888168404Spjd		 * blocksize after we get the lock in case it's changed!
889168404Spjd		 */
890168404Spjd		for (;;) {
891168404Spjd			if (ISP2(zp->z_blksz)) {
892168404Spjd				boff = P2ALIGN_TYPED(off, zp->z_blksz,
893168404Spjd				    uint64_t);
894168404Spjd			} else {
895168404Spjd				boff = 0;
896168404Spjd			}
897168404Spjd			dlen = zp->z_blksz;
898168404Spjd			rl = zfs_range_lock(zp, boff, dlen, RL_READER);
899168404Spjd			if (zp->z_blksz == dlen)
900168404Spjd				break;
901168404Spjd			zfs_range_unlock(rl);
902168404Spjd		}
903168404Spjd		/* test for truncation needs to be done while range locked */
904168404Spjd		if (off >= zp->z_phys->zp_size) {
905168404Spjd			error = ENOENT;
906168404Spjd			goto out;
907168404Spjd		}
908168404Spjd		zgd = (zgd_t *)kmem_alloc(sizeof (zgd_t), KM_SLEEP);
909168404Spjd		zgd->zgd_rl = rl;
910168404Spjd		zgd->zgd_zilog = zfsvfs->z_log;
911168404Spjd		zgd->zgd_bp = &lr->lr_blkptr;
912168404Spjd		VERIFY(0 == dmu_buf_hold(os, lr->lr_foid, boff, zgd, &db));
913168404Spjd		ASSERT(boff == db->db_offset);
914168404Spjd		lr->lr_blkoff = off - boff;
915168404Spjd		error = dmu_sync(zio, db, &lr->lr_blkptr,
916168404Spjd		    lr->lr_common.lrc_txg, zfs_get_done, zgd);
917168404Spjd		ASSERT(error == EEXIST || lr->lr_length <= zp->z_blksz);
918168404Spjd		if (error == 0) {
919168404Spjd			zil_add_vdev(zfsvfs->z_log,
920168404Spjd			    DVA_GET_VDEV(BP_IDENTITY(&lr->lr_blkptr)));
921168404Spjd		}
922168404Spjd		/*
923168404Spjd		 * If we get EINPROGRESS, then we need to wait for a
924168404Spjd		 * write IO initiated by dmu_sync() to complete before
925168404Spjd		 * we can release this dbuf.  We will finish everything
926168404Spjd		 * up in the zfs_get_done() callback.
927168404Spjd		 */
928168404Spjd		if (error == EINPROGRESS)
929168404Spjd			return (0);
930168404Spjd		dmu_buf_rele(db, zgd);
931168404Spjd		kmem_free(zgd, sizeof (zgd_t));
932168404Spjd	}
933168404Spjdout:
934168404Spjd	zfs_range_unlock(rl);
935168404Spjd	VN_RELE(ZTOV(zp));
936168404Spjd	return (error);
937168404Spjd}
938168404Spjd
939168404Spjd/*ARGSUSED*/
940168404Spjdstatic int
941168962Spjdzfs_access(vnode_t *vp, int mode, int flags, cred_t *cr)
942168404Spjd{
943168404Spjd	znode_t *zp = VTOZ(vp);
944168404Spjd	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
945168404Spjd	int error;
946168404Spjd
947168404Spjd	ZFS_ENTER(zfsvfs);
948168962Spjd	error = zfs_zaccess_rwx(zp, mode, cr);
949168404Spjd	ZFS_EXIT(zfsvfs);
950168404Spjd	return (error);
951168404Spjd}
952168404Spjd
953168404Spjd/*
954168404Spjd * Lookup an entry in a directory, or an extended attribute directory.
955168404Spjd * If it exists, return a held vnode reference for it.
956168404Spjd *
957168404Spjd *	IN:	dvp	- vnode of directory to search.
958168404Spjd *		nm	- name of entry to lookup.
959168404Spjd *		pnp	- full pathname to lookup [UNUSED].
960168404Spjd *		flags	- LOOKUP_XATTR set if looking for an attribute.
961168404Spjd *		rdir	- root directory vnode [UNUSED].
962168404Spjd *		cr	- credentials of caller.
963168404Spjd *
964168404Spjd *	OUT:	vpp	- vnode of located entry, NULL if not found.
965168404Spjd *
966168404Spjd *	RETURN:	0 if success
967168404Spjd *		error code if failure
968168404Spjd *
969168404Spjd * Timestamps:
970168404Spjd *	NA
971168404Spjd */
972168404Spjd/* ARGSUSED */
973168962Spjdstatic int
974168962Spjdzfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct componentname *cnp,
975168962Spjd     int nameiop, cred_t *cr, kthread_t *td)
976168404Spjd{
977168404Spjd
978168962Spjd	znode_t *zdp = VTOZ(dvp);
979168962Spjd	zfsvfs_t *zfsvfs = zdp->z_zfsvfs;
980168962Spjd	int	error;
981168404Spjd
982168404Spjd	ZFS_ENTER(zfsvfs);
983168404Spjd
984168404Spjd	*vpp = NULL;
985168404Spjd
986168404Spjd#ifdef TODO
987168404Spjd	if (flags & LOOKUP_XATTR) {
988168404Spjd		/*
989168404Spjd		 * If the xattr property is off, refuse the lookup request.
990168404Spjd		 */
991168404Spjd		if (!(zfsvfs->z_vfs->vfs_flag & VFS_XATTR)) {
992168404Spjd			ZFS_EXIT(zfsvfs);
993168404Spjd			return (EINVAL);
994168404Spjd		}
995168404Spjd
996168404Spjd		/*
997168404Spjd		 * We don't allow recursive attributes..
998168404Spjd		 * Maybe someday we will.
999168404Spjd		 */
1000168404Spjd		if (zdp->z_phys->zp_flags & ZFS_XATTR) {
1001168404Spjd			ZFS_EXIT(zfsvfs);
1002168404Spjd			return (EINVAL);
1003168404Spjd		}
1004168404Spjd
1005168404Spjd		if (error = zfs_get_xattrdir(VTOZ(dvp), vpp, cr, flags)) {
1006168404Spjd			ZFS_EXIT(zfsvfs);
1007168404Spjd			return (error);
1008168404Spjd		}
1009168404Spjd
1010168404Spjd		/*
1011168404Spjd		 * Do we have permission to get into attribute directory?
1012168404Spjd		 */
1013168404Spjd
1014168404Spjd		if (error = zfs_zaccess(VTOZ(*vpp), ACE_EXECUTE, cr)) {
1015168404Spjd			VN_RELE(*vpp);
1016168404Spjd		}
1017168404Spjd
1018168404Spjd		ZFS_EXIT(zfsvfs);
1019168404Spjd		return (error);
1020168404Spjd	}
1021168404Spjd#endif	/* TODO */
1022168404Spjd
1023168404Spjd	if (dvp->v_type != VDIR) {
1024168404Spjd		ZFS_EXIT(zfsvfs);
1025168404Spjd		return (ENOTDIR);
1026168404Spjd	}
1027168404Spjd
1028168404Spjd	/*
1029168404Spjd	 * Check accessibility of directory.
1030168404Spjd	 */
1031168404Spjd
1032168404Spjd	if (error = zfs_zaccess(zdp, ACE_EXECUTE, cr)) {
1033168404Spjd		ZFS_EXIT(zfsvfs);
1034168404Spjd		return (error);
1035168404Spjd	}
1036168404Spjd
1037168962Spjd	if ((error = zfs_dirlook(zdp, nm, vpp)) == 0) {
1038168404Spjd
1039168962Spjd		/*
1040168962Spjd		 * Convert device special files
1041168962Spjd		 */
1042168962Spjd		if (IS_DEVVP(*vpp)) {
1043168962Spjd			vnode_t	*svp;
1044168962Spjd
1045168962Spjd			svp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type, cr);
1046168962Spjd			VN_RELE(*vpp);
1047168962Spjd			if (svp == NULL)
1048168962Spjd				error = ENOSYS;
1049168962Spjd			else
1050168962Spjd				*vpp = svp;
1051168962Spjd		}
1052168962Spjd	}
1053168962Spjd
1054168404Spjd	ZFS_EXIT(zfsvfs);
1055168404Spjd
1056168404Spjd	/* Translate errors and add SAVENAME when needed. */
1057168404Spjd	if (cnp->cn_flags & ISLASTCN) {
1058168404Spjd		switch (nameiop) {
1059168404Spjd		case CREATE:
1060168404Spjd		case RENAME:
1061168404Spjd			if (error == ENOENT) {
1062168404Spjd				error = EJUSTRETURN;
1063168404Spjd				cnp->cn_flags |= SAVENAME;
1064168404Spjd				break;
1065168404Spjd			}
1066168404Spjd			/* FALLTHROUGH */
1067168404Spjd		case DELETE:
1068168404Spjd			if (error == 0)
1069168404Spjd				cnp->cn_flags |= SAVENAME;
1070168404Spjd			break;
1071168404Spjd		}
1072168404Spjd	}
1073168404Spjd	if (error == 0 && (nm[0] != '.' || nm[1] != '\0')) {
1074168962Spjd		if (cnp->cn_flags & ISDOTDOT)
1075168404Spjd			VOP_UNLOCK(dvp, 0, td);
1076168404Spjd		vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, td);
1077168962Spjd		if (cnp->cn_flags & ISDOTDOT)
1078168404Spjd			vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td);
1079168404Spjd	}
1080168404Spjd
1081168404Spjd#ifdef FREEBSD_NAMECACHE
1082168404Spjd	/*
1083168404Spjd	 * Insert name into cache (as non-existent) if appropriate.
1084168404Spjd	 */
1085168404Spjd	if (error == ENOENT && (cnp->cn_flags & MAKEENTRY) && nameiop != CREATE)
1086168404Spjd		cache_enter(dvp, *vpp, cnp);
1087168404Spjd        /*
1088168404Spjd         * Insert name into cache if appropriate.
1089168404Spjd         */
1090168404Spjd	if (error == 0 && (cnp->cn_flags & MAKEENTRY)) {
1091168404Spjd		if (!(cnp->cn_flags & ISLASTCN) ||
1092168404Spjd		    (nameiop != DELETE && nameiop != RENAME)) {
1093168404Spjd			cache_enter(dvp, *vpp, cnp);
1094168404Spjd		}
1095168404Spjd	}
1096168404Spjd#endif
1097168404Spjd
1098168404Spjd	return (error);
1099168404Spjd}
1100168404Spjd
1101168404Spjd/*
1102168404Spjd * Attempt to create a new entry in a directory.  If the entry
1103168404Spjd * already exists, truncate the file if permissible, else return
1104168404Spjd * an error.  Return the vp of the created or trunc'd file.
1105168404Spjd *
1106168404Spjd *	IN:	dvp	- vnode of directory to put new file entry in.
1107168404Spjd *		name	- name of new file entry.
1108168404Spjd *		vap	- attributes of new file.
1109168404Spjd *		excl	- flag indicating exclusive or non-exclusive mode.
1110168404Spjd *		mode	- mode to open file with.
1111168404Spjd *		cr	- credentials of caller.
1112168404Spjd *		flag	- large file flag [UNUSED].
1113168404Spjd *
1114168404Spjd *	OUT:	vpp	- vnode of created or trunc'd entry.
1115168404Spjd *
1116168404Spjd *	RETURN:	0 if success
1117168404Spjd *		error code if failure
1118168404Spjd *
1119168404Spjd * Timestamps:
1120168404Spjd *	dvp - ctime|mtime updated if new entry created
1121168404Spjd *	 vp - ctime|mtime always, atime if new
1122168404Spjd */
1123168404Spjd/* ARGSUSED */
1124168404Spjdstatic int
1125168962Spjdzfs_create(vnode_t *dvp, char *name, vattr_t *vap, int excl, int mode,
1126168962Spjd    vnode_t **vpp, cred_t *cr, kthread_t *td)
1127168404Spjd{
1128168404Spjd	znode_t		*zp, *dzp = VTOZ(dvp);
1129168404Spjd	zfsvfs_t	*zfsvfs = dzp->z_zfsvfs;
1130168404Spjd	zilog_t		*zilog = zfsvfs->z_log;
1131168404Spjd	objset_t	*os = zfsvfs->z_os;
1132168404Spjd	zfs_dirlock_t	*dl;
1133168404Spjd	dmu_tx_t	*tx;
1134168404Spjd	int		error;
1135168404Spjd	uint64_t	zoid;
1136168404Spjd
1137168404Spjd	ZFS_ENTER(zfsvfs);
1138168404Spjd
1139168404Spjdtop:
1140168404Spjd	*vpp = NULL;
1141168404Spjd
1142168404Spjd	if ((vap->va_mode & VSVTX) && secpolicy_vnode_stky_modify(cr))
1143168404Spjd		vap->va_mode &= ~VSVTX;
1144168404Spjd
1145168404Spjd	if (*name == '\0') {
1146168404Spjd		/*
1147168404Spjd		 * Null component name refers to the directory itself.
1148168404Spjd		 */
1149168404Spjd		VN_HOLD(dvp);
1150168404Spjd		zp = dzp;
1151168404Spjd		dl = NULL;
1152168404Spjd		error = 0;
1153168404Spjd	} else {
1154168404Spjd		/* possible VN_HOLD(zp) */
1155168404Spjd		if (error = zfs_dirent_lock(&dl, dzp, name, &zp, 0)) {
1156168404Spjd			if (strcmp(name, "..") == 0)
1157168404Spjd				error = EISDIR;
1158168404Spjd			ZFS_EXIT(zfsvfs);
1159168404Spjd			return (error);
1160168404Spjd		}
1161168404Spjd	}
1162168404Spjd
1163168404Spjd	zoid = zp ? zp->z_id : -1ULL;
1164168404Spjd
1165168404Spjd	if (zp == NULL) {
1166168404Spjd		/*
1167168404Spjd		 * Create a new file object and update the directory
1168168404Spjd		 * to reference it.
1169168404Spjd		 */
1170168404Spjd		if (error = zfs_zaccess(dzp, ACE_ADD_FILE, cr)) {
1171168404Spjd			goto out;
1172168404Spjd		}
1173168404Spjd
1174168404Spjd		/*
1175168404Spjd		 * We only support the creation of regular files in
1176168404Spjd		 * extended attribute directories.
1177168404Spjd		 */
1178168404Spjd		if ((dzp->z_phys->zp_flags & ZFS_XATTR) &&
1179168404Spjd		    (vap->va_type != VREG)) {
1180168404Spjd			error = EINVAL;
1181168404Spjd			goto out;
1182168404Spjd		}
1183168404Spjd
1184168404Spjd		tx = dmu_tx_create(os);
1185168404Spjd		dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT);
1186168404Spjd		dmu_tx_hold_bonus(tx, dzp->z_id);
1187168404Spjd		dmu_tx_hold_zap(tx, dzp->z_id, TRUE, name);
1188168404Spjd		if (dzp->z_phys->zp_flags & ZFS_INHERIT_ACE)
1189168404Spjd			dmu_tx_hold_write(tx, DMU_NEW_OBJECT,
1190168404Spjd			    0, SPA_MAXBLOCKSIZE);
1191168404Spjd		error = dmu_tx_assign(tx, zfsvfs->z_assign);
1192168404Spjd		if (error) {
1193168404Spjd			zfs_dirent_unlock(dl);
1194168404Spjd			if (error == ERESTART &&
1195168404Spjd			    zfsvfs->z_assign == TXG_NOWAIT) {
1196168404Spjd				dmu_tx_wait(tx);
1197168404Spjd				dmu_tx_abort(tx);
1198168404Spjd				goto top;
1199168404Spjd			}
1200168404Spjd			dmu_tx_abort(tx);
1201168404Spjd			ZFS_EXIT(zfsvfs);
1202168404Spjd			return (error);
1203168404Spjd		}
1204168404Spjd		zfs_mknode(dzp, vap, &zoid, tx, cr, 0, &zp, 0);
1205168404Spjd		ASSERT(zp->z_id == zoid);
1206168404Spjd		(void) zfs_link_create(dl, zp, tx, ZNEW);
1207168404Spjd		zfs_log_create(zilog, tx, TX_CREATE, dzp, zp, name);
1208168404Spjd		dmu_tx_commit(tx);
1209168404Spjd	} else {
1210168404Spjd		/*
1211168404Spjd		 * A directory entry already exists for this name.
1212168404Spjd		 */
1213168404Spjd		/*
1214168962Spjd		 * Can't truncate an existing file if in exclusive mode.
1215168962Spjd		 */
1216168962Spjd		if (excl == EXCL) {
1217168962Spjd			error = EEXIST;
1218168962Spjd			goto out;
1219168962Spjd		}
1220168962Spjd		/*
1221168404Spjd		 * Can't open a directory for writing.
1222168404Spjd		 */
1223168404Spjd		if ((ZTOV(zp)->v_type == VDIR) && (mode & S_IWRITE)) {
1224168404Spjd			error = EISDIR;
1225168404Spjd			goto out;
1226168404Spjd		}
1227168404Spjd		/*
1228168404Spjd		 * Verify requested access to file.
1229168404Spjd		 */
1230168404Spjd		if (mode && (error = zfs_zaccess_rwx(zp, mode, cr))) {
1231168404Spjd			goto out;
1232168404Spjd		}
1233168404Spjd
1234168404Spjd		mutex_enter(&dzp->z_lock);
1235168404Spjd		dzp->z_seq++;
1236168404Spjd		mutex_exit(&dzp->z_lock);
1237168404Spjd
1238168404Spjd		/*
1239168404Spjd		 * Truncate regular files if requested.
1240168404Spjd		 */
1241168404Spjd		if ((ZTOV(zp)->v_type == VREG) &&
1242168404Spjd		    (zp->z_phys->zp_size != 0) &&
1243168404Spjd		    (vap->va_mask & AT_SIZE) && (vap->va_size == 0)) {
1244168404Spjd			error = zfs_freesp(zp, 0, 0, mode, TRUE);
1245168404Spjd			if (error == ERESTART &&
1246168404Spjd			    zfsvfs->z_assign == TXG_NOWAIT) {
1247168404Spjd				/* NB: we already did dmu_tx_wait() */
1248168404Spjd				zfs_dirent_unlock(dl);
1249168404Spjd				VN_RELE(ZTOV(zp));
1250168404Spjd				goto top;
1251168404Spjd			}
1252168404Spjd		}
1253168404Spjd	}
1254168404Spjdout:
1255168404Spjd
1256168404Spjd	if (error == 0) {
1257168404Spjd		*vpp = ZTOV(zp);
1258168962Spjd		vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, td);
1259168404Spjd	}
1260168404Spjd
1261168404Spjd	if (dl)
1262168404Spjd		zfs_dirent_unlock(dl);
1263168404Spjd
1264168404Spjd	if (error) {
1265168404Spjd		if (zp)
1266168404Spjd			VN_RELE(ZTOV(zp));
1267168962Spjd	} else {
1268168962Spjd		*vpp = ZTOV(zp);
1269168962Spjd		/*
1270168962Spjd		 * If vnode is for a device return a specfs vnode instead.
1271168962Spjd		 */
1272168962Spjd		if (IS_DEVVP(*vpp)) {
1273168962Spjd			struct vnode *svp;
1274168962Spjd
1275168962Spjd			svp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type, cr);
1276168962Spjd			VN_RELE(*vpp);
1277168962Spjd			if (svp == NULL) {
1278168962Spjd				error = ENOSYS;
1279168962Spjd			}
1280168962Spjd			*vpp = svp;
1281168962Spjd		}
1282168404Spjd	}
1283168404Spjd
1284168404Spjd	ZFS_EXIT(zfsvfs);
1285168404Spjd	return (error);
1286168404Spjd}
1287168404Spjd
1288168404Spjd/*
1289168404Spjd * Remove an entry from a directory.
1290168404Spjd *
1291168404Spjd *	IN:	dvp	- vnode of directory to remove entry from.
1292168404Spjd *		name	- name of entry to remove.
1293168404Spjd *		cr	- credentials of caller.
1294168404Spjd *
1295168404Spjd *	RETURN:	0 if success
1296168404Spjd *		error code if failure
1297168404Spjd *
1298168404Spjd * Timestamps:
1299168404Spjd *	dvp - ctime|mtime
1300168404Spjd *	 vp - ctime (if nlink > 0)
1301168404Spjd */
1302168404Spjdstatic int
1303168962Spjdzfs_remove(vnode_t *dvp, char *name, cred_t *cr)
1304168404Spjd{
1305168404Spjd	znode_t		*zp, *dzp = VTOZ(dvp);
1306168404Spjd	znode_t		*xzp = NULL;
1307168404Spjd	vnode_t		*vp;
1308168404Spjd	zfsvfs_t	*zfsvfs = dzp->z_zfsvfs;
1309168404Spjd	zilog_t		*zilog = zfsvfs->z_log;
1310168962Spjd	uint64_t	acl_obj, xattr_obj;
1311168404Spjd	zfs_dirlock_t	*dl;
1312168404Spjd	dmu_tx_t	*tx;
1313168962Spjd	boolean_t	may_delete_now, delete_now = FALSE;
1314168404Spjd	boolean_t	unlinked;
1315168404Spjd	int		error;
1316168404Spjd
1317168404Spjd	ZFS_ENTER(zfsvfs);
1318168404Spjd
1319168404Spjdtop:
1320168404Spjd	/*
1321168404Spjd	 * Attempt to lock directory; fail if entry doesn't exist.
1322168404Spjd	 */
1323168404Spjd	if (error = zfs_dirent_lock(&dl, dzp, name, &zp, ZEXISTS)) {
1324168404Spjd		ZFS_EXIT(zfsvfs);
1325168404Spjd		return (error);
1326168404Spjd	}
1327168404Spjd
1328168404Spjd	vp = ZTOV(zp);
1329168404Spjd
1330168962Spjd	if (error = zfs_zaccess_delete(dzp, zp, cr)) {
1331168404Spjd		goto out;
1332168962Spjd	}
1333168404Spjd
1334168962Spjd	/*
1335168962Spjd	 * Need to use rmdir for removing directories.
1336168962Spjd	 */
1337168962Spjd	if (vp->v_type == VDIR) {
1338168962Spjd		error = EPERM;
1339168962Spjd		goto out;
1340168962Spjd	}
1341168962Spjd
1342168962Spjd	vnevent_remove(vp);
1343168962Spjd
1344168404Spjd	dnlc_remove(dvp, name);
1345168404Spjd
1346168962Spjd	may_delete_now = FALSE;
1347168962Spjd
1348168404Spjd	/*
1349168404Spjd	 * We may delete the znode now, or we may put it in the unlinked set;
1350168404Spjd	 * it depends on whether we're the last link, and on whether there are
1351168404Spjd	 * other holds on the vnode.  So we dmu_tx_hold() the right things to
1352168404Spjd	 * allow for either case.
1353168404Spjd	 */
1354168404Spjd	tx = dmu_tx_create(zfsvfs->z_os);
1355168404Spjd	dmu_tx_hold_zap(tx, dzp->z_id, FALSE, name);
1356168404Spjd	dmu_tx_hold_bonus(tx, zp->z_id);
1357168962Spjd	if (may_delete_now)
1358168962Spjd		dmu_tx_hold_free(tx, zp->z_id, 0, DMU_OBJECT_END);
1359168404Spjd
1360168404Spjd	/* are there any extended attributes? */
1361168404Spjd	if ((xattr_obj = zp->z_phys->zp_xattr) != 0) {
1362168404Spjd		/* XXX - do we need this if we are deleting? */
1363168404Spjd		dmu_tx_hold_bonus(tx, xattr_obj);
1364168404Spjd	}
1365168404Spjd
1366168962Spjd	/* are there any additional acls */
1367168962Spjd	if ((acl_obj = zp->z_phys->zp_acl.z_acl_extern_obj) != 0 &&
1368168962Spjd	    may_delete_now)
1369168962Spjd		dmu_tx_hold_free(tx, acl_obj, 0, DMU_OBJECT_END);
1370168962Spjd
1371168404Spjd	/* charge as an update -- would be nice not to charge at all */
1372168404Spjd	dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL);
1373168404Spjd
1374168404Spjd	error = dmu_tx_assign(tx, zfsvfs->z_assign);
1375168404Spjd	if (error) {
1376168404Spjd		zfs_dirent_unlock(dl);
1377168962Spjd		VN_RELE(vp);
1378168404Spjd		if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) {
1379168404Spjd			dmu_tx_wait(tx);
1380168404Spjd			dmu_tx_abort(tx);
1381168404Spjd			goto top;
1382168404Spjd		}
1383168404Spjd		dmu_tx_abort(tx);
1384168404Spjd		ZFS_EXIT(zfsvfs);
1385168404Spjd		return (error);
1386168404Spjd	}
1387168404Spjd
1388168404Spjd	/*
1389168404Spjd	 * Remove the directory entry.
1390168404Spjd	 */
1391168404Spjd	error = zfs_link_destroy(dl, zp, tx, 0, &unlinked);
1392168404Spjd
1393168404Spjd	if (error) {
1394168404Spjd		dmu_tx_commit(tx);
1395168404Spjd		goto out;
1396168404Spjd	}
1397168404Spjd
1398168962Spjd	if (0 && unlinked) {
1399168962Spjd		VI_LOCK(vp);
1400168962Spjd		delete_now = may_delete_now &&
1401168962Spjd		    vp->v_count == 1 && !vn_has_cached_data(vp) &&
1402168962Spjd		    zp->z_phys->zp_xattr == xattr_obj &&
1403168962Spjd		    zp->z_phys->zp_acl.z_acl_extern_obj == acl_obj;
1404168962Spjd		VI_UNLOCK(vp);
1405168962Spjd	}
1406168962Spjd
1407168962Spjd	if (delete_now) {
1408168962Spjd		if (zp->z_phys->zp_xattr) {
1409168962Spjd			error = zfs_zget(zfsvfs, zp->z_phys->zp_xattr, &xzp);
1410168962Spjd			ASSERT3U(error, ==, 0);
1411168962Spjd			ASSERT3U(xzp->z_phys->zp_links, ==, 2);
1412168962Spjd			dmu_buf_will_dirty(xzp->z_dbuf, tx);
1413168962Spjd			mutex_enter(&xzp->z_lock);
1414168962Spjd			xzp->z_unlinked = 1;
1415168962Spjd			xzp->z_phys->zp_links = 0;
1416168962Spjd			mutex_exit(&xzp->z_lock);
1417168962Spjd			zfs_unlinked_add(xzp, tx);
1418168962Spjd			zp->z_phys->zp_xattr = 0; /* probably unnecessary */
1419168962Spjd		}
1420168962Spjd		mutex_enter(&zp->z_lock);
1421168962Spjd		VI_LOCK(vp);
1422168962Spjd		vp->v_count--;
1423168962Spjd		ASSERT3U(vp->v_count, ==, 0);
1424168962Spjd		VI_UNLOCK(vp);
1425168962Spjd		mutex_exit(&zp->z_lock);
1426168962Spjd		zfs_znode_delete(zp, tx);
1427168962Spjd		VFS_RELE(zfsvfs->z_vfs);
1428168962Spjd	} else if (unlinked) {
1429168404Spjd		zfs_unlinked_add(zp, tx);
1430168962Spjd	}
1431168404Spjd
1432168404Spjd	zfs_log_remove(zilog, tx, TX_REMOVE, dzp, name);
1433168404Spjd
1434168404Spjd	dmu_tx_commit(tx);
1435168404Spjdout:
1436168404Spjd	zfs_dirent_unlock(dl);
1437168404Spjd
1438168962Spjd	if (!delete_now) {
1439168962Spjd		VN_RELE(vp);
1440168962Spjd	} else if (xzp) {
1441168962Spjd		/* this rele delayed to prevent nesting transactions */
1442168962Spjd		VN_RELE(ZTOV(xzp));
1443168962Spjd	}
1444168962Spjd
1445168404Spjd	ZFS_EXIT(zfsvfs);
1446168404Spjd	return (error);
1447168404Spjd}
1448168404Spjd
1449168404Spjd/*
1450168404Spjd * Create a new directory and insert it into dvp using the name
1451168404Spjd * provided.  Return a pointer to the inserted directory.
1452168404Spjd *
1453168404Spjd *	IN:	dvp	- vnode of directory to add subdir to.
1454168404Spjd *		dirname	- name of new directory.
1455168404Spjd *		vap	- attributes of new directory.
1456168404Spjd *		cr	- credentials of caller.
1457168404Spjd *
1458168404Spjd *	OUT:	vpp	- vnode of created directory.
1459168404Spjd *
1460168404Spjd *	RETURN:	0 if success
1461168404Spjd *		error code if failure
1462168404Spjd *
1463168404Spjd * Timestamps:
1464168404Spjd *	dvp - ctime|mtime updated
1465168404Spjd *	 vp - ctime|mtime|atime updated
1466168404Spjd */
1467168404Spjdstatic int
1468168962Spjdzfs_mkdir(vnode_t *dvp, char *dirname, vattr_t *vap, vnode_t **vpp, cred_t *cr)
1469168404Spjd{
1470168404Spjd	znode_t		*zp, *dzp = VTOZ(dvp);
1471168404Spjd	zfsvfs_t	*zfsvfs = dzp->z_zfsvfs;
1472168404Spjd	zilog_t		*zilog = zfsvfs->z_log;
1473168404Spjd	zfs_dirlock_t	*dl;
1474168404Spjd	uint64_t	zoid = 0;
1475168404Spjd	dmu_tx_t	*tx;
1476168404Spjd	int		error;
1477168404Spjd
1478168404Spjd	ASSERT(vap->va_type == VDIR);
1479168404Spjd
1480168404Spjd	ZFS_ENTER(zfsvfs);
1481168404Spjd
1482168404Spjd	if (dzp->z_phys->zp_flags & ZFS_XATTR) {
1483168404Spjd		ZFS_EXIT(zfsvfs);
1484168404Spjd		return (EINVAL);
1485168404Spjd	}
1486168404Spjdtop:
1487168404Spjd	*vpp = NULL;
1488168404Spjd
1489168404Spjd	/*
1490168404Spjd	 * First make sure the new directory doesn't exist.
1491168404Spjd	 */
1492168404Spjd	if (error = zfs_dirent_lock(&dl, dzp, dirname, &zp, ZNEW)) {
1493168404Spjd		ZFS_EXIT(zfsvfs);
1494168404Spjd		return (error);
1495168404Spjd	}
1496168404Spjd
1497168404Spjd	if (error = zfs_zaccess(dzp, ACE_ADD_SUBDIRECTORY, cr)) {
1498168404Spjd		zfs_dirent_unlock(dl);
1499168404Spjd		ZFS_EXIT(zfsvfs);
1500168404Spjd		return (error);
1501168404Spjd	}
1502168404Spjd
1503168404Spjd	/*
1504168404Spjd	 * Add a new entry to the directory.
1505168404Spjd	 */
1506168404Spjd	tx = dmu_tx_create(zfsvfs->z_os);
1507168404Spjd	dmu_tx_hold_zap(tx, dzp->z_id, TRUE, dirname);
1508168404Spjd	dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, FALSE, NULL);
1509168404Spjd	if (dzp->z_phys->zp_flags & ZFS_INHERIT_ACE)
1510168404Spjd		dmu_tx_hold_write(tx, DMU_NEW_OBJECT,
1511168404Spjd		    0, SPA_MAXBLOCKSIZE);
1512168404Spjd	error = dmu_tx_assign(tx, zfsvfs->z_assign);
1513168404Spjd	if (error) {
1514168404Spjd		zfs_dirent_unlock(dl);
1515168404Spjd		if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) {
1516168404Spjd			dmu_tx_wait(tx);
1517168404Spjd			dmu_tx_abort(tx);
1518168404Spjd			goto top;
1519168404Spjd		}
1520168404Spjd		dmu_tx_abort(tx);
1521168404Spjd		ZFS_EXIT(zfsvfs);
1522168404Spjd		return (error);
1523168404Spjd	}
1524168404Spjd
1525168404Spjd	/*
1526168404Spjd	 * Create new node.
1527168404Spjd	 */
1528168404Spjd	zfs_mknode(dzp, vap, &zoid, tx, cr, 0, &zp, 0);
1529168404Spjd
1530168404Spjd	/*
1531168404Spjd	 * Now put new name in parent dir.
1532168404Spjd	 */
1533168404Spjd	(void) zfs_link_create(dl, zp, tx, ZNEW);
1534168404Spjd
1535168404Spjd	*vpp = ZTOV(zp);
1536168404Spjd
1537168404Spjd	zfs_log_create(zilog, tx, TX_MKDIR, dzp, zp, dirname);
1538168404Spjd	dmu_tx_commit(tx);
1539168404Spjd
1540168962Spjd	vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, curthread);
1541168404Spjd
1542168404Spjd	zfs_dirent_unlock(dl);
1543168404Spjd
1544168404Spjd	ZFS_EXIT(zfsvfs);
1545168404Spjd	return (0);
1546168404Spjd}
1547168404Spjd
1548168404Spjd/*
1549168404Spjd * Remove a directory subdir entry.  If the current working
1550168404Spjd * directory is the same as the subdir to be removed, the
1551168404Spjd * remove will fail.
1552168404Spjd *
1553168404Spjd *	IN:	dvp	- vnode of directory to remove from.
1554168404Spjd *		name	- name of directory to be removed.
1555168404Spjd *		cwd	- vnode of current working directory.
1556168404Spjd *		cr	- credentials of caller.
1557168404Spjd *
1558168404Spjd *	RETURN:	0 if success
1559168404Spjd *		error code if failure
1560168404Spjd *
1561168404Spjd * Timestamps:
1562168404Spjd *	dvp - ctime|mtime updated
1563168404Spjd */
1564168404Spjdstatic int
1565168962Spjdzfs_rmdir(vnode_t *dvp, char *name, vnode_t *cwd, cred_t *cr)
1566168404Spjd{
1567168404Spjd	znode_t		*dzp = VTOZ(dvp);
1568168404Spjd	znode_t		*zp;
1569168404Spjd	vnode_t		*vp;
1570168404Spjd	zfsvfs_t	*zfsvfs = dzp->z_zfsvfs;
1571168404Spjd	zilog_t		*zilog = zfsvfs->z_log;
1572168404Spjd	zfs_dirlock_t	*dl;
1573168404Spjd	dmu_tx_t	*tx;
1574168404Spjd	int		error;
1575168404Spjd
1576168962Spjd	ZFS_ENTER(zfsvfs);
1577168404Spjd
1578168404Spjdtop:
1579168404Spjd	zp = NULL;
1580168404Spjd
1581168404Spjd	/*
1582168404Spjd	 * Attempt to lock directory; fail if entry doesn't exist.
1583168404Spjd	 */
1584168404Spjd	if (error = zfs_dirent_lock(&dl, dzp, name, &zp, ZEXISTS)) {
1585168404Spjd		ZFS_EXIT(zfsvfs);
1586168404Spjd		return (error);
1587168404Spjd	}
1588168404Spjd
1589168404Spjd	vp = ZTOV(zp);
1590168404Spjd
1591168404Spjd	if (error = zfs_zaccess_delete(dzp, zp, cr)) {
1592168404Spjd		goto out;
1593168404Spjd	}
1594168404Spjd
1595168962Spjd	if (vp->v_type != VDIR) {
1596168962Spjd		error = ENOTDIR;
1597168962Spjd		goto out;
1598168962Spjd	}
1599168962Spjd
1600168962Spjd	if (vp == cwd) {
1601168962Spjd		error = EINVAL;
1602168962Spjd		goto out;
1603168962Spjd	}
1604168962Spjd
1605168962Spjd	vnevent_rmdir(vp);
1606168962Spjd
1607168404Spjd	/*
1608168404Spjd	 * Grab a lock on the directory to make sure that noone is
1609168404Spjd	 * trying to add (or lookup) entries while we are removing it.
1610168404Spjd	 */
1611168404Spjd	rw_enter(&zp->z_name_lock, RW_WRITER);
1612168404Spjd
1613168404Spjd	/*
1614168404Spjd	 * Grab a lock on the parent pointer to make sure we play well
1615168404Spjd	 * with the treewalk and directory rename code.
1616168404Spjd	 */
1617168404Spjd	rw_enter(&zp->z_parent_lock, RW_WRITER);
1618168404Spjd
1619168404Spjd	tx = dmu_tx_create(zfsvfs->z_os);
1620168404Spjd	dmu_tx_hold_zap(tx, dzp->z_id, FALSE, name);
1621168404Spjd	dmu_tx_hold_bonus(tx, zp->z_id);
1622168404Spjd	dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL);
1623168404Spjd	error = dmu_tx_assign(tx, zfsvfs->z_assign);
1624168404Spjd	if (error) {
1625168404Spjd		rw_exit(&zp->z_parent_lock);
1626168404Spjd		rw_exit(&zp->z_name_lock);
1627168404Spjd		zfs_dirent_unlock(dl);
1628168962Spjd		VN_RELE(vp);
1629168404Spjd		if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) {
1630168404Spjd			dmu_tx_wait(tx);
1631168404Spjd			dmu_tx_abort(tx);
1632168404Spjd			goto top;
1633168404Spjd		}
1634168404Spjd		dmu_tx_abort(tx);
1635168404Spjd		ZFS_EXIT(zfsvfs);
1636168404Spjd		return (error);
1637168404Spjd	}
1638168404Spjd
1639168404Spjd#ifdef FREEBSD_NAMECACHE
1640168404Spjd	cache_purge(dvp);
1641168404Spjd#endif
1642168404Spjd
1643168404Spjd	error = zfs_link_destroy(dl, zp, tx, 0, NULL);
1644168404Spjd
1645168404Spjd	if (error == 0)
1646168404Spjd		zfs_log_remove(zilog, tx, TX_RMDIR, dzp, name);
1647168404Spjd
1648168404Spjd	dmu_tx_commit(tx);
1649168404Spjd
1650168404Spjd	rw_exit(&zp->z_parent_lock);
1651168404Spjd	rw_exit(&zp->z_name_lock);
1652168404Spjd#ifdef FREEBSD_NAMECACHE
1653168404Spjd	cache_purge(vp);
1654168404Spjd#endif
1655168404Spjdout:
1656168404Spjd	zfs_dirent_unlock(dl);
1657168404Spjd
1658168962Spjd	VN_RELE(vp);
1659168962Spjd
1660168404Spjd	ZFS_EXIT(zfsvfs);
1661168404Spjd	return (error);
1662168404Spjd}
1663168404Spjd
1664168404Spjd/*
1665168404Spjd * Read as many directory entries as will fit into the provided
1666168404Spjd * buffer from the given directory cursor position (specified in
1667168404Spjd * the uio structure.
1668168404Spjd *
1669168404Spjd *	IN:	vp	- vnode of directory to read.
1670168404Spjd *		uio	- structure supplying read location, range info,
1671168404Spjd *			  and return buffer.
1672168404Spjd *		cr	- credentials of caller.
1673168404Spjd *
1674168404Spjd *	OUT:	uio	- updated offset and range, buffer filled.
1675168404Spjd *		eofp	- set to true if end-of-file detected.
1676168404Spjd *
1677168404Spjd *	RETURN:	0 if success
1678168404Spjd *		error code if failure
1679168404Spjd *
1680168404Spjd * Timestamps:
1681168404Spjd *	vp - atime updated
1682168404Spjd *
1683168404Spjd * Note that the low 4 bits of the cookie returned by zap is always zero.
1684168404Spjd * This allows us to use the low range for "special" directory entries:
1685168404Spjd * We use 0 for '.', and 1 for '..'.  If this is the root of the filesystem,
1686168404Spjd * we use the offset 2 for the '.zfs' directory.
1687168404Spjd */
1688168404Spjd/* ARGSUSED */
1689168404Spjdstatic int
1690168962Spjdzfs_readdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp, int *ncookies, u_long **cookies)
1691168404Spjd{
1692168404Spjd	znode_t		*zp = VTOZ(vp);
1693168404Spjd	iovec_t		*iovp;
1694168404Spjd	dirent64_t	*odp;
1695168404Spjd	zfsvfs_t	*zfsvfs = zp->z_zfsvfs;
1696168404Spjd	objset_t	*os;
1697168404Spjd	caddr_t		outbuf;
1698168404Spjd	size_t		bufsize;
1699168404Spjd	zap_cursor_t	zc;
1700168404Spjd	zap_attribute_t	zap;
1701168404Spjd	uint_t		bytes_wanted;
1702168404Spjd	uint64_t	offset; /* must be unsigned; checks for < 1 */
1703168404Spjd	int		local_eof;
1704168404Spjd	int		outcount;
1705168404Spjd	int		error;
1706168404Spjd	uint8_t		prefetch;
1707168404Spjd	uint8_t		type;
1708168962Spjd	int		ncooks;
1709168962Spjd	u_long		*cooks = NULL;
1710168404Spjd
1711168404Spjd	ZFS_ENTER(zfsvfs);
1712168404Spjd
1713168404Spjd	/*
1714168404Spjd	 * If we are not given an eof variable,
1715168404Spjd	 * use a local one.
1716168404Spjd	 */
1717168404Spjd	if (eofp == NULL)
1718168404Spjd		eofp = &local_eof;
1719168404Spjd
1720168404Spjd	/*
1721168404Spjd	 * Check for valid iov_len.
1722168404Spjd	 */
1723168404Spjd	if (uio->uio_iov->iov_len <= 0) {
1724168404Spjd		ZFS_EXIT(zfsvfs);
1725168404Spjd		return (EINVAL);
1726168404Spjd	}
1727168404Spjd
1728168404Spjd	/*
1729168404Spjd	 * Quit if directory has been removed (posix)
1730168404Spjd	 */
1731168404Spjd	if ((*eofp = zp->z_unlinked) != 0) {
1732168404Spjd		ZFS_EXIT(zfsvfs);
1733168404Spjd		return (0);
1734168404Spjd	}
1735168404Spjd
1736168404Spjd	error = 0;
1737168404Spjd	os = zfsvfs->z_os;
1738168404Spjd	offset = uio->uio_loffset;
1739168404Spjd	prefetch = zp->z_zn_prefetch;
1740168404Spjd
1741168404Spjd	/*
1742168404Spjd	 * Initialize the iterator cursor.
1743168404Spjd	 */
1744168404Spjd	if (offset <= 3) {
1745168404Spjd		/*
1746168404Spjd		 * Start iteration from the beginning of the directory.
1747168404Spjd		 */
1748168404Spjd		zap_cursor_init(&zc, os, zp->z_id);
1749168404Spjd	} else {
1750168404Spjd		/*
1751168404Spjd		 * The offset is a serialized cursor.
1752168404Spjd		 */
1753168404Spjd		zap_cursor_init_serialized(&zc, os, zp->z_id, offset);
1754168404Spjd	}
1755168404Spjd
1756168404Spjd	/*
1757168404Spjd	 * Get space to change directory entries into fs independent format.
1758168404Spjd	 */
1759168404Spjd	iovp = uio->uio_iov;
1760168404Spjd	bytes_wanted = iovp->iov_len;
1761168404Spjd	if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) {
1762168404Spjd		bufsize = bytes_wanted;
1763168404Spjd		outbuf = kmem_alloc(bufsize, KM_SLEEP);
1764168404Spjd		odp = (struct dirent64 *)outbuf;
1765168404Spjd	} else {
1766168404Spjd		bufsize = bytes_wanted;
1767168404Spjd		odp = (struct dirent64 *)iovp->iov_base;
1768168404Spjd	}
1769168404Spjd
1770168962Spjd	if (ncookies != NULL) {
1771168404Spjd		/*
1772168404Spjd		 * Minimum entry size is dirent size and 1 byte for a file name.
1773168404Spjd		 */
1774168962Spjd		ncooks = uio->uio_resid / (sizeof(struct dirent) - sizeof(((struct dirent *)NULL)->d_name) + 1);
1775168962Spjd		cooks = malloc(ncooks * sizeof(u_long), M_TEMP, M_WAITOK);
1776168962Spjd		*cookies = cooks;
1777168962Spjd		*ncookies = ncooks;
1778168404Spjd	}
1779168404Spjd
1780168404Spjd	/*
1781168404Spjd	 * Transform to file-system independent format
1782168404Spjd	 */
1783168404Spjd	outcount = 0;
1784168404Spjd	while (outcount < bytes_wanted) {
1785168404Spjd		ino64_t objnum;
1786168404Spjd		ushort_t reclen;
1787168404Spjd
1788168404Spjd		/*
1789168404Spjd		 * Special case `.', `..', and `.zfs'.
1790168404Spjd		 */
1791168404Spjd		if (offset == 0) {
1792168404Spjd			(void) strcpy(zap.za_name, ".");
1793168404Spjd			objnum = zp->z_id;
1794168404Spjd		} else if (offset == 1) {
1795168404Spjd			(void) strcpy(zap.za_name, "..");
1796168404Spjd			objnum = zp->z_phys->zp_parent;
1797168404Spjd		} else if (offset == 2 && zfs_show_ctldir(zp)) {
1798168404Spjd			(void) strcpy(zap.za_name, ZFS_CTLDIR_NAME);
1799168404Spjd			objnum = ZFSCTL_INO_ROOT;
1800168404Spjd		} else {
1801168404Spjd			/*
1802168404Spjd			 * Grab next entry.
1803168404Spjd			 */
1804168404Spjd			if (error = zap_cursor_retrieve(&zc, &zap)) {
1805168404Spjd				if ((*eofp = (error == ENOENT)) != 0)
1806168404Spjd					break;
1807168404Spjd				else
1808168404Spjd					goto update;
1809168404Spjd			}
1810168404Spjd
1811168404Spjd			if (zap.za_integer_length != 8 ||
1812168404Spjd			    zap.za_num_integers != 1) {
1813168404Spjd				cmn_err(CE_WARN, "zap_readdir: bad directory "
1814168404Spjd				    "entry, obj = %lld, offset = %lld\n",
1815168404Spjd				    (u_longlong_t)zp->z_id,
1816168404Spjd				    (u_longlong_t)offset);
1817168404Spjd				error = ENXIO;
1818168404Spjd				goto update;
1819168404Spjd			}
1820168404Spjd
1821168404Spjd			objnum = ZFS_DIRENT_OBJ(zap.za_first_integer);
1822168404Spjd			/*
1823168404Spjd			 * MacOS X can extract the object type here such as:
1824168404Spjd			 * uint8_t type = ZFS_DIRENT_TYPE(zap.za_first_integer);
1825168404Spjd			 */
1826168404Spjd			type = ZFS_DIRENT_TYPE(zap.za_first_integer);
1827168404Spjd		}
1828168404Spjd		reclen = DIRENT64_RECLEN(strlen(zap.za_name));
1829168404Spjd
1830168404Spjd		/*
1831168404Spjd		 * Will this entry fit in the buffer?
1832168404Spjd		 */
1833168404Spjd		if (outcount + reclen > bufsize) {
1834168404Spjd			/*
1835168404Spjd			 * Did we manage to fit anything in the buffer?
1836168404Spjd			 */
1837168404Spjd			if (!outcount) {
1838168404Spjd				error = EINVAL;
1839168404Spjd				goto update;
1840168404Spjd			}
1841168404Spjd			break;
1842168404Spjd		}
1843168404Spjd		/*
1844168404Spjd		 * Add this entry:
1845168404Spjd		 */
1846168404Spjd		odp->d_ino = objnum;
1847168404Spjd		odp->d_reclen = reclen;
1848168404Spjd		odp->d_namlen = strlen(zap.za_name);
1849168404Spjd		(void) strlcpy(odp->d_name, zap.za_name, odp->d_namlen + 1);
1850168404Spjd		odp->d_type = type;
1851168404Spjd		outcount += reclen;
1852168404Spjd		odp = (dirent64_t *)((intptr_t)odp + reclen);
1853168404Spjd
1854168404Spjd		ASSERT(outcount <= bufsize);
1855168404Spjd
1856168404Spjd		/* Prefetch znode */
1857168404Spjd		if (prefetch)
1858168404Spjd			dmu_prefetch(os, objnum, 0, 0);
1859168404Spjd
1860168404Spjd		/*
1861168404Spjd		 * Move to the next entry, fill in the previous offset.
1862168404Spjd		 */
1863168404Spjd		if (offset > 2 || (offset == 2 && !zfs_show_ctldir(zp))) {
1864168404Spjd			zap_cursor_advance(&zc);
1865168404Spjd			offset = zap_cursor_serialize(&zc);
1866168404Spjd		} else {
1867168404Spjd			offset += 1;
1868168404Spjd		}
1869168404Spjd
1870168962Spjd		if (cooks != NULL) {
1871168962Spjd			*cooks++ = offset;
1872168962Spjd			ncooks--;
1873168962Spjd			KASSERT(ncooks >= 0, ("ncookies=%d", ncooks));
1874168404Spjd		}
1875168404Spjd	}
1876168404Spjd	zp->z_zn_prefetch = B_FALSE; /* a lookup will re-enable pre-fetching */
1877168404Spjd
1878168404Spjd	/* Subtract unused cookies */
1879168962Spjd	if (ncookies != NULL)
1880168962Spjd		*ncookies -= ncooks;
1881168404Spjd
1882168404Spjd	if (uio->uio_segflg == UIO_SYSSPACE && uio->uio_iovcnt == 1) {
1883168404Spjd		iovp->iov_base += outcount;
1884168404Spjd		iovp->iov_len -= outcount;
1885168404Spjd		uio->uio_resid -= outcount;
1886168404Spjd	} else if (error = uiomove(outbuf, (long)outcount, UIO_READ, uio)) {
1887168404Spjd		/*
1888168404Spjd		 * Reset the pointer.
1889168404Spjd		 */
1890168404Spjd		offset = uio->uio_loffset;
1891168404Spjd	}
1892168404Spjd
1893168404Spjdupdate:
1894168404Spjd	zap_cursor_fini(&zc);
1895168404Spjd	if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
1896168404Spjd		kmem_free(outbuf, bufsize);
1897168404Spjd
1898168404Spjd	if (error == ENOENT)
1899168404Spjd		error = 0;
1900168404Spjd
1901168404Spjd	ZFS_ACCESSTIME_STAMP(zfsvfs, zp);
1902168404Spjd
1903168404Spjd	uio->uio_loffset = offset;
1904168404Spjd	ZFS_EXIT(zfsvfs);
1905168404Spjd	if (error != 0) {
1906168962Spjd		free(*cookies, M_TEMP);
1907168962Spjd		*cookies = NULL;
1908168962Spjd		*ncookies = 0;
1909168404Spjd	}
1910168404Spjd	return (error);
1911168404Spjd}
1912168404Spjd
1913168404Spjdstatic int
1914168962Spjdzfs_fsync(vnode_t *vp, int syncflag, cred_t *cr)
1915168404Spjd{
1916168962Spjd	znode_t	*zp = VTOZ(vp);
1917168962Spjd	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
1918168404Spjd
1919168404Spjd	ZFS_ENTER(zfsvfs);
1920168404Spjd	zil_commit(zfsvfs->z_log, zp->z_last_itx, zp->z_id);
1921168404Spjd	ZFS_EXIT(zfsvfs);
1922168404Spjd	return (0);
1923168404Spjd}
1924168404Spjd
1925168404Spjd/*
1926168404Spjd * Get the requested file attributes and place them in the provided
1927168404Spjd * vattr structure.
1928168404Spjd *
1929168404Spjd *	IN:	vp	- vnode of file.
1930168404Spjd *		vap	- va_mask identifies requested attributes.
1931168404Spjd *		flags	- [UNUSED]
1932168404Spjd *		cr	- credentials of caller.
1933168404Spjd *
1934168404Spjd *	OUT:	vap	- attribute values.
1935168404Spjd *
1936168404Spjd *	RETURN:	0 (always succeeds)
1937168404Spjd */
1938168404Spjd/* ARGSUSED */
1939168404Spjdstatic int
1940168962Spjdzfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr)
1941168404Spjd{
1942168962Spjd	znode_t *zp = VTOZ(vp);
1943168962Spjd	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
1944168962Spjd	znode_phys_t *pzp = zp->z_phys;
1945168962Spjd	uint32_t blksize;
1946168962Spjd	u_longlong_t nblocks;
1947168962Spjd	int	error;
1948168404Spjd
1949168404Spjd	ZFS_ENTER(zfsvfs);
1950168404Spjd
1951168404Spjd	/*
1952168404Spjd	 * Return all attributes.  It's cheaper to provide the answer
1953168404Spjd	 * than to determine whether we were asked the question.
1954168404Spjd	 */
1955168404Spjd	mutex_enter(&zp->z_lock);
1956168404Spjd
1957168404Spjd	vap->va_type = IFTOVT(pzp->zp_mode);
1958168404Spjd	vap->va_mode = pzp->zp_mode & ~S_IFMT;
1959168404Spjd	vap->va_uid = zp->z_phys->zp_uid;
1960168404Spjd	vap->va_gid = zp->z_phys->zp_gid;
1961168404Spjd	vap->va_nodeid = zp->z_id;
1962168404Spjd	vap->va_nlink = MIN(pzp->zp_links, UINT32_MAX);	/* nlink_t limit! */
1963168404Spjd	vap->va_size = pzp->zp_size;
1964168404Spjd	vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
1965168958Spjd	vap->va_rdev = zfs_cmpldev(pzp->zp_rdev);
1966168404Spjd	vap->va_seq = zp->z_seq;
1967168404Spjd	vap->va_flags = 0;	/* FreeBSD: Reset chflags(2) flags. */
1968168404Spjd
1969168404Spjd	ZFS_TIME_DECODE(&vap->va_atime, pzp->zp_atime);
1970168404Spjd	ZFS_TIME_DECODE(&vap->va_mtime, pzp->zp_mtime);
1971168404Spjd	ZFS_TIME_DECODE(&vap->va_ctime, pzp->zp_ctime);
1972168404Spjd	ZFS_TIME_DECODE(&vap->va_birthtime, pzp->zp_crtime);
1973168404Spjd
1974168404Spjd	/*
1975168404Spjd	 * If ACL is trivial don't bother looking for ACE_READ_ATTRIBUTES.
1976168404Spjd	 * Also, if we are the owner don't bother, since owner should
1977168404Spjd	 * always be allowed to read basic attributes of file.
1978168404Spjd	 */
1979168404Spjd	if (!(zp->z_phys->zp_flags & ZFS_ACL_TRIVIAL) &&
1980168404Spjd	    (zp->z_phys->zp_uid != crgetuid(cr))) {
1981168404Spjd		if (error = zfs_zaccess(zp, ACE_READ_ATTRIBUTES, cr)) {
1982168404Spjd			mutex_exit(&zp->z_lock);
1983168404Spjd			ZFS_EXIT(zfsvfs);
1984168404Spjd			return (error);
1985168404Spjd		}
1986168404Spjd	}
1987168404Spjd
1988168404Spjd	mutex_exit(&zp->z_lock);
1989168404Spjd
1990168404Spjd	dmu_object_size_from_db(zp->z_dbuf, &blksize, &nblocks);
1991168404Spjd	vap->va_blksize = blksize;
1992168404Spjd	vap->va_bytes = nblocks << 9;	/* nblocks * 512 */
1993168404Spjd
1994168404Spjd	if (zp->z_blksz == 0) {
1995168404Spjd		/*
1996168404Spjd		 * Block size hasn't been set; suggest maximal I/O transfers.
1997168404Spjd		 */
1998168404Spjd		vap->va_blksize = zfsvfs->z_max_blksz;
1999168404Spjd	}
2000168404Spjd
2001168404Spjd	ZFS_EXIT(zfsvfs);
2002168404Spjd	return (0);
2003168404Spjd}
2004168404Spjd
2005168404Spjd/*
2006168404Spjd * Set the file attributes to the values contained in the
2007168404Spjd * vattr structure.
2008168404Spjd *
2009168404Spjd *	IN:	vp	- vnode of file to be modified.
2010168404Spjd *		vap	- new attribute values.
2011168404Spjd *		flags	- ATTR_UTIME set if non-default time values provided.
2012168404Spjd *		cr	- credentials of caller.
2013168404Spjd *
2014168404Spjd *	RETURN:	0 if success
2015168404Spjd *		error code if failure
2016168404Spjd *
2017168404Spjd * Timestamps:
2018168404Spjd *	vp - ctime updated, mtime updated if size changed.
2019168404Spjd */
2020168404Spjd/* ARGSUSED */
2021168404Spjdstatic int
2022168962Spjdzfs_setattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
2023168962Spjd	caller_context_t *ct)
2024168404Spjd{
2025168962Spjd	struct znode	*zp = VTOZ(vp);
2026168404Spjd	znode_phys_t	*pzp = zp->z_phys;
2027168404Spjd	zfsvfs_t	*zfsvfs = zp->z_zfsvfs;
2028168404Spjd	zilog_t		*zilog = zfsvfs->z_log;
2029168404Spjd	dmu_tx_t	*tx;
2030168404Spjd	vattr_t		oldva;
2031168962Spjd	uint_t		mask = vap->va_mask;
2032168404Spjd	uint_t		saved_mask;
2033168404Spjd	int		trim_mask = 0;
2034168404Spjd	uint64_t	new_mode;
2035168404Spjd	znode_t		*attrzp;
2036168404Spjd	int		need_policy = FALSE;
2037168404Spjd	int		err;
2038168404Spjd
2039168404Spjd	if (mask == 0)
2040168404Spjd		return (0);
2041168404Spjd
2042168962Spjd	if (mask & AT_NOSET)
2043168962Spjd		return (EINVAL);
2044168962Spjd
2045168404Spjd	if (mask & AT_SIZE && vp->v_type == VDIR)
2046168404Spjd		return (EISDIR);
2047168404Spjd
2048168404Spjd	if (mask & AT_SIZE && vp->v_type != VREG && vp->v_type != VFIFO)
2049168404Spjd		return (EINVAL);
2050168404Spjd
2051168404Spjd	ZFS_ENTER(zfsvfs);
2052168404Spjd
2053168404Spjdtop:
2054168404Spjd	attrzp = NULL;
2055168404Spjd
2056168404Spjd	if (zfsvfs->z_vfs->vfs_flag & VFS_RDONLY) {
2057168404Spjd		ZFS_EXIT(zfsvfs);
2058168404Spjd		return (EROFS);
2059168404Spjd	}
2060168404Spjd
2061168404Spjd	/*
2062168404Spjd	 * First validate permissions
2063168404Spjd	 */
2064168404Spjd
2065168404Spjd	if (mask & AT_SIZE) {
2066168404Spjd		err = zfs_zaccess(zp, ACE_WRITE_DATA, cr);
2067168404Spjd		if (err) {
2068168404Spjd			ZFS_EXIT(zfsvfs);
2069168404Spjd			return (err);
2070168404Spjd		}
2071168404Spjd		/*
2072168404Spjd		 * XXX - Note, we are not providing any open
2073168404Spjd		 * mode flags here (like FNDELAY), so we may
2074168404Spjd		 * block if there are locks present... this
2075168404Spjd		 * should be addressed in openat().
2076168404Spjd		 */
2077168404Spjd		do {
2078168404Spjd			err = zfs_freesp(zp, vap->va_size, 0, 0, FALSE);
2079168404Spjd			/* NB: we already did dmu_tx_wait() if necessary */
2080168404Spjd		} while (err == ERESTART && zfsvfs->z_assign == TXG_NOWAIT);
2081168404Spjd		if (err) {
2082168404Spjd			ZFS_EXIT(zfsvfs);
2083168404Spjd			return (err);
2084168404Spjd		}
2085168404Spjd	}
2086168404Spjd
2087168404Spjd	if (mask & (AT_ATIME|AT_MTIME))
2088168404Spjd		need_policy = zfs_zaccess_v4_perm(zp, ACE_WRITE_ATTRIBUTES, cr);
2089168404Spjd
2090168404Spjd	if (mask & (AT_UID|AT_GID)) {
2091168404Spjd		int	idmask = (mask & (AT_UID|AT_GID));
2092168404Spjd		int	take_owner;
2093168404Spjd		int	take_group;
2094168404Spjd
2095168404Spjd		/*
2096168404Spjd		 * NOTE: even if a new mode is being set,
2097168404Spjd		 * we may clear S_ISUID/S_ISGID bits.
2098168404Spjd		 */
2099168404Spjd
2100168404Spjd		if (!(mask & AT_MODE))
2101168404Spjd			vap->va_mode = pzp->zp_mode;
2102168404Spjd
2103168404Spjd		/*
2104168404Spjd		 * Take ownership or chgrp to group we are a member of
2105168404Spjd		 */
2106168404Spjd
2107168404Spjd		take_owner = (mask & AT_UID) && (vap->va_uid == crgetuid(cr));
2108168404Spjd		take_group = (mask & AT_GID) && groupmember(vap->va_gid, cr);
2109168404Spjd
2110168404Spjd		/*
2111168404Spjd		 * If both AT_UID and AT_GID are set then take_owner and
2112168404Spjd		 * take_group must both be set in order to allow taking
2113168404Spjd		 * ownership.
2114168404Spjd		 *
2115168404Spjd		 * Otherwise, send the check through secpolicy_vnode_setattr()
2116168404Spjd		 *
2117168404Spjd		 */
2118168404Spjd
2119168404Spjd		if (((idmask == (AT_UID|AT_GID)) && take_owner && take_group) ||
2120168404Spjd		    ((idmask == AT_UID) && take_owner) ||
2121168404Spjd		    ((idmask == AT_GID) && take_group)) {
2122168404Spjd			if (zfs_zaccess_v4_perm(zp, ACE_WRITE_OWNER, cr) == 0) {
2123168404Spjd				/*
2124168404Spjd				 * Remove setuid/setgid for non-privileged users
2125168404Spjd				 */
2126168404Spjd				secpolicy_setid_clear(vap, cr);
2127168404Spjd				trim_mask = (mask & (AT_UID|AT_GID));
2128168404Spjd			} else {
2129168404Spjd				need_policy =  TRUE;
2130168404Spjd			}
2131168404Spjd		} else {
2132168404Spjd			need_policy =  TRUE;
2133168404Spjd		}
2134168404Spjd	}
2135168404Spjd
2136168404Spjd	mutex_enter(&zp->z_lock);
2137168404Spjd	oldva.va_mode = pzp->zp_mode;
2138168404Spjd	oldva.va_uid = zp->z_phys->zp_uid;
2139168404Spjd	oldva.va_gid = zp->z_phys->zp_gid;
2140168404Spjd	mutex_exit(&zp->z_lock);
2141168404Spjd
2142168404Spjd	if (mask & AT_MODE) {
2143168404Spjd		if (zfs_zaccess_v4_perm(zp, ACE_WRITE_ACL, cr) == 0) {
2144168962Spjd			err = secpolicy_setid_setsticky_clear(vp, vap,
2145168962Spjd			    &oldva, cr);
2146168962Spjd			if (err) {
2147168962Spjd				ZFS_EXIT(zfsvfs);
2148168962Spjd				return (err);
2149168962Spjd			}
2150168404Spjd			trim_mask |= AT_MODE;
2151168404Spjd		} else {
2152168404Spjd			need_policy = TRUE;
2153168404Spjd		}
2154168404Spjd	}
2155168404Spjd
2156168404Spjd	if (need_policy) {
2157168404Spjd		/*
2158168404Spjd		 * If trim_mask is set then take ownership
2159168404Spjd		 * has been granted or write_acl is present and user
2160168404Spjd		 * has the ability to modify mode.  In that case remove
2161168404Spjd		 * UID|GID and or MODE from mask so that
2162168404Spjd		 * secpolicy_vnode_setattr() doesn't revoke it.
2163168404Spjd		 */
2164168404Spjd
2165168404Spjd		if (trim_mask) {
2166168404Spjd			saved_mask = vap->va_mask;
2167168404Spjd			vap->va_mask &= ~trim_mask;
2168168404Spjd
2169168404Spjd		}
2170168404Spjd		err = secpolicy_vnode_setattr(cr, vp, vap, &oldva, flags,
2171168404Spjd		    (int (*)(void *, int, cred_t *))zfs_zaccess_rwx, zp);
2172168404Spjd		if (err) {
2173168404Spjd			ZFS_EXIT(zfsvfs);
2174168404Spjd			return (err);
2175168404Spjd		}
2176168404Spjd
2177168404Spjd		if (trim_mask)
2178168404Spjd			vap->va_mask |= saved_mask;
2179168404Spjd	}
2180168404Spjd
2181168404Spjd	/*
2182168404Spjd	 * secpolicy_vnode_setattr, or take ownership may have
2183168404Spjd	 * changed va_mask
2184168404Spjd	 */
2185168404Spjd	mask = vap->va_mask;
2186168404Spjd
2187168404Spjd	tx = dmu_tx_create(zfsvfs->z_os);
2188168404Spjd	dmu_tx_hold_bonus(tx, zp->z_id);
2189168404Spjd
2190168404Spjd	if (mask & AT_MODE) {
2191168404Spjd		uint64_t pmode = pzp->zp_mode;
2192168404Spjd
2193168404Spjd		new_mode = (pmode & S_IFMT) | (vap->va_mode & ~S_IFMT);
2194168404Spjd
2195168404Spjd		if (zp->z_phys->zp_acl.z_acl_extern_obj)
2196168404Spjd			dmu_tx_hold_write(tx,
2197168404Spjd			    pzp->zp_acl.z_acl_extern_obj, 0, SPA_MAXBLOCKSIZE);
2198168404Spjd		else
2199168404Spjd			dmu_tx_hold_write(tx, DMU_NEW_OBJECT,
2200168404Spjd			    0, ZFS_ACL_SIZE(MAX_ACL_SIZE));
2201168404Spjd	}
2202168404Spjd
2203168404Spjd	if ((mask & (AT_UID | AT_GID)) && zp->z_phys->zp_xattr != 0) {
2204168404Spjd		err = zfs_zget(zp->z_zfsvfs, zp->z_phys->zp_xattr, &attrzp);
2205168404Spjd		if (err) {
2206168404Spjd			dmu_tx_abort(tx);
2207168404Spjd			ZFS_EXIT(zfsvfs);
2208168404Spjd			return (err);
2209168404Spjd		}
2210168404Spjd		dmu_tx_hold_bonus(tx, attrzp->z_id);
2211168404Spjd	}
2212168404Spjd
2213168404Spjd	err = dmu_tx_assign(tx, zfsvfs->z_assign);
2214168404Spjd	if (err) {
2215168404Spjd		if (attrzp)
2216168404Spjd			VN_RELE(ZTOV(attrzp));
2217168404Spjd		if (err == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) {
2218168404Spjd			dmu_tx_wait(tx);
2219168404Spjd			dmu_tx_abort(tx);
2220168404Spjd			goto top;
2221168404Spjd		}
2222168404Spjd		dmu_tx_abort(tx);
2223168404Spjd		ZFS_EXIT(zfsvfs);
2224168404Spjd		return (err);
2225168404Spjd	}
2226168404Spjd
2227168404Spjd	dmu_buf_will_dirty(zp->z_dbuf, tx);
2228168404Spjd
2229168404Spjd	/*
2230168404Spjd	 * Set each attribute requested.
2231168404Spjd	 * We group settings according to the locks they need to acquire.
2232168404Spjd	 *
2233168404Spjd	 * Note: you cannot set ctime directly, although it will be
2234168404Spjd	 * updated as a side-effect of calling this function.
2235168404Spjd	 */
2236168404Spjd
2237168404Spjd	mutex_enter(&zp->z_lock);
2238168404Spjd
2239168404Spjd	if (mask & AT_MODE) {
2240168404Spjd		err = zfs_acl_chmod_setattr(zp, new_mode, tx);
2241168404Spjd		ASSERT3U(err, ==, 0);
2242168404Spjd	}
2243168404Spjd
2244168404Spjd	if (attrzp)
2245168404Spjd		mutex_enter(&attrzp->z_lock);
2246168404Spjd
2247168404Spjd	if (mask & AT_UID) {
2248168404Spjd		zp->z_phys->zp_uid = (uint64_t)vap->va_uid;
2249168404Spjd		if (attrzp) {
2250168404Spjd			attrzp->z_phys->zp_uid = (uint64_t)vap->va_uid;
2251168404Spjd		}
2252168404Spjd	}
2253168404Spjd
2254168404Spjd	if (mask & AT_GID) {
2255168404Spjd		zp->z_phys->zp_gid = (uint64_t)vap->va_gid;
2256168404Spjd		if (attrzp)
2257168404Spjd			attrzp->z_phys->zp_gid = (uint64_t)vap->va_gid;
2258168404Spjd	}
2259168404Spjd
2260168404Spjd	if (attrzp)
2261168404Spjd		mutex_exit(&attrzp->z_lock);
2262168404Spjd
2263168404Spjd	if (mask & AT_ATIME)
2264168404Spjd		ZFS_TIME_ENCODE(&vap->va_atime, pzp->zp_atime);
2265168404Spjd
2266168404Spjd	if (mask & AT_MTIME)
2267168404Spjd		ZFS_TIME_ENCODE(&vap->va_mtime, pzp->zp_mtime);
2268168404Spjd
2269168404Spjd	if (mask & AT_SIZE)
2270168404Spjd		zfs_time_stamper_locked(zp, CONTENT_MODIFIED, tx);
2271168404Spjd	else if (mask != 0)
2272168404Spjd		zfs_time_stamper_locked(zp, STATE_CHANGED, tx);
2273168404Spjd
2274168404Spjd	if (mask != 0)
2275168404Spjd		zfs_log_setattr(zilog, tx, TX_SETATTR, zp, vap, mask);
2276168404Spjd
2277168404Spjd	mutex_exit(&zp->z_lock);
2278168404Spjd
2279168404Spjd	if (attrzp)
2280168404Spjd		VN_RELE(ZTOV(attrzp));
2281168404Spjd
2282168404Spjd	dmu_tx_commit(tx);
2283168404Spjd
2284168404Spjd	ZFS_EXIT(zfsvfs);
2285168404Spjd	return (err);
2286168404Spjd}
2287168404Spjd
2288168404Spjdtypedef struct zfs_zlock {
2289168404Spjd	krwlock_t	*zl_rwlock;	/* lock we acquired */
2290168404Spjd	znode_t		*zl_znode;	/* znode we held */
2291168404Spjd	struct zfs_zlock *zl_next;	/* next in list */
2292168404Spjd} zfs_zlock_t;
2293168404Spjd
2294168404Spjd/*
2295168404Spjd * Drop locks and release vnodes that were held by zfs_rename_lock().
2296168404Spjd */
2297168404Spjdstatic void
2298168404Spjdzfs_rename_unlock(zfs_zlock_t **zlpp)
2299168404Spjd{
2300168404Spjd	zfs_zlock_t *zl;
2301168404Spjd
2302168404Spjd	while ((zl = *zlpp) != NULL) {
2303168404Spjd		if (zl->zl_znode != NULL)
2304168404Spjd			VN_RELE(ZTOV(zl->zl_znode));
2305168404Spjd		rw_exit(zl->zl_rwlock);
2306168404Spjd		*zlpp = zl->zl_next;
2307168404Spjd		kmem_free(zl, sizeof (*zl));
2308168404Spjd	}
2309168404Spjd}
2310168404Spjd
2311168404Spjd/*
2312168404Spjd * Search back through the directory tree, using the ".." entries.
2313168404Spjd * Lock each directory in the chain to prevent concurrent renames.
2314168404Spjd * Fail any attempt to move a directory into one of its own descendants.
2315168404Spjd * XXX - z_parent_lock can overlap with map or grow locks
2316168404Spjd */
2317168404Spjdstatic int
2318168404Spjdzfs_rename_lock(znode_t *szp, znode_t *tdzp, znode_t *sdzp, zfs_zlock_t **zlpp)
2319168404Spjd{
2320168404Spjd	zfs_zlock_t	*zl;
2321168404Spjd	znode_t		*zp = tdzp;
2322168404Spjd	uint64_t	rootid = zp->z_zfsvfs->z_root;
2323168404Spjd	uint64_t	*oidp = &zp->z_id;
2324168404Spjd	krwlock_t	*rwlp = &szp->z_parent_lock;
2325168404Spjd	krw_t		rw = RW_WRITER;
2326168404Spjd
2327168404Spjd	/*
2328168404Spjd	 * First pass write-locks szp and compares to zp->z_id.
2329168404Spjd	 * Later passes read-lock zp and compare to zp->z_parent.
2330168404Spjd	 */
2331168404Spjd	do {
2332168404Spjd		if (!rw_tryenter(rwlp, rw)) {
2333168404Spjd			/*
2334168404Spjd			 * Another thread is renaming in this path.
2335168404Spjd			 * Note that if we are a WRITER, we don't have any
2336168404Spjd			 * parent_locks held yet.
2337168404Spjd			 */
2338168404Spjd			if (rw == RW_READER && zp->z_id > szp->z_id) {
2339168404Spjd				/*
2340168404Spjd				 * Drop our locks and restart
2341168404Spjd				 */
2342168404Spjd				zfs_rename_unlock(&zl);
2343168404Spjd				*zlpp = NULL;
2344168404Spjd				zp = tdzp;
2345168404Spjd				oidp = &zp->z_id;
2346168404Spjd				rwlp = &szp->z_parent_lock;
2347168404Spjd				rw = RW_WRITER;
2348168404Spjd				continue;
2349168404Spjd			} else {
2350168404Spjd				/*
2351168404Spjd				 * Wait for other thread to drop its locks
2352168404Spjd				 */
2353168404Spjd				rw_enter(rwlp, rw);
2354168404Spjd			}
2355168404Spjd		}
2356168404Spjd
2357168404Spjd		zl = kmem_alloc(sizeof (*zl), KM_SLEEP);
2358168404Spjd		zl->zl_rwlock = rwlp;
2359168404Spjd		zl->zl_znode = NULL;
2360168404Spjd		zl->zl_next = *zlpp;
2361168404Spjd		*zlpp = zl;
2362168404Spjd
2363168404Spjd		if (*oidp == szp->z_id)		/* We're a descendant of szp */
2364168404Spjd			return (EINVAL);
2365168404Spjd
2366168404Spjd		if (*oidp == rootid)		/* We've hit the top */
2367168404Spjd			return (0);
2368168404Spjd
2369168404Spjd		if (rw == RW_READER) {		/* i.e. not the first pass */
2370168404Spjd			int error = zfs_zget(zp->z_zfsvfs, *oidp, &zp);
2371168404Spjd			if (error)
2372168404Spjd				return (error);
2373168404Spjd			zl->zl_znode = zp;
2374168404Spjd		}
2375168404Spjd		oidp = &zp->z_phys->zp_parent;
2376168404Spjd		rwlp = &zp->z_parent_lock;
2377168404Spjd		rw = RW_READER;
2378168404Spjd
2379168404Spjd	} while (zp->z_id != sdzp->z_id);
2380168404Spjd
2381168404Spjd	return (0);
2382168404Spjd}
2383168404Spjd
2384168404Spjd/*
2385168404Spjd * Move an entry from the provided source directory to the target
2386168404Spjd * directory.  Change the entry name as indicated.
2387168404Spjd *
2388168404Spjd *	IN:	sdvp	- Source directory containing the "old entry".
2389168404Spjd *		snm	- Old entry name.
2390168404Spjd *		tdvp	- Target directory to contain the "new entry".
2391168404Spjd *		tnm	- New entry name.
2392168404Spjd *		cr	- credentials of caller.
2393168404Spjd *
2394168404Spjd *	RETURN:	0 if success
2395168404Spjd *		error code if failure
2396168404Spjd *
2397168404Spjd * Timestamps:
2398168404Spjd *	sdvp,tdvp - ctime|mtime updated
2399168404Spjd */
2400168404Spjdstatic int
2401168962Spjdzfs_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm, cred_t *cr)
2402168404Spjd{
2403168404Spjd	znode_t		*tdzp, *szp, *tzp;
2404168404Spjd	znode_t		*sdzp = VTOZ(sdvp);
2405168404Spjd	zfsvfs_t	*zfsvfs = sdzp->z_zfsvfs;
2406168404Spjd	zilog_t		*zilog = zfsvfs->z_log;
2407168962Spjd	vnode_t		*realvp;
2408168404Spjd	zfs_dirlock_t	*sdl, *tdl;
2409168404Spjd	dmu_tx_t	*tx;
2410168404Spjd	zfs_zlock_t	*zl;
2411168962Spjd	int		cmp, serr, terr, error;
2412168404Spjd
2413168404Spjd	ZFS_ENTER(zfsvfs);
2414168404Spjd
2415168962Spjd	/*
2416168962Spjd	 * Make sure we have the real vp for the target directory.
2417168962Spjd	 */
2418168962Spjd	if (VOP_REALVP(tdvp, &realvp) == 0)
2419168962Spjd		tdvp = realvp;
2420168962Spjd
2421168404Spjd	if (tdvp->v_vfsp != sdvp->v_vfsp) {
2422168404Spjd		ZFS_EXIT(zfsvfs);
2423168962Spjd		return (EXDEV);
2424168404Spjd	}
2425168404Spjd
2426168404Spjd	tdzp = VTOZ(tdvp);
2427168404Spjdtop:
2428168404Spjd	szp = NULL;
2429168404Spjd	tzp = NULL;
2430168404Spjd	zl = NULL;
2431168404Spjd
2432168404Spjd	/*
2433168404Spjd	 * This is to prevent the creation of links into attribute space
2434168404Spjd	 * by renaming a linked file into/outof an attribute directory.
2435168404Spjd	 * See the comment in zfs_link() for why this is considered bad.
2436168404Spjd	 */
2437168404Spjd	if ((tdzp->z_phys->zp_flags & ZFS_XATTR) !=
2438168404Spjd	    (sdzp->z_phys->zp_flags & ZFS_XATTR)) {
2439168962Spjd		ZFS_EXIT(zfsvfs);
2440168962Spjd		return (EINVAL);
2441168404Spjd	}
2442168404Spjd
2443168404Spjd	/*
2444168404Spjd	 * Lock source and target directory entries.  To prevent deadlock,
2445168404Spjd	 * a lock ordering must be defined.  We lock the directory with
2446168404Spjd	 * the smallest object id first, or if it's a tie, the one with
2447168404Spjd	 * the lexically first name.
2448168404Spjd	 */
2449168404Spjd	if (sdzp->z_id < tdzp->z_id) {
2450168962Spjd		cmp = -1;
2451168962Spjd	} else if (sdzp->z_id > tdzp->z_id) {
2452168962Spjd		cmp = 1;
2453168962Spjd	} else {
2454168962Spjd		cmp = strcmp(snm, tnm);
2455168962Spjd		if (cmp == 0) {
2456168962Spjd			/*
2457168962Spjd			 * POSIX: "If the old argument and the new argument
2458168962Spjd			 * both refer to links to the same existing file,
2459168962Spjd			 * the rename() function shall return successfully
2460168962Spjd			 * and perform no other action."
2461168962Spjd			 */
2462168962Spjd			ZFS_EXIT(zfsvfs);
2463168962Spjd			return (0);
2464168962Spjd		}
2465168962Spjd	}
2466168962Spjd	if (cmp < 0) {
2467168404Spjd		serr = zfs_dirent_lock(&sdl, sdzp, snm, &szp, ZEXISTS);
2468168404Spjd		terr = zfs_dirent_lock(&tdl, tdzp, tnm, &tzp, 0);
2469168962Spjd	} else {
2470168404Spjd		terr = zfs_dirent_lock(&tdl, tdzp, tnm, &tzp, 0);
2471168404Spjd		serr = zfs_dirent_lock(&sdl, sdzp, snm, &szp, ZEXISTS);
2472168404Spjd	}
2473168404Spjd
2474168962Spjd	if (serr) {
2475168404Spjd		/*
2476168404Spjd		 * Source entry invalid or not there.
2477168404Spjd		 */
2478168962Spjd		if (!terr) {
2479168404Spjd			zfs_dirent_unlock(tdl);
2480168962Spjd			if (tzp)
2481168962Spjd				VN_RELE(ZTOV(tzp));
2482168962Spjd		}
2483168404Spjd		if (strcmp(snm, ".") == 0 || strcmp(snm, "..") == 0)
2484168404Spjd			serr = EINVAL;
2485168962Spjd		ZFS_EXIT(zfsvfs);
2486168962Spjd		return (serr);
2487168404Spjd	}
2488168404Spjd	if (terr) {
2489168404Spjd		zfs_dirent_unlock(sdl);
2490168962Spjd		VN_RELE(ZTOV(szp));
2491168404Spjd		if (strcmp(tnm, "..") == 0)
2492168404Spjd			terr = EINVAL;
2493168962Spjd		ZFS_EXIT(zfsvfs);
2494168962Spjd		return (terr);
2495168404Spjd	}
2496168404Spjd
2497168404Spjd	/*
2498168404Spjd	 * Must have write access at the source to remove the old entry
2499168404Spjd	 * and write access at the target to create the new entry.
2500168404Spjd	 * Note that if target and source are the same, this can be
2501168404Spjd	 * done in a single check.
2502168404Spjd	 */
2503168404Spjd
2504168404Spjd	if (error = zfs_zaccess_rename(sdzp, szp, tdzp, tzp, cr))
2505168404Spjd		goto out;
2506168404Spjd
2507168962Spjd	if (ZTOV(szp)->v_type == VDIR) {
2508168404Spjd		/*
2509168404Spjd		 * Check to make sure rename is valid.
2510168404Spjd		 * Can't do a move like this: /usr/a/b to /usr/a/b/c/d
2511168404Spjd		 */
2512168404Spjd		if (error = zfs_rename_lock(szp, tdzp, sdzp, &zl))
2513168404Spjd			goto out;
2514168404Spjd	}
2515168404Spjd
2516168404Spjd	/*
2517168404Spjd	 * Does target exist?
2518168404Spjd	 */
2519168404Spjd	if (tzp) {
2520168404Spjd		/*
2521168404Spjd		 * Source and target must be the same type.
2522168404Spjd		 */
2523168962Spjd		if (ZTOV(szp)->v_type == VDIR) {
2524168962Spjd			if (ZTOV(tzp)->v_type != VDIR) {
2525168404Spjd				error = ENOTDIR;
2526168404Spjd				goto out;
2527168404Spjd			}
2528168404Spjd		} else {
2529168962Spjd			if (ZTOV(tzp)->v_type == VDIR) {
2530168404Spjd				error = EISDIR;
2531168404Spjd				goto out;
2532168404Spjd			}
2533168404Spjd		}
2534168404Spjd		/*
2535168404Spjd		 * POSIX dictates that when the source and target
2536168404Spjd		 * entries refer to the same file object, rename
2537168404Spjd		 * must do nothing and exit without error.
2538168404Spjd		 */
2539168404Spjd		if (szp->z_id == tzp->z_id) {
2540168404Spjd			error = 0;
2541168404Spjd			goto out;
2542168404Spjd		}
2543168404Spjd	}
2544168404Spjd
2545168962Spjd	vnevent_rename_src(ZTOV(szp));
2546168962Spjd	if (tzp)
2547168962Spjd		vnevent_rename_dest(ZTOV(tzp));
2548168962Spjd
2549168404Spjd	tx = dmu_tx_create(zfsvfs->z_os);
2550168404Spjd	dmu_tx_hold_bonus(tx, szp->z_id);	/* nlink changes */
2551168404Spjd	dmu_tx_hold_bonus(tx, sdzp->z_id);	/* nlink changes */
2552168404Spjd	dmu_tx_hold_zap(tx, sdzp->z_id, FALSE, snm);
2553168404Spjd	dmu_tx_hold_zap(tx, tdzp->z_id, TRUE, tnm);
2554168404Spjd	if (sdzp != tdzp)
2555168404Spjd		dmu_tx_hold_bonus(tx, tdzp->z_id);	/* nlink changes */
2556168404Spjd	if (tzp)
2557168404Spjd		dmu_tx_hold_bonus(tx, tzp->z_id);	/* parent changes */
2558168404Spjd	dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL);
2559168404Spjd	error = dmu_tx_assign(tx, zfsvfs->z_assign);
2560168404Spjd	if (error) {
2561168404Spjd		if (zl != NULL)
2562168404Spjd			zfs_rename_unlock(&zl);
2563168404Spjd		zfs_dirent_unlock(sdl);
2564168404Spjd		zfs_dirent_unlock(tdl);
2565168962Spjd		VN_RELE(ZTOV(szp));
2566168962Spjd		if (tzp)
2567168962Spjd			VN_RELE(ZTOV(tzp));
2568168404Spjd		if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) {
2569168404Spjd			dmu_tx_wait(tx);
2570168404Spjd			dmu_tx_abort(tx);
2571168404Spjd			goto top;
2572168404Spjd		}
2573168404Spjd		dmu_tx_abort(tx);
2574168962Spjd		ZFS_EXIT(zfsvfs);
2575168962Spjd		return (error);
2576168404Spjd	}
2577168404Spjd
2578168404Spjd	if (tzp)	/* Attempt to remove the existing target */
2579168404Spjd		error = zfs_link_destroy(tdl, tzp, tx, 0, NULL);
2580168404Spjd
2581168404Spjd	if (error == 0) {
2582168404Spjd		error = zfs_link_create(tdl, szp, tx, ZRENAMING);
2583168404Spjd		if (error == 0) {
2584168404Spjd			error = zfs_link_destroy(sdl, szp, tx, ZRENAMING, NULL);
2585168404Spjd			ASSERT(error == 0);
2586168404Spjd			zfs_log_rename(zilog, tx, TX_RENAME, sdzp,
2587168404Spjd			    sdl->dl_name, tdzp, tdl->dl_name, szp);
2588168404Spjd		}
2589168404Spjd#ifdef FREEBSD_NAMECACHE
2590168404Spjd		if (error == 0) {
2591168404Spjd			cache_purge(sdvp);
2592168404Spjd			cache_purge(tdvp);
2593168404Spjd		}
2594168404Spjd#endif
2595168404Spjd	}
2596168404Spjd
2597168404Spjd	dmu_tx_commit(tx);
2598168404Spjdout:
2599168404Spjd	if (zl != NULL)
2600168404Spjd		zfs_rename_unlock(&zl);
2601168404Spjd
2602168404Spjd	zfs_dirent_unlock(sdl);
2603168404Spjd	zfs_dirent_unlock(tdl);
2604168404Spjd
2605168962Spjd	VN_RELE(ZTOV(szp));
2606168404Spjd	if (tzp)
2607168962Spjd		VN_RELE(ZTOV(tzp));
2608168404Spjd
2609168404Spjd	ZFS_EXIT(zfsvfs);
2610168404Spjd
2611168404Spjd	return (error);
2612168404Spjd}
2613168404Spjd
2614168404Spjd/*
2615168404Spjd * Insert the indicated symbolic reference entry into the directory.
2616168404Spjd *
2617168404Spjd *	IN:	dvp	- Directory to contain new symbolic link.
2618168404Spjd *		link	- Name for new symlink entry.
2619168404Spjd *		vap	- Attributes of new entry.
2620168404Spjd *		target	- Target path of new symlink.
2621168404Spjd *		cr	- credentials of caller.
2622168404Spjd *
2623168404Spjd *	RETURN:	0 if success
2624168404Spjd *		error code if failure
2625168404Spjd *
2626168404Spjd * Timestamps:
2627168404Spjd *	dvp - ctime|mtime updated
2628168404Spjd */
2629168404Spjdstatic int
2630168962Spjdzfs_symlink(vnode_t *dvp, vnode_t **vpp, char *name, vattr_t *vap, char *link, cred_t *cr, kthread_t *td)
2631168404Spjd{
2632168404Spjd	znode_t		*zp, *dzp = VTOZ(dvp);
2633168404Spjd	zfs_dirlock_t	*dl;
2634168404Spjd	dmu_tx_t	*tx;
2635168404Spjd	zfsvfs_t	*zfsvfs = dzp->z_zfsvfs;
2636168404Spjd	zilog_t		*zilog = zfsvfs->z_log;
2637168404Spjd	uint64_t	zoid;
2638168404Spjd	int		len = strlen(link);
2639168404Spjd	int		error;
2640168404Spjd
2641168962Spjd	ASSERT(vap->va_type == VLNK);
2642168404Spjd
2643168404Spjd	ZFS_ENTER(zfsvfs);
2644168404Spjdtop:
2645168404Spjd	if (error = zfs_zaccess(dzp, ACE_ADD_FILE, cr)) {
2646168404Spjd		ZFS_EXIT(zfsvfs);
2647168404Spjd		return (error);
2648168404Spjd	}
2649168404Spjd
2650168404Spjd	if (len > MAXPATHLEN) {
2651168404Spjd		ZFS_EXIT(zfsvfs);
2652168404Spjd		return (ENAMETOOLONG);
2653168404Spjd	}
2654168404Spjd
2655168404Spjd	/*
2656168404Spjd	 * Attempt to lock directory; fail if entry already exists.
2657168404Spjd	 */
2658168404Spjd	if (error = zfs_dirent_lock(&dl, dzp, name, &zp, ZNEW)) {
2659168404Spjd		ZFS_EXIT(zfsvfs);
2660168404Spjd		return (error);
2661168404Spjd	}
2662168404Spjd
2663168404Spjd	tx = dmu_tx_create(zfsvfs->z_os);
2664168404Spjd	dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, MAX(1, len));
2665168404Spjd	dmu_tx_hold_bonus(tx, dzp->z_id);
2666168404Spjd	dmu_tx_hold_zap(tx, dzp->z_id, TRUE, name);
2667168404Spjd	if (dzp->z_phys->zp_flags & ZFS_INHERIT_ACE)
2668168404Spjd		dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, SPA_MAXBLOCKSIZE);
2669168404Spjd	error = dmu_tx_assign(tx, zfsvfs->z_assign);
2670168404Spjd	if (error) {
2671168404Spjd		zfs_dirent_unlock(dl);
2672168404Spjd		if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) {
2673168404Spjd			dmu_tx_wait(tx);
2674168404Spjd			dmu_tx_abort(tx);
2675168404Spjd			goto top;
2676168404Spjd		}
2677168404Spjd		dmu_tx_abort(tx);
2678168404Spjd		ZFS_EXIT(zfsvfs);
2679168404Spjd		return (error);
2680168404Spjd	}
2681168404Spjd
2682168404Spjd	dmu_buf_will_dirty(dzp->z_dbuf, tx);
2683168404Spjd
2684168404Spjd	/*
2685168404Spjd	 * Create a new object for the symlink.
2686168404Spjd	 * Put the link content into bonus buffer if it will fit;
2687168404Spjd	 * otherwise, store it just like any other file data.
2688168404Spjd	 */
2689168404Spjd	zoid = 0;
2690168404Spjd	if (sizeof (znode_phys_t) + len <= dmu_bonus_max()) {
2691168404Spjd		zfs_mknode(dzp, vap, &zoid, tx, cr, 0, &zp, len);
2692168404Spjd		if (len != 0)
2693168404Spjd			bcopy(link, zp->z_phys + 1, len);
2694168404Spjd	} else {
2695168404Spjd		dmu_buf_t *dbp;
2696168404Spjd
2697168404Spjd		zfs_mknode(dzp, vap, &zoid, tx, cr, 0, &zp, 0);
2698168404Spjd
2699168404Spjd		/*
2700168404Spjd		 * Nothing can access the znode yet so no locking needed
2701168404Spjd		 * for growing the znode's blocksize.
2702168404Spjd		 */
2703168404Spjd		zfs_grow_blocksize(zp, len, tx);
2704168404Spjd
2705168404Spjd		VERIFY(0 == dmu_buf_hold(zfsvfs->z_os, zoid, 0, FTAG, &dbp));
2706168404Spjd		dmu_buf_will_dirty(dbp, tx);
2707168404Spjd
2708168404Spjd		ASSERT3U(len, <=, dbp->db_size);
2709168404Spjd		bcopy(link, dbp->db_data, len);
2710168404Spjd		dmu_buf_rele(dbp, FTAG);
2711168404Spjd	}
2712168404Spjd	zp->z_phys->zp_size = len;
2713168404Spjd
2714168404Spjd	/*
2715168404Spjd	 * Insert the new object into the directory.
2716168404Spjd	 */
2717168404Spjd	(void) zfs_link_create(dl, zp, tx, ZNEW);
2718168962Spjdout:
2719168404Spjd	if (error == 0) {
2720168404Spjd		zfs_log_symlink(zilog, tx, TX_SYMLINK, dzp, zp, name, link);
2721168962Spjd		*vpp = ZTOV(zp);
2722168962Spjd		vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, td);
2723168404Spjd	}
2724168404Spjd
2725168404Spjd	dmu_tx_commit(tx);
2726168404Spjd
2727168404Spjd	zfs_dirent_unlock(dl);
2728168404Spjd
2729168404Spjd	ZFS_EXIT(zfsvfs);
2730168404Spjd	return (error);
2731168404Spjd}
2732168404Spjd
2733168404Spjd/*
2734168404Spjd * Return, in the buffer contained in the provided uio structure,
2735168404Spjd * the symbolic path referred to by vp.
2736168404Spjd *
2737168404Spjd *	IN:	vp	- vnode of symbolic link.
2738168404Spjd *		uoip	- structure to contain the link path.
2739168404Spjd *		cr	- credentials of caller.
2740168404Spjd *
2741168404Spjd *	OUT:	uio	- structure to contain the link path.
2742168404Spjd *
2743168404Spjd *	RETURN:	0 if success
2744168404Spjd *		error code if failure
2745168404Spjd *
2746168404Spjd * Timestamps:
2747168404Spjd *	vp - atime updated
2748168404Spjd */
2749168404Spjd/* ARGSUSED */
2750168404Spjdstatic int
2751168962Spjdzfs_readlink(vnode_t *vp, uio_t *uio, cred_t *cr)
2752168404Spjd{
2753168404Spjd	znode_t		*zp = VTOZ(vp);
2754168404Spjd	zfsvfs_t	*zfsvfs = zp->z_zfsvfs;
2755168404Spjd	size_t		bufsz;
2756168404Spjd	int		error;
2757168404Spjd
2758168404Spjd	ZFS_ENTER(zfsvfs);
2759168404Spjd
2760168404Spjd	bufsz = (size_t)zp->z_phys->zp_size;
2761168404Spjd	if (bufsz + sizeof (znode_phys_t) <= zp->z_dbuf->db_size) {
2762168404Spjd		error = uiomove(zp->z_phys + 1,
2763168404Spjd		    MIN((size_t)bufsz, uio->uio_resid), UIO_READ, uio);
2764168404Spjd	} else {
2765168404Spjd		dmu_buf_t *dbp;
2766168404Spjd		error = dmu_buf_hold(zfsvfs->z_os, zp->z_id, 0, FTAG, &dbp);
2767168404Spjd		if (error) {
2768168404Spjd			ZFS_EXIT(zfsvfs);
2769168404Spjd			return (error);
2770168404Spjd		}
2771168404Spjd		error = uiomove(dbp->db_data,
2772168404Spjd		    MIN((size_t)bufsz, uio->uio_resid), UIO_READ, uio);
2773168404Spjd		dmu_buf_rele(dbp, FTAG);
2774168404Spjd	}
2775168404Spjd
2776168404Spjd	ZFS_ACCESSTIME_STAMP(zfsvfs, zp);
2777168404Spjd	ZFS_EXIT(zfsvfs);
2778168404Spjd	return (error);
2779168404Spjd}
2780168404Spjd
2781168404Spjd/*
2782168404Spjd * Insert a new entry into directory tdvp referencing svp.
2783168404Spjd *
2784168404Spjd *	IN:	tdvp	- Directory to contain new entry.
2785168404Spjd *		svp	- vnode of new entry.
2786168404Spjd *		name	- name of new entry.
2787168404Spjd *		cr	- credentials of caller.
2788168404Spjd *
2789168404Spjd *	RETURN:	0 if success
2790168404Spjd *		error code if failure
2791168404Spjd *
2792168404Spjd * Timestamps:
2793168404Spjd *	tdvp - ctime|mtime updated
2794168404Spjd *	 svp - ctime updated
2795168404Spjd */
2796168404Spjd/* ARGSUSED */
2797168404Spjdstatic int
2798168962Spjdzfs_link(vnode_t *tdvp, vnode_t *svp, char *name, cred_t *cr)
2799168404Spjd{
2800168404Spjd	znode_t		*dzp = VTOZ(tdvp);
2801168404Spjd	znode_t		*tzp, *szp;
2802168404Spjd	zfsvfs_t	*zfsvfs = dzp->z_zfsvfs;
2803168404Spjd	zilog_t		*zilog = zfsvfs->z_log;
2804168404Spjd	zfs_dirlock_t	*dl;
2805168404Spjd	dmu_tx_t	*tx;
2806168962Spjd	vnode_t		*realvp;
2807168404Spjd	int		error;
2808168404Spjd
2809168404Spjd	ASSERT(tdvp->v_type == VDIR);
2810168404Spjd
2811168404Spjd	ZFS_ENTER(zfsvfs);
2812168404Spjd
2813168962Spjd	if (VOP_REALVP(svp, &realvp) == 0)
2814168962Spjd		svp = realvp;
2815168962Spjd
2816168404Spjd	if (svp->v_vfsp != tdvp->v_vfsp) {
2817168404Spjd		ZFS_EXIT(zfsvfs);
2818168404Spjd		return (EXDEV);
2819168404Spjd	}
2820168404Spjd
2821168404Spjd	szp = VTOZ(svp);
2822168404Spjdtop:
2823168404Spjd	/*
2824168404Spjd	 * We do not support links between attributes and non-attributes
2825168404Spjd	 * because of the potential security risk of creating links
2826168404Spjd	 * into "normal" file space in order to circumvent restrictions
2827168404Spjd	 * imposed in attribute space.
2828168404Spjd	 */
2829168404Spjd	if ((szp->z_phys->zp_flags & ZFS_XATTR) !=
2830168404Spjd	    (dzp->z_phys->zp_flags & ZFS_XATTR)) {
2831168404Spjd		ZFS_EXIT(zfsvfs);
2832168404Spjd		return (EINVAL);
2833168404Spjd	}
2834168404Spjd
2835168404Spjd	/*
2836168404Spjd	 * POSIX dictates that we return EPERM here.
2837168404Spjd	 * Better choices include ENOTSUP or EISDIR.
2838168404Spjd	 */
2839168404Spjd	if (svp->v_type == VDIR) {
2840168404Spjd		ZFS_EXIT(zfsvfs);
2841168404Spjd		return (EPERM);
2842168404Spjd	}
2843168404Spjd
2844168404Spjd	if ((uid_t)szp->z_phys->zp_uid != crgetuid(cr) &&
2845168404Spjd	    secpolicy_basic_link(cr) != 0) {
2846168404Spjd		ZFS_EXIT(zfsvfs);
2847168404Spjd		return (EPERM);
2848168404Spjd	}
2849168404Spjd
2850168404Spjd	if (error = zfs_zaccess(dzp, ACE_ADD_FILE, cr)) {
2851168404Spjd		ZFS_EXIT(zfsvfs);
2852168404Spjd		return (error);
2853168404Spjd	}
2854168404Spjd
2855168404Spjd	/*
2856168404Spjd	 * Attempt to lock directory; fail if entry already exists.
2857168404Spjd	 */
2858168404Spjd	if (error = zfs_dirent_lock(&dl, dzp, name, &tzp, ZNEW)) {
2859168404Spjd		ZFS_EXIT(zfsvfs);
2860168404Spjd		return (error);
2861168404Spjd	}
2862168404Spjd
2863168404Spjd	tx = dmu_tx_create(zfsvfs->z_os);
2864168404Spjd	dmu_tx_hold_bonus(tx, szp->z_id);
2865168404Spjd	dmu_tx_hold_zap(tx, dzp->z_id, TRUE, name);
2866168404Spjd	error = dmu_tx_assign(tx, zfsvfs->z_assign);
2867168404Spjd	if (error) {
2868168404Spjd		zfs_dirent_unlock(dl);
2869168404Spjd		if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) {
2870168404Spjd			dmu_tx_wait(tx);
2871168404Spjd			dmu_tx_abort(tx);
2872168404Spjd			goto top;
2873168404Spjd		}
2874168404Spjd		dmu_tx_abort(tx);
2875168404Spjd		ZFS_EXIT(zfsvfs);
2876168404Spjd		return (error);
2877168404Spjd	}
2878168404Spjd
2879168404Spjd	error = zfs_link_create(dl, szp, tx, 0);
2880168404Spjd
2881168404Spjd	if (error == 0)
2882168404Spjd		zfs_log_link(zilog, tx, TX_LINK, dzp, szp, name);
2883168404Spjd
2884168404Spjd	dmu_tx_commit(tx);
2885168404Spjd
2886168404Spjd	zfs_dirent_unlock(dl);
2887168404Spjd
2888168404Spjd	ZFS_EXIT(zfsvfs);
2889168404Spjd	return (error);
2890168404Spjd}
2891168404Spjd
2892168962Spjdvoid
2893168962Spjdzfs_inactive(vnode_t *vp, cred_t *cr)
2894168404Spjd{
2895168962Spjd	znode_t	*zp = VTOZ(vp);
2896168962Spjd	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
2897168962Spjd	int error;
2898168404Spjd
2899168404Spjd	rw_enter(&zfsvfs->z_um_lock, RW_READER);
2900168404Spjd	if (zfsvfs->z_unmounted2) {
2901168404Spjd		ASSERT(zp->z_dbuf_held == 0);
2902168404Spjd
2903168404Spjd		mutex_enter(&zp->z_lock);
2904168404Spjd		VI_LOCK(vp);
2905168404Spjd		vp->v_count = 0; /* count arrives as 1 */
2906168404Spjd		VI_UNLOCK(vp);
2907168404Spjd		if (zp->z_dbuf == NULL) {
2908168404Spjd			mutex_exit(&zp->z_lock);
2909168404Spjd			zfs_znode_free(zp);
2910168404Spjd		} else {
2911168404Spjd			mutex_exit(&zp->z_lock);
2912168404Spjd		}
2913168404Spjd		rw_exit(&zfsvfs->z_um_lock);
2914168404Spjd		VFS_RELE(zfsvfs->z_vfs);
2915168962Spjd		return;
2916168404Spjd	}
2917168404Spjd
2918168404Spjd	if (zp->z_atime_dirty && zp->z_unlinked == 0) {
2919168404Spjd		dmu_tx_t *tx = dmu_tx_create(zfsvfs->z_os);
2920168404Spjd
2921168404Spjd		dmu_tx_hold_bonus(tx, zp->z_id);
2922168404Spjd		error = dmu_tx_assign(tx, TXG_WAIT);
2923168404Spjd		if (error) {
2924168404Spjd			dmu_tx_abort(tx);
2925168404Spjd		} else {
2926168404Spjd			dmu_buf_will_dirty(zp->z_dbuf, tx);
2927168404Spjd			mutex_enter(&zp->z_lock);
2928168404Spjd			zp->z_atime_dirty = 0;
2929168404Spjd			mutex_exit(&zp->z_lock);
2930168404Spjd			dmu_tx_commit(tx);
2931168404Spjd		}
2932168404Spjd	}
2933168404Spjd
2934168404Spjd	zfs_zinactive(zp);
2935168404Spjd	rw_exit(&zfsvfs->z_um_lock);
2936168404Spjd}
2937168404Spjd
2938168404SpjdCTASSERT(sizeof(struct zfid_short) <= sizeof(struct fid));
2939168404SpjdCTASSERT(sizeof(struct zfid_long) <= sizeof(struct fid));
2940168404Spjd
2941168404Spjdstatic int
2942168962Spjdzfs_fid(vnode_t *vp, fid_t *fidp)
2943168404Spjd{
2944168404Spjd	znode_t		*zp = VTOZ(vp);
2945168404Spjd	zfsvfs_t	*zfsvfs = zp->z_zfsvfs;
2946168404Spjd	uint32_t	gen = (uint32_t)zp->z_phys->zp_gen;
2947168404Spjd	uint64_t	object = zp->z_id;
2948168404Spjd	zfid_short_t	*zfid;
2949168404Spjd	int		size, i;
2950168404Spjd
2951168404Spjd	ZFS_ENTER(zfsvfs);
2952168404Spjd
2953168404Spjd	size = (zfsvfs->z_parent != zfsvfs) ? LONG_FID_LEN : SHORT_FID_LEN;
2954168404Spjd	fidp->fid_len = size;
2955168404Spjd
2956168404Spjd	zfid = (zfid_short_t *)fidp;
2957168404Spjd
2958168404Spjd	zfid->zf_len = size;
2959168404Spjd
2960168404Spjd	for (i = 0; i < sizeof (zfid->zf_object); i++)
2961168404Spjd		zfid->zf_object[i] = (uint8_t)(object >> (8 * i));
2962168404Spjd
2963168404Spjd	/* Must have a non-zero generation number to distinguish from .zfs */
2964168404Spjd	if (gen == 0)
2965168404Spjd		gen = 1;
2966168404Spjd	for (i = 0; i < sizeof (zfid->zf_gen); i++)
2967168404Spjd		zfid->zf_gen[i] = (uint8_t)(gen >> (8 * i));
2968168404Spjd
2969168404Spjd	if (size == LONG_FID_LEN) {
2970168404Spjd		uint64_t	objsetid = dmu_objset_id(zfsvfs->z_os);
2971169023Spjd		zfid_long_t	*zlfid;
2972168404Spjd
2973168404Spjd		zlfid = (zfid_long_t *)fidp;
2974168404Spjd
2975168404Spjd		for (i = 0; i < sizeof (zlfid->zf_setid); i++)
2976168404Spjd			zlfid->zf_setid[i] = (uint8_t)(objsetid >> (8 * i));
2977168404Spjd
2978168404Spjd		/* XXX - this should be the generation number for the objset */
2979168404Spjd		for (i = 0; i < sizeof (zlfid->zf_setgen); i++)
2980168404Spjd			zlfid->zf_setgen[i] = 0;
2981168404Spjd	}
2982168404Spjd
2983168404Spjd	ZFS_EXIT(zfsvfs);
2984168404Spjd	return (0);
2985168404Spjd}
2986168404Spjd
2987168404Spjdstatic int
2988168962Spjdzfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr)
2989168404Spjd{
2990168404Spjd	znode_t		*zp, *xzp;
2991168404Spjd	zfsvfs_t	*zfsvfs;
2992168404Spjd	zfs_dirlock_t	*dl;
2993168404Spjd	int		error;
2994168404Spjd
2995168404Spjd	switch (cmd) {
2996168404Spjd	case _PC_LINK_MAX:
2997168404Spjd		*valp = INT_MAX;
2998168404Spjd		return (0);
2999168404Spjd
3000168404Spjd	case _PC_FILESIZEBITS:
3001168404Spjd		*valp = 64;
3002168404Spjd		return (0);
3003168404Spjd
3004168404Spjd#if 0
3005168404Spjd	case _PC_XATTR_EXISTS:
3006168404Spjd		zp = VTOZ(vp);
3007168404Spjd		zfsvfs = zp->z_zfsvfs;
3008168404Spjd		ZFS_ENTER(zfsvfs);
3009168404Spjd		*valp = 0;
3010168404Spjd		error = zfs_dirent_lock(&dl, zp, "", &xzp,
3011168404Spjd		    ZXATTR | ZEXISTS | ZSHARED);
3012168404Spjd		if (error == 0) {
3013168404Spjd			zfs_dirent_unlock(dl);
3014168404Spjd			if (!zfs_dirempty(xzp))
3015168404Spjd				*valp = 1;
3016168404Spjd			VN_RELE(ZTOV(xzp));
3017168404Spjd		} else if (error == ENOENT) {
3018168404Spjd			/*
3019168404Spjd			 * If there aren't extended attributes, it's the
3020168404Spjd			 * same as having zero of them.
3021168404Spjd			 */
3022168404Spjd			error = 0;
3023168404Spjd		}
3024168404Spjd		ZFS_EXIT(zfsvfs);
3025168404Spjd		return (error);
3026168404Spjd#endif
3027168404Spjd
3028168404Spjd	case _PC_ACL_EXTENDED:
3029168404Spjd		*valp = 0;	/* TODO */
3030168404Spjd		return (0);
3031168404Spjd
3032168404Spjd	case _PC_MIN_HOLE_SIZE:
3033168404Spjd		*valp = (int)SPA_MINBLOCKSIZE;
3034168404Spjd		return (0);
3035168404Spjd
3036168404Spjd	default:
3037168962Spjd		return (EOPNOTSUPP);
3038168404Spjd	}
3039168404Spjd}
3040168404Spjd
3041168404Spjd#ifdef TODO
3042168404Spjd/*ARGSUSED*/
3043168404Spjdstatic int
3044168404Spjdzfs_getsecattr(vnode_t *vp, vsecattr_t *vsecp, int flag, cred_t *cr)
3045168404Spjd{
3046168404Spjd	znode_t *zp = VTOZ(vp);
3047168404Spjd	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
3048168404Spjd	int error;
3049168404Spjd
3050168404Spjd	ZFS_ENTER(zfsvfs);
3051168404Spjd	error = zfs_getacl(zp, vsecp, cr);
3052168404Spjd	ZFS_EXIT(zfsvfs);
3053168404Spjd
3054168404Spjd	return (error);
3055168404Spjd}
3056168404Spjd#endif	/* TODO */
3057168404Spjd
3058168404Spjd#ifdef TODO
3059168404Spjd/*ARGSUSED*/
3060168404Spjdstatic int
3061168404Spjdzfs_setsecattr(vnode_t *vp, vsecattr_t *vsecp, int flag, cred_t *cr)
3062168404Spjd{
3063168404Spjd	znode_t *zp = VTOZ(vp);
3064168404Spjd	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
3065168404Spjd	int error;
3066168404Spjd
3067168404Spjd	ZFS_ENTER(zfsvfs);
3068168404Spjd	error = zfs_setacl(zp, vsecp, cr);
3069168404Spjd	ZFS_EXIT(zfsvfs);
3070168404Spjd	return (error);
3071168404Spjd}
3072168404Spjd#endif	/* TODO */
3073168404Spjd
3074168962Spjdstatic int
3075168962Spjdzfs_freebsd_open(ap)
3076168962Spjd	struct vop_open_args /* {
3077168962Spjd		struct vnode *a_vp;
3078168962Spjd		int a_mode;
3079168962Spjd		struct ucred *a_cred;
3080168962Spjd		struct thread *a_td;
3081168962Spjd	} */ *ap;
3082168962Spjd{
3083168962Spjd	vnode_t	*vp = ap->a_vp;
3084168962Spjd	znode_t *zp = VTOZ(vp);
3085168962Spjd	int error;
3086168962Spjd
3087168962Spjd	error = zfs_open(&vp, ap->a_mode, ap->a_cred);
3088168962Spjd	if (error == 0)
3089168962Spjd		vnode_create_vobject(vp, zp->z_phys->zp_size, ap->a_td);
3090168962Spjd	return (error);
3091168962Spjd}
3092168962Spjd
3093168962Spjdstatic int
3094168962Spjdzfs_freebsd_close(ap)
3095168962Spjd	struct vop_close_args /* {
3096168962Spjd		struct vnode *a_vp;
3097168962Spjd		int  a_fflag;
3098168962Spjd		struct ucred *a_cred;
3099168962Spjd		struct thread *a_td;
3100168962Spjd	} */ *ap;
3101168962Spjd{
3102168962Spjd
3103168962Spjd	return (zfs_close(ap->a_vp, ap->a_fflag, 0, 0, ap->a_cred));
3104168962Spjd}
3105168962Spjd
3106168962Spjdstatic int
3107168962Spjdzfs_freebsd_ioctl(ap)
3108168962Spjd	struct vop_ioctl_args /* {
3109168962Spjd		struct vnode *a_vp;
3110168962Spjd		u_long a_command;
3111168962Spjd		caddr_t a_data;
3112168962Spjd		int a_fflag;
3113168962Spjd		struct ucred *cred;
3114168962Spjd		struct thread *td;
3115168962Spjd	} */ *ap;
3116168962Spjd{
3117168962Spjd
3118168978Spjd	return (zfs_ioctl(ap->a_vp, ap->a_command, (intptr_t)ap->a_data,
3119168962Spjd	    ap->a_fflag, ap->a_cred, NULL));
3120168962Spjd}
3121168962Spjd
3122168962Spjdstatic int
3123168962Spjdzfs_freebsd_read(ap)
3124168962Spjd	struct vop_read_args /* {
3125168962Spjd		struct vnode *a_vp;
3126168962Spjd		struct uio *a_uio;
3127168962Spjd		int a_ioflag;
3128168962Spjd		struct ucred *a_cred;
3129168962Spjd	} */ *ap;
3130168962Spjd{
3131168962Spjd
3132168962Spjd	return (zfs_read(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred, NULL));
3133168962Spjd}
3134168962Spjd
3135168962Spjdstatic int
3136168962Spjdzfs_freebsd_write(ap)
3137168962Spjd	struct vop_write_args /* {
3138168962Spjd		struct vnode *a_vp;
3139168962Spjd		struct uio *a_uio;
3140168962Spjd		int a_ioflag;
3141168962Spjd		struct ucred *a_cred;
3142168962Spjd	} */ *ap;
3143168962Spjd{
3144168962Spjd
3145168962Spjd	return (zfs_write(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred, NULL));
3146168962Spjd}
3147168962Spjd
3148168962Spjdstatic int
3149168962Spjdzfs_freebsd_access(ap)
3150168962Spjd	struct vop_access_args /* {
3151168962Spjd		struct vnode *a_vp;
3152168962Spjd		int  a_mode;
3153168962Spjd		struct ucred *a_cred;
3154168962Spjd		struct thread *a_td;
3155168962Spjd	} */ *ap;
3156168962Spjd{
3157168962Spjd
3158168962Spjd	return (zfs_access(ap->a_vp, ap->a_mode, 0, ap->a_cred));
3159168962Spjd}
3160168962Spjd
3161168962Spjdstatic int
3162168962Spjdzfs_freebsd_lookup(ap)
3163168962Spjd	struct vop_lookup_args /* {
3164168962Spjd		struct vnode *a_dvp;
3165168962Spjd		struct vnode **a_vpp;
3166168962Spjd		struct componentname *a_cnp;
3167168962Spjd	} */ *ap;
3168168962Spjd{
3169168962Spjd	struct componentname *cnp = ap->a_cnp;
3170168962Spjd	char nm[NAME_MAX + 1];
3171168962Spjd
3172168962Spjd	ASSERT(cnp->cn_namelen < sizeof(nm));
3173168962Spjd	strlcpy(nm, cnp->cn_nameptr, MIN(cnp->cn_namelen + 1, sizeof(nm)));
3174168962Spjd
3175168962Spjd	return (zfs_lookup(ap->a_dvp, nm, ap->a_vpp, cnp, cnp->cn_nameiop,
3176168962Spjd	    cnp->cn_cred, cnp->cn_thread));
3177168962Spjd}
3178168962Spjd
3179168962Spjdstatic int
3180168962Spjdzfs_freebsd_create(ap)
3181168962Spjd	struct vop_create_args /* {
3182168962Spjd		struct vnode *a_dvp;
3183168962Spjd		struct vnode **a_vpp;
3184168962Spjd		struct componentname *a_cnp;
3185168962Spjd		struct vattr *a_vap;
3186168962Spjd	} */ *ap;
3187168962Spjd{
3188168962Spjd	struct componentname *cnp = ap->a_cnp;
3189168962Spjd	vattr_t *vap = ap->a_vap;
3190168962Spjd	int mode;
3191168962Spjd
3192168962Spjd	ASSERT(cnp->cn_flags & SAVENAME);
3193168962Spjd
3194168962Spjd	vattr_init_mask(vap);
3195168962Spjd	mode = vap->va_mode & ALLPERMS;
3196168962Spjd
3197168962Spjd	return (zfs_create(ap->a_dvp, cnp->cn_nameptr, vap, !EXCL, mode,
3198168962Spjd	    ap->a_vpp, cnp->cn_cred, cnp->cn_thread));
3199168962Spjd}
3200168962Spjd
3201168962Spjdstatic int
3202168962Spjdzfs_freebsd_remove(ap)
3203168962Spjd	struct vop_remove_args /* {
3204168962Spjd		struct vnode *a_dvp;
3205168962Spjd		struct vnode *a_vp;
3206168962Spjd		struct componentname *a_cnp;
3207168962Spjd	} */ *ap;
3208168962Spjd{
3209168962Spjd
3210168962Spjd	ASSERT(ap->a_cnp->cn_flags & SAVENAME);
3211168962Spjd
3212168962Spjd	return (zfs_remove(ap->a_dvp, ap->a_cnp->cn_nameptr,
3213168962Spjd	    ap->a_cnp->cn_cred));
3214168962Spjd}
3215168962Spjd
3216168962Spjdstatic int
3217168962Spjdzfs_freebsd_mkdir(ap)
3218168962Spjd	struct vop_mkdir_args /* {
3219168962Spjd		struct vnode *a_dvp;
3220168962Spjd		struct vnode **a_vpp;
3221168962Spjd		struct componentname *a_cnp;
3222168962Spjd		struct vattr *a_vap;
3223168962Spjd	} */ *ap;
3224168962Spjd{
3225168962Spjd	vattr_t *vap = ap->a_vap;
3226168962Spjd
3227168962Spjd	ASSERT(ap->a_cnp->cn_flags & SAVENAME);
3228168962Spjd
3229168962Spjd	vattr_init_mask(vap);
3230168962Spjd
3231168962Spjd	return (zfs_mkdir(ap->a_dvp, ap->a_cnp->cn_nameptr, vap, ap->a_vpp,
3232168962Spjd	    ap->a_cnp->cn_cred));
3233168962Spjd}
3234168962Spjd
3235168962Spjdstatic int
3236168962Spjdzfs_freebsd_rmdir(ap)
3237168962Spjd	struct vop_rmdir_args /* {
3238168962Spjd		struct vnode *a_dvp;
3239168962Spjd		struct vnode *a_vp;
3240168962Spjd		struct componentname *a_cnp;
3241168962Spjd	} */ *ap;
3242168962Spjd{
3243168962Spjd	struct componentname *cnp = ap->a_cnp;
3244168962Spjd
3245168962Spjd	ASSERT(cnp->cn_flags & SAVENAME);
3246168962Spjd
3247168962Spjd	return (zfs_rmdir(ap->a_dvp, cnp->cn_nameptr, NULL, cnp->cn_cred));
3248168962Spjd}
3249168962Spjd
3250168962Spjdstatic int
3251168962Spjdzfs_freebsd_readdir(ap)
3252168962Spjd	struct vop_readdir_args /* {
3253168962Spjd		struct vnode *a_vp;
3254168962Spjd		struct uio *a_uio;
3255168962Spjd		struct ucred *a_cred;
3256168962Spjd		int *a_eofflag;
3257168962Spjd		int *a_ncookies;
3258168962Spjd		u_long **a_cookies;
3259168962Spjd	} */ *ap;
3260168962Spjd{
3261168962Spjd
3262168962Spjd	return (zfs_readdir(ap->a_vp, ap->a_uio, ap->a_cred, ap->a_eofflag,
3263168962Spjd	    ap->a_ncookies, ap->a_cookies));
3264168962Spjd}
3265168962Spjd
3266168962Spjdstatic int
3267168962Spjdzfs_freebsd_fsync(ap)
3268168962Spjd	struct vop_fsync_args /* {
3269168962Spjd		struct vnode *a_vp;
3270168962Spjd		int a_waitfor;
3271168962Spjd		struct thread *a_td;
3272168962Spjd	} */ *ap;
3273168962Spjd{
3274168962Spjd
3275168962Spjd	vop_stdfsync(ap);
3276168962Spjd	return (zfs_fsync(ap->a_vp, 0, ap->a_td->td_ucred));
3277168962Spjd}
3278168962Spjd
3279168962Spjdstatic int
3280168962Spjdzfs_freebsd_getattr(ap)
3281168962Spjd	struct vop_getattr_args /* {
3282168962Spjd		struct vnode *a_vp;
3283168962Spjd		struct vattr *a_vap;
3284168962Spjd		struct ucred *a_cred;
3285168962Spjd		struct thread *a_td;
3286168962Spjd	} */ *ap;
3287168962Spjd{
3288168962Spjd
3289168962Spjd	return (zfs_getattr(ap->a_vp, ap->a_vap, 0, ap->a_cred));
3290168962Spjd}
3291168962Spjd
3292168962Spjdstatic int
3293168962Spjdzfs_freebsd_setattr(ap)
3294168962Spjd	struct vop_setattr_args /* {
3295168962Spjd		struct vnode *a_vp;
3296168962Spjd		struct vattr *a_vap;
3297168962Spjd		struct ucred *a_cred;
3298168962Spjd		struct thread *a_td;
3299168962Spjd	} */ *ap;
3300168962Spjd{
3301168962Spjd	vattr_t *vap = ap->a_vap;
3302168962Spjd
3303168962Spjd	/* No support for FreeBSD's chflags(2). */
3304168962Spjd	if (vap->va_flags != VNOVAL)
3305168962Spjd		return (EOPNOTSUPP);
3306168962Spjd
3307168962Spjd	vattr_init_mask(vap);
3308168962Spjd
3309168962Spjd	return (zfs_setattr(ap->a_vp, vap, 0, ap->a_cred, NULL));
3310168962Spjd}
3311168962Spjd
3312168962Spjdstatic int
3313168962Spjdzfs_freebsd_rename(ap)
3314168962Spjd	struct vop_rename_args  /* {
3315168962Spjd		struct vnode *a_fdvp;
3316168962Spjd		struct vnode *a_fvp;
3317168962Spjd		struct componentname *a_fcnp;
3318168962Spjd		struct vnode *a_tdvp;
3319168962Spjd		struct vnode *a_tvp;
3320168962Spjd		struct componentname *a_tcnp;
3321168962Spjd	} */ *ap;
3322168962Spjd{
3323168962Spjd	vnode_t *fdvp = ap->a_fdvp;
3324168962Spjd	vnode_t *fvp = ap->a_fvp;
3325168962Spjd	vnode_t *tdvp = ap->a_tdvp;
3326168962Spjd	vnode_t *tvp = ap->a_tvp;
3327168962Spjd	int error;
3328168962Spjd
3329168962Spjd	ASSERT(ap->a_fcnp->cn_flags & SAVENAME);
3330168962Spjd	ASSERT(ap->a_tcnp->cn_flags & SAVENAME);
3331168962Spjd
3332168962Spjd	error = zfs_rename(fdvp, ap->a_fcnp->cn_nameptr, tdvp,
3333168962Spjd	    ap->a_tcnp->cn_nameptr, ap->a_fcnp->cn_cred);
3334168962Spjd
3335168962Spjd	if (tdvp == tvp)
3336168962Spjd		VN_RELE(tdvp);
3337168962Spjd	else
3338168962Spjd		VN_URELE(tdvp);
3339168962Spjd	if (tvp)
3340168962Spjd		VN_URELE(tvp);
3341168962Spjd	VN_RELE(fdvp);
3342168962Spjd	VN_RELE(fvp);
3343168962Spjd
3344168962Spjd	return (error);
3345168962Spjd}
3346168962Spjd
3347168962Spjdstatic int
3348168962Spjdzfs_freebsd_symlink(ap)
3349168962Spjd	struct vop_symlink_args /* {
3350168962Spjd		struct vnode *a_dvp;
3351168962Spjd		struct vnode **a_vpp;
3352168962Spjd		struct componentname *a_cnp;
3353168962Spjd		struct vattr *a_vap;
3354168962Spjd		char *a_target;
3355168962Spjd	} */ *ap;
3356168962Spjd{
3357168962Spjd	struct componentname *cnp = ap->a_cnp;
3358168962Spjd	vattr_t *vap = ap->a_vap;
3359168962Spjd
3360168962Spjd	ASSERT(cnp->cn_flags & SAVENAME);
3361168962Spjd
3362168962Spjd	vap->va_type = VLNK;	/* FreeBSD: Syscall only sets va_mode. */
3363168962Spjd	vattr_init_mask(vap);
3364168962Spjd
3365168962Spjd	return (zfs_symlink(ap->a_dvp, ap->a_vpp, cnp->cn_nameptr, vap,
3366168962Spjd	    ap->a_target, cnp->cn_cred, cnp->cn_thread));
3367168962Spjd}
3368168962Spjd
3369168962Spjdstatic int
3370168962Spjdzfs_freebsd_readlink(ap)
3371168962Spjd	struct vop_readlink_args /* {
3372168962Spjd		struct vnode *a_vp;
3373168962Spjd		struct uio *a_uio;
3374168962Spjd		struct ucred *a_cred;
3375168962Spjd	} */ *ap;
3376168962Spjd{
3377168962Spjd
3378168962Spjd	return (zfs_readlink(ap->a_vp, ap->a_uio, ap->a_cred));
3379168962Spjd}
3380168962Spjd
3381168962Spjdstatic int
3382168962Spjdzfs_freebsd_link(ap)
3383168962Spjd	struct vop_link_args /* {
3384168962Spjd		struct vnode *a_tdvp;
3385168962Spjd		struct vnode *a_vp;
3386168962Spjd		struct componentname *a_cnp;
3387168962Spjd	} */ *ap;
3388168962Spjd{
3389168962Spjd	struct componentname *cnp = ap->a_cnp;
3390168962Spjd
3391168962Spjd	ASSERT(cnp->cn_flags & SAVENAME);
3392168962Spjd
3393168962Spjd	return (zfs_link(ap->a_tdvp, ap->a_vp, cnp->cn_nameptr, cnp->cn_cred));
3394168962Spjd}
3395168962Spjd
3396168962Spjdstatic int
3397168962Spjdzfs_freebsd_inactive(ap)
3398168962Spjd        struct vop_inactive_args /* {
3399168962Spjd                struct vnode *a_vp;
3400168962Spjd                struct thread *a_td;
3401168962Spjd        } */ *ap;
3402168962Spjd{
3403168962Spjd	vnode_t *vp = ap->a_vp;
3404168962Spjd
3405168962Spjd	zfs_inactive(vp, ap->a_td->td_ucred);
3406168962Spjd	return (0);
3407168962Spjd}
3408168962Spjd
3409168962Spjdstatic int
3410168962Spjdzfs_freebsd_reclaim(ap)
3411168962Spjd	struct vop_reclaim_args /* {
3412168962Spjd		struct vnode *a_vp;
3413168962Spjd		struct thread *a_td;
3414168962Spjd	} */ *ap;
3415168962Spjd{
3416169025Spjd        vnode_t	*vp = ap->a_vp;
3417168962Spjd	znode_t	*zp = VTOZ(vp);
3418169025Spjd	zfsvfs_t *zfsvfs;
3419169025Spjd	int rele = 1;
3420168962Spjd
3421169025Spjd	ASSERT(zp != NULL);
3422169025Spjd
3423168962Spjd	/*
3424168962Spjd	 * Destroy the vm object and flush associated pages.
3425168962Spjd	 */
3426168962Spjd	vnode_destroy_vobject(vp);
3427169025Spjd
3428169025Spjd	mutex_enter(&zp->z_lock);
3429169025Spjd	ASSERT(zp->z_phys);
3430169025Spjd	ASSERT(zp->z_dbuf_held);
3431169025Spjd	zfsvfs = zp->z_zfsvfs;
3432169025Spjd	if (!zp->z_unlinked) {
3433169025Spjd		zp->z_dbuf_held = 0;
3434169025Spjd		ZTOV(zp) = NULL;
3435169025Spjd		mutex_exit(&zp->z_lock);
3436169025Spjd		dmu_buf_rele(zp->z_dbuf, NULL);
3437169025Spjd	} else {
3438169025Spjd		mutex_exit(&zp->z_lock);
3439169025Spjd	}
3440168962Spjd	VI_LOCK(vp);
3441169025Spjd	if (vp->v_count > 0)
3442169025Spjd		rele = 0;
3443168962Spjd	vp->v_data = NULL;
3444168962Spjd	ASSERT(vp->v_holdcnt > 1);
3445168962Spjd	vdropl(vp);
3446169025Spjd	if (!zp->z_unlinked && rele)
3447169025Spjd		VFS_RELE(zfsvfs->z_vfs);
3448168962Spjd	return (0);
3449168962Spjd}
3450168962Spjd
3451168962Spjdstatic int
3452168962Spjdzfs_freebsd_fid(ap)
3453168962Spjd	struct vop_fid_args /* {
3454168962Spjd		struct vnode *a_vp;
3455168962Spjd		struct fid *a_fid;
3456168962Spjd	} */ *ap;
3457168962Spjd{
3458168962Spjd
3459168962Spjd	return (zfs_fid(ap->a_vp, (void *)ap->a_fid));
3460168962Spjd}
3461168962Spjd
3462168962Spjdstatic int
3463168962Spjdzfs_freebsd_pathconf(ap)
3464168962Spjd	struct vop_pathconf_args /* {
3465168962Spjd		struct vnode *a_vp;
3466168962Spjd		int a_name;
3467168962Spjd		register_t *a_retval;
3468168962Spjd	} */ *ap;
3469168962Spjd{
3470168962Spjd	ulong_t val;
3471168962Spjd	int error;
3472168962Spjd
3473168962Spjd	error = zfs_pathconf(ap->a_vp, ap->a_name, &val, curthread->td_ucred);
3474168962Spjd	if (error == 0)
3475168962Spjd		*ap->a_retval = val;
3476168962Spjd	else if (error == EOPNOTSUPP)
3477168962Spjd		error = vop_stdpathconf(ap);
3478168962Spjd	return (error);
3479168962Spjd}
3480168962Spjd
3481168404Spjd/*
3482168404Spjd * Advisory record locking support
3483168404Spjd */
3484168404Spjdstatic int
3485168962Spjdzfs_freebsd_advlock(ap)
3486168404Spjd	struct vop_advlock_args /* {
3487168404Spjd		struct vnode *a_vp;
3488168404Spjd		caddr_t  a_id;
3489168404Spjd		int  a_op;
3490168404Spjd		struct flock *a_fl;
3491168404Spjd		int  a_flags;
3492168404Spjd	} */ *ap;
3493168404Spjd{
3494168404Spjd	znode_t	*zp = VTOZ(ap->a_vp);
3495168404Spjd
3496168404Spjd	return (lf_advlock(ap, &(zp->z_lockf), zp->z_phys->zp_size));
3497168404Spjd}
3498168404Spjd
3499168404Spjdstruct vop_vector zfs_vnodeops;
3500168404Spjdstruct vop_vector zfs_fifoops;
3501168404Spjd
3502168404Spjdstruct vop_vector zfs_vnodeops = {
3503168404Spjd	.vop_default =	&default_vnodeops,
3504168962Spjd	.vop_inactive =	zfs_freebsd_inactive,
3505168962Spjd	.vop_reclaim =	zfs_freebsd_reclaim,
3506168962Spjd	.vop_access =	zfs_freebsd_access,
3507168404Spjd#ifdef FREEBSD_NAMECACHE
3508168404Spjd	.vop_lookup =	vfs_cache_lookup,
3509168962Spjd	.vop_cachedlookup = zfs_freebsd_lookup,
3510168404Spjd#else
3511168962Spjd	.vop_lookup =	zfs_freebsd_lookup,
3512168404Spjd#endif
3513168962Spjd	.vop_getattr =	zfs_freebsd_getattr,
3514168962Spjd	.vop_setattr =	zfs_freebsd_setattr,
3515168962Spjd	.vop_create =	zfs_freebsd_create,
3516168962Spjd	.vop_mknod =	zfs_freebsd_create,
3517168962Spjd	.vop_mkdir =	zfs_freebsd_mkdir,
3518168962Spjd	.vop_readdir =	zfs_freebsd_readdir,
3519168962Spjd	.vop_fsync =	zfs_freebsd_fsync,
3520168962Spjd	.vop_open =	zfs_freebsd_open,
3521168962Spjd	.vop_close =	zfs_freebsd_close,
3522168962Spjd	.vop_rmdir =	zfs_freebsd_rmdir,
3523168962Spjd	.vop_ioctl =	zfs_freebsd_ioctl,
3524168962Spjd	.vop_link =	zfs_freebsd_link,
3525168962Spjd	.vop_symlink =	zfs_freebsd_symlink,
3526168962Spjd	.vop_readlink =	zfs_freebsd_readlink,
3527168962Spjd	.vop_read =	zfs_freebsd_read,
3528168962Spjd	.vop_write =	zfs_freebsd_write,
3529168962Spjd	.vop_remove =	zfs_freebsd_remove,
3530168962Spjd	.vop_rename =	zfs_freebsd_rename,
3531168962Spjd	.vop_advlock =	zfs_freebsd_advlock,
3532168962Spjd	.vop_pathconf =	zfs_freebsd_pathconf,
3533168404Spjd	.vop_bmap =	VOP_EOPNOTSUPP,
3534168962Spjd	.vop_fid =	zfs_freebsd_fid,
3535168404Spjd};
3536168404Spjd
3537168404Spjdstruct vop_vector zfs_fifoops = {
3538168404Spjd	.vop_default =	&fifo_specops,
3539168404Spjd	.vop_fsync =	VOP_PANIC,
3540168962Spjd	.vop_access =	zfs_freebsd_access,
3541168962Spjd	.vop_getattr =	zfs_freebsd_getattr,
3542168962Spjd	.vop_inactive =	zfs_freebsd_inactive,
3543168404Spjd	.vop_read =	VOP_PANIC,
3544168962Spjd	.vop_reclaim =	zfs_freebsd_reclaim,
3545168962Spjd	.vop_setattr =	zfs_freebsd_setattr,
3546168404Spjd	.vop_write =	VOP_PANIC,
3547168962Spjd	.vop_fid =	zfs_freebsd_fid,
3548168404Spjd};
3549