zfs_vnops.c revision 169167
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;
291169059Spjd	uint64_t dirbytes;
292168404Spjd
293168404Spjd	ASSERT(vp->v_mount != NULL);
294168404Spjd	obj = vp->v_object;
295168404Spjd	ASSERT(obj != NULL);
296168404Spjd
297168404Spjd	start = uio->uio_loffset;
298168404Spjd	off = start & PAGEOFFSET;
299169059Spjd	dirbytes = 0;
300168404Spjd	VM_OBJECT_LOCK(obj);
301168404Spjd	for (start &= PAGEMASK; len > 0; start += PAGESIZE) {
302168404Spjd		uint64_t bytes = MIN(PAGESIZE - off, len);
303169059Spjd		uint64_t fsize;
304168404Spjd
305168404Spjdagain:
306168404Spjd		if ((m = vm_page_lookup(obj, OFF_TO_IDX(start))) != NULL &&
307168404Spjd		    vm_page_is_valid(m, (vm_offset_t)off, bytes)) {
308169059Spjd			uint64_t woff;
309168404Spjd			caddr_t va;
310168404Spjd
311168404Spjd			if (vm_page_sleep_if_busy(m, FALSE, "zfsmwb"))
312168404Spjd				goto again;
313169059Spjd			fsize = obj->un_pager.vnp.vnp_size;
314168404Spjd			vm_page_busy(m);
315169057Spjd			vm_page_lock_queues();
316169057Spjd			vm_page_undirty(m);
317169057Spjd			vm_page_unlock_queues();
318168404Spjd			VM_OBJECT_UNLOCK(obj);
319169059Spjd			if (dirbytes > 0) {
320169059Spjd				error = dmu_write_uio(os, zp->z_id, uio,
321169059Spjd				    dirbytes, tx);
322169059Spjd				dirbytes = 0;
323169059Spjd			}
324169059Spjd			if (error == 0) {
325169059Spjd				sched_pin();
326169059Spjd				sf = sf_buf_alloc(m, SFB_CPUPRIVATE);
327169059Spjd				va = (caddr_t)sf_buf_kva(sf);
328169059Spjd				woff = uio->uio_loffset - off;
329169059Spjd				error = uiomove(va + off, bytes, UIO_WRITE, uio);
330169167Spjd				/*
331169167Spjd				 * The uiomove() above could have been partially
332169167Spjd				 * successful, that's why we call dmu_write()
333169167Spjd				 * below unconditionally. The page was marked
334169167Spjd				 * non-dirty above and we would lose the changes
335169167Spjd				 * without doing so. If the uiomove() failed
336169167Spjd				 * entirely, well, we just write what we got
337169167Spjd				 * before one more time.
338169167Spjd				 */
339169059Spjd				dmu_write(os, zp->z_id, woff,
340169059Spjd				    MIN(PAGESIZE, fsize - woff), va, tx);
341169059Spjd				sf_buf_free(sf);
342169059Spjd				sched_unpin();
343169059Spjd			}
344168404Spjd			VM_OBJECT_LOCK(obj);
345168404Spjd			vm_page_wakeup(m);
346168404Spjd		} else {
347169059Spjd			dirbytes += bytes;
348168404Spjd		}
349168404Spjd		len -= bytes;
350168404Spjd		off = 0;
351168404Spjd		if (error)
352168404Spjd			break;
353168404Spjd	}
354168404Spjd	VM_OBJECT_UNLOCK(obj);
355169059Spjd	if (error == 0 && dirbytes > 0)
356169059Spjd		error = dmu_write_uio(os, zp->z_id, uio, dirbytes, tx);
357168404Spjd	return (error);
358168404Spjd}
359168404Spjd
360168404Spjd/*
361168404Spjd * When a file is memory mapped, we must keep the IO data synchronized
362168404Spjd * between the DMU cache and the memory mapped pages.  What this means:
363168404Spjd *
364168404Spjd * On Read:	We "read" preferentially from memory mapped pages,
365168404Spjd *		else we default from the dmu buffer.
366168404Spjd *
367168404Spjd * NOTE: We will always "break up" the IO into PAGESIZE uiomoves when
368168404Spjd *	the file is memory mapped.
369168404Spjd */
370168404Spjdstatic int
371168404Spjdmappedread(vnode_t *vp, int nbytes, uio_t *uio)
372168404Spjd{
373168404Spjd	znode_t *zp = VTOZ(vp);
374168404Spjd	objset_t *os = zp->z_zfsvfs->z_os;
375168404Spjd	vm_object_t obj;
376168404Spjd	vm_page_t m;
377168404Spjd	struct sf_buf *sf;
378168404Spjd	int64_t start, off;
379168926Spjd	caddr_t va;
380168404Spjd	int len = nbytes;
381168404Spjd	int error = 0;
382169059Spjd	uint64_t dirbytes;
383168404Spjd
384168404Spjd	ASSERT(vp->v_mount != NULL);
385168404Spjd	obj = vp->v_object;
386168404Spjd	ASSERT(obj != NULL);
387168404Spjd
388168404Spjd	start = uio->uio_loffset;
389168404Spjd	off = start & PAGEOFFSET;
390169059Spjd	dirbytes = 0;
391168404Spjd	VM_OBJECT_LOCK(obj);
392168404Spjd	for (start &= PAGEMASK; len > 0; start += PAGESIZE) {
393168404Spjd		uint64_t bytes = MIN(PAGESIZE - off, len);
394168404Spjd
395168404Spjdagain:
396168404Spjd		if ((m = vm_page_lookup(obj, OFF_TO_IDX(start))) != NULL &&
397168404Spjd		    vm_page_is_valid(m, (vm_offset_t)off, bytes)) {
398168404Spjd			if (vm_page_sleep_if_busy(m, FALSE, "zfsmrb"))
399168404Spjd				goto again;
400168404Spjd			vm_page_busy(m);
401168404Spjd			VM_OBJECT_UNLOCK(obj);
402169059Spjd			if (dirbytes > 0) {
403169059Spjd				error = dmu_read_uio(os, zp->z_id, uio,
404169059Spjd				    dirbytes);
405169059Spjd				dirbytes = 0;
406169059Spjd			}
407169059Spjd			if (error == 0) {
408169059Spjd				sched_pin();
409169059Spjd				sf = sf_buf_alloc(m, SFB_CPUPRIVATE);
410169059Spjd				va = (caddr_t)sf_buf_kva(sf);
411169059Spjd				error = uiomove(va + off, bytes, UIO_READ, uio);
412169059Spjd				sf_buf_free(sf);
413169059Spjd				sched_unpin();
414169059Spjd			}
415168404Spjd			VM_OBJECT_LOCK(obj);
416168404Spjd			vm_page_wakeup(m);
417168926Spjd		} else if (m != NULL && uio->uio_segflg == UIO_NOCOPY) {
418168962Spjd			/*
419168962Spjd			 * The code below is here to make sendfile(2) work
420168962Spjd			 * correctly with ZFS. As pointed out by ups@
421168962Spjd			 * sendfile(2) should be changed to use VOP_GETPAGES(),
422168962Spjd			 * but it pessimize performance of sendfile/UFS, that's
423168962Spjd			 * why I handle this special case in ZFS code.
424168962Spjd			 */
425168926Spjd			if (vm_page_sleep_if_busy(m, FALSE, "zfsmrb"))
426168926Spjd				goto again;
427168926Spjd			vm_page_busy(m);
428168926Spjd			VM_OBJECT_UNLOCK(obj);
429169059Spjd			if (dirbytes > 0) {
430169059Spjd				error = dmu_read_uio(os, zp->z_id, uio,
431169059Spjd				    dirbytes);
432169059Spjd				dirbytes = 0;
433169059Spjd			}
434169059Spjd			if (error == 0) {
435169059Spjd				sched_pin();
436169059Spjd				sf = sf_buf_alloc(m, SFB_CPUPRIVATE);
437169059Spjd				va = (caddr_t)sf_buf_kva(sf);
438169059Spjd				error = dmu_read(os, zp->z_id, start + off,
439169059Spjd				    bytes, (void *)(va + off));
440169059Spjd				sf_buf_free(sf);
441169059Spjd				sched_unpin();
442169059Spjd			}
443168926Spjd			VM_OBJECT_LOCK(obj);
444168926Spjd			vm_page_wakeup(m);
445169059Spjd			if (error == 0)
446169059Spjd				uio->uio_resid -= bytes;
447168404Spjd		} else {
448169059Spjd			dirbytes += bytes;
449168404Spjd		}
450168404Spjd		len -= bytes;
451168404Spjd		off = 0;
452168404Spjd		if (error)
453168404Spjd			break;
454168404Spjd	}
455168404Spjd	VM_OBJECT_UNLOCK(obj);
456169059Spjd	if (error == 0 && dirbytes > 0)
457169059Spjd		error = dmu_read_uio(os, zp->z_id, uio, dirbytes);
458168404Spjd	return (error);
459168404Spjd}
460168404Spjd
461168404Spjdoffset_t zfs_read_chunk_size = 1024 * 1024; /* Tunable */
462168404Spjd
463168404Spjd/*
464168404Spjd * Read bytes from specified file into supplied buffer.
465168404Spjd *
466168404Spjd *	IN:	vp	- vnode of file to be read from.
467168404Spjd *		uio	- structure supplying read location, range info,
468168404Spjd *			  and return buffer.
469168404Spjd *		ioflag	- SYNC flags; used to provide FRSYNC semantics.
470168404Spjd *		cr	- credentials of caller.
471168404Spjd *
472168404Spjd *	OUT:	uio	- updated offset and range, buffer filled.
473168404Spjd *
474168404Spjd *	RETURN:	0 if success
475168404Spjd *		error code if failure
476168404Spjd *
477168404Spjd * Side Effects:
478168404Spjd *	vp - atime updated if byte count > 0
479168404Spjd */
480168404Spjd/* ARGSUSED */
481168404Spjdstatic int
482168962Spjdzfs_read(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct)
483168404Spjd{
484168404Spjd	znode_t		*zp = VTOZ(vp);
485168404Spjd	zfsvfs_t	*zfsvfs = zp->z_zfsvfs;
486168404Spjd	objset_t	*os = zfsvfs->z_os;
487168404Spjd	ssize_t		n, nbytes;
488168404Spjd	int		error;
489168404Spjd	rl_t		*rl;
490168404Spjd
491168404Spjd	ZFS_ENTER(zfsvfs);
492168404Spjd
493168404Spjd	/*
494168404Spjd	 * Validate file offset
495168404Spjd	 */
496168404Spjd	if (uio->uio_loffset < (offset_t)0) {
497168404Spjd		ZFS_EXIT(zfsvfs);
498168404Spjd		return (EINVAL);
499168404Spjd	}
500168404Spjd
501168404Spjd	/*
502168404Spjd	 * Fasttrack empty reads
503168404Spjd	 */
504168404Spjd	if (uio->uio_resid == 0) {
505168404Spjd		ZFS_EXIT(zfsvfs);
506168404Spjd		return (0);
507168404Spjd	}
508168404Spjd
509168404Spjd	/*
510168962Spjd	 * Check for mandatory locks
511168962Spjd	 */
512168962Spjd	if (MANDMODE((mode_t)zp->z_phys->zp_mode)) {
513168962Spjd		if (error = chklock(vp, FREAD,
514168962Spjd		    uio->uio_loffset, uio->uio_resid, uio->uio_fmode, ct)) {
515168962Spjd			ZFS_EXIT(zfsvfs);
516168962Spjd			return (error);
517168962Spjd		}
518168962Spjd	}
519168962Spjd
520168962Spjd	/*
521168404Spjd	 * If we're in FRSYNC mode, sync out this znode before reading it.
522168404Spjd	 */
523168962Spjd	if (ioflag & FRSYNC)
524168404Spjd		zil_commit(zfsvfs->z_log, zp->z_last_itx, zp->z_id);
525168404Spjd
526168404Spjd	/*
527168404Spjd	 * Lock the range against changes.
528168404Spjd	 */
529168404Spjd	rl = zfs_range_lock(zp, uio->uio_loffset, uio->uio_resid, RL_READER);
530168404Spjd
531168404Spjd	/*
532168404Spjd	 * If we are reading past end-of-file we can skip
533168404Spjd	 * to the end; but we might still need to set atime.
534168404Spjd	 */
535168404Spjd	if (uio->uio_loffset >= zp->z_phys->zp_size) {
536168404Spjd		error = 0;
537168404Spjd		goto out;
538168404Spjd	}
539168404Spjd
540168404Spjd	ASSERT(uio->uio_loffset < zp->z_phys->zp_size);
541168404Spjd	n = MIN(uio->uio_resid, zp->z_phys->zp_size - uio->uio_loffset);
542168404Spjd
543168404Spjd	while (n > 0) {
544168404Spjd		nbytes = MIN(n, zfs_read_chunk_size -
545168404Spjd		    P2PHASE(uio->uio_loffset, zfs_read_chunk_size));
546168404Spjd
547168404Spjd		if (vn_has_cached_data(vp))
548168404Spjd			error = mappedread(vp, nbytes, uio);
549168404Spjd		else
550168404Spjd			error = dmu_read_uio(os, zp->z_id, uio, nbytes);
551168404Spjd		if (error)
552168404Spjd			break;
553168962Spjd
554168404Spjd		n -= nbytes;
555168404Spjd	}
556168404Spjd
557168404Spjdout:
558168404Spjd	zfs_range_unlock(rl);
559168404Spjd
560168404Spjd	ZFS_ACCESSTIME_STAMP(zfsvfs, zp);
561168404Spjd	ZFS_EXIT(zfsvfs);
562168404Spjd	return (error);
563168404Spjd}
564168404Spjd
565168404Spjd/*
566168404Spjd * Fault in the pages of the first n bytes specified by the uio structure.
567168404Spjd * 1 byte in each page is touched and the uio struct is unmodified.
568168404Spjd * Any error will exit this routine as this is only a best
569168404Spjd * attempt to get the pages resident. This is a copy of ufs_trans_touch().
570168404Spjd */
571168404Spjdstatic void
572168404Spjdzfs_prefault_write(ssize_t n, struct uio *uio)
573168404Spjd{
574168404Spjd	struct iovec *iov;
575168404Spjd	ulong_t cnt, incr;
576168404Spjd	caddr_t p;
577168404Spjd
578168404Spjd	if (uio->uio_segflg != UIO_USERSPACE)
579168404Spjd		return;
580168404Spjd
581168404Spjd	iov = uio->uio_iov;
582168404Spjd
583168404Spjd	while (n) {
584168404Spjd		cnt = MIN(iov->iov_len, n);
585168404Spjd		if (cnt == 0) {
586168404Spjd			/* empty iov entry */
587168404Spjd			iov++;
588168404Spjd			continue;
589168404Spjd		}
590168404Spjd		n -= cnt;
591168404Spjd		/*
592168404Spjd		 * touch each page in this segment.
593168404Spjd		 */
594168404Spjd		p = iov->iov_base;
595168404Spjd		while (cnt) {
596168404Spjd			if (fubyte(p) == -1)
597168404Spjd				return;
598168404Spjd			incr = MIN(cnt, PAGESIZE);
599168404Spjd			p += incr;
600168404Spjd			cnt -= incr;
601168404Spjd		}
602168404Spjd		/*
603168404Spjd		 * touch the last byte in case it straddles a page.
604168404Spjd		 */
605168404Spjd		p--;
606168404Spjd		if (fubyte(p) == -1)
607168404Spjd			return;
608168404Spjd		iov++;
609168404Spjd	}
610168404Spjd}
611168404Spjd
612168404Spjd/*
613168404Spjd * Write the bytes to a file.
614168404Spjd *
615168404Spjd *	IN:	vp	- vnode of file to be written to.
616168404Spjd *		uio	- structure supplying write location, range info,
617168404Spjd *			  and data buffer.
618168404Spjd *		ioflag	- IO_APPEND flag set if in append mode.
619168404Spjd *		cr	- credentials of caller.
620168404Spjd *
621168404Spjd *	OUT:	uio	- updated offset and range.
622168404Spjd *
623168404Spjd *	RETURN:	0 if success
624168404Spjd *		error code if failure
625168404Spjd *
626168404Spjd * Timestamps:
627168404Spjd *	vp - ctime|mtime updated if byte count > 0
628168404Spjd */
629168404Spjd/* ARGSUSED */
630168404Spjdstatic int
631168962Spjdzfs_write(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct)
632168404Spjd{
633168404Spjd	znode_t		*zp = VTOZ(vp);
634168962Spjd	rlim64_t	limit = MAXOFFSET_T;
635168404Spjd	ssize_t		start_resid = uio->uio_resid;
636168404Spjd	ssize_t		tx_bytes;
637168404Spjd	uint64_t	end_size;
638168404Spjd	dmu_tx_t	*tx;
639168404Spjd	zfsvfs_t	*zfsvfs = zp->z_zfsvfs;
640168404Spjd	zilog_t		*zilog = zfsvfs->z_log;
641168404Spjd	offset_t	woff;
642168404Spjd	ssize_t		n, nbytes;
643168404Spjd	rl_t		*rl;
644168404Spjd	int		max_blksz = zfsvfs->z_max_blksz;
645168404Spjd	int		error;
646168404Spjd
647168404Spjd	/*
648168404Spjd	 * Fasttrack empty write
649168404Spjd	 */
650168404Spjd	n = start_resid;
651168404Spjd	if (n == 0)
652168404Spjd		return (0);
653168404Spjd
654168962Spjd	if (limit == RLIM64_INFINITY || limit > MAXOFFSET_T)
655168962Spjd		limit = MAXOFFSET_T;
656168962Spjd
657168404Spjd	ZFS_ENTER(zfsvfs);
658168404Spjd
659168404Spjd	/*
660168404Spjd	 * Pre-fault the pages to ensure slow (eg NFS) pages
661168404Spjd	 * don't hold up txg.
662168404Spjd	 */
663168404Spjd	zfs_prefault_write(n, uio);
664168404Spjd
665168404Spjd	/*
666168404Spjd	 * If in append mode, set the io offset pointer to eof.
667168404Spjd	 */
668168404Spjd	if (ioflag & IO_APPEND) {
669168404Spjd		/*
670168404Spjd		 * Range lock for a file append:
671168404Spjd		 * The value for the start of range will be determined by
672168404Spjd		 * zfs_range_lock() (to guarantee append semantics).
673168404Spjd		 * If this write will cause the block size to increase,
674168404Spjd		 * zfs_range_lock() will lock the entire file, so we must
675168404Spjd		 * later reduce the range after we grow the block size.
676168404Spjd		 */
677168404Spjd		rl = zfs_range_lock(zp, 0, n, RL_APPEND);
678168404Spjd		if (rl->r_len == UINT64_MAX) {
679168404Spjd			/* overlocked, zp_size can't change */
680168404Spjd			woff = uio->uio_loffset = zp->z_phys->zp_size;
681168404Spjd		} else {
682168404Spjd			woff = uio->uio_loffset = rl->r_off;
683168404Spjd		}
684168404Spjd	} else {
685168404Spjd		woff = uio->uio_loffset;
686168404Spjd		/*
687168404Spjd		 * Validate file offset
688168404Spjd		 */
689168404Spjd		if (woff < 0) {
690168404Spjd			ZFS_EXIT(zfsvfs);
691168404Spjd			return (EINVAL);
692168404Spjd		}
693168404Spjd
694168404Spjd		/*
695168404Spjd		 * If we need to grow the block size then zfs_range_lock()
696168404Spjd		 * will lock a wider range than we request here.
697168404Spjd		 * Later after growing the block size we reduce the range.
698168404Spjd		 */
699168404Spjd		rl = zfs_range_lock(zp, woff, n, RL_WRITER);
700168404Spjd	}
701168404Spjd
702168962Spjd	if (woff >= limit) {
703168962Spjd		zfs_range_unlock(rl);
704168962Spjd		ZFS_EXIT(zfsvfs);
705168962Spjd		return (EFBIG);
706168962Spjd	}
707168962Spjd
708168962Spjd	if ((woff + n) > limit || woff > (limit - n))
709168962Spjd		n = limit - woff;
710168962Spjd
711168962Spjd	/*
712168962Spjd	 * Check for mandatory locks
713168962Spjd	 */
714168962Spjd	if (MANDMODE((mode_t)zp->z_phys->zp_mode) &&
715168962Spjd	    (error = chklock(vp, FWRITE, woff, n, uio->uio_fmode, ct)) != 0) {
716168962Spjd		zfs_range_unlock(rl);
717168962Spjd		ZFS_EXIT(zfsvfs);
718168962Spjd		return (error);
719168962Spjd	}
720168404Spjd	end_size = MAX(zp->z_phys->zp_size, woff + n);
721168404Spjd
722168404Spjd	/*
723168404Spjd	 * Write the file in reasonable size chunks.  Each chunk is written
724168404Spjd	 * in a separate transaction; this keeps the intent log records small
725168404Spjd	 * and allows us to do more fine-grained space accounting.
726168404Spjd	 */
727168404Spjd	while (n > 0) {
728168404Spjd		/*
729168404Spjd		 * Start a transaction.
730168404Spjd		 */
731168404Spjd		woff = uio->uio_loffset;
732168404Spjd		tx = dmu_tx_create(zfsvfs->z_os);
733168404Spjd		dmu_tx_hold_bonus(tx, zp->z_id);
734168404Spjd		dmu_tx_hold_write(tx, zp->z_id, woff, MIN(n, max_blksz));
735168404Spjd		error = dmu_tx_assign(tx, zfsvfs->z_assign);
736168404Spjd		if (error) {
737168404Spjd			if (error == ERESTART &&
738168404Spjd			    zfsvfs->z_assign == TXG_NOWAIT) {
739168404Spjd				dmu_tx_wait(tx);
740168404Spjd				dmu_tx_abort(tx);
741168404Spjd				continue;
742168404Spjd			}
743168404Spjd			dmu_tx_abort(tx);
744168404Spjd			break;
745168404Spjd		}
746168404Spjd
747168404Spjd		/*
748168404Spjd		 * If zfs_range_lock() over-locked we grow the blocksize
749168404Spjd		 * and then reduce the lock range.  This will only happen
750168404Spjd		 * on the first iteration since zfs_range_reduce() will
751168404Spjd		 * shrink down r_len to the appropriate size.
752168404Spjd		 */
753168404Spjd		if (rl->r_len == UINT64_MAX) {
754168404Spjd			uint64_t new_blksz;
755168404Spjd
756168404Spjd			if (zp->z_blksz > max_blksz) {
757168404Spjd				ASSERT(!ISP2(zp->z_blksz));
758168404Spjd				new_blksz = MIN(end_size, SPA_MAXBLOCKSIZE);
759168404Spjd			} else {
760168404Spjd				new_blksz = MIN(end_size, max_blksz);
761168404Spjd			}
762168404Spjd			zfs_grow_blocksize(zp, new_blksz, tx);
763168404Spjd			zfs_range_reduce(rl, woff, n);
764168404Spjd		}
765168404Spjd
766168404Spjd		/*
767168404Spjd		 * XXX - should we really limit each write to z_max_blksz?
768168404Spjd		 * Perhaps we should use SPA_MAXBLOCKSIZE chunks?
769168404Spjd		 */
770168404Spjd		nbytes = MIN(n, max_blksz - P2PHASE(woff, max_blksz));
771168404Spjd		rw_enter(&zp->z_map_lock, RW_READER);
772168404Spjd
773168404Spjd		if (woff + nbytes > zp->z_phys->zp_size)
774168404Spjd			vnode_pager_setsize(vp, woff + nbytes);
775168404Spjd
776168962Spjd		tx_bytes = uio->uio_resid;
777168404Spjd		if (vn_has_cached_data(vp)) {
778168404Spjd			rw_exit(&zp->z_map_lock);
779168404Spjd			error = mappedwrite(vp, nbytes, uio, tx);
780168404Spjd		} else {
781168404Spjd			error = dmu_write_uio(zfsvfs->z_os, zp->z_id,
782168404Spjd			    uio, nbytes, tx);
783168404Spjd			rw_exit(&zp->z_map_lock);
784168404Spjd		}
785168404Spjd		tx_bytes -= uio->uio_resid;
786168404Spjd
787168404Spjd		/*
788168404Spjd		 * If we made no progress, we're done.  If we made even
789168404Spjd		 * partial progress, update the znode and ZIL accordingly.
790168404Spjd		 */
791168404Spjd		if (tx_bytes == 0) {
792168404Spjd			dmu_tx_commit(tx);
793168404Spjd			ASSERT(error != 0);
794168404Spjd			break;
795168404Spjd		}
796168404Spjd
797168404Spjd		/*
798168404Spjd		 * Clear Set-UID/Set-GID bits on successful write if not
799168404Spjd		 * privileged and at least one of the excute bits is set.
800168404Spjd		 *
801168404Spjd		 * It would be nice to to this after all writes have
802168404Spjd		 * been done, but that would still expose the ISUID/ISGID
803168404Spjd		 * to another app after the partial write is committed.
804168404Spjd		 */
805168404Spjd		mutex_enter(&zp->z_acl_lock);
806168404Spjd		if ((zp->z_phys->zp_mode & (S_IXUSR | (S_IXUSR >> 3) |
807168404Spjd		    (S_IXUSR >> 6))) != 0 &&
808168404Spjd		    (zp->z_phys->zp_mode & (S_ISUID | S_ISGID)) != 0 &&
809168404Spjd		    secpolicy_vnode_setid_retain(cr,
810168404Spjd		    (zp->z_phys->zp_mode & S_ISUID) != 0 &&
811168404Spjd		    zp->z_phys->zp_uid == 0) != 0) {
812168404Spjd			    zp->z_phys->zp_mode &= ~(S_ISUID | S_ISGID);
813168404Spjd		}
814168404Spjd		mutex_exit(&zp->z_acl_lock);
815168404Spjd
816168404Spjd		/*
817168404Spjd		 * Update time stamp.  NOTE: This marks the bonus buffer as
818168404Spjd		 * dirty, so we don't have to do it again for zp_size.
819168404Spjd		 */
820168404Spjd		zfs_time_stamper(zp, CONTENT_MODIFIED, tx);
821168404Spjd
822168404Spjd		/*
823168404Spjd		 * Update the file size (zp_size) if it has changed;
824168404Spjd		 * account for possible concurrent updates.
825168404Spjd		 */
826168404Spjd		while ((end_size = zp->z_phys->zp_size) < uio->uio_loffset)
827168404Spjd			(void) atomic_cas_64(&zp->z_phys->zp_size, end_size,
828168404Spjd			    uio->uio_loffset);
829168404Spjd		zfs_log_write(zilog, tx, TX_WRITE, zp, woff, tx_bytes, ioflag);
830168404Spjd		dmu_tx_commit(tx);
831168404Spjd
832168404Spjd		if (error != 0)
833168404Spjd			break;
834168404Spjd		ASSERT(tx_bytes == nbytes);
835168404Spjd		n -= nbytes;
836168404Spjd	}
837168404Spjd
838168404Spjd	zfs_range_unlock(rl);
839168404Spjd
840168404Spjd	/*
841168404Spjd	 * If we're in replay mode, or we made no progress, return error.
842168404Spjd	 * Otherwise, it's at least a partial write, so it's successful.
843168404Spjd	 */
844168404Spjd	if (zfsvfs->z_assign >= TXG_INITIAL || uio->uio_resid == start_resid) {
845168404Spjd		ZFS_EXIT(zfsvfs);
846168404Spjd		return (error);
847168404Spjd	}
848168404Spjd
849168962Spjd	if (ioflag & (FSYNC | FDSYNC))
850168404Spjd		zil_commit(zilog, zp->z_last_itx, zp->z_id);
851168404Spjd
852168404Spjd	ZFS_EXIT(zfsvfs);
853168404Spjd	return (0);
854168404Spjd}
855168404Spjd
856168404Spjdvoid
857168404Spjdzfs_get_done(dmu_buf_t *db, void *vzgd)
858168404Spjd{
859168404Spjd	zgd_t *zgd = (zgd_t *)vzgd;
860168404Spjd	rl_t *rl = zgd->zgd_rl;
861168404Spjd	vnode_t *vp = ZTOV(rl->r_zp);
862168404Spjd	int vfslocked;
863168404Spjd
864168404Spjd	vfslocked = VFS_LOCK_GIANT(vp->v_vfsp);
865168404Spjd	dmu_buf_rele(db, vzgd);
866168404Spjd	zfs_range_unlock(rl);
867168404Spjd	VN_RELE(vp);
868168404Spjd	zil_add_vdev(zgd->zgd_zilog, DVA_GET_VDEV(BP_IDENTITY(zgd->zgd_bp)));
869168404Spjd	kmem_free(zgd, sizeof (zgd_t));
870168404Spjd	VFS_UNLOCK_GIANT(vfslocked);
871168404Spjd}
872168404Spjd
873168404Spjd/*
874168404Spjd * Get data to generate a TX_WRITE intent log record.
875168404Spjd */
876168404Spjdint
877168404Spjdzfs_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio)
878168404Spjd{
879168404Spjd	zfsvfs_t *zfsvfs = arg;
880168404Spjd	objset_t *os = zfsvfs->z_os;
881168404Spjd	znode_t *zp;
882168404Spjd	uint64_t off = lr->lr_offset;
883168404Spjd	dmu_buf_t *db;
884168404Spjd	rl_t *rl;
885168404Spjd	zgd_t *zgd;
886168404Spjd	int dlen = lr->lr_length;		/* length of user data */
887168404Spjd	int error = 0;
888168404Spjd
889168404Spjd	ASSERT(zio);
890168404Spjd	ASSERT(dlen != 0);
891168404Spjd
892168404Spjd	/*
893168404Spjd	 * Nothing to do if the file has been removed
894168404Spjd	 */
895168404Spjd	if (zfs_zget(zfsvfs, lr->lr_foid, &zp) != 0)
896168404Spjd		return (ENOENT);
897168404Spjd	if (zp->z_unlinked) {
898168404Spjd		VN_RELE(ZTOV(zp));
899168404Spjd		return (ENOENT);
900168404Spjd	}
901168404Spjd
902168404Spjd	/*
903168404Spjd	 * Write records come in two flavors: immediate and indirect.
904168404Spjd	 * For small writes it's cheaper to store the data with the
905168404Spjd	 * log record (immediate); for large writes it's cheaper to
906168404Spjd	 * sync the data and get a pointer to it (indirect) so that
907168404Spjd	 * we don't have to write the data twice.
908168404Spjd	 */
909168404Spjd	if (buf != NULL) { /* immediate write */
910168404Spjd		rl = zfs_range_lock(zp, off, dlen, RL_READER);
911168404Spjd		/* test for truncation needs to be done while range locked */
912168404Spjd		if (off >= zp->z_phys->zp_size) {
913168404Spjd			error = ENOENT;
914168404Spjd			goto out;
915168404Spjd		}
916168404Spjd		VERIFY(0 == dmu_read(os, lr->lr_foid, off, dlen, buf));
917168404Spjd	} else { /* indirect write */
918168404Spjd		uint64_t boff; /* block starting offset */
919168404Spjd
920168404Spjd		/*
921168404Spjd		 * Have to lock the whole block to ensure when it's
922168404Spjd		 * written out and it's checksum is being calculated
923168404Spjd		 * that no one can change the data. We need to re-check
924168404Spjd		 * blocksize after we get the lock in case it's changed!
925168404Spjd		 */
926168404Spjd		for (;;) {
927168404Spjd			if (ISP2(zp->z_blksz)) {
928168404Spjd				boff = P2ALIGN_TYPED(off, zp->z_blksz,
929168404Spjd				    uint64_t);
930168404Spjd			} else {
931168404Spjd				boff = 0;
932168404Spjd			}
933168404Spjd			dlen = zp->z_blksz;
934168404Spjd			rl = zfs_range_lock(zp, boff, dlen, RL_READER);
935168404Spjd			if (zp->z_blksz == dlen)
936168404Spjd				break;
937168404Spjd			zfs_range_unlock(rl);
938168404Spjd		}
939168404Spjd		/* test for truncation needs to be done while range locked */
940168404Spjd		if (off >= zp->z_phys->zp_size) {
941168404Spjd			error = ENOENT;
942168404Spjd			goto out;
943168404Spjd		}
944168404Spjd		zgd = (zgd_t *)kmem_alloc(sizeof (zgd_t), KM_SLEEP);
945168404Spjd		zgd->zgd_rl = rl;
946168404Spjd		zgd->zgd_zilog = zfsvfs->z_log;
947168404Spjd		zgd->zgd_bp = &lr->lr_blkptr;
948168404Spjd		VERIFY(0 == dmu_buf_hold(os, lr->lr_foid, boff, zgd, &db));
949168404Spjd		ASSERT(boff == db->db_offset);
950168404Spjd		lr->lr_blkoff = off - boff;
951168404Spjd		error = dmu_sync(zio, db, &lr->lr_blkptr,
952168404Spjd		    lr->lr_common.lrc_txg, zfs_get_done, zgd);
953168404Spjd		ASSERT(error == EEXIST || lr->lr_length <= zp->z_blksz);
954168404Spjd		if (error == 0) {
955168404Spjd			zil_add_vdev(zfsvfs->z_log,
956168404Spjd			    DVA_GET_VDEV(BP_IDENTITY(&lr->lr_blkptr)));
957168404Spjd		}
958168404Spjd		/*
959168404Spjd		 * If we get EINPROGRESS, then we need to wait for a
960168404Spjd		 * write IO initiated by dmu_sync() to complete before
961168404Spjd		 * we can release this dbuf.  We will finish everything
962168404Spjd		 * up in the zfs_get_done() callback.
963168404Spjd		 */
964168404Spjd		if (error == EINPROGRESS)
965168404Spjd			return (0);
966168404Spjd		dmu_buf_rele(db, zgd);
967168404Spjd		kmem_free(zgd, sizeof (zgd_t));
968168404Spjd	}
969168404Spjdout:
970168404Spjd	zfs_range_unlock(rl);
971168404Spjd	VN_RELE(ZTOV(zp));
972168404Spjd	return (error);
973168404Spjd}
974168404Spjd
975168404Spjd/*ARGSUSED*/
976168404Spjdstatic int
977168962Spjdzfs_access(vnode_t *vp, int mode, int flags, cred_t *cr)
978168404Spjd{
979168404Spjd	znode_t *zp = VTOZ(vp);
980168404Spjd	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
981168404Spjd	int error;
982168404Spjd
983168404Spjd	ZFS_ENTER(zfsvfs);
984168962Spjd	error = zfs_zaccess_rwx(zp, mode, cr);
985168404Spjd	ZFS_EXIT(zfsvfs);
986168404Spjd	return (error);
987168404Spjd}
988168404Spjd
989168404Spjd/*
990168404Spjd * Lookup an entry in a directory, or an extended attribute directory.
991168404Spjd * If it exists, return a held vnode reference for it.
992168404Spjd *
993168404Spjd *	IN:	dvp	- vnode of directory to search.
994168404Spjd *		nm	- name of entry to lookup.
995168404Spjd *		pnp	- full pathname to lookup [UNUSED].
996168404Spjd *		flags	- LOOKUP_XATTR set if looking for an attribute.
997168404Spjd *		rdir	- root directory vnode [UNUSED].
998168404Spjd *		cr	- credentials of caller.
999168404Spjd *
1000168404Spjd *	OUT:	vpp	- vnode of located entry, NULL if not found.
1001168404Spjd *
1002168404Spjd *	RETURN:	0 if success
1003168404Spjd *		error code if failure
1004168404Spjd *
1005168404Spjd * Timestamps:
1006168404Spjd *	NA
1007168404Spjd */
1008168404Spjd/* ARGSUSED */
1009168962Spjdstatic int
1010168962Spjdzfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct componentname *cnp,
1011168962Spjd     int nameiop, cred_t *cr, kthread_t *td)
1012168404Spjd{
1013168404Spjd
1014168962Spjd	znode_t *zdp = VTOZ(dvp);
1015168962Spjd	zfsvfs_t *zfsvfs = zdp->z_zfsvfs;
1016168962Spjd	int	error;
1017168404Spjd
1018168404Spjd	ZFS_ENTER(zfsvfs);
1019168404Spjd
1020168404Spjd	*vpp = NULL;
1021168404Spjd
1022168404Spjd#ifdef TODO
1023168404Spjd	if (flags & LOOKUP_XATTR) {
1024168404Spjd		/*
1025168404Spjd		 * If the xattr property is off, refuse the lookup request.
1026168404Spjd		 */
1027168404Spjd		if (!(zfsvfs->z_vfs->vfs_flag & VFS_XATTR)) {
1028168404Spjd			ZFS_EXIT(zfsvfs);
1029168404Spjd			return (EINVAL);
1030168404Spjd		}
1031168404Spjd
1032168404Spjd		/*
1033168404Spjd		 * We don't allow recursive attributes..
1034168404Spjd		 * Maybe someday we will.
1035168404Spjd		 */
1036168404Spjd		if (zdp->z_phys->zp_flags & ZFS_XATTR) {
1037168404Spjd			ZFS_EXIT(zfsvfs);
1038168404Spjd			return (EINVAL);
1039168404Spjd		}
1040168404Spjd
1041168404Spjd		if (error = zfs_get_xattrdir(VTOZ(dvp), vpp, cr, flags)) {
1042168404Spjd			ZFS_EXIT(zfsvfs);
1043168404Spjd			return (error);
1044168404Spjd		}
1045168404Spjd
1046168404Spjd		/*
1047168404Spjd		 * Do we have permission to get into attribute directory?
1048168404Spjd		 */
1049168404Spjd
1050168404Spjd		if (error = zfs_zaccess(VTOZ(*vpp), ACE_EXECUTE, cr)) {
1051168404Spjd			VN_RELE(*vpp);
1052168404Spjd		}
1053168404Spjd
1054168404Spjd		ZFS_EXIT(zfsvfs);
1055168404Spjd		return (error);
1056168404Spjd	}
1057168404Spjd#endif	/* TODO */
1058168404Spjd
1059168404Spjd	if (dvp->v_type != VDIR) {
1060168404Spjd		ZFS_EXIT(zfsvfs);
1061168404Spjd		return (ENOTDIR);
1062168404Spjd	}
1063168404Spjd
1064168404Spjd	/*
1065168404Spjd	 * Check accessibility of directory.
1066168404Spjd	 */
1067168404Spjd
1068168404Spjd	if (error = zfs_zaccess(zdp, ACE_EXECUTE, cr)) {
1069168404Spjd		ZFS_EXIT(zfsvfs);
1070168404Spjd		return (error);
1071168404Spjd	}
1072168404Spjd
1073168962Spjd	if ((error = zfs_dirlook(zdp, nm, vpp)) == 0) {
1074168404Spjd
1075168962Spjd		/*
1076168962Spjd		 * Convert device special files
1077168962Spjd		 */
1078168962Spjd		if (IS_DEVVP(*vpp)) {
1079168962Spjd			vnode_t	*svp;
1080168962Spjd
1081168962Spjd			svp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type, cr);
1082168962Spjd			VN_RELE(*vpp);
1083168962Spjd			if (svp == NULL)
1084168962Spjd				error = ENOSYS;
1085168962Spjd			else
1086168962Spjd				*vpp = svp;
1087168962Spjd		}
1088168962Spjd	}
1089168962Spjd
1090168404Spjd	ZFS_EXIT(zfsvfs);
1091168404Spjd
1092168404Spjd	/* Translate errors and add SAVENAME when needed. */
1093168404Spjd	if (cnp->cn_flags & ISLASTCN) {
1094168404Spjd		switch (nameiop) {
1095168404Spjd		case CREATE:
1096168404Spjd		case RENAME:
1097168404Spjd			if (error == ENOENT) {
1098168404Spjd				error = EJUSTRETURN;
1099168404Spjd				cnp->cn_flags |= SAVENAME;
1100168404Spjd				break;
1101168404Spjd			}
1102168404Spjd			/* FALLTHROUGH */
1103168404Spjd		case DELETE:
1104168404Spjd			if (error == 0)
1105168404Spjd				cnp->cn_flags |= SAVENAME;
1106168404Spjd			break;
1107168404Spjd		}
1108168404Spjd	}
1109168404Spjd	if (error == 0 && (nm[0] != '.' || nm[1] != '\0')) {
1110168962Spjd		if (cnp->cn_flags & ISDOTDOT)
1111168404Spjd			VOP_UNLOCK(dvp, 0, td);
1112168404Spjd		vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, td);
1113168962Spjd		if (cnp->cn_flags & ISDOTDOT)
1114168404Spjd			vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td);
1115168404Spjd	}
1116168404Spjd
1117168404Spjd#ifdef FREEBSD_NAMECACHE
1118168404Spjd	/*
1119168404Spjd	 * Insert name into cache (as non-existent) if appropriate.
1120168404Spjd	 */
1121168404Spjd	if (error == ENOENT && (cnp->cn_flags & MAKEENTRY) && nameiop != CREATE)
1122168404Spjd		cache_enter(dvp, *vpp, cnp);
1123168404Spjd        /*
1124168404Spjd         * Insert name into cache if appropriate.
1125168404Spjd         */
1126168404Spjd	if (error == 0 && (cnp->cn_flags & MAKEENTRY)) {
1127168404Spjd		if (!(cnp->cn_flags & ISLASTCN) ||
1128168404Spjd		    (nameiop != DELETE && nameiop != RENAME)) {
1129168404Spjd			cache_enter(dvp, *vpp, cnp);
1130168404Spjd		}
1131168404Spjd	}
1132168404Spjd#endif
1133168404Spjd
1134168404Spjd	return (error);
1135168404Spjd}
1136168404Spjd
1137168404Spjd/*
1138168404Spjd * Attempt to create a new entry in a directory.  If the entry
1139168404Spjd * already exists, truncate the file if permissible, else return
1140168404Spjd * an error.  Return the vp of the created or trunc'd file.
1141168404Spjd *
1142168404Spjd *	IN:	dvp	- vnode of directory to put new file entry in.
1143168404Spjd *		name	- name of new file entry.
1144168404Spjd *		vap	- attributes of new file.
1145168404Spjd *		excl	- flag indicating exclusive or non-exclusive mode.
1146168404Spjd *		mode	- mode to open file with.
1147168404Spjd *		cr	- credentials of caller.
1148168404Spjd *		flag	- large file flag [UNUSED].
1149168404Spjd *
1150168404Spjd *	OUT:	vpp	- vnode of created or trunc'd entry.
1151168404Spjd *
1152168404Spjd *	RETURN:	0 if success
1153168404Spjd *		error code if failure
1154168404Spjd *
1155168404Spjd * Timestamps:
1156168404Spjd *	dvp - ctime|mtime updated if new entry created
1157168404Spjd *	 vp - ctime|mtime always, atime if new
1158168404Spjd */
1159168404Spjd/* ARGSUSED */
1160168404Spjdstatic int
1161168962Spjdzfs_create(vnode_t *dvp, char *name, vattr_t *vap, int excl, int mode,
1162168962Spjd    vnode_t **vpp, cred_t *cr, kthread_t *td)
1163168404Spjd{
1164168404Spjd	znode_t		*zp, *dzp = VTOZ(dvp);
1165168404Spjd	zfsvfs_t	*zfsvfs = dzp->z_zfsvfs;
1166168404Spjd	zilog_t		*zilog = zfsvfs->z_log;
1167168404Spjd	objset_t	*os = zfsvfs->z_os;
1168168404Spjd	zfs_dirlock_t	*dl;
1169168404Spjd	dmu_tx_t	*tx;
1170168404Spjd	int		error;
1171168404Spjd	uint64_t	zoid;
1172168404Spjd
1173168404Spjd	ZFS_ENTER(zfsvfs);
1174168404Spjd
1175168404Spjdtop:
1176168404Spjd	*vpp = NULL;
1177168404Spjd
1178168404Spjd	if ((vap->va_mode & VSVTX) && secpolicy_vnode_stky_modify(cr))
1179168404Spjd		vap->va_mode &= ~VSVTX;
1180168404Spjd
1181168404Spjd	if (*name == '\0') {
1182168404Spjd		/*
1183168404Spjd		 * Null component name refers to the directory itself.
1184168404Spjd		 */
1185168404Spjd		VN_HOLD(dvp);
1186168404Spjd		zp = dzp;
1187168404Spjd		dl = NULL;
1188168404Spjd		error = 0;
1189168404Spjd	} else {
1190168404Spjd		/* possible VN_HOLD(zp) */
1191168404Spjd		if (error = zfs_dirent_lock(&dl, dzp, name, &zp, 0)) {
1192168404Spjd			if (strcmp(name, "..") == 0)
1193168404Spjd				error = EISDIR;
1194168404Spjd			ZFS_EXIT(zfsvfs);
1195168404Spjd			return (error);
1196168404Spjd		}
1197168404Spjd	}
1198168404Spjd
1199168404Spjd	zoid = zp ? zp->z_id : -1ULL;
1200168404Spjd
1201168404Spjd	if (zp == NULL) {
1202168404Spjd		/*
1203168404Spjd		 * Create a new file object and update the directory
1204168404Spjd		 * to reference it.
1205168404Spjd		 */
1206168404Spjd		if (error = zfs_zaccess(dzp, ACE_ADD_FILE, cr)) {
1207168404Spjd			goto out;
1208168404Spjd		}
1209168404Spjd
1210168404Spjd		/*
1211168404Spjd		 * We only support the creation of regular files in
1212168404Spjd		 * extended attribute directories.
1213168404Spjd		 */
1214168404Spjd		if ((dzp->z_phys->zp_flags & ZFS_XATTR) &&
1215168404Spjd		    (vap->va_type != VREG)) {
1216168404Spjd			error = EINVAL;
1217168404Spjd			goto out;
1218168404Spjd		}
1219168404Spjd
1220168404Spjd		tx = dmu_tx_create(os);
1221168404Spjd		dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT);
1222168404Spjd		dmu_tx_hold_bonus(tx, dzp->z_id);
1223168404Spjd		dmu_tx_hold_zap(tx, dzp->z_id, TRUE, name);
1224168404Spjd		if (dzp->z_phys->zp_flags & ZFS_INHERIT_ACE)
1225168404Spjd			dmu_tx_hold_write(tx, DMU_NEW_OBJECT,
1226168404Spjd			    0, SPA_MAXBLOCKSIZE);
1227168404Spjd		error = dmu_tx_assign(tx, zfsvfs->z_assign);
1228168404Spjd		if (error) {
1229168404Spjd			zfs_dirent_unlock(dl);
1230168404Spjd			if (error == ERESTART &&
1231168404Spjd			    zfsvfs->z_assign == TXG_NOWAIT) {
1232168404Spjd				dmu_tx_wait(tx);
1233168404Spjd				dmu_tx_abort(tx);
1234168404Spjd				goto top;
1235168404Spjd			}
1236168404Spjd			dmu_tx_abort(tx);
1237168404Spjd			ZFS_EXIT(zfsvfs);
1238168404Spjd			return (error);
1239168404Spjd		}
1240168404Spjd		zfs_mknode(dzp, vap, &zoid, tx, cr, 0, &zp, 0);
1241168404Spjd		ASSERT(zp->z_id == zoid);
1242168404Spjd		(void) zfs_link_create(dl, zp, tx, ZNEW);
1243168404Spjd		zfs_log_create(zilog, tx, TX_CREATE, dzp, zp, name);
1244168404Spjd		dmu_tx_commit(tx);
1245168404Spjd	} else {
1246168404Spjd		/*
1247168404Spjd		 * A directory entry already exists for this name.
1248168404Spjd		 */
1249168404Spjd		/*
1250168962Spjd		 * Can't truncate an existing file if in exclusive mode.
1251168962Spjd		 */
1252168962Spjd		if (excl == EXCL) {
1253168962Spjd			error = EEXIST;
1254168962Spjd			goto out;
1255168962Spjd		}
1256168962Spjd		/*
1257168404Spjd		 * Can't open a directory for writing.
1258168404Spjd		 */
1259168404Spjd		if ((ZTOV(zp)->v_type == VDIR) && (mode & S_IWRITE)) {
1260168404Spjd			error = EISDIR;
1261168404Spjd			goto out;
1262168404Spjd		}
1263168404Spjd		/*
1264168404Spjd		 * Verify requested access to file.
1265168404Spjd		 */
1266168404Spjd		if (mode && (error = zfs_zaccess_rwx(zp, mode, cr))) {
1267168404Spjd			goto out;
1268168404Spjd		}
1269168404Spjd
1270168404Spjd		mutex_enter(&dzp->z_lock);
1271168404Spjd		dzp->z_seq++;
1272168404Spjd		mutex_exit(&dzp->z_lock);
1273168404Spjd
1274168404Spjd		/*
1275168404Spjd		 * Truncate regular files if requested.
1276168404Spjd		 */
1277168404Spjd		if ((ZTOV(zp)->v_type == VREG) &&
1278168404Spjd		    (zp->z_phys->zp_size != 0) &&
1279168404Spjd		    (vap->va_mask & AT_SIZE) && (vap->va_size == 0)) {
1280168404Spjd			error = zfs_freesp(zp, 0, 0, mode, TRUE);
1281168404Spjd			if (error == ERESTART &&
1282168404Spjd			    zfsvfs->z_assign == TXG_NOWAIT) {
1283168404Spjd				/* NB: we already did dmu_tx_wait() */
1284168404Spjd				zfs_dirent_unlock(dl);
1285168404Spjd				VN_RELE(ZTOV(zp));
1286168404Spjd				goto top;
1287168404Spjd			}
1288168404Spjd		}
1289168404Spjd	}
1290168404Spjdout:
1291168404Spjd
1292168404Spjd	if (error == 0) {
1293168404Spjd		*vpp = ZTOV(zp);
1294168962Spjd		vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, td);
1295168404Spjd	}
1296168404Spjd
1297168404Spjd	if (dl)
1298168404Spjd		zfs_dirent_unlock(dl);
1299168404Spjd
1300168404Spjd	if (error) {
1301168404Spjd		if (zp)
1302168404Spjd			VN_RELE(ZTOV(zp));
1303168962Spjd	} else {
1304168962Spjd		*vpp = ZTOV(zp);
1305168962Spjd		/*
1306168962Spjd		 * If vnode is for a device return a specfs vnode instead.
1307168962Spjd		 */
1308168962Spjd		if (IS_DEVVP(*vpp)) {
1309168962Spjd			struct vnode *svp;
1310168962Spjd
1311168962Spjd			svp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type, cr);
1312168962Spjd			VN_RELE(*vpp);
1313168962Spjd			if (svp == NULL) {
1314168962Spjd				error = ENOSYS;
1315168962Spjd			}
1316168962Spjd			*vpp = svp;
1317168962Spjd		}
1318168404Spjd	}
1319168404Spjd
1320168404Spjd	ZFS_EXIT(zfsvfs);
1321168404Spjd	return (error);
1322168404Spjd}
1323168404Spjd
1324168404Spjd/*
1325168404Spjd * Remove an entry from a directory.
1326168404Spjd *
1327168404Spjd *	IN:	dvp	- vnode of directory to remove entry from.
1328168404Spjd *		name	- name of entry to remove.
1329168404Spjd *		cr	- credentials of caller.
1330168404Spjd *
1331168404Spjd *	RETURN:	0 if success
1332168404Spjd *		error code if failure
1333168404Spjd *
1334168404Spjd * Timestamps:
1335168404Spjd *	dvp - ctime|mtime
1336168404Spjd *	 vp - ctime (if nlink > 0)
1337168404Spjd */
1338168404Spjdstatic int
1339168962Spjdzfs_remove(vnode_t *dvp, char *name, cred_t *cr)
1340168404Spjd{
1341168404Spjd	znode_t		*zp, *dzp = VTOZ(dvp);
1342168404Spjd	znode_t		*xzp = NULL;
1343168404Spjd	vnode_t		*vp;
1344168404Spjd	zfsvfs_t	*zfsvfs = dzp->z_zfsvfs;
1345168404Spjd	zilog_t		*zilog = zfsvfs->z_log;
1346168962Spjd	uint64_t	acl_obj, xattr_obj;
1347168404Spjd	zfs_dirlock_t	*dl;
1348168404Spjd	dmu_tx_t	*tx;
1349168962Spjd	boolean_t	may_delete_now, delete_now = FALSE;
1350168404Spjd	boolean_t	unlinked;
1351168404Spjd	int		error;
1352168404Spjd
1353168404Spjd	ZFS_ENTER(zfsvfs);
1354168404Spjd
1355168404Spjdtop:
1356168404Spjd	/*
1357168404Spjd	 * Attempt to lock directory; fail if entry doesn't exist.
1358168404Spjd	 */
1359168404Spjd	if (error = zfs_dirent_lock(&dl, dzp, name, &zp, ZEXISTS)) {
1360168404Spjd		ZFS_EXIT(zfsvfs);
1361168404Spjd		return (error);
1362168404Spjd	}
1363168404Spjd
1364168404Spjd	vp = ZTOV(zp);
1365168404Spjd
1366168962Spjd	if (error = zfs_zaccess_delete(dzp, zp, cr)) {
1367168404Spjd		goto out;
1368168962Spjd	}
1369168404Spjd
1370168962Spjd	/*
1371168962Spjd	 * Need to use rmdir for removing directories.
1372168962Spjd	 */
1373168962Spjd	if (vp->v_type == VDIR) {
1374168962Spjd		error = EPERM;
1375168962Spjd		goto out;
1376168962Spjd	}
1377168962Spjd
1378168962Spjd	vnevent_remove(vp);
1379168962Spjd
1380168404Spjd	dnlc_remove(dvp, name);
1381168404Spjd
1382168962Spjd	may_delete_now = FALSE;
1383168962Spjd
1384168404Spjd	/*
1385168404Spjd	 * We may delete the znode now, or we may put it in the unlinked set;
1386168404Spjd	 * it depends on whether we're the last link, and on whether there are
1387168404Spjd	 * other holds on the vnode.  So we dmu_tx_hold() the right things to
1388168404Spjd	 * allow for either case.
1389168404Spjd	 */
1390168404Spjd	tx = dmu_tx_create(zfsvfs->z_os);
1391168404Spjd	dmu_tx_hold_zap(tx, dzp->z_id, FALSE, name);
1392168404Spjd	dmu_tx_hold_bonus(tx, zp->z_id);
1393168962Spjd	if (may_delete_now)
1394168962Spjd		dmu_tx_hold_free(tx, zp->z_id, 0, DMU_OBJECT_END);
1395168404Spjd
1396168404Spjd	/* are there any extended attributes? */
1397168404Spjd	if ((xattr_obj = zp->z_phys->zp_xattr) != 0) {
1398168404Spjd		/* XXX - do we need this if we are deleting? */
1399168404Spjd		dmu_tx_hold_bonus(tx, xattr_obj);
1400168404Spjd	}
1401168404Spjd
1402168962Spjd	/* are there any additional acls */
1403168962Spjd	if ((acl_obj = zp->z_phys->zp_acl.z_acl_extern_obj) != 0 &&
1404168962Spjd	    may_delete_now)
1405168962Spjd		dmu_tx_hold_free(tx, acl_obj, 0, DMU_OBJECT_END);
1406168962Spjd
1407168404Spjd	/* charge as an update -- would be nice not to charge at all */
1408168404Spjd	dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL);
1409168404Spjd
1410168404Spjd	error = dmu_tx_assign(tx, zfsvfs->z_assign);
1411168404Spjd	if (error) {
1412168404Spjd		zfs_dirent_unlock(dl);
1413168962Spjd		VN_RELE(vp);
1414168404Spjd		if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) {
1415168404Spjd			dmu_tx_wait(tx);
1416168404Spjd			dmu_tx_abort(tx);
1417168404Spjd			goto top;
1418168404Spjd		}
1419168404Spjd		dmu_tx_abort(tx);
1420168404Spjd		ZFS_EXIT(zfsvfs);
1421168404Spjd		return (error);
1422168404Spjd	}
1423168404Spjd
1424168404Spjd	/*
1425168404Spjd	 * Remove the directory entry.
1426168404Spjd	 */
1427168404Spjd	error = zfs_link_destroy(dl, zp, tx, 0, &unlinked);
1428168404Spjd
1429168404Spjd	if (error) {
1430168404Spjd		dmu_tx_commit(tx);
1431168404Spjd		goto out;
1432168404Spjd	}
1433168404Spjd
1434168962Spjd	if (0 && unlinked) {
1435168962Spjd		VI_LOCK(vp);
1436168962Spjd		delete_now = may_delete_now &&
1437168962Spjd		    vp->v_count == 1 && !vn_has_cached_data(vp) &&
1438168962Spjd		    zp->z_phys->zp_xattr == xattr_obj &&
1439168962Spjd		    zp->z_phys->zp_acl.z_acl_extern_obj == acl_obj;
1440168962Spjd		VI_UNLOCK(vp);
1441168962Spjd	}
1442168962Spjd
1443168962Spjd	if (delete_now) {
1444168962Spjd		if (zp->z_phys->zp_xattr) {
1445168962Spjd			error = zfs_zget(zfsvfs, zp->z_phys->zp_xattr, &xzp);
1446168962Spjd			ASSERT3U(error, ==, 0);
1447168962Spjd			ASSERT3U(xzp->z_phys->zp_links, ==, 2);
1448168962Spjd			dmu_buf_will_dirty(xzp->z_dbuf, tx);
1449168962Spjd			mutex_enter(&xzp->z_lock);
1450168962Spjd			xzp->z_unlinked = 1;
1451168962Spjd			xzp->z_phys->zp_links = 0;
1452168962Spjd			mutex_exit(&xzp->z_lock);
1453168962Spjd			zfs_unlinked_add(xzp, tx);
1454168962Spjd			zp->z_phys->zp_xattr = 0; /* probably unnecessary */
1455168962Spjd		}
1456168962Spjd		mutex_enter(&zp->z_lock);
1457168962Spjd		VI_LOCK(vp);
1458168962Spjd		vp->v_count--;
1459168962Spjd		ASSERT3U(vp->v_count, ==, 0);
1460168962Spjd		VI_UNLOCK(vp);
1461168962Spjd		mutex_exit(&zp->z_lock);
1462168962Spjd		zfs_znode_delete(zp, tx);
1463168962Spjd		VFS_RELE(zfsvfs->z_vfs);
1464168962Spjd	} else if (unlinked) {
1465168404Spjd		zfs_unlinked_add(zp, tx);
1466168962Spjd	}
1467168404Spjd
1468168404Spjd	zfs_log_remove(zilog, tx, TX_REMOVE, dzp, name);
1469168404Spjd
1470168404Spjd	dmu_tx_commit(tx);
1471168404Spjdout:
1472168404Spjd	zfs_dirent_unlock(dl);
1473168404Spjd
1474168962Spjd	if (!delete_now) {
1475168962Spjd		VN_RELE(vp);
1476168962Spjd	} else if (xzp) {
1477168962Spjd		/* this rele delayed to prevent nesting transactions */
1478168962Spjd		VN_RELE(ZTOV(xzp));
1479168962Spjd	}
1480168962Spjd
1481168404Spjd	ZFS_EXIT(zfsvfs);
1482168404Spjd	return (error);
1483168404Spjd}
1484168404Spjd
1485168404Spjd/*
1486168404Spjd * Create a new directory and insert it into dvp using the name
1487168404Spjd * provided.  Return a pointer to the inserted directory.
1488168404Spjd *
1489168404Spjd *	IN:	dvp	- vnode of directory to add subdir to.
1490168404Spjd *		dirname	- name of new directory.
1491168404Spjd *		vap	- attributes of new directory.
1492168404Spjd *		cr	- credentials of caller.
1493168404Spjd *
1494168404Spjd *	OUT:	vpp	- vnode of created directory.
1495168404Spjd *
1496168404Spjd *	RETURN:	0 if success
1497168404Spjd *		error code if failure
1498168404Spjd *
1499168404Spjd * Timestamps:
1500168404Spjd *	dvp - ctime|mtime updated
1501168404Spjd *	 vp - ctime|mtime|atime updated
1502168404Spjd */
1503168404Spjdstatic int
1504168962Spjdzfs_mkdir(vnode_t *dvp, char *dirname, vattr_t *vap, vnode_t **vpp, cred_t *cr)
1505168404Spjd{
1506168404Spjd	znode_t		*zp, *dzp = VTOZ(dvp);
1507168404Spjd	zfsvfs_t	*zfsvfs = dzp->z_zfsvfs;
1508168404Spjd	zilog_t		*zilog = zfsvfs->z_log;
1509168404Spjd	zfs_dirlock_t	*dl;
1510168404Spjd	uint64_t	zoid = 0;
1511168404Spjd	dmu_tx_t	*tx;
1512168404Spjd	int		error;
1513168404Spjd
1514168404Spjd	ASSERT(vap->va_type == VDIR);
1515168404Spjd
1516168404Spjd	ZFS_ENTER(zfsvfs);
1517168404Spjd
1518168404Spjd	if (dzp->z_phys->zp_flags & ZFS_XATTR) {
1519168404Spjd		ZFS_EXIT(zfsvfs);
1520168404Spjd		return (EINVAL);
1521168404Spjd	}
1522168404Spjdtop:
1523168404Spjd	*vpp = NULL;
1524168404Spjd
1525168404Spjd	/*
1526168404Spjd	 * First make sure the new directory doesn't exist.
1527168404Spjd	 */
1528168404Spjd	if (error = zfs_dirent_lock(&dl, dzp, dirname, &zp, ZNEW)) {
1529168404Spjd		ZFS_EXIT(zfsvfs);
1530168404Spjd		return (error);
1531168404Spjd	}
1532168404Spjd
1533168404Spjd	if (error = zfs_zaccess(dzp, ACE_ADD_SUBDIRECTORY, cr)) {
1534168404Spjd		zfs_dirent_unlock(dl);
1535168404Spjd		ZFS_EXIT(zfsvfs);
1536168404Spjd		return (error);
1537168404Spjd	}
1538168404Spjd
1539168404Spjd	/*
1540168404Spjd	 * Add a new entry to the directory.
1541168404Spjd	 */
1542168404Spjd	tx = dmu_tx_create(zfsvfs->z_os);
1543168404Spjd	dmu_tx_hold_zap(tx, dzp->z_id, TRUE, dirname);
1544168404Spjd	dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, FALSE, NULL);
1545168404Spjd	if (dzp->z_phys->zp_flags & ZFS_INHERIT_ACE)
1546168404Spjd		dmu_tx_hold_write(tx, DMU_NEW_OBJECT,
1547168404Spjd		    0, SPA_MAXBLOCKSIZE);
1548168404Spjd	error = dmu_tx_assign(tx, zfsvfs->z_assign);
1549168404Spjd	if (error) {
1550168404Spjd		zfs_dirent_unlock(dl);
1551168404Spjd		if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) {
1552168404Spjd			dmu_tx_wait(tx);
1553168404Spjd			dmu_tx_abort(tx);
1554168404Spjd			goto top;
1555168404Spjd		}
1556168404Spjd		dmu_tx_abort(tx);
1557168404Spjd		ZFS_EXIT(zfsvfs);
1558168404Spjd		return (error);
1559168404Spjd	}
1560168404Spjd
1561168404Spjd	/*
1562168404Spjd	 * Create new node.
1563168404Spjd	 */
1564168404Spjd	zfs_mknode(dzp, vap, &zoid, tx, cr, 0, &zp, 0);
1565168404Spjd
1566168404Spjd	/*
1567168404Spjd	 * Now put new name in parent dir.
1568168404Spjd	 */
1569168404Spjd	(void) zfs_link_create(dl, zp, tx, ZNEW);
1570168404Spjd
1571168404Spjd	*vpp = ZTOV(zp);
1572168404Spjd
1573168404Spjd	zfs_log_create(zilog, tx, TX_MKDIR, dzp, zp, dirname);
1574168404Spjd	dmu_tx_commit(tx);
1575168404Spjd
1576168962Spjd	vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, curthread);
1577168404Spjd
1578168404Spjd	zfs_dirent_unlock(dl);
1579168404Spjd
1580168404Spjd	ZFS_EXIT(zfsvfs);
1581168404Spjd	return (0);
1582168404Spjd}
1583168404Spjd
1584168404Spjd/*
1585168404Spjd * Remove a directory subdir entry.  If the current working
1586168404Spjd * directory is the same as the subdir to be removed, the
1587168404Spjd * remove will fail.
1588168404Spjd *
1589168404Spjd *	IN:	dvp	- vnode of directory to remove from.
1590168404Spjd *		name	- name of directory to be removed.
1591168404Spjd *		cwd	- vnode of current working directory.
1592168404Spjd *		cr	- credentials of caller.
1593168404Spjd *
1594168404Spjd *	RETURN:	0 if success
1595168404Spjd *		error code if failure
1596168404Spjd *
1597168404Spjd * Timestamps:
1598168404Spjd *	dvp - ctime|mtime updated
1599168404Spjd */
1600168404Spjdstatic int
1601168962Spjdzfs_rmdir(vnode_t *dvp, char *name, vnode_t *cwd, cred_t *cr)
1602168404Spjd{
1603168404Spjd	znode_t		*dzp = VTOZ(dvp);
1604168404Spjd	znode_t		*zp;
1605168404Spjd	vnode_t		*vp;
1606168404Spjd	zfsvfs_t	*zfsvfs = dzp->z_zfsvfs;
1607168404Spjd	zilog_t		*zilog = zfsvfs->z_log;
1608168404Spjd	zfs_dirlock_t	*dl;
1609168404Spjd	dmu_tx_t	*tx;
1610168404Spjd	int		error;
1611168404Spjd
1612168962Spjd	ZFS_ENTER(zfsvfs);
1613168404Spjd
1614168404Spjdtop:
1615168404Spjd	zp = NULL;
1616168404Spjd
1617168404Spjd	/*
1618168404Spjd	 * Attempt to lock directory; fail if entry doesn't exist.
1619168404Spjd	 */
1620168404Spjd	if (error = zfs_dirent_lock(&dl, dzp, name, &zp, ZEXISTS)) {
1621168404Spjd		ZFS_EXIT(zfsvfs);
1622168404Spjd		return (error);
1623168404Spjd	}
1624168404Spjd
1625168404Spjd	vp = ZTOV(zp);
1626168404Spjd
1627168404Spjd	if (error = zfs_zaccess_delete(dzp, zp, cr)) {
1628168404Spjd		goto out;
1629168404Spjd	}
1630168404Spjd
1631168962Spjd	if (vp->v_type != VDIR) {
1632168962Spjd		error = ENOTDIR;
1633168962Spjd		goto out;
1634168962Spjd	}
1635168962Spjd
1636168962Spjd	if (vp == cwd) {
1637168962Spjd		error = EINVAL;
1638168962Spjd		goto out;
1639168962Spjd	}
1640168962Spjd
1641168962Spjd	vnevent_rmdir(vp);
1642168962Spjd
1643168404Spjd	/*
1644168404Spjd	 * Grab a lock on the directory to make sure that noone is
1645168404Spjd	 * trying to add (or lookup) entries while we are removing it.
1646168404Spjd	 */
1647168404Spjd	rw_enter(&zp->z_name_lock, RW_WRITER);
1648168404Spjd
1649168404Spjd	/*
1650168404Spjd	 * Grab a lock on the parent pointer to make sure we play well
1651168404Spjd	 * with the treewalk and directory rename code.
1652168404Spjd	 */
1653168404Spjd	rw_enter(&zp->z_parent_lock, RW_WRITER);
1654168404Spjd
1655168404Spjd	tx = dmu_tx_create(zfsvfs->z_os);
1656168404Spjd	dmu_tx_hold_zap(tx, dzp->z_id, FALSE, name);
1657168404Spjd	dmu_tx_hold_bonus(tx, zp->z_id);
1658168404Spjd	dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL);
1659168404Spjd	error = dmu_tx_assign(tx, zfsvfs->z_assign);
1660168404Spjd	if (error) {
1661168404Spjd		rw_exit(&zp->z_parent_lock);
1662168404Spjd		rw_exit(&zp->z_name_lock);
1663168404Spjd		zfs_dirent_unlock(dl);
1664168962Spjd		VN_RELE(vp);
1665168404Spjd		if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) {
1666168404Spjd			dmu_tx_wait(tx);
1667168404Spjd			dmu_tx_abort(tx);
1668168404Spjd			goto top;
1669168404Spjd		}
1670168404Spjd		dmu_tx_abort(tx);
1671168404Spjd		ZFS_EXIT(zfsvfs);
1672168404Spjd		return (error);
1673168404Spjd	}
1674168404Spjd
1675168404Spjd#ifdef FREEBSD_NAMECACHE
1676168404Spjd	cache_purge(dvp);
1677168404Spjd#endif
1678168404Spjd
1679168404Spjd	error = zfs_link_destroy(dl, zp, tx, 0, NULL);
1680168404Spjd
1681168404Spjd	if (error == 0)
1682168404Spjd		zfs_log_remove(zilog, tx, TX_RMDIR, dzp, name);
1683168404Spjd
1684168404Spjd	dmu_tx_commit(tx);
1685168404Spjd
1686168404Spjd	rw_exit(&zp->z_parent_lock);
1687168404Spjd	rw_exit(&zp->z_name_lock);
1688168404Spjd#ifdef FREEBSD_NAMECACHE
1689168404Spjd	cache_purge(vp);
1690168404Spjd#endif
1691168404Spjdout:
1692168404Spjd	zfs_dirent_unlock(dl);
1693168404Spjd
1694168962Spjd	VN_RELE(vp);
1695168962Spjd
1696168404Spjd	ZFS_EXIT(zfsvfs);
1697168404Spjd	return (error);
1698168404Spjd}
1699168404Spjd
1700168404Spjd/*
1701168404Spjd * Read as many directory entries as will fit into the provided
1702168404Spjd * buffer from the given directory cursor position (specified in
1703168404Spjd * the uio structure.
1704168404Spjd *
1705168404Spjd *	IN:	vp	- vnode of directory to read.
1706168404Spjd *		uio	- structure supplying read location, range info,
1707168404Spjd *			  and return buffer.
1708168404Spjd *		cr	- credentials of caller.
1709168404Spjd *
1710168404Spjd *	OUT:	uio	- updated offset and range, buffer filled.
1711168404Spjd *		eofp	- set to true if end-of-file detected.
1712168404Spjd *
1713168404Spjd *	RETURN:	0 if success
1714168404Spjd *		error code if failure
1715168404Spjd *
1716168404Spjd * Timestamps:
1717168404Spjd *	vp - atime updated
1718168404Spjd *
1719168404Spjd * Note that the low 4 bits of the cookie returned by zap is always zero.
1720168404Spjd * This allows us to use the low range for "special" directory entries:
1721168404Spjd * We use 0 for '.', and 1 for '..'.  If this is the root of the filesystem,
1722168404Spjd * we use the offset 2 for the '.zfs' directory.
1723168404Spjd */
1724168404Spjd/* ARGSUSED */
1725168404Spjdstatic int
1726168962Spjdzfs_readdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp, int *ncookies, u_long **cookies)
1727168404Spjd{
1728168404Spjd	znode_t		*zp = VTOZ(vp);
1729168404Spjd	iovec_t		*iovp;
1730168404Spjd	dirent64_t	*odp;
1731168404Spjd	zfsvfs_t	*zfsvfs = zp->z_zfsvfs;
1732168404Spjd	objset_t	*os;
1733168404Spjd	caddr_t		outbuf;
1734168404Spjd	size_t		bufsize;
1735168404Spjd	zap_cursor_t	zc;
1736168404Spjd	zap_attribute_t	zap;
1737168404Spjd	uint_t		bytes_wanted;
1738168404Spjd	uint64_t	offset; /* must be unsigned; checks for < 1 */
1739168404Spjd	int		local_eof;
1740168404Spjd	int		outcount;
1741168404Spjd	int		error;
1742168404Spjd	uint8_t		prefetch;
1743168404Spjd	uint8_t		type;
1744168962Spjd	int		ncooks;
1745168962Spjd	u_long		*cooks = NULL;
1746168404Spjd
1747168404Spjd	ZFS_ENTER(zfsvfs);
1748168404Spjd
1749168404Spjd	/*
1750168404Spjd	 * If we are not given an eof variable,
1751168404Spjd	 * use a local one.
1752168404Spjd	 */
1753168404Spjd	if (eofp == NULL)
1754168404Spjd		eofp = &local_eof;
1755168404Spjd
1756168404Spjd	/*
1757168404Spjd	 * Check for valid iov_len.
1758168404Spjd	 */
1759168404Spjd	if (uio->uio_iov->iov_len <= 0) {
1760168404Spjd		ZFS_EXIT(zfsvfs);
1761168404Spjd		return (EINVAL);
1762168404Spjd	}
1763168404Spjd
1764168404Spjd	/*
1765168404Spjd	 * Quit if directory has been removed (posix)
1766168404Spjd	 */
1767168404Spjd	if ((*eofp = zp->z_unlinked) != 0) {
1768168404Spjd		ZFS_EXIT(zfsvfs);
1769168404Spjd		return (0);
1770168404Spjd	}
1771168404Spjd
1772168404Spjd	error = 0;
1773168404Spjd	os = zfsvfs->z_os;
1774168404Spjd	offset = uio->uio_loffset;
1775168404Spjd	prefetch = zp->z_zn_prefetch;
1776168404Spjd
1777168404Spjd	/*
1778168404Spjd	 * Initialize the iterator cursor.
1779168404Spjd	 */
1780168404Spjd	if (offset <= 3) {
1781168404Spjd		/*
1782168404Spjd		 * Start iteration from the beginning of the directory.
1783168404Spjd		 */
1784168404Spjd		zap_cursor_init(&zc, os, zp->z_id);
1785168404Spjd	} else {
1786168404Spjd		/*
1787168404Spjd		 * The offset is a serialized cursor.
1788168404Spjd		 */
1789168404Spjd		zap_cursor_init_serialized(&zc, os, zp->z_id, offset);
1790168404Spjd	}
1791168404Spjd
1792168404Spjd	/*
1793168404Spjd	 * Get space to change directory entries into fs independent format.
1794168404Spjd	 */
1795168404Spjd	iovp = uio->uio_iov;
1796168404Spjd	bytes_wanted = iovp->iov_len;
1797168404Spjd	if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) {
1798168404Spjd		bufsize = bytes_wanted;
1799168404Spjd		outbuf = kmem_alloc(bufsize, KM_SLEEP);
1800168404Spjd		odp = (struct dirent64 *)outbuf;
1801168404Spjd	} else {
1802168404Spjd		bufsize = bytes_wanted;
1803168404Spjd		odp = (struct dirent64 *)iovp->iov_base;
1804168404Spjd	}
1805168404Spjd
1806168962Spjd	if (ncookies != NULL) {
1807168404Spjd		/*
1808168404Spjd		 * Minimum entry size is dirent size and 1 byte for a file name.
1809168404Spjd		 */
1810168962Spjd		ncooks = uio->uio_resid / (sizeof(struct dirent) - sizeof(((struct dirent *)NULL)->d_name) + 1);
1811168962Spjd		cooks = malloc(ncooks * sizeof(u_long), M_TEMP, M_WAITOK);
1812168962Spjd		*cookies = cooks;
1813168962Spjd		*ncookies = ncooks;
1814168404Spjd	}
1815168404Spjd
1816168404Spjd	/*
1817168404Spjd	 * Transform to file-system independent format
1818168404Spjd	 */
1819168404Spjd	outcount = 0;
1820168404Spjd	while (outcount < bytes_wanted) {
1821168404Spjd		ino64_t objnum;
1822168404Spjd		ushort_t reclen;
1823168404Spjd
1824168404Spjd		/*
1825168404Spjd		 * Special case `.', `..', and `.zfs'.
1826168404Spjd		 */
1827168404Spjd		if (offset == 0) {
1828168404Spjd			(void) strcpy(zap.za_name, ".");
1829168404Spjd			objnum = zp->z_id;
1830169108Spjd			type = DT_DIR;
1831168404Spjd		} else if (offset == 1) {
1832168404Spjd			(void) strcpy(zap.za_name, "..");
1833168404Spjd			objnum = zp->z_phys->zp_parent;
1834169108Spjd			type = DT_DIR;
1835168404Spjd		} else if (offset == 2 && zfs_show_ctldir(zp)) {
1836168404Spjd			(void) strcpy(zap.za_name, ZFS_CTLDIR_NAME);
1837168404Spjd			objnum = ZFSCTL_INO_ROOT;
1838169108Spjd			type = DT_DIR;
1839168404Spjd		} else {
1840168404Spjd			/*
1841168404Spjd			 * Grab next entry.
1842168404Spjd			 */
1843168404Spjd			if (error = zap_cursor_retrieve(&zc, &zap)) {
1844168404Spjd				if ((*eofp = (error == ENOENT)) != 0)
1845168404Spjd					break;
1846168404Spjd				else
1847168404Spjd					goto update;
1848168404Spjd			}
1849168404Spjd
1850168404Spjd			if (zap.za_integer_length != 8 ||
1851168404Spjd			    zap.za_num_integers != 1) {
1852168404Spjd				cmn_err(CE_WARN, "zap_readdir: bad directory "
1853168404Spjd				    "entry, obj = %lld, offset = %lld\n",
1854168404Spjd				    (u_longlong_t)zp->z_id,
1855168404Spjd				    (u_longlong_t)offset);
1856168404Spjd				error = ENXIO;
1857168404Spjd				goto update;
1858168404Spjd			}
1859168404Spjd
1860168404Spjd			objnum = ZFS_DIRENT_OBJ(zap.za_first_integer);
1861168404Spjd			/*
1862168404Spjd			 * MacOS X can extract the object type here such as:
1863168404Spjd			 * uint8_t type = ZFS_DIRENT_TYPE(zap.za_first_integer);
1864168404Spjd			 */
1865168404Spjd			type = ZFS_DIRENT_TYPE(zap.za_first_integer);
1866168404Spjd		}
1867168404Spjd		reclen = DIRENT64_RECLEN(strlen(zap.za_name));
1868168404Spjd
1869168404Spjd		/*
1870168404Spjd		 * Will this entry fit in the buffer?
1871168404Spjd		 */
1872168404Spjd		if (outcount + reclen > bufsize) {
1873168404Spjd			/*
1874168404Spjd			 * Did we manage to fit anything in the buffer?
1875168404Spjd			 */
1876168404Spjd			if (!outcount) {
1877168404Spjd				error = EINVAL;
1878168404Spjd				goto update;
1879168404Spjd			}
1880168404Spjd			break;
1881168404Spjd		}
1882168404Spjd		/*
1883168404Spjd		 * Add this entry:
1884168404Spjd		 */
1885168404Spjd		odp->d_ino = objnum;
1886168404Spjd		odp->d_reclen = reclen;
1887168404Spjd		odp->d_namlen = strlen(zap.za_name);
1888168404Spjd		(void) strlcpy(odp->d_name, zap.za_name, odp->d_namlen + 1);
1889168404Spjd		odp->d_type = type;
1890168404Spjd		outcount += reclen;
1891168404Spjd		odp = (dirent64_t *)((intptr_t)odp + reclen);
1892168404Spjd
1893168404Spjd		ASSERT(outcount <= bufsize);
1894168404Spjd
1895168404Spjd		/* Prefetch znode */
1896168404Spjd		if (prefetch)
1897168404Spjd			dmu_prefetch(os, objnum, 0, 0);
1898168404Spjd
1899168404Spjd		/*
1900168404Spjd		 * Move to the next entry, fill in the previous offset.
1901168404Spjd		 */
1902168404Spjd		if (offset > 2 || (offset == 2 && !zfs_show_ctldir(zp))) {
1903168404Spjd			zap_cursor_advance(&zc);
1904168404Spjd			offset = zap_cursor_serialize(&zc);
1905168404Spjd		} else {
1906168404Spjd			offset += 1;
1907168404Spjd		}
1908168404Spjd
1909168962Spjd		if (cooks != NULL) {
1910168962Spjd			*cooks++ = offset;
1911168962Spjd			ncooks--;
1912168962Spjd			KASSERT(ncooks >= 0, ("ncookies=%d", ncooks));
1913168404Spjd		}
1914168404Spjd	}
1915168404Spjd	zp->z_zn_prefetch = B_FALSE; /* a lookup will re-enable pre-fetching */
1916168404Spjd
1917168404Spjd	/* Subtract unused cookies */
1918168962Spjd	if (ncookies != NULL)
1919168962Spjd		*ncookies -= ncooks;
1920168404Spjd
1921168404Spjd	if (uio->uio_segflg == UIO_SYSSPACE && uio->uio_iovcnt == 1) {
1922168404Spjd		iovp->iov_base += outcount;
1923168404Spjd		iovp->iov_len -= outcount;
1924168404Spjd		uio->uio_resid -= outcount;
1925168404Spjd	} else if (error = uiomove(outbuf, (long)outcount, UIO_READ, uio)) {
1926168404Spjd		/*
1927168404Spjd		 * Reset the pointer.
1928168404Spjd		 */
1929168404Spjd		offset = uio->uio_loffset;
1930168404Spjd	}
1931168404Spjd
1932168404Spjdupdate:
1933168404Spjd	zap_cursor_fini(&zc);
1934168404Spjd	if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
1935168404Spjd		kmem_free(outbuf, bufsize);
1936168404Spjd
1937168404Spjd	if (error == ENOENT)
1938168404Spjd		error = 0;
1939168404Spjd
1940168404Spjd	ZFS_ACCESSTIME_STAMP(zfsvfs, zp);
1941168404Spjd
1942168404Spjd	uio->uio_loffset = offset;
1943168404Spjd	ZFS_EXIT(zfsvfs);
1944169107Spjd	if (error != 0 && cookies != NULL) {
1945168962Spjd		free(*cookies, M_TEMP);
1946168962Spjd		*cookies = NULL;
1947168962Spjd		*ncookies = 0;
1948168404Spjd	}
1949168404Spjd	return (error);
1950168404Spjd}
1951168404Spjd
1952168404Spjdstatic int
1953168962Spjdzfs_fsync(vnode_t *vp, int syncflag, cred_t *cr)
1954168404Spjd{
1955168962Spjd	znode_t	*zp = VTOZ(vp);
1956168962Spjd	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
1957168404Spjd
1958168404Spjd	ZFS_ENTER(zfsvfs);
1959168404Spjd	zil_commit(zfsvfs->z_log, zp->z_last_itx, zp->z_id);
1960168404Spjd	ZFS_EXIT(zfsvfs);
1961168404Spjd	return (0);
1962168404Spjd}
1963168404Spjd
1964168404Spjd/*
1965168404Spjd * Get the requested file attributes and place them in the provided
1966168404Spjd * vattr structure.
1967168404Spjd *
1968168404Spjd *	IN:	vp	- vnode of file.
1969168404Spjd *		vap	- va_mask identifies requested attributes.
1970168404Spjd *		flags	- [UNUSED]
1971168404Spjd *		cr	- credentials of caller.
1972168404Spjd *
1973168404Spjd *	OUT:	vap	- attribute values.
1974168404Spjd *
1975168404Spjd *	RETURN:	0 (always succeeds)
1976168404Spjd */
1977168404Spjd/* ARGSUSED */
1978168404Spjdstatic int
1979168962Spjdzfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr)
1980168404Spjd{
1981168962Spjd	znode_t *zp = VTOZ(vp);
1982168962Spjd	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
1983168962Spjd	znode_phys_t *pzp = zp->z_phys;
1984168962Spjd	uint32_t blksize;
1985168962Spjd	u_longlong_t nblocks;
1986168962Spjd	int	error;
1987168404Spjd
1988168404Spjd	ZFS_ENTER(zfsvfs);
1989168404Spjd
1990168404Spjd	/*
1991168404Spjd	 * Return all attributes.  It's cheaper to provide the answer
1992168404Spjd	 * than to determine whether we were asked the question.
1993168404Spjd	 */
1994168404Spjd	mutex_enter(&zp->z_lock);
1995168404Spjd
1996168404Spjd	vap->va_type = IFTOVT(pzp->zp_mode);
1997168404Spjd	vap->va_mode = pzp->zp_mode & ~S_IFMT;
1998168404Spjd	vap->va_uid = zp->z_phys->zp_uid;
1999168404Spjd	vap->va_gid = zp->z_phys->zp_gid;
2000168404Spjd	vap->va_nodeid = zp->z_id;
2001168404Spjd	vap->va_nlink = MIN(pzp->zp_links, UINT32_MAX);	/* nlink_t limit! */
2002168404Spjd	vap->va_size = pzp->zp_size;
2003168404Spjd	vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
2004168958Spjd	vap->va_rdev = zfs_cmpldev(pzp->zp_rdev);
2005168404Spjd	vap->va_seq = zp->z_seq;
2006168404Spjd	vap->va_flags = 0;	/* FreeBSD: Reset chflags(2) flags. */
2007168404Spjd
2008168404Spjd	ZFS_TIME_DECODE(&vap->va_atime, pzp->zp_atime);
2009168404Spjd	ZFS_TIME_DECODE(&vap->va_mtime, pzp->zp_mtime);
2010168404Spjd	ZFS_TIME_DECODE(&vap->va_ctime, pzp->zp_ctime);
2011168404Spjd	ZFS_TIME_DECODE(&vap->va_birthtime, pzp->zp_crtime);
2012168404Spjd
2013168404Spjd	/*
2014168404Spjd	 * If ACL is trivial don't bother looking for ACE_READ_ATTRIBUTES.
2015168404Spjd	 * Also, if we are the owner don't bother, since owner should
2016168404Spjd	 * always be allowed to read basic attributes of file.
2017168404Spjd	 */
2018168404Spjd	if (!(zp->z_phys->zp_flags & ZFS_ACL_TRIVIAL) &&
2019168404Spjd	    (zp->z_phys->zp_uid != crgetuid(cr))) {
2020168404Spjd		if (error = zfs_zaccess(zp, ACE_READ_ATTRIBUTES, cr)) {
2021168404Spjd			mutex_exit(&zp->z_lock);
2022168404Spjd			ZFS_EXIT(zfsvfs);
2023168404Spjd			return (error);
2024168404Spjd		}
2025168404Spjd	}
2026168404Spjd
2027168404Spjd	mutex_exit(&zp->z_lock);
2028168404Spjd
2029168404Spjd	dmu_object_size_from_db(zp->z_dbuf, &blksize, &nblocks);
2030168404Spjd	vap->va_blksize = blksize;
2031168404Spjd	vap->va_bytes = nblocks << 9;	/* nblocks * 512 */
2032168404Spjd
2033168404Spjd	if (zp->z_blksz == 0) {
2034168404Spjd		/*
2035168404Spjd		 * Block size hasn't been set; suggest maximal I/O transfers.
2036168404Spjd		 */
2037168404Spjd		vap->va_blksize = zfsvfs->z_max_blksz;
2038168404Spjd	}
2039168404Spjd
2040168404Spjd	ZFS_EXIT(zfsvfs);
2041168404Spjd	return (0);
2042168404Spjd}
2043168404Spjd
2044168404Spjd/*
2045168404Spjd * Set the file attributes to the values contained in the
2046168404Spjd * vattr structure.
2047168404Spjd *
2048168404Spjd *	IN:	vp	- vnode of file to be modified.
2049168404Spjd *		vap	- new attribute values.
2050168404Spjd *		flags	- ATTR_UTIME set if non-default time values provided.
2051168404Spjd *		cr	- credentials of caller.
2052168404Spjd *
2053168404Spjd *	RETURN:	0 if success
2054168404Spjd *		error code if failure
2055168404Spjd *
2056168404Spjd * Timestamps:
2057168404Spjd *	vp - ctime updated, mtime updated if size changed.
2058168404Spjd */
2059168404Spjd/* ARGSUSED */
2060168404Spjdstatic int
2061168962Spjdzfs_setattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
2062168962Spjd	caller_context_t *ct)
2063168404Spjd{
2064168962Spjd	struct znode	*zp = VTOZ(vp);
2065168404Spjd	znode_phys_t	*pzp = zp->z_phys;
2066168404Spjd	zfsvfs_t	*zfsvfs = zp->z_zfsvfs;
2067168404Spjd	zilog_t		*zilog = zfsvfs->z_log;
2068168404Spjd	dmu_tx_t	*tx;
2069168404Spjd	vattr_t		oldva;
2070168962Spjd	uint_t		mask = vap->va_mask;
2071168404Spjd	uint_t		saved_mask;
2072168404Spjd	int		trim_mask = 0;
2073168404Spjd	uint64_t	new_mode;
2074168404Spjd	znode_t		*attrzp;
2075168404Spjd	int		need_policy = FALSE;
2076168404Spjd	int		err;
2077168404Spjd
2078168404Spjd	if (mask == 0)
2079168404Spjd		return (0);
2080168404Spjd
2081168962Spjd	if (mask & AT_NOSET)
2082168962Spjd		return (EINVAL);
2083168962Spjd
2084168404Spjd	if (mask & AT_SIZE && vp->v_type == VDIR)
2085168404Spjd		return (EISDIR);
2086168404Spjd
2087168404Spjd	if (mask & AT_SIZE && vp->v_type != VREG && vp->v_type != VFIFO)
2088168404Spjd		return (EINVAL);
2089168404Spjd
2090168404Spjd	ZFS_ENTER(zfsvfs);
2091168404Spjd
2092168404Spjdtop:
2093168404Spjd	attrzp = NULL;
2094168404Spjd
2095168404Spjd	if (zfsvfs->z_vfs->vfs_flag & VFS_RDONLY) {
2096168404Spjd		ZFS_EXIT(zfsvfs);
2097168404Spjd		return (EROFS);
2098168404Spjd	}
2099168404Spjd
2100168404Spjd	/*
2101168404Spjd	 * First validate permissions
2102168404Spjd	 */
2103168404Spjd
2104168404Spjd	if (mask & AT_SIZE) {
2105168404Spjd		err = zfs_zaccess(zp, ACE_WRITE_DATA, cr);
2106168404Spjd		if (err) {
2107168404Spjd			ZFS_EXIT(zfsvfs);
2108168404Spjd			return (err);
2109168404Spjd		}
2110168404Spjd		/*
2111168404Spjd		 * XXX - Note, we are not providing any open
2112168404Spjd		 * mode flags here (like FNDELAY), so we may
2113168404Spjd		 * block if there are locks present... this
2114168404Spjd		 * should be addressed in openat().
2115168404Spjd		 */
2116168404Spjd		do {
2117168404Spjd			err = zfs_freesp(zp, vap->va_size, 0, 0, FALSE);
2118168404Spjd			/* NB: we already did dmu_tx_wait() if necessary */
2119168404Spjd		} while (err == ERESTART && zfsvfs->z_assign == TXG_NOWAIT);
2120168404Spjd		if (err) {
2121168404Spjd			ZFS_EXIT(zfsvfs);
2122168404Spjd			return (err);
2123168404Spjd		}
2124168404Spjd	}
2125168404Spjd
2126168404Spjd	if (mask & (AT_ATIME|AT_MTIME))
2127168404Spjd		need_policy = zfs_zaccess_v4_perm(zp, ACE_WRITE_ATTRIBUTES, cr);
2128168404Spjd
2129168404Spjd	if (mask & (AT_UID|AT_GID)) {
2130168404Spjd		int	idmask = (mask & (AT_UID|AT_GID));
2131168404Spjd		int	take_owner;
2132168404Spjd		int	take_group;
2133168404Spjd
2134168404Spjd		/*
2135168404Spjd		 * NOTE: even if a new mode is being set,
2136168404Spjd		 * we may clear S_ISUID/S_ISGID bits.
2137168404Spjd		 */
2138168404Spjd
2139168404Spjd		if (!(mask & AT_MODE))
2140168404Spjd			vap->va_mode = pzp->zp_mode;
2141168404Spjd
2142168404Spjd		/*
2143168404Spjd		 * Take ownership or chgrp to group we are a member of
2144168404Spjd		 */
2145168404Spjd
2146168404Spjd		take_owner = (mask & AT_UID) && (vap->va_uid == crgetuid(cr));
2147168404Spjd		take_group = (mask & AT_GID) && groupmember(vap->va_gid, cr);
2148168404Spjd
2149168404Spjd		/*
2150168404Spjd		 * If both AT_UID and AT_GID are set then take_owner and
2151168404Spjd		 * take_group must both be set in order to allow taking
2152168404Spjd		 * ownership.
2153168404Spjd		 *
2154168404Spjd		 * Otherwise, send the check through secpolicy_vnode_setattr()
2155168404Spjd		 *
2156168404Spjd		 */
2157168404Spjd
2158168404Spjd		if (((idmask == (AT_UID|AT_GID)) && take_owner && take_group) ||
2159168404Spjd		    ((idmask == AT_UID) && take_owner) ||
2160168404Spjd		    ((idmask == AT_GID) && take_group)) {
2161168404Spjd			if (zfs_zaccess_v4_perm(zp, ACE_WRITE_OWNER, cr) == 0) {
2162168404Spjd				/*
2163168404Spjd				 * Remove setuid/setgid for non-privileged users
2164168404Spjd				 */
2165168404Spjd				secpolicy_setid_clear(vap, cr);
2166168404Spjd				trim_mask = (mask & (AT_UID|AT_GID));
2167168404Spjd			} else {
2168168404Spjd				need_policy =  TRUE;
2169168404Spjd			}
2170168404Spjd		} else {
2171168404Spjd			need_policy =  TRUE;
2172168404Spjd		}
2173168404Spjd	}
2174168404Spjd
2175168404Spjd	mutex_enter(&zp->z_lock);
2176168404Spjd	oldva.va_mode = pzp->zp_mode;
2177168404Spjd	oldva.va_uid = zp->z_phys->zp_uid;
2178168404Spjd	oldva.va_gid = zp->z_phys->zp_gid;
2179168404Spjd	mutex_exit(&zp->z_lock);
2180168404Spjd
2181168404Spjd	if (mask & AT_MODE) {
2182168404Spjd		if (zfs_zaccess_v4_perm(zp, ACE_WRITE_ACL, cr) == 0) {
2183168962Spjd			err = secpolicy_setid_setsticky_clear(vp, vap,
2184168962Spjd			    &oldva, cr);
2185168962Spjd			if (err) {
2186168962Spjd				ZFS_EXIT(zfsvfs);
2187168962Spjd				return (err);
2188168962Spjd			}
2189168404Spjd			trim_mask |= AT_MODE;
2190168404Spjd		} else {
2191168404Spjd			need_policy = TRUE;
2192168404Spjd		}
2193168404Spjd	}
2194168404Spjd
2195168404Spjd	if (need_policy) {
2196168404Spjd		/*
2197168404Spjd		 * If trim_mask is set then take ownership
2198168404Spjd		 * has been granted or write_acl is present and user
2199168404Spjd		 * has the ability to modify mode.  In that case remove
2200168404Spjd		 * UID|GID and or MODE from mask so that
2201168404Spjd		 * secpolicy_vnode_setattr() doesn't revoke it.
2202168404Spjd		 */
2203168404Spjd
2204168404Spjd		if (trim_mask) {
2205168404Spjd			saved_mask = vap->va_mask;
2206168404Spjd			vap->va_mask &= ~trim_mask;
2207168404Spjd
2208168404Spjd		}
2209168404Spjd		err = secpolicy_vnode_setattr(cr, vp, vap, &oldva, flags,
2210168404Spjd		    (int (*)(void *, int, cred_t *))zfs_zaccess_rwx, zp);
2211168404Spjd		if (err) {
2212168404Spjd			ZFS_EXIT(zfsvfs);
2213168404Spjd			return (err);
2214168404Spjd		}
2215168404Spjd
2216168404Spjd		if (trim_mask)
2217168404Spjd			vap->va_mask |= saved_mask;
2218168404Spjd	}
2219168404Spjd
2220168404Spjd	/*
2221168404Spjd	 * secpolicy_vnode_setattr, or take ownership may have
2222168404Spjd	 * changed va_mask
2223168404Spjd	 */
2224168404Spjd	mask = vap->va_mask;
2225168404Spjd
2226168404Spjd	tx = dmu_tx_create(zfsvfs->z_os);
2227168404Spjd	dmu_tx_hold_bonus(tx, zp->z_id);
2228168404Spjd
2229168404Spjd	if (mask & AT_MODE) {
2230168404Spjd		uint64_t pmode = pzp->zp_mode;
2231168404Spjd
2232168404Spjd		new_mode = (pmode & S_IFMT) | (vap->va_mode & ~S_IFMT);
2233168404Spjd
2234168404Spjd		if (zp->z_phys->zp_acl.z_acl_extern_obj)
2235168404Spjd			dmu_tx_hold_write(tx,
2236168404Spjd			    pzp->zp_acl.z_acl_extern_obj, 0, SPA_MAXBLOCKSIZE);
2237168404Spjd		else
2238168404Spjd			dmu_tx_hold_write(tx, DMU_NEW_OBJECT,
2239168404Spjd			    0, ZFS_ACL_SIZE(MAX_ACL_SIZE));
2240168404Spjd	}
2241168404Spjd
2242168404Spjd	if ((mask & (AT_UID | AT_GID)) && zp->z_phys->zp_xattr != 0) {
2243168404Spjd		err = zfs_zget(zp->z_zfsvfs, zp->z_phys->zp_xattr, &attrzp);
2244168404Spjd		if (err) {
2245168404Spjd			dmu_tx_abort(tx);
2246168404Spjd			ZFS_EXIT(zfsvfs);
2247168404Spjd			return (err);
2248168404Spjd		}
2249168404Spjd		dmu_tx_hold_bonus(tx, attrzp->z_id);
2250168404Spjd	}
2251168404Spjd
2252168404Spjd	err = dmu_tx_assign(tx, zfsvfs->z_assign);
2253168404Spjd	if (err) {
2254168404Spjd		if (attrzp)
2255168404Spjd			VN_RELE(ZTOV(attrzp));
2256168404Spjd		if (err == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) {
2257168404Spjd			dmu_tx_wait(tx);
2258168404Spjd			dmu_tx_abort(tx);
2259168404Spjd			goto top;
2260168404Spjd		}
2261168404Spjd		dmu_tx_abort(tx);
2262168404Spjd		ZFS_EXIT(zfsvfs);
2263168404Spjd		return (err);
2264168404Spjd	}
2265168404Spjd
2266168404Spjd	dmu_buf_will_dirty(zp->z_dbuf, tx);
2267168404Spjd
2268168404Spjd	/*
2269168404Spjd	 * Set each attribute requested.
2270168404Spjd	 * We group settings according to the locks they need to acquire.
2271168404Spjd	 *
2272168404Spjd	 * Note: you cannot set ctime directly, although it will be
2273168404Spjd	 * updated as a side-effect of calling this function.
2274168404Spjd	 */
2275168404Spjd
2276168404Spjd	mutex_enter(&zp->z_lock);
2277168404Spjd
2278168404Spjd	if (mask & AT_MODE) {
2279168404Spjd		err = zfs_acl_chmod_setattr(zp, new_mode, tx);
2280168404Spjd		ASSERT3U(err, ==, 0);
2281168404Spjd	}
2282168404Spjd
2283168404Spjd	if (attrzp)
2284168404Spjd		mutex_enter(&attrzp->z_lock);
2285168404Spjd
2286168404Spjd	if (mask & AT_UID) {
2287168404Spjd		zp->z_phys->zp_uid = (uint64_t)vap->va_uid;
2288168404Spjd		if (attrzp) {
2289168404Spjd			attrzp->z_phys->zp_uid = (uint64_t)vap->va_uid;
2290168404Spjd		}
2291168404Spjd	}
2292168404Spjd
2293168404Spjd	if (mask & AT_GID) {
2294168404Spjd		zp->z_phys->zp_gid = (uint64_t)vap->va_gid;
2295168404Spjd		if (attrzp)
2296168404Spjd			attrzp->z_phys->zp_gid = (uint64_t)vap->va_gid;
2297168404Spjd	}
2298168404Spjd
2299168404Spjd	if (attrzp)
2300168404Spjd		mutex_exit(&attrzp->z_lock);
2301168404Spjd
2302168404Spjd	if (mask & AT_ATIME)
2303168404Spjd		ZFS_TIME_ENCODE(&vap->va_atime, pzp->zp_atime);
2304168404Spjd
2305168404Spjd	if (mask & AT_MTIME)
2306168404Spjd		ZFS_TIME_ENCODE(&vap->va_mtime, pzp->zp_mtime);
2307168404Spjd
2308168404Spjd	if (mask & AT_SIZE)
2309168404Spjd		zfs_time_stamper_locked(zp, CONTENT_MODIFIED, tx);
2310168404Spjd	else if (mask != 0)
2311168404Spjd		zfs_time_stamper_locked(zp, STATE_CHANGED, tx);
2312168404Spjd
2313168404Spjd	if (mask != 0)
2314168404Spjd		zfs_log_setattr(zilog, tx, TX_SETATTR, zp, vap, mask);
2315168404Spjd
2316168404Spjd	mutex_exit(&zp->z_lock);
2317168404Spjd
2318168404Spjd	if (attrzp)
2319168404Spjd		VN_RELE(ZTOV(attrzp));
2320168404Spjd
2321168404Spjd	dmu_tx_commit(tx);
2322168404Spjd
2323168404Spjd	ZFS_EXIT(zfsvfs);
2324168404Spjd	return (err);
2325168404Spjd}
2326168404Spjd
2327168404Spjdtypedef struct zfs_zlock {
2328168404Spjd	krwlock_t	*zl_rwlock;	/* lock we acquired */
2329168404Spjd	znode_t		*zl_znode;	/* znode we held */
2330168404Spjd	struct zfs_zlock *zl_next;	/* next in list */
2331168404Spjd} zfs_zlock_t;
2332168404Spjd
2333168404Spjd/*
2334168404Spjd * Drop locks and release vnodes that were held by zfs_rename_lock().
2335168404Spjd */
2336168404Spjdstatic void
2337168404Spjdzfs_rename_unlock(zfs_zlock_t **zlpp)
2338168404Spjd{
2339168404Spjd	zfs_zlock_t *zl;
2340168404Spjd
2341168404Spjd	while ((zl = *zlpp) != NULL) {
2342168404Spjd		if (zl->zl_znode != NULL)
2343168404Spjd			VN_RELE(ZTOV(zl->zl_znode));
2344168404Spjd		rw_exit(zl->zl_rwlock);
2345168404Spjd		*zlpp = zl->zl_next;
2346168404Spjd		kmem_free(zl, sizeof (*zl));
2347168404Spjd	}
2348168404Spjd}
2349168404Spjd
2350168404Spjd/*
2351168404Spjd * Search back through the directory tree, using the ".." entries.
2352168404Spjd * Lock each directory in the chain to prevent concurrent renames.
2353168404Spjd * Fail any attempt to move a directory into one of its own descendants.
2354168404Spjd * XXX - z_parent_lock can overlap with map or grow locks
2355168404Spjd */
2356168404Spjdstatic int
2357168404Spjdzfs_rename_lock(znode_t *szp, znode_t *tdzp, znode_t *sdzp, zfs_zlock_t **zlpp)
2358168404Spjd{
2359168404Spjd	zfs_zlock_t	*zl;
2360168404Spjd	znode_t		*zp = tdzp;
2361168404Spjd	uint64_t	rootid = zp->z_zfsvfs->z_root;
2362168404Spjd	uint64_t	*oidp = &zp->z_id;
2363168404Spjd	krwlock_t	*rwlp = &szp->z_parent_lock;
2364168404Spjd	krw_t		rw = RW_WRITER;
2365168404Spjd
2366168404Spjd	/*
2367168404Spjd	 * First pass write-locks szp and compares to zp->z_id.
2368168404Spjd	 * Later passes read-lock zp and compare to zp->z_parent.
2369168404Spjd	 */
2370168404Spjd	do {
2371168404Spjd		if (!rw_tryenter(rwlp, rw)) {
2372168404Spjd			/*
2373168404Spjd			 * Another thread is renaming in this path.
2374168404Spjd			 * Note that if we are a WRITER, we don't have any
2375168404Spjd			 * parent_locks held yet.
2376168404Spjd			 */
2377168404Spjd			if (rw == RW_READER && zp->z_id > szp->z_id) {
2378168404Spjd				/*
2379168404Spjd				 * Drop our locks and restart
2380168404Spjd				 */
2381168404Spjd				zfs_rename_unlock(&zl);
2382168404Spjd				*zlpp = NULL;
2383168404Spjd				zp = tdzp;
2384168404Spjd				oidp = &zp->z_id;
2385168404Spjd				rwlp = &szp->z_parent_lock;
2386168404Spjd				rw = RW_WRITER;
2387168404Spjd				continue;
2388168404Spjd			} else {
2389168404Spjd				/*
2390168404Spjd				 * Wait for other thread to drop its locks
2391168404Spjd				 */
2392168404Spjd				rw_enter(rwlp, rw);
2393168404Spjd			}
2394168404Spjd		}
2395168404Spjd
2396168404Spjd		zl = kmem_alloc(sizeof (*zl), KM_SLEEP);
2397168404Spjd		zl->zl_rwlock = rwlp;
2398168404Spjd		zl->zl_znode = NULL;
2399168404Spjd		zl->zl_next = *zlpp;
2400168404Spjd		*zlpp = zl;
2401168404Spjd
2402168404Spjd		if (*oidp == szp->z_id)		/* We're a descendant of szp */
2403168404Spjd			return (EINVAL);
2404168404Spjd
2405168404Spjd		if (*oidp == rootid)		/* We've hit the top */
2406168404Spjd			return (0);
2407168404Spjd
2408168404Spjd		if (rw == RW_READER) {		/* i.e. not the first pass */
2409168404Spjd			int error = zfs_zget(zp->z_zfsvfs, *oidp, &zp);
2410168404Spjd			if (error)
2411168404Spjd				return (error);
2412168404Spjd			zl->zl_znode = zp;
2413168404Spjd		}
2414168404Spjd		oidp = &zp->z_phys->zp_parent;
2415168404Spjd		rwlp = &zp->z_parent_lock;
2416168404Spjd		rw = RW_READER;
2417168404Spjd
2418168404Spjd	} while (zp->z_id != sdzp->z_id);
2419168404Spjd
2420168404Spjd	return (0);
2421168404Spjd}
2422168404Spjd
2423168404Spjd/*
2424168404Spjd * Move an entry from the provided source directory to the target
2425168404Spjd * directory.  Change the entry name as indicated.
2426168404Spjd *
2427168404Spjd *	IN:	sdvp	- Source directory containing the "old entry".
2428168404Spjd *		snm	- Old entry name.
2429168404Spjd *		tdvp	- Target directory to contain the "new entry".
2430168404Spjd *		tnm	- New entry name.
2431168404Spjd *		cr	- credentials of caller.
2432168404Spjd *
2433168404Spjd *	RETURN:	0 if success
2434168404Spjd *		error code if failure
2435168404Spjd *
2436168404Spjd * Timestamps:
2437168404Spjd *	sdvp,tdvp - ctime|mtime updated
2438168404Spjd */
2439168404Spjdstatic int
2440168962Spjdzfs_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm, cred_t *cr)
2441168404Spjd{
2442168404Spjd	znode_t		*tdzp, *szp, *tzp;
2443168404Spjd	znode_t		*sdzp = VTOZ(sdvp);
2444168404Spjd	zfsvfs_t	*zfsvfs = sdzp->z_zfsvfs;
2445168404Spjd	zilog_t		*zilog = zfsvfs->z_log;
2446168962Spjd	vnode_t		*realvp;
2447168404Spjd	zfs_dirlock_t	*sdl, *tdl;
2448168404Spjd	dmu_tx_t	*tx;
2449168404Spjd	zfs_zlock_t	*zl;
2450168962Spjd	int		cmp, serr, terr, error;
2451168404Spjd
2452168404Spjd	ZFS_ENTER(zfsvfs);
2453168404Spjd
2454168962Spjd	/*
2455168962Spjd	 * Make sure we have the real vp for the target directory.
2456168962Spjd	 */
2457168962Spjd	if (VOP_REALVP(tdvp, &realvp) == 0)
2458168962Spjd		tdvp = realvp;
2459168962Spjd
2460168404Spjd	if (tdvp->v_vfsp != sdvp->v_vfsp) {
2461168404Spjd		ZFS_EXIT(zfsvfs);
2462168962Spjd		return (EXDEV);
2463168404Spjd	}
2464168404Spjd
2465168404Spjd	tdzp = VTOZ(tdvp);
2466168404Spjdtop:
2467168404Spjd	szp = NULL;
2468168404Spjd	tzp = NULL;
2469168404Spjd	zl = NULL;
2470168404Spjd
2471168404Spjd	/*
2472168404Spjd	 * This is to prevent the creation of links into attribute space
2473168404Spjd	 * by renaming a linked file into/outof an attribute directory.
2474168404Spjd	 * See the comment in zfs_link() for why this is considered bad.
2475168404Spjd	 */
2476168404Spjd	if ((tdzp->z_phys->zp_flags & ZFS_XATTR) !=
2477168404Spjd	    (sdzp->z_phys->zp_flags & ZFS_XATTR)) {
2478168962Spjd		ZFS_EXIT(zfsvfs);
2479168962Spjd		return (EINVAL);
2480168404Spjd	}
2481168404Spjd
2482168404Spjd	/*
2483168404Spjd	 * Lock source and target directory entries.  To prevent deadlock,
2484168404Spjd	 * a lock ordering must be defined.  We lock the directory with
2485168404Spjd	 * the smallest object id first, or if it's a tie, the one with
2486168404Spjd	 * the lexically first name.
2487168404Spjd	 */
2488168404Spjd	if (sdzp->z_id < tdzp->z_id) {
2489168962Spjd		cmp = -1;
2490168962Spjd	} else if (sdzp->z_id > tdzp->z_id) {
2491168962Spjd		cmp = 1;
2492168962Spjd	} else {
2493168962Spjd		cmp = strcmp(snm, tnm);
2494168962Spjd		if (cmp == 0) {
2495168962Spjd			/*
2496168962Spjd			 * POSIX: "If the old argument and the new argument
2497168962Spjd			 * both refer to links to the same existing file,
2498168962Spjd			 * the rename() function shall return successfully
2499168962Spjd			 * and perform no other action."
2500168962Spjd			 */
2501168962Spjd			ZFS_EXIT(zfsvfs);
2502168962Spjd			return (0);
2503168962Spjd		}
2504168962Spjd	}
2505168962Spjd	if (cmp < 0) {
2506168404Spjd		serr = zfs_dirent_lock(&sdl, sdzp, snm, &szp, ZEXISTS);
2507168404Spjd		terr = zfs_dirent_lock(&tdl, tdzp, tnm, &tzp, 0);
2508168962Spjd	} else {
2509168404Spjd		terr = zfs_dirent_lock(&tdl, tdzp, tnm, &tzp, 0);
2510168404Spjd		serr = zfs_dirent_lock(&sdl, sdzp, snm, &szp, ZEXISTS);
2511168404Spjd	}
2512168404Spjd
2513168962Spjd	if (serr) {
2514168404Spjd		/*
2515168404Spjd		 * Source entry invalid or not there.
2516168404Spjd		 */
2517168962Spjd		if (!terr) {
2518168404Spjd			zfs_dirent_unlock(tdl);
2519168962Spjd			if (tzp)
2520168962Spjd				VN_RELE(ZTOV(tzp));
2521168962Spjd		}
2522168404Spjd		if (strcmp(snm, ".") == 0 || strcmp(snm, "..") == 0)
2523168404Spjd			serr = EINVAL;
2524168962Spjd		ZFS_EXIT(zfsvfs);
2525168962Spjd		return (serr);
2526168404Spjd	}
2527168404Spjd	if (terr) {
2528168404Spjd		zfs_dirent_unlock(sdl);
2529168962Spjd		VN_RELE(ZTOV(szp));
2530168404Spjd		if (strcmp(tnm, "..") == 0)
2531168404Spjd			terr = EINVAL;
2532168962Spjd		ZFS_EXIT(zfsvfs);
2533168962Spjd		return (terr);
2534168404Spjd	}
2535168404Spjd
2536168404Spjd	/*
2537168404Spjd	 * Must have write access at the source to remove the old entry
2538168404Spjd	 * and write access at the target to create the new entry.
2539168404Spjd	 * Note that if target and source are the same, this can be
2540168404Spjd	 * done in a single check.
2541168404Spjd	 */
2542168404Spjd
2543168404Spjd	if (error = zfs_zaccess_rename(sdzp, szp, tdzp, tzp, cr))
2544168404Spjd		goto out;
2545168404Spjd
2546168962Spjd	if (ZTOV(szp)->v_type == VDIR) {
2547168404Spjd		/*
2548168404Spjd		 * Check to make sure rename is valid.
2549168404Spjd		 * Can't do a move like this: /usr/a/b to /usr/a/b/c/d
2550168404Spjd		 */
2551168404Spjd		if (error = zfs_rename_lock(szp, tdzp, sdzp, &zl))
2552168404Spjd			goto out;
2553168404Spjd	}
2554168404Spjd
2555168404Spjd	/*
2556168404Spjd	 * Does target exist?
2557168404Spjd	 */
2558168404Spjd	if (tzp) {
2559168404Spjd		/*
2560168404Spjd		 * Source and target must be the same type.
2561168404Spjd		 */
2562168962Spjd		if (ZTOV(szp)->v_type == VDIR) {
2563168962Spjd			if (ZTOV(tzp)->v_type != VDIR) {
2564168404Spjd				error = ENOTDIR;
2565168404Spjd				goto out;
2566168404Spjd			}
2567168404Spjd		} else {
2568168962Spjd			if (ZTOV(tzp)->v_type == VDIR) {
2569168404Spjd				error = EISDIR;
2570168404Spjd				goto out;
2571168404Spjd			}
2572168404Spjd		}
2573168404Spjd		/*
2574168404Spjd		 * POSIX dictates that when the source and target
2575168404Spjd		 * entries refer to the same file object, rename
2576168404Spjd		 * must do nothing and exit without error.
2577168404Spjd		 */
2578168404Spjd		if (szp->z_id == tzp->z_id) {
2579168404Spjd			error = 0;
2580168404Spjd			goto out;
2581168404Spjd		}
2582168404Spjd	}
2583168404Spjd
2584168962Spjd	vnevent_rename_src(ZTOV(szp));
2585168962Spjd	if (tzp)
2586168962Spjd		vnevent_rename_dest(ZTOV(tzp));
2587168962Spjd
2588168404Spjd	tx = dmu_tx_create(zfsvfs->z_os);
2589168404Spjd	dmu_tx_hold_bonus(tx, szp->z_id);	/* nlink changes */
2590168404Spjd	dmu_tx_hold_bonus(tx, sdzp->z_id);	/* nlink changes */
2591168404Spjd	dmu_tx_hold_zap(tx, sdzp->z_id, FALSE, snm);
2592168404Spjd	dmu_tx_hold_zap(tx, tdzp->z_id, TRUE, tnm);
2593168404Spjd	if (sdzp != tdzp)
2594168404Spjd		dmu_tx_hold_bonus(tx, tdzp->z_id);	/* nlink changes */
2595168404Spjd	if (tzp)
2596168404Spjd		dmu_tx_hold_bonus(tx, tzp->z_id);	/* parent changes */
2597168404Spjd	dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL);
2598168404Spjd	error = dmu_tx_assign(tx, zfsvfs->z_assign);
2599168404Spjd	if (error) {
2600168404Spjd		if (zl != NULL)
2601168404Spjd			zfs_rename_unlock(&zl);
2602168404Spjd		zfs_dirent_unlock(sdl);
2603168404Spjd		zfs_dirent_unlock(tdl);
2604168962Spjd		VN_RELE(ZTOV(szp));
2605168962Spjd		if (tzp)
2606168962Spjd			VN_RELE(ZTOV(tzp));
2607168404Spjd		if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) {
2608168404Spjd			dmu_tx_wait(tx);
2609168404Spjd			dmu_tx_abort(tx);
2610168404Spjd			goto top;
2611168404Spjd		}
2612168404Spjd		dmu_tx_abort(tx);
2613168962Spjd		ZFS_EXIT(zfsvfs);
2614168962Spjd		return (error);
2615168404Spjd	}
2616168404Spjd
2617168404Spjd	if (tzp)	/* Attempt to remove the existing target */
2618168404Spjd		error = zfs_link_destroy(tdl, tzp, tx, 0, NULL);
2619168404Spjd
2620168404Spjd	if (error == 0) {
2621168404Spjd		error = zfs_link_create(tdl, szp, tx, ZRENAMING);
2622168404Spjd		if (error == 0) {
2623168404Spjd			error = zfs_link_destroy(sdl, szp, tx, ZRENAMING, NULL);
2624168404Spjd			ASSERT(error == 0);
2625168404Spjd			zfs_log_rename(zilog, tx, TX_RENAME, sdzp,
2626168404Spjd			    sdl->dl_name, tdzp, tdl->dl_name, szp);
2627168404Spjd		}
2628168404Spjd#ifdef FREEBSD_NAMECACHE
2629168404Spjd		if (error == 0) {
2630168404Spjd			cache_purge(sdvp);
2631168404Spjd			cache_purge(tdvp);
2632168404Spjd		}
2633168404Spjd#endif
2634168404Spjd	}
2635168404Spjd
2636168404Spjd	dmu_tx_commit(tx);
2637168404Spjdout:
2638168404Spjd	if (zl != NULL)
2639168404Spjd		zfs_rename_unlock(&zl);
2640168404Spjd
2641168404Spjd	zfs_dirent_unlock(sdl);
2642168404Spjd	zfs_dirent_unlock(tdl);
2643168404Spjd
2644168962Spjd	VN_RELE(ZTOV(szp));
2645168404Spjd	if (tzp)
2646168962Spjd		VN_RELE(ZTOV(tzp));
2647168404Spjd
2648168404Spjd	ZFS_EXIT(zfsvfs);
2649168404Spjd
2650168404Spjd	return (error);
2651168404Spjd}
2652168404Spjd
2653168404Spjd/*
2654168404Spjd * Insert the indicated symbolic reference entry into the directory.
2655168404Spjd *
2656168404Spjd *	IN:	dvp	- Directory to contain new symbolic link.
2657168404Spjd *		link	- Name for new symlink entry.
2658168404Spjd *		vap	- Attributes of new entry.
2659168404Spjd *		target	- Target path of new symlink.
2660168404Spjd *		cr	- credentials of caller.
2661168404Spjd *
2662168404Spjd *	RETURN:	0 if success
2663168404Spjd *		error code if failure
2664168404Spjd *
2665168404Spjd * Timestamps:
2666168404Spjd *	dvp - ctime|mtime updated
2667168404Spjd */
2668168404Spjdstatic int
2669168962Spjdzfs_symlink(vnode_t *dvp, vnode_t **vpp, char *name, vattr_t *vap, char *link, cred_t *cr, kthread_t *td)
2670168404Spjd{
2671168404Spjd	znode_t		*zp, *dzp = VTOZ(dvp);
2672168404Spjd	zfs_dirlock_t	*dl;
2673168404Spjd	dmu_tx_t	*tx;
2674168404Spjd	zfsvfs_t	*zfsvfs = dzp->z_zfsvfs;
2675168404Spjd	zilog_t		*zilog = zfsvfs->z_log;
2676168404Spjd	uint64_t	zoid;
2677168404Spjd	int		len = strlen(link);
2678168404Spjd	int		error;
2679168404Spjd
2680168962Spjd	ASSERT(vap->va_type == VLNK);
2681168404Spjd
2682168404Spjd	ZFS_ENTER(zfsvfs);
2683168404Spjdtop:
2684168404Spjd	if (error = zfs_zaccess(dzp, ACE_ADD_FILE, cr)) {
2685168404Spjd		ZFS_EXIT(zfsvfs);
2686168404Spjd		return (error);
2687168404Spjd	}
2688168404Spjd
2689168404Spjd	if (len > MAXPATHLEN) {
2690168404Spjd		ZFS_EXIT(zfsvfs);
2691168404Spjd		return (ENAMETOOLONG);
2692168404Spjd	}
2693168404Spjd
2694168404Spjd	/*
2695168404Spjd	 * Attempt to lock directory; fail if entry already exists.
2696168404Spjd	 */
2697168404Spjd	if (error = zfs_dirent_lock(&dl, dzp, name, &zp, ZNEW)) {
2698168404Spjd		ZFS_EXIT(zfsvfs);
2699168404Spjd		return (error);
2700168404Spjd	}
2701168404Spjd
2702168404Spjd	tx = dmu_tx_create(zfsvfs->z_os);
2703168404Spjd	dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, MAX(1, len));
2704168404Spjd	dmu_tx_hold_bonus(tx, dzp->z_id);
2705168404Spjd	dmu_tx_hold_zap(tx, dzp->z_id, TRUE, name);
2706168404Spjd	if (dzp->z_phys->zp_flags & ZFS_INHERIT_ACE)
2707168404Spjd		dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, SPA_MAXBLOCKSIZE);
2708168404Spjd	error = dmu_tx_assign(tx, zfsvfs->z_assign);
2709168404Spjd	if (error) {
2710168404Spjd		zfs_dirent_unlock(dl);
2711168404Spjd		if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) {
2712168404Spjd			dmu_tx_wait(tx);
2713168404Spjd			dmu_tx_abort(tx);
2714168404Spjd			goto top;
2715168404Spjd		}
2716168404Spjd		dmu_tx_abort(tx);
2717168404Spjd		ZFS_EXIT(zfsvfs);
2718168404Spjd		return (error);
2719168404Spjd	}
2720168404Spjd
2721168404Spjd	dmu_buf_will_dirty(dzp->z_dbuf, tx);
2722168404Spjd
2723168404Spjd	/*
2724168404Spjd	 * Create a new object for the symlink.
2725168404Spjd	 * Put the link content into bonus buffer if it will fit;
2726168404Spjd	 * otherwise, store it just like any other file data.
2727168404Spjd	 */
2728168404Spjd	zoid = 0;
2729168404Spjd	if (sizeof (znode_phys_t) + len <= dmu_bonus_max()) {
2730168404Spjd		zfs_mknode(dzp, vap, &zoid, tx, cr, 0, &zp, len);
2731168404Spjd		if (len != 0)
2732168404Spjd			bcopy(link, zp->z_phys + 1, len);
2733168404Spjd	} else {
2734168404Spjd		dmu_buf_t *dbp;
2735168404Spjd
2736168404Spjd		zfs_mknode(dzp, vap, &zoid, tx, cr, 0, &zp, 0);
2737168404Spjd
2738168404Spjd		/*
2739168404Spjd		 * Nothing can access the znode yet so no locking needed
2740168404Spjd		 * for growing the znode's blocksize.
2741168404Spjd		 */
2742168404Spjd		zfs_grow_blocksize(zp, len, tx);
2743168404Spjd
2744168404Spjd		VERIFY(0 == dmu_buf_hold(zfsvfs->z_os, zoid, 0, FTAG, &dbp));
2745168404Spjd		dmu_buf_will_dirty(dbp, tx);
2746168404Spjd
2747168404Spjd		ASSERT3U(len, <=, dbp->db_size);
2748168404Spjd		bcopy(link, dbp->db_data, len);
2749168404Spjd		dmu_buf_rele(dbp, FTAG);
2750168404Spjd	}
2751168404Spjd	zp->z_phys->zp_size = len;
2752168404Spjd
2753168404Spjd	/*
2754168404Spjd	 * Insert the new object into the directory.
2755168404Spjd	 */
2756168404Spjd	(void) zfs_link_create(dl, zp, tx, ZNEW);
2757168962Spjdout:
2758168404Spjd	if (error == 0) {
2759168404Spjd		zfs_log_symlink(zilog, tx, TX_SYMLINK, dzp, zp, name, link);
2760168962Spjd		*vpp = ZTOV(zp);
2761168962Spjd		vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, td);
2762168404Spjd	}
2763168404Spjd
2764168404Spjd	dmu_tx_commit(tx);
2765168404Spjd
2766168404Spjd	zfs_dirent_unlock(dl);
2767168404Spjd
2768168404Spjd	ZFS_EXIT(zfsvfs);
2769168404Spjd	return (error);
2770168404Spjd}
2771168404Spjd
2772168404Spjd/*
2773168404Spjd * Return, in the buffer contained in the provided uio structure,
2774168404Spjd * the symbolic path referred to by vp.
2775168404Spjd *
2776168404Spjd *	IN:	vp	- vnode of symbolic link.
2777168404Spjd *		uoip	- structure to contain the link path.
2778168404Spjd *		cr	- credentials of caller.
2779168404Spjd *
2780168404Spjd *	OUT:	uio	- structure to contain the link path.
2781168404Spjd *
2782168404Spjd *	RETURN:	0 if success
2783168404Spjd *		error code if failure
2784168404Spjd *
2785168404Spjd * Timestamps:
2786168404Spjd *	vp - atime updated
2787168404Spjd */
2788168404Spjd/* ARGSUSED */
2789168404Spjdstatic int
2790168962Spjdzfs_readlink(vnode_t *vp, uio_t *uio, cred_t *cr)
2791168404Spjd{
2792168404Spjd	znode_t		*zp = VTOZ(vp);
2793168404Spjd	zfsvfs_t	*zfsvfs = zp->z_zfsvfs;
2794168404Spjd	size_t		bufsz;
2795168404Spjd	int		error;
2796168404Spjd
2797168404Spjd	ZFS_ENTER(zfsvfs);
2798168404Spjd
2799168404Spjd	bufsz = (size_t)zp->z_phys->zp_size;
2800168404Spjd	if (bufsz + sizeof (znode_phys_t) <= zp->z_dbuf->db_size) {
2801168404Spjd		error = uiomove(zp->z_phys + 1,
2802168404Spjd		    MIN((size_t)bufsz, uio->uio_resid), UIO_READ, uio);
2803168404Spjd	} else {
2804168404Spjd		dmu_buf_t *dbp;
2805168404Spjd		error = dmu_buf_hold(zfsvfs->z_os, zp->z_id, 0, FTAG, &dbp);
2806168404Spjd		if (error) {
2807168404Spjd			ZFS_EXIT(zfsvfs);
2808168404Spjd			return (error);
2809168404Spjd		}
2810168404Spjd		error = uiomove(dbp->db_data,
2811168404Spjd		    MIN((size_t)bufsz, uio->uio_resid), UIO_READ, uio);
2812168404Spjd		dmu_buf_rele(dbp, FTAG);
2813168404Spjd	}
2814168404Spjd
2815168404Spjd	ZFS_ACCESSTIME_STAMP(zfsvfs, zp);
2816168404Spjd	ZFS_EXIT(zfsvfs);
2817168404Spjd	return (error);
2818168404Spjd}
2819168404Spjd
2820168404Spjd/*
2821168404Spjd * Insert a new entry into directory tdvp referencing svp.
2822168404Spjd *
2823168404Spjd *	IN:	tdvp	- Directory to contain new entry.
2824168404Spjd *		svp	- vnode of new entry.
2825168404Spjd *		name	- name of new entry.
2826168404Spjd *		cr	- credentials of caller.
2827168404Spjd *
2828168404Spjd *	RETURN:	0 if success
2829168404Spjd *		error code if failure
2830168404Spjd *
2831168404Spjd * Timestamps:
2832168404Spjd *	tdvp - ctime|mtime updated
2833168404Spjd *	 svp - ctime updated
2834168404Spjd */
2835168404Spjd/* ARGSUSED */
2836168404Spjdstatic int
2837168962Spjdzfs_link(vnode_t *tdvp, vnode_t *svp, char *name, cred_t *cr)
2838168404Spjd{
2839168404Spjd	znode_t		*dzp = VTOZ(tdvp);
2840168404Spjd	znode_t		*tzp, *szp;
2841168404Spjd	zfsvfs_t	*zfsvfs = dzp->z_zfsvfs;
2842168404Spjd	zilog_t		*zilog = zfsvfs->z_log;
2843168404Spjd	zfs_dirlock_t	*dl;
2844168404Spjd	dmu_tx_t	*tx;
2845168962Spjd	vnode_t		*realvp;
2846168404Spjd	int		error;
2847168404Spjd
2848168404Spjd	ASSERT(tdvp->v_type == VDIR);
2849168404Spjd
2850168404Spjd	ZFS_ENTER(zfsvfs);
2851168404Spjd
2852168962Spjd	if (VOP_REALVP(svp, &realvp) == 0)
2853168962Spjd		svp = realvp;
2854168962Spjd
2855168404Spjd	if (svp->v_vfsp != tdvp->v_vfsp) {
2856168404Spjd		ZFS_EXIT(zfsvfs);
2857168404Spjd		return (EXDEV);
2858168404Spjd	}
2859168404Spjd
2860168404Spjd	szp = VTOZ(svp);
2861168404Spjdtop:
2862168404Spjd	/*
2863168404Spjd	 * We do not support links between attributes and non-attributes
2864168404Spjd	 * because of the potential security risk of creating links
2865168404Spjd	 * into "normal" file space in order to circumvent restrictions
2866168404Spjd	 * imposed in attribute space.
2867168404Spjd	 */
2868168404Spjd	if ((szp->z_phys->zp_flags & ZFS_XATTR) !=
2869168404Spjd	    (dzp->z_phys->zp_flags & ZFS_XATTR)) {
2870168404Spjd		ZFS_EXIT(zfsvfs);
2871168404Spjd		return (EINVAL);
2872168404Spjd	}
2873168404Spjd
2874168404Spjd	/*
2875168404Spjd	 * POSIX dictates that we return EPERM here.
2876168404Spjd	 * Better choices include ENOTSUP or EISDIR.
2877168404Spjd	 */
2878168404Spjd	if (svp->v_type == VDIR) {
2879168404Spjd		ZFS_EXIT(zfsvfs);
2880168404Spjd		return (EPERM);
2881168404Spjd	}
2882168404Spjd
2883168404Spjd	if ((uid_t)szp->z_phys->zp_uid != crgetuid(cr) &&
2884168404Spjd	    secpolicy_basic_link(cr) != 0) {
2885168404Spjd		ZFS_EXIT(zfsvfs);
2886168404Spjd		return (EPERM);
2887168404Spjd	}
2888168404Spjd
2889168404Spjd	if (error = zfs_zaccess(dzp, ACE_ADD_FILE, cr)) {
2890168404Spjd		ZFS_EXIT(zfsvfs);
2891168404Spjd		return (error);
2892168404Spjd	}
2893168404Spjd
2894168404Spjd	/*
2895168404Spjd	 * Attempt to lock directory; fail if entry already exists.
2896168404Spjd	 */
2897168404Spjd	if (error = zfs_dirent_lock(&dl, dzp, name, &tzp, ZNEW)) {
2898168404Spjd		ZFS_EXIT(zfsvfs);
2899168404Spjd		return (error);
2900168404Spjd	}
2901168404Spjd
2902168404Spjd	tx = dmu_tx_create(zfsvfs->z_os);
2903168404Spjd	dmu_tx_hold_bonus(tx, szp->z_id);
2904168404Spjd	dmu_tx_hold_zap(tx, dzp->z_id, TRUE, name);
2905168404Spjd	error = dmu_tx_assign(tx, zfsvfs->z_assign);
2906168404Spjd	if (error) {
2907168404Spjd		zfs_dirent_unlock(dl);
2908168404Spjd		if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) {
2909168404Spjd			dmu_tx_wait(tx);
2910168404Spjd			dmu_tx_abort(tx);
2911168404Spjd			goto top;
2912168404Spjd		}
2913168404Spjd		dmu_tx_abort(tx);
2914168404Spjd		ZFS_EXIT(zfsvfs);
2915168404Spjd		return (error);
2916168404Spjd	}
2917168404Spjd
2918168404Spjd	error = zfs_link_create(dl, szp, tx, 0);
2919168404Spjd
2920168404Spjd	if (error == 0)
2921168404Spjd		zfs_log_link(zilog, tx, TX_LINK, dzp, szp, name);
2922168404Spjd
2923168404Spjd	dmu_tx_commit(tx);
2924168404Spjd
2925168404Spjd	zfs_dirent_unlock(dl);
2926168404Spjd
2927168404Spjd	ZFS_EXIT(zfsvfs);
2928168404Spjd	return (error);
2929168404Spjd}
2930168404Spjd
2931168962Spjdvoid
2932168962Spjdzfs_inactive(vnode_t *vp, cred_t *cr)
2933168404Spjd{
2934168962Spjd	znode_t	*zp = VTOZ(vp);
2935168962Spjd	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
2936168962Spjd	int error;
2937168404Spjd
2938168404Spjd	rw_enter(&zfsvfs->z_um_lock, RW_READER);
2939168404Spjd	if (zfsvfs->z_unmounted2) {
2940168404Spjd		ASSERT(zp->z_dbuf_held == 0);
2941168404Spjd
2942168404Spjd		mutex_enter(&zp->z_lock);
2943168404Spjd		VI_LOCK(vp);
2944168404Spjd		vp->v_count = 0; /* count arrives as 1 */
2945168404Spjd		VI_UNLOCK(vp);
2946168404Spjd		if (zp->z_dbuf == NULL) {
2947168404Spjd			mutex_exit(&zp->z_lock);
2948168404Spjd			zfs_znode_free(zp);
2949168404Spjd		} else {
2950168404Spjd			mutex_exit(&zp->z_lock);
2951168404Spjd		}
2952168404Spjd		rw_exit(&zfsvfs->z_um_lock);
2953168404Spjd		VFS_RELE(zfsvfs->z_vfs);
2954168962Spjd		return;
2955168404Spjd	}
2956168404Spjd
2957168404Spjd	if (zp->z_atime_dirty && zp->z_unlinked == 0) {
2958168404Spjd		dmu_tx_t *tx = dmu_tx_create(zfsvfs->z_os);
2959168404Spjd
2960168404Spjd		dmu_tx_hold_bonus(tx, zp->z_id);
2961168404Spjd		error = dmu_tx_assign(tx, TXG_WAIT);
2962168404Spjd		if (error) {
2963168404Spjd			dmu_tx_abort(tx);
2964168404Spjd		} else {
2965168404Spjd			dmu_buf_will_dirty(zp->z_dbuf, tx);
2966168404Spjd			mutex_enter(&zp->z_lock);
2967168404Spjd			zp->z_atime_dirty = 0;
2968168404Spjd			mutex_exit(&zp->z_lock);
2969168404Spjd			dmu_tx_commit(tx);
2970168404Spjd		}
2971168404Spjd	}
2972168404Spjd
2973168404Spjd	zfs_zinactive(zp);
2974168404Spjd	rw_exit(&zfsvfs->z_um_lock);
2975168404Spjd}
2976168404Spjd
2977168404SpjdCTASSERT(sizeof(struct zfid_short) <= sizeof(struct fid));
2978168404SpjdCTASSERT(sizeof(struct zfid_long) <= sizeof(struct fid));
2979168404Spjd
2980168404Spjdstatic int
2981168962Spjdzfs_fid(vnode_t *vp, fid_t *fidp)
2982168404Spjd{
2983168404Spjd	znode_t		*zp = VTOZ(vp);
2984168404Spjd	zfsvfs_t	*zfsvfs = zp->z_zfsvfs;
2985168404Spjd	uint32_t	gen = (uint32_t)zp->z_phys->zp_gen;
2986168404Spjd	uint64_t	object = zp->z_id;
2987168404Spjd	zfid_short_t	*zfid;
2988168404Spjd	int		size, i;
2989168404Spjd
2990168404Spjd	ZFS_ENTER(zfsvfs);
2991168404Spjd
2992168404Spjd	size = (zfsvfs->z_parent != zfsvfs) ? LONG_FID_LEN : SHORT_FID_LEN;
2993168404Spjd	fidp->fid_len = size;
2994168404Spjd
2995168404Spjd	zfid = (zfid_short_t *)fidp;
2996168404Spjd
2997168404Spjd	zfid->zf_len = size;
2998168404Spjd
2999168404Spjd	for (i = 0; i < sizeof (zfid->zf_object); i++)
3000168404Spjd		zfid->zf_object[i] = (uint8_t)(object >> (8 * i));
3001168404Spjd
3002168404Spjd	/* Must have a non-zero generation number to distinguish from .zfs */
3003168404Spjd	if (gen == 0)
3004168404Spjd		gen = 1;
3005168404Spjd	for (i = 0; i < sizeof (zfid->zf_gen); i++)
3006168404Spjd		zfid->zf_gen[i] = (uint8_t)(gen >> (8 * i));
3007168404Spjd
3008168404Spjd	if (size == LONG_FID_LEN) {
3009168404Spjd		uint64_t	objsetid = dmu_objset_id(zfsvfs->z_os);
3010169023Spjd		zfid_long_t	*zlfid;
3011168404Spjd
3012168404Spjd		zlfid = (zfid_long_t *)fidp;
3013168404Spjd
3014168404Spjd		for (i = 0; i < sizeof (zlfid->zf_setid); i++)
3015168404Spjd			zlfid->zf_setid[i] = (uint8_t)(objsetid >> (8 * i));
3016168404Spjd
3017168404Spjd		/* XXX - this should be the generation number for the objset */
3018168404Spjd		for (i = 0; i < sizeof (zlfid->zf_setgen); i++)
3019168404Spjd			zlfid->zf_setgen[i] = 0;
3020168404Spjd	}
3021168404Spjd
3022168404Spjd	ZFS_EXIT(zfsvfs);
3023168404Spjd	return (0);
3024168404Spjd}
3025168404Spjd
3026168404Spjdstatic int
3027168962Spjdzfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr)
3028168404Spjd{
3029168404Spjd	znode_t		*zp, *xzp;
3030168404Spjd	zfsvfs_t	*zfsvfs;
3031168404Spjd	zfs_dirlock_t	*dl;
3032168404Spjd	int		error;
3033168404Spjd
3034168404Spjd	switch (cmd) {
3035168404Spjd	case _PC_LINK_MAX:
3036168404Spjd		*valp = INT_MAX;
3037168404Spjd		return (0);
3038168404Spjd
3039168404Spjd	case _PC_FILESIZEBITS:
3040168404Spjd		*valp = 64;
3041168404Spjd		return (0);
3042168404Spjd
3043168404Spjd#if 0
3044168404Spjd	case _PC_XATTR_EXISTS:
3045168404Spjd		zp = VTOZ(vp);
3046168404Spjd		zfsvfs = zp->z_zfsvfs;
3047168404Spjd		ZFS_ENTER(zfsvfs);
3048168404Spjd		*valp = 0;
3049168404Spjd		error = zfs_dirent_lock(&dl, zp, "", &xzp,
3050168404Spjd		    ZXATTR | ZEXISTS | ZSHARED);
3051168404Spjd		if (error == 0) {
3052168404Spjd			zfs_dirent_unlock(dl);
3053168404Spjd			if (!zfs_dirempty(xzp))
3054168404Spjd				*valp = 1;
3055168404Spjd			VN_RELE(ZTOV(xzp));
3056168404Spjd		} else if (error == ENOENT) {
3057168404Spjd			/*
3058168404Spjd			 * If there aren't extended attributes, it's the
3059168404Spjd			 * same as having zero of them.
3060168404Spjd			 */
3061168404Spjd			error = 0;
3062168404Spjd		}
3063168404Spjd		ZFS_EXIT(zfsvfs);
3064168404Spjd		return (error);
3065168404Spjd#endif
3066168404Spjd
3067168404Spjd	case _PC_ACL_EXTENDED:
3068168404Spjd		*valp = 0;	/* TODO */
3069168404Spjd		return (0);
3070168404Spjd
3071168404Spjd	case _PC_MIN_HOLE_SIZE:
3072168404Spjd		*valp = (int)SPA_MINBLOCKSIZE;
3073168404Spjd		return (0);
3074168404Spjd
3075168404Spjd	default:
3076168962Spjd		return (EOPNOTSUPP);
3077168404Spjd	}
3078168404Spjd}
3079168404Spjd
3080168404Spjd#ifdef TODO
3081168404Spjd/*ARGSUSED*/
3082168404Spjdstatic int
3083168404Spjdzfs_getsecattr(vnode_t *vp, vsecattr_t *vsecp, int flag, cred_t *cr)
3084168404Spjd{
3085168404Spjd	znode_t *zp = VTOZ(vp);
3086168404Spjd	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
3087168404Spjd	int error;
3088168404Spjd
3089168404Spjd	ZFS_ENTER(zfsvfs);
3090168404Spjd	error = zfs_getacl(zp, vsecp, cr);
3091168404Spjd	ZFS_EXIT(zfsvfs);
3092168404Spjd
3093168404Spjd	return (error);
3094168404Spjd}
3095168404Spjd#endif	/* TODO */
3096168404Spjd
3097168404Spjd#ifdef TODO
3098168404Spjd/*ARGSUSED*/
3099168404Spjdstatic int
3100168404Spjdzfs_setsecattr(vnode_t *vp, vsecattr_t *vsecp, int flag, cred_t *cr)
3101168404Spjd{
3102168404Spjd	znode_t *zp = VTOZ(vp);
3103168404Spjd	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
3104168404Spjd	int error;
3105168404Spjd
3106168404Spjd	ZFS_ENTER(zfsvfs);
3107168404Spjd	error = zfs_setacl(zp, vsecp, cr);
3108168404Spjd	ZFS_EXIT(zfsvfs);
3109168404Spjd	return (error);
3110168404Spjd}
3111168404Spjd#endif	/* TODO */
3112168404Spjd
3113168962Spjdstatic int
3114168962Spjdzfs_freebsd_open(ap)
3115168962Spjd	struct vop_open_args /* {
3116168962Spjd		struct vnode *a_vp;
3117168962Spjd		int a_mode;
3118168962Spjd		struct ucred *a_cred;
3119168962Spjd		struct thread *a_td;
3120168962Spjd	} */ *ap;
3121168962Spjd{
3122168962Spjd	vnode_t	*vp = ap->a_vp;
3123168962Spjd	znode_t *zp = VTOZ(vp);
3124168962Spjd	int error;
3125168962Spjd
3126168962Spjd	error = zfs_open(&vp, ap->a_mode, ap->a_cred);
3127168962Spjd	if (error == 0)
3128168962Spjd		vnode_create_vobject(vp, zp->z_phys->zp_size, ap->a_td);
3129168962Spjd	return (error);
3130168962Spjd}
3131168962Spjd
3132168962Spjdstatic int
3133168962Spjdzfs_freebsd_close(ap)
3134168962Spjd	struct vop_close_args /* {
3135168962Spjd		struct vnode *a_vp;
3136168962Spjd		int  a_fflag;
3137168962Spjd		struct ucred *a_cred;
3138168962Spjd		struct thread *a_td;
3139168962Spjd	} */ *ap;
3140168962Spjd{
3141168962Spjd
3142168962Spjd	return (zfs_close(ap->a_vp, ap->a_fflag, 0, 0, ap->a_cred));
3143168962Spjd}
3144168962Spjd
3145168962Spjdstatic int
3146168962Spjdzfs_freebsd_ioctl(ap)
3147168962Spjd	struct vop_ioctl_args /* {
3148168962Spjd		struct vnode *a_vp;
3149168962Spjd		u_long a_command;
3150168962Spjd		caddr_t a_data;
3151168962Spjd		int a_fflag;
3152168962Spjd		struct ucred *cred;
3153168962Spjd		struct thread *td;
3154168962Spjd	} */ *ap;
3155168962Spjd{
3156168962Spjd
3157168978Spjd	return (zfs_ioctl(ap->a_vp, ap->a_command, (intptr_t)ap->a_data,
3158168962Spjd	    ap->a_fflag, ap->a_cred, NULL));
3159168962Spjd}
3160168962Spjd
3161168962Spjdstatic int
3162168962Spjdzfs_freebsd_read(ap)
3163168962Spjd	struct vop_read_args /* {
3164168962Spjd		struct vnode *a_vp;
3165168962Spjd		struct uio *a_uio;
3166168962Spjd		int a_ioflag;
3167168962Spjd		struct ucred *a_cred;
3168168962Spjd	} */ *ap;
3169168962Spjd{
3170168962Spjd
3171168962Spjd	return (zfs_read(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred, NULL));
3172168962Spjd}
3173168962Spjd
3174168962Spjdstatic int
3175168962Spjdzfs_freebsd_write(ap)
3176168962Spjd	struct vop_write_args /* {
3177168962Spjd		struct vnode *a_vp;
3178168962Spjd		struct uio *a_uio;
3179168962Spjd		int a_ioflag;
3180168962Spjd		struct ucred *a_cred;
3181168962Spjd	} */ *ap;
3182168962Spjd{
3183168962Spjd
3184168962Spjd	return (zfs_write(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred, NULL));
3185168962Spjd}
3186168962Spjd
3187168962Spjdstatic int
3188168962Spjdzfs_freebsd_access(ap)
3189168962Spjd	struct vop_access_args /* {
3190168962Spjd		struct vnode *a_vp;
3191168962Spjd		int  a_mode;
3192168962Spjd		struct ucred *a_cred;
3193168962Spjd		struct thread *a_td;
3194168962Spjd	} */ *ap;
3195168962Spjd{
3196168962Spjd
3197168962Spjd	return (zfs_access(ap->a_vp, ap->a_mode, 0, ap->a_cred));
3198168962Spjd}
3199168962Spjd
3200168962Spjdstatic int
3201168962Spjdzfs_freebsd_lookup(ap)
3202168962Spjd	struct vop_lookup_args /* {
3203168962Spjd		struct vnode *a_dvp;
3204168962Spjd		struct vnode **a_vpp;
3205168962Spjd		struct componentname *a_cnp;
3206168962Spjd	} */ *ap;
3207168962Spjd{
3208168962Spjd	struct componentname *cnp = ap->a_cnp;
3209168962Spjd	char nm[NAME_MAX + 1];
3210168962Spjd
3211168962Spjd	ASSERT(cnp->cn_namelen < sizeof(nm));
3212168962Spjd	strlcpy(nm, cnp->cn_nameptr, MIN(cnp->cn_namelen + 1, sizeof(nm)));
3213168962Spjd
3214168962Spjd	return (zfs_lookup(ap->a_dvp, nm, ap->a_vpp, cnp, cnp->cn_nameiop,
3215168962Spjd	    cnp->cn_cred, cnp->cn_thread));
3216168962Spjd}
3217168962Spjd
3218168962Spjdstatic int
3219168962Spjdzfs_freebsd_create(ap)
3220168962Spjd	struct vop_create_args /* {
3221168962Spjd		struct vnode *a_dvp;
3222168962Spjd		struct vnode **a_vpp;
3223168962Spjd		struct componentname *a_cnp;
3224168962Spjd		struct vattr *a_vap;
3225168962Spjd	} */ *ap;
3226168962Spjd{
3227168962Spjd	struct componentname *cnp = ap->a_cnp;
3228168962Spjd	vattr_t *vap = ap->a_vap;
3229168962Spjd	int mode;
3230168962Spjd
3231168962Spjd	ASSERT(cnp->cn_flags & SAVENAME);
3232168962Spjd
3233168962Spjd	vattr_init_mask(vap);
3234168962Spjd	mode = vap->va_mode & ALLPERMS;
3235168962Spjd
3236168962Spjd	return (zfs_create(ap->a_dvp, cnp->cn_nameptr, vap, !EXCL, mode,
3237168962Spjd	    ap->a_vpp, cnp->cn_cred, cnp->cn_thread));
3238168962Spjd}
3239168962Spjd
3240168962Spjdstatic int
3241168962Spjdzfs_freebsd_remove(ap)
3242168962Spjd	struct vop_remove_args /* {
3243168962Spjd		struct vnode *a_dvp;
3244168962Spjd		struct vnode *a_vp;
3245168962Spjd		struct componentname *a_cnp;
3246168962Spjd	} */ *ap;
3247168962Spjd{
3248168962Spjd
3249168962Spjd	ASSERT(ap->a_cnp->cn_flags & SAVENAME);
3250168962Spjd
3251168962Spjd	return (zfs_remove(ap->a_dvp, ap->a_cnp->cn_nameptr,
3252168962Spjd	    ap->a_cnp->cn_cred));
3253168962Spjd}
3254168962Spjd
3255168962Spjdstatic int
3256168962Spjdzfs_freebsd_mkdir(ap)
3257168962Spjd	struct vop_mkdir_args /* {
3258168962Spjd		struct vnode *a_dvp;
3259168962Spjd		struct vnode **a_vpp;
3260168962Spjd		struct componentname *a_cnp;
3261168962Spjd		struct vattr *a_vap;
3262168962Spjd	} */ *ap;
3263168962Spjd{
3264168962Spjd	vattr_t *vap = ap->a_vap;
3265168962Spjd
3266168962Spjd	ASSERT(ap->a_cnp->cn_flags & SAVENAME);
3267168962Spjd
3268168962Spjd	vattr_init_mask(vap);
3269168962Spjd
3270168962Spjd	return (zfs_mkdir(ap->a_dvp, ap->a_cnp->cn_nameptr, vap, ap->a_vpp,
3271168962Spjd	    ap->a_cnp->cn_cred));
3272168962Spjd}
3273168962Spjd
3274168962Spjdstatic int
3275168962Spjdzfs_freebsd_rmdir(ap)
3276168962Spjd	struct vop_rmdir_args /* {
3277168962Spjd		struct vnode *a_dvp;
3278168962Spjd		struct vnode *a_vp;
3279168962Spjd		struct componentname *a_cnp;
3280168962Spjd	} */ *ap;
3281168962Spjd{
3282168962Spjd	struct componentname *cnp = ap->a_cnp;
3283168962Spjd
3284168962Spjd	ASSERT(cnp->cn_flags & SAVENAME);
3285168962Spjd
3286168962Spjd	return (zfs_rmdir(ap->a_dvp, cnp->cn_nameptr, NULL, cnp->cn_cred));
3287168962Spjd}
3288168962Spjd
3289168962Spjdstatic int
3290168962Spjdzfs_freebsd_readdir(ap)
3291168962Spjd	struct vop_readdir_args /* {
3292168962Spjd		struct vnode *a_vp;
3293168962Spjd		struct uio *a_uio;
3294168962Spjd		struct ucred *a_cred;
3295168962Spjd		int *a_eofflag;
3296168962Spjd		int *a_ncookies;
3297168962Spjd		u_long **a_cookies;
3298168962Spjd	} */ *ap;
3299168962Spjd{
3300168962Spjd
3301168962Spjd	return (zfs_readdir(ap->a_vp, ap->a_uio, ap->a_cred, ap->a_eofflag,
3302168962Spjd	    ap->a_ncookies, ap->a_cookies));
3303168962Spjd}
3304168962Spjd
3305168962Spjdstatic int
3306168962Spjdzfs_freebsd_fsync(ap)
3307168962Spjd	struct vop_fsync_args /* {
3308168962Spjd		struct vnode *a_vp;
3309168962Spjd		int a_waitfor;
3310168962Spjd		struct thread *a_td;
3311168962Spjd	} */ *ap;
3312168962Spjd{
3313168962Spjd
3314168962Spjd	vop_stdfsync(ap);
3315168962Spjd	return (zfs_fsync(ap->a_vp, 0, ap->a_td->td_ucred));
3316168962Spjd}
3317168962Spjd
3318168962Spjdstatic int
3319168962Spjdzfs_freebsd_getattr(ap)
3320168962Spjd	struct vop_getattr_args /* {
3321168962Spjd		struct vnode *a_vp;
3322168962Spjd		struct vattr *a_vap;
3323168962Spjd		struct ucred *a_cred;
3324168962Spjd		struct thread *a_td;
3325168962Spjd	} */ *ap;
3326168962Spjd{
3327168962Spjd
3328168962Spjd	return (zfs_getattr(ap->a_vp, ap->a_vap, 0, ap->a_cred));
3329168962Spjd}
3330168962Spjd
3331168962Spjdstatic int
3332168962Spjdzfs_freebsd_setattr(ap)
3333168962Spjd	struct vop_setattr_args /* {
3334168962Spjd		struct vnode *a_vp;
3335168962Spjd		struct vattr *a_vap;
3336168962Spjd		struct ucred *a_cred;
3337168962Spjd		struct thread *a_td;
3338168962Spjd	} */ *ap;
3339168962Spjd{
3340168962Spjd	vattr_t *vap = ap->a_vap;
3341168962Spjd
3342168962Spjd	/* No support for FreeBSD's chflags(2). */
3343168962Spjd	if (vap->va_flags != VNOVAL)
3344168962Spjd		return (EOPNOTSUPP);
3345168962Spjd
3346168962Spjd	vattr_init_mask(vap);
3347168962Spjd
3348168962Spjd	return (zfs_setattr(ap->a_vp, vap, 0, ap->a_cred, NULL));
3349168962Spjd}
3350168962Spjd
3351168962Spjdstatic int
3352168962Spjdzfs_freebsd_rename(ap)
3353168962Spjd	struct vop_rename_args  /* {
3354168962Spjd		struct vnode *a_fdvp;
3355168962Spjd		struct vnode *a_fvp;
3356168962Spjd		struct componentname *a_fcnp;
3357168962Spjd		struct vnode *a_tdvp;
3358168962Spjd		struct vnode *a_tvp;
3359168962Spjd		struct componentname *a_tcnp;
3360168962Spjd	} */ *ap;
3361168962Spjd{
3362168962Spjd	vnode_t *fdvp = ap->a_fdvp;
3363168962Spjd	vnode_t *fvp = ap->a_fvp;
3364168962Spjd	vnode_t *tdvp = ap->a_tdvp;
3365168962Spjd	vnode_t *tvp = ap->a_tvp;
3366168962Spjd	int error;
3367168962Spjd
3368168962Spjd	ASSERT(ap->a_fcnp->cn_flags & SAVENAME);
3369168962Spjd	ASSERT(ap->a_tcnp->cn_flags & SAVENAME);
3370168962Spjd
3371168962Spjd	error = zfs_rename(fdvp, ap->a_fcnp->cn_nameptr, tdvp,
3372168962Spjd	    ap->a_tcnp->cn_nameptr, ap->a_fcnp->cn_cred);
3373168962Spjd
3374168962Spjd	if (tdvp == tvp)
3375168962Spjd		VN_RELE(tdvp);
3376168962Spjd	else
3377168962Spjd		VN_URELE(tdvp);
3378168962Spjd	if (tvp)
3379168962Spjd		VN_URELE(tvp);
3380168962Spjd	VN_RELE(fdvp);
3381168962Spjd	VN_RELE(fvp);
3382168962Spjd
3383168962Spjd	return (error);
3384168962Spjd}
3385168962Spjd
3386168962Spjdstatic int
3387168962Spjdzfs_freebsd_symlink(ap)
3388168962Spjd	struct vop_symlink_args /* {
3389168962Spjd		struct vnode *a_dvp;
3390168962Spjd		struct vnode **a_vpp;
3391168962Spjd		struct componentname *a_cnp;
3392168962Spjd		struct vattr *a_vap;
3393168962Spjd		char *a_target;
3394168962Spjd	} */ *ap;
3395168962Spjd{
3396168962Spjd	struct componentname *cnp = ap->a_cnp;
3397168962Spjd	vattr_t *vap = ap->a_vap;
3398168962Spjd
3399168962Spjd	ASSERT(cnp->cn_flags & SAVENAME);
3400168962Spjd
3401168962Spjd	vap->va_type = VLNK;	/* FreeBSD: Syscall only sets va_mode. */
3402168962Spjd	vattr_init_mask(vap);
3403168962Spjd
3404168962Spjd	return (zfs_symlink(ap->a_dvp, ap->a_vpp, cnp->cn_nameptr, vap,
3405168962Spjd	    ap->a_target, cnp->cn_cred, cnp->cn_thread));
3406168962Spjd}
3407168962Spjd
3408168962Spjdstatic int
3409168962Spjdzfs_freebsd_readlink(ap)
3410168962Spjd	struct vop_readlink_args /* {
3411168962Spjd		struct vnode *a_vp;
3412168962Spjd		struct uio *a_uio;
3413168962Spjd		struct ucred *a_cred;
3414168962Spjd	} */ *ap;
3415168962Spjd{
3416168962Spjd
3417168962Spjd	return (zfs_readlink(ap->a_vp, ap->a_uio, ap->a_cred));
3418168962Spjd}
3419168962Spjd
3420168962Spjdstatic int
3421168962Spjdzfs_freebsd_link(ap)
3422168962Spjd	struct vop_link_args /* {
3423168962Spjd		struct vnode *a_tdvp;
3424168962Spjd		struct vnode *a_vp;
3425168962Spjd		struct componentname *a_cnp;
3426168962Spjd	} */ *ap;
3427168962Spjd{
3428168962Spjd	struct componentname *cnp = ap->a_cnp;
3429168962Spjd
3430168962Spjd	ASSERT(cnp->cn_flags & SAVENAME);
3431168962Spjd
3432168962Spjd	return (zfs_link(ap->a_tdvp, ap->a_vp, cnp->cn_nameptr, cnp->cn_cred));
3433168962Spjd}
3434168962Spjd
3435168962Spjdstatic int
3436168962Spjdzfs_freebsd_inactive(ap)
3437168962Spjd        struct vop_inactive_args /* {
3438168962Spjd                struct vnode *a_vp;
3439168962Spjd                struct thread *a_td;
3440168962Spjd        } */ *ap;
3441168962Spjd{
3442168962Spjd	vnode_t *vp = ap->a_vp;
3443168962Spjd
3444168962Spjd	zfs_inactive(vp, ap->a_td->td_ucred);
3445168962Spjd	return (0);
3446168962Spjd}
3447168962Spjd
3448168962Spjdstatic int
3449168962Spjdzfs_freebsd_reclaim(ap)
3450168962Spjd	struct vop_reclaim_args /* {
3451168962Spjd		struct vnode *a_vp;
3452168962Spjd		struct thread *a_td;
3453168962Spjd	} */ *ap;
3454168962Spjd{
3455169025Spjd        vnode_t	*vp = ap->a_vp;
3456168962Spjd	znode_t	*zp = VTOZ(vp);
3457169025Spjd	zfsvfs_t *zfsvfs;
3458169025Spjd	int rele = 1;
3459168962Spjd
3460169025Spjd	ASSERT(zp != NULL);
3461169025Spjd
3462168962Spjd	/*
3463168962Spjd	 * Destroy the vm object and flush associated pages.
3464168962Spjd	 */
3465168962Spjd	vnode_destroy_vobject(vp);
3466169025Spjd
3467169025Spjd	mutex_enter(&zp->z_lock);
3468169025Spjd	ASSERT(zp->z_phys);
3469169025Spjd	ASSERT(zp->z_dbuf_held);
3470169025Spjd	zfsvfs = zp->z_zfsvfs;
3471169025Spjd	if (!zp->z_unlinked) {
3472169025Spjd		zp->z_dbuf_held = 0;
3473169025Spjd		ZTOV(zp) = NULL;
3474169025Spjd		mutex_exit(&zp->z_lock);
3475169025Spjd		dmu_buf_rele(zp->z_dbuf, NULL);
3476169025Spjd	} else {
3477169025Spjd		mutex_exit(&zp->z_lock);
3478169025Spjd	}
3479168962Spjd	VI_LOCK(vp);
3480169025Spjd	if (vp->v_count > 0)
3481169025Spjd		rele = 0;
3482168962Spjd	vp->v_data = NULL;
3483168962Spjd	ASSERT(vp->v_holdcnt > 1);
3484168962Spjd	vdropl(vp);
3485169025Spjd	if (!zp->z_unlinked && rele)
3486169025Spjd		VFS_RELE(zfsvfs->z_vfs);
3487168962Spjd	return (0);
3488168962Spjd}
3489168962Spjd
3490168962Spjdstatic int
3491168962Spjdzfs_freebsd_fid(ap)
3492168962Spjd	struct vop_fid_args /* {
3493168962Spjd		struct vnode *a_vp;
3494168962Spjd		struct fid *a_fid;
3495168962Spjd	} */ *ap;
3496168962Spjd{
3497168962Spjd
3498168962Spjd	return (zfs_fid(ap->a_vp, (void *)ap->a_fid));
3499168962Spjd}
3500168962Spjd
3501168962Spjdstatic int
3502168962Spjdzfs_freebsd_pathconf(ap)
3503168962Spjd	struct vop_pathconf_args /* {
3504168962Spjd		struct vnode *a_vp;
3505168962Spjd		int a_name;
3506168962Spjd		register_t *a_retval;
3507168962Spjd	} */ *ap;
3508168962Spjd{
3509168962Spjd	ulong_t val;
3510168962Spjd	int error;
3511168962Spjd
3512168962Spjd	error = zfs_pathconf(ap->a_vp, ap->a_name, &val, curthread->td_ucred);
3513168962Spjd	if (error == 0)
3514168962Spjd		*ap->a_retval = val;
3515168962Spjd	else if (error == EOPNOTSUPP)
3516168962Spjd		error = vop_stdpathconf(ap);
3517168962Spjd	return (error);
3518168962Spjd}
3519168962Spjd
3520168404Spjd/*
3521168404Spjd * Advisory record locking support
3522168404Spjd */
3523168404Spjdstatic int
3524168962Spjdzfs_freebsd_advlock(ap)
3525168404Spjd	struct vop_advlock_args /* {
3526168404Spjd		struct vnode *a_vp;
3527168404Spjd		caddr_t  a_id;
3528168404Spjd		int  a_op;
3529168404Spjd		struct flock *a_fl;
3530168404Spjd		int  a_flags;
3531168404Spjd	} */ *ap;
3532168404Spjd{
3533168404Spjd	znode_t	*zp = VTOZ(ap->a_vp);
3534168404Spjd
3535168404Spjd	return (lf_advlock(ap, &(zp->z_lockf), zp->z_phys->zp_size));
3536168404Spjd}
3537168404Spjd
3538168404Spjdstruct vop_vector zfs_vnodeops;
3539168404Spjdstruct vop_vector zfs_fifoops;
3540168404Spjd
3541168404Spjdstruct vop_vector zfs_vnodeops = {
3542168404Spjd	.vop_default =	&default_vnodeops,
3543168962Spjd	.vop_inactive =	zfs_freebsd_inactive,
3544168962Spjd	.vop_reclaim =	zfs_freebsd_reclaim,
3545168962Spjd	.vop_access =	zfs_freebsd_access,
3546168404Spjd#ifdef FREEBSD_NAMECACHE
3547168404Spjd	.vop_lookup =	vfs_cache_lookup,
3548168962Spjd	.vop_cachedlookup = zfs_freebsd_lookup,
3549168404Spjd#else
3550168962Spjd	.vop_lookup =	zfs_freebsd_lookup,
3551168404Spjd#endif
3552168962Spjd	.vop_getattr =	zfs_freebsd_getattr,
3553168962Spjd	.vop_setattr =	zfs_freebsd_setattr,
3554168962Spjd	.vop_create =	zfs_freebsd_create,
3555168962Spjd	.vop_mknod =	zfs_freebsd_create,
3556168962Spjd	.vop_mkdir =	zfs_freebsd_mkdir,
3557168962Spjd	.vop_readdir =	zfs_freebsd_readdir,
3558168962Spjd	.vop_fsync =	zfs_freebsd_fsync,
3559168962Spjd	.vop_open =	zfs_freebsd_open,
3560168962Spjd	.vop_close =	zfs_freebsd_close,
3561168962Spjd	.vop_rmdir =	zfs_freebsd_rmdir,
3562168962Spjd	.vop_ioctl =	zfs_freebsd_ioctl,
3563168962Spjd	.vop_link =	zfs_freebsd_link,
3564168962Spjd	.vop_symlink =	zfs_freebsd_symlink,
3565168962Spjd	.vop_readlink =	zfs_freebsd_readlink,
3566168962Spjd	.vop_read =	zfs_freebsd_read,
3567168962Spjd	.vop_write =	zfs_freebsd_write,
3568168962Spjd	.vop_remove =	zfs_freebsd_remove,
3569168962Spjd	.vop_rename =	zfs_freebsd_rename,
3570168962Spjd	.vop_advlock =	zfs_freebsd_advlock,
3571168962Spjd	.vop_pathconf =	zfs_freebsd_pathconf,
3572168404Spjd	.vop_bmap =	VOP_EOPNOTSUPP,
3573168962Spjd	.vop_fid =	zfs_freebsd_fid,
3574168404Spjd};
3575168404Spjd
3576168404Spjdstruct vop_vector zfs_fifoops = {
3577168404Spjd	.vop_default =	&fifo_specops,
3578168404Spjd	.vop_fsync =	VOP_PANIC,
3579168962Spjd	.vop_access =	zfs_freebsd_access,
3580168962Spjd	.vop_getattr =	zfs_freebsd_getattr,
3581168962Spjd	.vop_inactive =	zfs_freebsd_inactive,
3582168404Spjd	.vop_read =	VOP_PANIC,
3583168962Spjd	.vop_reclaim =	zfs_freebsd_reclaim,
3584168962Spjd	.vop_setattr =	zfs_freebsd_setattr,
3585168404Spjd	.vop_write =	VOP_PANIC,
3586168962Spjd	.vop_fid =	zfs_freebsd_fid,
3587168404Spjd};
3588