zfs_vnops.c revision 176559
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
26169195Spjd/* Portions Copyright 2007 Jeremy Teo */
27169195Spjd
28168404Spjd#pragma ident	"%Z%%M%	%I%	%E% SMI"
29168404Spjd
30168404Spjd#include <sys/types.h>
31168404Spjd#include <sys/param.h>
32168404Spjd#include <sys/time.h>
33168404Spjd#include <sys/systm.h>
34168404Spjd#include <sys/sysmacros.h>
35168404Spjd#include <sys/resource.h>
36168404Spjd#include <sys/vfs.h>
37168404Spjd#include <sys/vnode.h>
38168404Spjd#include <sys/file.h>
39168404Spjd#include <sys/stat.h>
40168404Spjd#include <sys/kmem.h>
41168404Spjd#include <sys/taskq.h>
42168404Spjd#include <sys/uio.h>
43168404Spjd#include <sys/atomic.h>
44168404Spjd#include <sys/namei.h>
45168404Spjd#include <sys/mman.h>
46168404Spjd#include <sys/cmn_err.h>
47168404Spjd#include <sys/errno.h>
48168404Spjd#include <sys/unistd.h>
49168404Spjd#include <sys/zfs_vfsops.h>
50168404Spjd#include <sys/zfs_dir.h>
51168404Spjd#include <sys/zfs_acl.h>
52168404Spjd#include <sys/zfs_ioctl.h>
53168404Spjd#include <sys/fs/zfs.h>
54168404Spjd#include <sys/dmu.h>
55168404Spjd#include <sys/spa.h>
56168404Spjd#include <sys/txg.h>
57168404Spjd#include <sys/dbuf.h>
58168404Spjd#include <sys/zap.h>
59168404Spjd#include <sys/dirent.h>
60168962Spjd#include <sys/policy.h>
61168962Spjd#include <sys/sunddi.h>
62168404Spjd#include <sys/filio.h>
63168404Spjd#include <sys/zfs_ctldir.h>
64168404Spjd#include <sys/dnlc.h>
65168404Spjd#include <sys/zfs_rlock.h>
66168404Spjd#include <sys/bio.h>
67168404Spjd#include <sys/buf.h>
68168404Spjd#include <sys/sf_buf.h>
69168404Spjd#include <sys/sched.h>
70168404Spjd
71168404Spjd/*
72168404Spjd * Programming rules.
73168404Spjd *
74168404Spjd * Each vnode op performs some logical unit of work.  To do this, the ZPL must
75168404Spjd * properly lock its in-core state, create a DMU transaction, do the work,
76168404Spjd * record this work in the intent log (ZIL), commit the DMU transaction,
77168404Spjd * and wait the the intent log to commit if it's is a synchronous operation.
78168404Spjd * Morover, the vnode ops must work in both normal and log replay context.
79168404Spjd * The ordering of events is important to avoid deadlocks and references
80168404Spjd * to freed memory.  The example below illustrates the following Big Rules:
81168404Spjd *
82168404Spjd *  (1) A check must be made in each zfs thread for a mounted file system.
83168404Spjd *	This is done avoiding races using ZFS_ENTER(zfsvfs).
84168404Spjd *	A ZFS_EXIT(zfsvfs) is needed before all returns.
85168404Spjd *
86168404Spjd *  (2)	VN_RELE() should always be the last thing except for zil_commit()
87168404Spjd *	(if necessary) and ZFS_EXIT(). This is for 3 reasons:
88168404Spjd *	First, if it's the last reference, the vnode/znode
89168404Spjd *	can be freed, so the zp may point to freed memory.  Second, the last
90168404Spjd *	reference will call zfs_zinactive(), which may induce a lot of work --
91168404Spjd *	pushing cached pages (which acquires range locks) and syncing out
92168404Spjd *	cached atime changes.  Third, zfs_zinactive() may require a new tx,
93168404Spjd *	which could deadlock the system if you were already holding one.
94168404Spjd *
95168404Spjd *  (3)	All range locks must be grabbed before calling dmu_tx_assign(),
96168404Spjd *	as they can span dmu_tx_assign() calls.
97168404Spjd *
98168404Spjd *  (4)	Always pass zfsvfs->z_assign as the second argument to dmu_tx_assign().
99168404Spjd *	In normal operation, this will be TXG_NOWAIT.  During ZIL replay,
100168404Spjd *	it will be a specific txg.  Either way, dmu_tx_assign() never blocks.
101168404Spjd *	This is critical because we don't want to block while holding locks.
102168404Spjd *	Note, in particular, that if a lock is sometimes acquired before
103168404Spjd *	the tx assigns, and sometimes after (e.g. z_lock), then failing to
104168404Spjd *	use a non-blocking assign can deadlock the system.  The scenario:
105168404Spjd *
106168404Spjd *	Thread A has grabbed a lock before calling dmu_tx_assign().
107168404Spjd *	Thread B is in an already-assigned tx, and blocks for this lock.
108168404Spjd *	Thread A calls dmu_tx_assign(TXG_WAIT) and blocks in txg_wait_open()
109168404Spjd *	forever, because the previous txg can't quiesce until B's tx commits.
110168404Spjd *
111168404Spjd *	If dmu_tx_assign() returns ERESTART and zfsvfs->z_assign is TXG_NOWAIT,
112168404Spjd *	then drop all locks, call dmu_tx_wait(), and try again.
113168404Spjd *
114168404Spjd *  (5)	If the operation succeeded, generate the intent log entry for it
115168404Spjd *	before dropping locks.  This ensures that the ordering of events
116168404Spjd *	in the intent log matches the order in which they actually occurred.
117168404Spjd *
118168404Spjd *  (6)	At the end of each vnode op, the DMU tx must always commit,
119168404Spjd *	regardless of whether there were any errors.
120168404Spjd *
121168404Spjd *  (7)	After dropping all locks, invoke zil_commit(zilog, seq, foid)
122168404Spjd *	to ensure that synchronous semantics are provided when necessary.
123168404Spjd *
124168404Spjd * In general, this is how things should be ordered in each vnode op:
125168404Spjd *
126168404Spjd *	ZFS_ENTER(zfsvfs);		// exit if unmounted
127168404Spjd * top:
128168404Spjd *	zfs_dirent_lock(&dl, ...)	// lock directory entry (may VN_HOLD())
129168404Spjd *	rw_enter(...);			// grab any other locks you need
130168404Spjd *	tx = dmu_tx_create(...);	// get DMU tx
131168404Spjd *	dmu_tx_hold_*();		// hold each object you might modify
132168404Spjd *	error = dmu_tx_assign(tx, zfsvfs->z_assign);	// try to assign
133168404Spjd *	if (error) {
134168404Spjd *		rw_exit(...);		// drop locks
135168404Spjd *		zfs_dirent_unlock(dl);	// unlock directory entry
136168404Spjd *		VN_RELE(...);		// release held vnodes
137168404Spjd *		if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) {
138168404Spjd *			dmu_tx_wait(tx);
139168404Spjd *			dmu_tx_abort(tx);
140168404Spjd *			goto top;
141168404Spjd *		}
142168404Spjd *		dmu_tx_abort(tx);	// abort DMU tx
143168404Spjd *		ZFS_EXIT(zfsvfs);	// finished in zfs
144168404Spjd *		return (error);		// really out of space
145168404Spjd *	}
146168404Spjd *	error = do_real_work();		// do whatever this VOP does
147168404Spjd *	if (error == 0)
148168404Spjd *		zfs_log_*(...);		// on success, make ZIL entry
149168404Spjd *	dmu_tx_commit(tx);		// commit DMU tx -- error or not
150168404Spjd *	rw_exit(...);			// drop locks
151168404Spjd *	zfs_dirent_unlock(dl);		// unlock directory entry
152168404Spjd *	VN_RELE(...);			// release held vnodes
153168404Spjd *	zil_commit(zilog, seq, foid);	// synchronous when necessary
154168404Spjd *	ZFS_EXIT(zfsvfs);		// finished in zfs
155168404Spjd *	return (error);			// done, report error
156168404Spjd */
157168404Spjd/* ARGSUSED */
158168404Spjdstatic int
159168962Spjdzfs_open(vnode_t **vpp, int flag, cred_t *cr)
160168404Spjd{
161168962Spjd	znode_t	*zp = VTOZ(*vpp);
162168404Spjd
163168404Spjd	/* Keep a count of the synchronous opens in the znode */
164168962Spjd	if (flag & (FSYNC | FDSYNC))
165168404Spjd		atomic_inc_32(&zp->z_sync_cnt);
166168404Spjd	return (0);
167168404Spjd}
168168404Spjd
169168404Spjd/* ARGSUSED */
170168404Spjdstatic int
171168962Spjdzfs_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr)
172168404Spjd{
173168962Spjd	znode_t	*zp = VTOZ(vp);
174168404Spjd
175168404Spjd	/* Decrement the synchronous opens in the znode */
176168962Spjd	if (flag & (FSYNC | FDSYNC))
177168404Spjd		atomic_dec_32(&zp->z_sync_cnt);
178168404Spjd
179168962Spjd	/*
180168962Spjd	 * Clean up any locks held by this process on the vp.
181168962Spjd	 */
182168962Spjd	cleanlocks(vp, ddi_get_pid(), 0);
183168962Spjd	cleanshares(vp, ddi_get_pid());
184168962Spjd
185168404Spjd	return (0);
186168404Spjd}
187168404Spjd
188168404Spjd/*
189168404Spjd * Lseek support for finding holes (cmd == _FIO_SEEK_HOLE) and
190168404Spjd * data (cmd == _FIO_SEEK_DATA). "off" is an in/out parameter.
191168404Spjd */
192168404Spjdstatic int
193168978Spjdzfs_holey(vnode_t *vp, u_long cmd, offset_t *off)
194168404Spjd{
195168404Spjd	znode_t	*zp = VTOZ(vp);
196168404Spjd	uint64_t noff = (uint64_t)*off; /* new offset */
197168404Spjd	uint64_t file_sz;
198168404Spjd	int error;
199168404Spjd	boolean_t hole;
200168404Spjd
201168404Spjd	file_sz = zp->z_phys->zp_size;
202168404Spjd	if (noff >= file_sz)  {
203168404Spjd		return (ENXIO);
204168404Spjd	}
205168404Spjd
206168962Spjd	if (cmd == _FIO_SEEK_HOLE)
207168404Spjd		hole = B_TRUE;
208168404Spjd	else
209168404Spjd		hole = B_FALSE;
210168404Spjd
211168404Spjd	error = dmu_offset_next(zp->z_zfsvfs->z_os, zp->z_id, hole, &noff);
212168404Spjd
213168404Spjd	/* end of file? */
214168404Spjd	if ((error == ESRCH) || (noff > file_sz)) {
215168404Spjd		/*
216168404Spjd		 * Handle the virtual hole at the end of file.
217168404Spjd		 */
218168404Spjd		if (hole) {
219168404Spjd			*off = file_sz;
220168404Spjd			return (0);
221168404Spjd		}
222168404Spjd		return (ENXIO);
223168404Spjd	}
224168404Spjd
225168404Spjd	if (noff < *off)
226168404Spjd		return (error);
227168404Spjd	*off = noff;
228168404Spjd	return (error);
229168404Spjd}
230168404Spjd
231168404Spjd/* ARGSUSED */
232168404Spjdstatic int
233168978Spjdzfs_ioctl(vnode_t *vp, u_long com, intptr_t data, int flag, cred_t *cred,
234168962Spjd    int *rvalp)
235168404Spjd{
236168962Spjd	offset_t off;
237168962Spjd	int error;
238168962Spjd	zfsvfs_t *zfsvfs;
239168404Spjd
240168404Spjd	switch (com) {
241168962Spjd	    case _FIOFFS:
242168962Spjd		return (0);
243168404Spjd
244168962Spjd		/*
245168962Spjd		 * The following two ioctls are used by bfu.  Faking out,
246168962Spjd		 * necessary to avoid bfu errors.
247168962Spjd		 */
248168962Spjd	    case _FIOGDIO:
249168962Spjd	    case _FIOSDIO:
250168962Spjd		return (0);
251168962Spjd
252168962Spjd	    case _FIO_SEEK_DATA:
253168962Spjd	    case _FIO_SEEK_HOLE:
254168962Spjd		if (ddi_copyin((void *)data, &off, sizeof (off), flag))
255168962Spjd			return (EFAULT);
256168962Spjd
257168404Spjd		zfsvfs = VTOZ(vp)->z_zfsvfs;
258168404Spjd		ZFS_ENTER(zfsvfs);
259168404Spjd
260168404Spjd		/* offset parameter is in/out */
261168404Spjd		error = zfs_holey(vp, com, &off);
262168404Spjd		ZFS_EXIT(zfsvfs);
263168404Spjd		if (error)
264168404Spjd			return (error);
265168962Spjd		if (ddi_copyout(&off, (void *)data, sizeof (off), flag))
266168962Spjd			return (EFAULT);
267168404Spjd		return (0);
268168404Spjd	}
269168404Spjd	return (ENOTTY);
270168404Spjd}
271168404Spjd
272168404Spjd/*
273168404Spjd * When a file is memory mapped, we must keep the IO data synchronized
274168404Spjd * between the DMU cache and the memory mapped pages.  What this means:
275168404Spjd *
276168404Spjd * On Write:	If we find a memory mapped page, we write to *both*
277168404Spjd *		the page and the dmu buffer.
278168404Spjd *
279168404Spjd * NOTE: We will always "break up" the IO into PAGESIZE uiomoves when
280168404Spjd *	the file is memory mapped.
281168404Spjd */
282168404Spjdstatic int
283168404Spjdmappedwrite(vnode_t *vp, int nbytes, uio_t *uio, dmu_tx_t *tx)
284168404Spjd{
285168404Spjd	znode_t *zp = VTOZ(vp);
286168404Spjd	objset_t *os = zp->z_zfsvfs->z_os;
287168404Spjd	vm_object_t obj;
288168404Spjd	vm_page_t m;
289168404Spjd	struct sf_buf *sf;
290168404Spjd	int64_t start, off;
291168404Spjd	int len = nbytes;
292168404Spjd	int error = 0;
293169059Spjd	uint64_t dirbytes;
294168404Spjd
295168404Spjd	ASSERT(vp->v_mount != NULL);
296168404Spjd	obj = vp->v_object;
297168404Spjd	ASSERT(obj != NULL);
298168404Spjd
299168404Spjd	start = uio->uio_loffset;
300168404Spjd	off = start & PAGEOFFSET;
301169059Spjd	dirbytes = 0;
302168404Spjd	VM_OBJECT_LOCK(obj);
303168404Spjd	for (start &= PAGEMASK; len > 0; start += PAGESIZE) {
304168404Spjd		uint64_t bytes = MIN(PAGESIZE - off, len);
305169059Spjd		uint64_t fsize;
306168404Spjd
307168404Spjdagain:
308168404Spjd		if ((m = vm_page_lookup(obj, OFF_TO_IDX(start))) != NULL &&
309168404Spjd		    vm_page_is_valid(m, (vm_offset_t)off, bytes)) {
310169059Spjd			uint64_t woff;
311168404Spjd			caddr_t va;
312168404Spjd
313168404Spjd			if (vm_page_sleep_if_busy(m, FALSE, "zfsmwb"))
314168404Spjd				goto again;
315169059Spjd			fsize = obj->un_pager.vnp.vnp_size;
316168404Spjd			vm_page_busy(m);
317169057Spjd			vm_page_lock_queues();
318169057Spjd			vm_page_undirty(m);
319169057Spjd			vm_page_unlock_queues();
320168404Spjd			VM_OBJECT_UNLOCK(obj);
321169059Spjd			if (dirbytes > 0) {
322169059Spjd				error = dmu_write_uio(os, zp->z_id, uio,
323169059Spjd				    dirbytes, tx);
324169059Spjd				dirbytes = 0;
325169059Spjd			}
326169059Spjd			if (error == 0) {
327169059Spjd				sched_pin();
328169059Spjd				sf = sf_buf_alloc(m, SFB_CPUPRIVATE);
329169059Spjd				va = (caddr_t)sf_buf_kva(sf);
330169059Spjd				woff = uio->uio_loffset - off;
331169059Spjd				error = uiomove(va + off, bytes, UIO_WRITE, uio);
332169167Spjd				/*
333169167Spjd				 * The uiomove() above could have been partially
334169167Spjd				 * successful, that's why we call dmu_write()
335169167Spjd				 * below unconditionally. The page was marked
336169167Spjd				 * non-dirty above and we would lose the changes
337169167Spjd				 * without doing so. If the uiomove() failed
338169167Spjd				 * entirely, well, we just write what we got
339169167Spjd				 * before one more time.
340169167Spjd				 */
341169059Spjd				dmu_write(os, zp->z_id, woff,
342169059Spjd				    MIN(PAGESIZE, fsize - woff), va, tx);
343169059Spjd				sf_buf_free(sf);
344169059Spjd				sched_unpin();
345169059Spjd			}
346168404Spjd			VM_OBJECT_LOCK(obj);
347168404Spjd			vm_page_wakeup(m);
348168404Spjd		} else {
349169059Spjd			dirbytes += bytes;
350168404Spjd		}
351168404Spjd		len -= bytes;
352168404Spjd		off = 0;
353168404Spjd		if (error)
354168404Spjd			break;
355168404Spjd	}
356168404Spjd	VM_OBJECT_UNLOCK(obj);
357169059Spjd	if (error == 0 && dirbytes > 0)
358169059Spjd		error = dmu_write_uio(os, zp->z_id, uio, dirbytes, tx);
359168404Spjd	return (error);
360168404Spjd}
361168404Spjd
362168404Spjd/*
363168404Spjd * When a file is memory mapped, we must keep the IO data synchronized
364168404Spjd * between the DMU cache and the memory mapped pages.  What this means:
365168404Spjd *
366168404Spjd * On Read:	We "read" preferentially from memory mapped pages,
367168404Spjd *		else we default from the dmu buffer.
368168404Spjd *
369168404Spjd * NOTE: We will always "break up" the IO into PAGESIZE uiomoves when
370168404Spjd *	the file is memory mapped.
371168404Spjd */
372168404Spjdstatic int
373168404Spjdmappedread(vnode_t *vp, int nbytes, uio_t *uio)
374168404Spjd{
375168404Spjd	znode_t *zp = VTOZ(vp);
376168404Spjd	objset_t *os = zp->z_zfsvfs->z_os;
377168404Spjd	vm_object_t obj;
378168404Spjd	vm_page_t m;
379168404Spjd	struct sf_buf *sf;
380168404Spjd	int64_t start, off;
381168926Spjd	caddr_t va;
382168404Spjd	int len = nbytes;
383168404Spjd	int error = 0;
384169059Spjd	uint64_t dirbytes;
385168404Spjd
386168404Spjd	ASSERT(vp->v_mount != NULL);
387168404Spjd	obj = vp->v_object;
388168404Spjd	ASSERT(obj != NULL);
389168404Spjd
390168404Spjd	start = uio->uio_loffset;
391168404Spjd	off = start & PAGEOFFSET;
392169059Spjd	dirbytes = 0;
393168404Spjd	VM_OBJECT_LOCK(obj);
394168404Spjd	for (start &= PAGEMASK; len > 0; start += PAGESIZE) {
395168404Spjd		uint64_t bytes = MIN(PAGESIZE - off, len);
396168404Spjd
397168404Spjdagain:
398168404Spjd		if ((m = vm_page_lookup(obj, OFF_TO_IDX(start))) != NULL &&
399168404Spjd		    vm_page_is_valid(m, (vm_offset_t)off, bytes)) {
400168404Spjd			if (vm_page_sleep_if_busy(m, FALSE, "zfsmrb"))
401168404Spjd				goto again;
402168404Spjd			vm_page_busy(m);
403168404Spjd			VM_OBJECT_UNLOCK(obj);
404169059Spjd			if (dirbytes > 0) {
405169059Spjd				error = dmu_read_uio(os, zp->z_id, uio,
406169059Spjd				    dirbytes);
407169059Spjd				dirbytes = 0;
408169059Spjd			}
409169059Spjd			if (error == 0) {
410169059Spjd				sched_pin();
411169059Spjd				sf = sf_buf_alloc(m, SFB_CPUPRIVATE);
412169059Spjd				va = (caddr_t)sf_buf_kva(sf);
413169059Spjd				error = uiomove(va + off, bytes, UIO_READ, uio);
414169059Spjd				sf_buf_free(sf);
415169059Spjd				sched_unpin();
416169059Spjd			}
417168404Spjd			VM_OBJECT_LOCK(obj);
418168404Spjd			vm_page_wakeup(m);
419168926Spjd		} else if (m != NULL && uio->uio_segflg == UIO_NOCOPY) {
420168962Spjd			/*
421168962Spjd			 * The code below is here to make sendfile(2) work
422168962Spjd			 * correctly with ZFS. As pointed out by ups@
423168962Spjd			 * sendfile(2) should be changed to use VOP_GETPAGES(),
424168962Spjd			 * but it pessimize performance of sendfile/UFS, that's
425168962Spjd			 * why I handle this special case in ZFS code.
426168962Spjd			 */
427168926Spjd			if (vm_page_sleep_if_busy(m, FALSE, "zfsmrb"))
428168926Spjd				goto again;
429168926Spjd			vm_page_busy(m);
430168926Spjd			VM_OBJECT_UNLOCK(obj);
431169059Spjd			if (dirbytes > 0) {
432169059Spjd				error = dmu_read_uio(os, zp->z_id, uio,
433169059Spjd				    dirbytes);
434169059Spjd				dirbytes = 0;
435169059Spjd			}
436169059Spjd			if (error == 0) {
437169059Spjd				sched_pin();
438169059Spjd				sf = sf_buf_alloc(m, SFB_CPUPRIVATE);
439169059Spjd				va = (caddr_t)sf_buf_kva(sf);
440169059Spjd				error = dmu_read(os, zp->z_id, start + off,
441169059Spjd				    bytes, (void *)(va + off));
442169059Spjd				sf_buf_free(sf);
443169059Spjd				sched_unpin();
444169059Spjd			}
445168926Spjd			VM_OBJECT_LOCK(obj);
446168926Spjd			vm_page_wakeup(m);
447169059Spjd			if (error == 0)
448169059Spjd				uio->uio_resid -= bytes;
449168404Spjd		} else {
450169059Spjd			dirbytes += bytes;
451168404Spjd		}
452168404Spjd		len -= bytes;
453168404Spjd		off = 0;
454168404Spjd		if (error)
455168404Spjd			break;
456168404Spjd	}
457168404Spjd	VM_OBJECT_UNLOCK(obj);
458169059Spjd	if (error == 0 && dirbytes > 0)
459169059Spjd		error = dmu_read_uio(os, zp->z_id, uio, dirbytes);
460168404Spjd	return (error);
461168404Spjd}
462168404Spjd
463168404Spjdoffset_t zfs_read_chunk_size = 1024 * 1024; /* Tunable */
464168404Spjd
465168404Spjd/*
466168404Spjd * Read bytes from specified file into supplied buffer.
467168404Spjd *
468168404Spjd *	IN:	vp	- vnode of file to be read from.
469168404Spjd *		uio	- structure supplying read location, range info,
470168404Spjd *			  and return buffer.
471168404Spjd *		ioflag	- SYNC flags; used to provide FRSYNC semantics.
472168404Spjd *		cr	- credentials of caller.
473168404Spjd *
474168404Spjd *	OUT:	uio	- updated offset and range, buffer filled.
475168404Spjd *
476168404Spjd *	RETURN:	0 if success
477168404Spjd *		error code if failure
478168404Spjd *
479168404Spjd * Side Effects:
480168404Spjd *	vp - atime updated if byte count > 0
481168404Spjd */
482168404Spjd/* ARGSUSED */
483168404Spjdstatic int
484168962Spjdzfs_read(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct)
485168404Spjd{
486168404Spjd	znode_t		*zp = VTOZ(vp);
487168404Spjd	zfsvfs_t	*zfsvfs = zp->z_zfsvfs;
488168404Spjd	objset_t	*os = zfsvfs->z_os;
489168404Spjd	ssize_t		n, nbytes;
490168404Spjd	int		error;
491168404Spjd	rl_t		*rl;
492168404Spjd
493168404Spjd	ZFS_ENTER(zfsvfs);
494168404Spjd
495168404Spjd	/*
496168404Spjd	 * Validate file offset
497168404Spjd	 */
498168404Spjd	if (uio->uio_loffset < (offset_t)0) {
499168404Spjd		ZFS_EXIT(zfsvfs);
500168404Spjd		return (EINVAL);
501168404Spjd	}
502168404Spjd
503168404Spjd	/*
504168404Spjd	 * Fasttrack empty reads
505168404Spjd	 */
506168404Spjd	if (uio->uio_resid == 0) {
507168404Spjd		ZFS_EXIT(zfsvfs);
508168404Spjd		return (0);
509168404Spjd	}
510168404Spjd
511168404Spjd	/*
512168962Spjd	 * Check for mandatory locks
513168962Spjd	 */
514168962Spjd	if (MANDMODE((mode_t)zp->z_phys->zp_mode)) {
515168962Spjd		if (error = chklock(vp, FREAD,
516168962Spjd		    uio->uio_loffset, uio->uio_resid, uio->uio_fmode, ct)) {
517168962Spjd			ZFS_EXIT(zfsvfs);
518168962Spjd			return (error);
519168962Spjd		}
520168962Spjd	}
521168962Spjd
522168962Spjd	/*
523168404Spjd	 * If we're in FRSYNC mode, sync out this znode before reading it.
524168404Spjd	 */
525168962Spjd	if (ioflag & FRSYNC)
526168404Spjd		zil_commit(zfsvfs->z_log, zp->z_last_itx, zp->z_id);
527168404Spjd
528168404Spjd	/*
529168404Spjd	 * Lock the range against changes.
530168404Spjd	 */
531168404Spjd	rl = zfs_range_lock(zp, uio->uio_loffset, uio->uio_resid, RL_READER);
532168404Spjd
533168404Spjd	/*
534168404Spjd	 * If we are reading past end-of-file we can skip
535168404Spjd	 * to the end; but we might still need to set atime.
536168404Spjd	 */
537168404Spjd	if (uio->uio_loffset >= zp->z_phys->zp_size) {
538168404Spjd		error = 0;
539168404Spjd		goto out;
540168404Spjd	}
541168404Spjd
542168404Spjd	ASSERT(uio->uio_loffset < zp->z_phys->zp_size);
543168404Spjd	n = MIN(uio->uio_resid, zp->z_phys->zp_size - uio->uio_loffset);
544168404Spjd
545168404Spjd	while (n > 0) {
546168404Spjd		nbytes = MIN(n, zfs_read_chunk_size -
547168404Spjd		    P2PHASE(uio->uio_loffset, zfs_read_chunk_size));
548168404Spjd
549168404Spjd		if (vn_has_cached_data(vp))
550168404Spjd			error = mappedread(vp, nbytes, uio);
551168404Spjd		else
552168404Spjd			error = dmu_read_uio(os, zp->z_id, uio, nbytes);
553168404Spjd		if (error)
554168404Spjd			break;
555168962Spjd
556168404Spjd		n -= nbytes;
557168404Spjd	}
558168404Spjd
559168404Spjdout:
560168404Spjd	zfs_range_unlock(rl);
561168404Spjd
562168404Spjd	ZFS_ACCESSTIME_STAMP(zfsvfs, zp);
563168404Spjd	ZFS_EXIT(zfsvfs);
564168404Spjd	return (error);
565168404Spjd}
566168404Spjd
567168404Spjd/*
568168404Spjd * Fault in the pages of the first n bytes specified by the uio structure.
569168404Spjd * 1 byte in each page is touched and the uio struct is unmodified.
570168404Spjd * Any error will exit this routine as this is only a best
571168404Spjd * attempt to get the pages resident. This is a copy of ufs_trans_touch().
572168404Spjd */
573168404Spjdstatic void
574168404Spjdzfs_prefault_write(ssize_t n, struct uio *uio)
575168404Spjd{
576168404Spjd	struct iovec *iov;
577168404Spjd	ulong_t cnt, incr;
578168404Spjd	caddr_t p;
579168404Spjd
580168404Spjd	if (uio->uio_segflg != UIO_USERSPACE)
581168404Spjd		return;
582168404Spjd
583168404Spjd	iov = uio->uio_iov;
584168404Spjd
585168404Spjd	while (n) {
586168404Spjd		cnt = MIN(iov->iov_len, n);
587168404Spjd		if (cnt == 0) {
588168404Spjd			/* empty iov entry */
589168404Spjd			iov++;
590168404Spjd			continue;
591168404Spjd		}
592168404Spjd		n -= cnt;
593168404Spjd		/*
594168404Spjd		 * touch each page in this segment.
595168404Spjd		 */
596168404Spjd		p = iov->iov_base;
597168404Spjd		while (cnt) {
598168404Spjd			if (fubyte(p) == -1)
599168404Spjd				return;
600168404Spjd			incr = MIN(cnt, PAGESIZE);
601168404Spjd			p += incr;
602168404Spjd			cnt -= incr;
603168404Spjd		}
604168404Spjd		/*
605168404Spjd		 * touch the last byte in case it straddles a page.
606168404Spjd		 */
607168404Spjd		p--;
608168404Spjd		if (fubyte(p) == -1)
609168404Spjd			return;
610168404Spjd		iov++;
611168404Spjd	}
612168404Spjd}
613168404Spjd
614168404Spjd/*
615168404Spjd * Write the bytes to a file.
616168404Spjd *
617168404Spjd *	IN:	vp	- vnode of file to be written to.
618168404Spjd *		uio	- structure supplying write location, range info,
619168404Spjd *			  and data buffer.
620168404Spjd *		ioflag	- IO_APPEND flag set if in append mode.
621168404Spjd *		cr	- credentials of caller.
622168404Spjd *
623168404Spjd *	OUT:	uio	- updated offset and range.
624168404Spjd *
625168404Spjd *	RETURN:	0 if success
626168404Spjd *		error code if failure
627168404Spjd *
628168404Spjd * Timestamps:
629168404Spjd *	vp - ctime|mtime updated if byte count > 0
630168404Spjd */
631168404Spjd/* ARGSUSED */
632168404Spjdstatic int
633168962Spjdzfs_write(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct)
634168404Spjd{
635168404Spjd	znode_t		*zp = VTOZ(vp);
636168962Spjd	rlim64_t	limit = MAXOFFSET_T;
637168404Spjd	ssize_t		start_resid = uio->uio_resid;
638168404Spjd	ssize_t		tx_bytes;
639168404Spjd	uint64_t	end_size;
640168404Spjd	dmu_tx_t	*tx;
641168404Spjd	zfsvfs_t	*zfsvfs = zp->z_zfsvfs;
642168404Spjd	zilog_t		*zilog = zfsvfs->z_log;
643168404Spjd	offset_t	woff;
644168404Spjd	ssize_t		n, nbytes;
645168404Spjd	rl_t		*rl;
646168404Spjd	int		max_blksz = zfsvfs->z_max_blksz;
647168404Spjd	int		error;
648168404Spjd
649168404Spjd	/*
650168404Spjd	 * Fasttrack empty write
651168404Spjd	 */
652168404Spjd	n = start_resid;
653168404Spjd	if (n == 0)
654168404Spjd		return (0);
655168404Spjd
656168962Spjd	if (limit == RLIM64_INFINITY || limit > MAXOFFSET_T)
657168962Spjd		limit = MAXOFFSET_T;
658168962Spjd
659168404Spjd	ZFS_ENTER(zfsvfs);
660168404Spjd
661168404Spjd	/*
662168404Spjd	 * Pre-fault the pages to ensure slow (eg NFS) pages
663168404Spjd	 * don't hold up txg.
664168404Spjd	 */
665168404Spjd	zfs_prefault_write(n, uio);
666168404Spjd
667168404Spjd	/*
668168404Spjd	 * If in append mode, set the io offset pointer to eof.
669168404Spjd	 */
670168404Spjd	if (ioflag & IO_APPEND) {
671168404Spjd		/*
672168404Spjd		 * Range lock for a file append:
673168404Spjd		 * The value for the start of range will be determined by
674168404Spjd		 * zfs_range_lock() (to guarantee append semantics).
675168404Spjd		 * If this write will cause the block size to increase,
676168404Spjd		 * zfs_range_lock() will lock the entire file, so we must
677168404Spjd		 * later reduce the range after we grow the block size.
678168404Spjd		 */
679168404Spjd		rl = zfs_range_lock(zp, 0, n, RL_APPEND);
680168404Spjd		if (rl->r_len == UINT64_MAX) {
681168404Spjd			/* overlocked, zp_size can't change */
682168404Spjd			woff = uio->uio_loffset = zp->z_phys->zp_size;
683168404Spjd		} else {
684168404Spjd			woff = uio->uio_loffset = rl->r_off;
685168404Spjd		}
686168404Spjd	} else {
687168404Spjd		woff = uio->uio_loffset;
688168404Spjd		/*
689168404Spjd		 * Validate file offset
690168404Spjd		 */
691168404Spjd		if (woff < 0) {
692168404Spjd			ZFS_EXIT(zfsvfs);
693168404Spjd			return (EINVAL);
694168404Spjd		}
695168404Spjd
696168404Spjd		/*
697168404Spjd		 * If we need to grow the block size then zfs_range_lock()
698168404Spjd		 * will lock a wider range than we request here.
699168404Spjd		 * Later after growing the block size we reduce the range.
700168404Spjd		 */
701168404Spjd		rl = zfs_range_lock(zp, woff, n, RL_WRITER);
702168404Spjd	}
703168404Spjd
704168962Spjd	if (woff >= limit) {
705168962Spjd		zfs_range_unlock(rl);
706168962Spjd		ZFS_EXIT(zfsvfs);
707168962Spjd		return (EFBIG);
708168962Spjd	}
709168962Spjd
710168962Spjd	if ((woff + n) > limit || woff > (limit - n))
711168962Spjd		n = limit - woff;
712168962Spjd
713168962Spjd	/*
714168962Spjd	 * Check for mandatory locks
715168962Spjd	 */
716168962Spjd	if (MANDMODE((mode_t)zp->z_phys->zp_mode) &&
717168962Spjd	    (error = chklock(vp, FWRITE, woff, n, uio->uio_fmode, ct)) != 0) {
718168962Spjd		zfs_range_unlock(rl);
719168962Spjd		ZFS_EXIT(zfsvfs);
720168962Spjd		return (error);
721168962Spjd	}
722168404Spjd	end_size = MAX(zp->z_phys->zp_size, woff + n);
723168404Spjd
724168404Spjd	/*
725168404Spjd	 * Write the file in reasonable size chunks.  Each chunk is written
726168404Spjd	 * in a separate transaction; this keeps the intent log records small
727168404Spjd	 * and allows us to do more fine-grained space accounting.
728168404Spjd	 */
729168404Spjd	while (n > 0) {
730168404Spjd		/*
731168404Spjd		 * Start a transaction.
732168404Spjd		 */
733168404Spjd		woff = uio->uio_loffset;
734168404Spjd		tx = dmu_tx_create(zfsvfs->z_os);
735168404Spjd		dmu_tx_hold_bonus(tx, zp->z_id);
736168404Spjd		dmu_tx_hold_write(tx, zp->z_id, woff, MIN(n, max_blksz));
737168404Spjd		error = dmu_tx_assign(tx, zfsvfs->z_assign);
738168404Spjd		if (error) {
739168404Spjd			if (error == ERESTART &&
740168404Spjd			    zfsvfs->z_assign == TXG_NOWAIT) {
741168404Spjd				dmu_tx_wait(tx);
742168404Spjd				dmu_tx_abort(tx);
743168404Spjd				continue;
744168404Spjd			}
745168404Spjd			dmu_tx_abort(tx);
746168404Spjd			break;
747168404Spjd		}
748168404Spjd
749168404Spjd		/*
750168404Spjd		 * If zfs_range_lock() over-locked we grow the blocksize
751168404Spjd		 * and then reduce the lock range.  This will only happen
752168404Spjd		 * on the first iteration since zfs_range_reduce() will
753168404Spjd		 * shrink down r_len to the appropriate size.
754168404Spjd		 */
755168404Spjd		if (rl->r_len == UINT64_MAX) {
756168404Spjd			uint64_t new_blksz;
757168404Spjd
758168404Spjd			if (zp->z_blksz > max_blksz) {
759168404Spjd				ASSERT(!ISP2(zp->z_blksz));
760168404Spjd				new_blksz = MIN(end_size, SPA_MAXBLOCKSIZE);
761168404Spjd			} else {
762168404Spjd				new_blksz = MIN(end_size, max_blksz);
763168404Spjd			}
764168404Spjd			zfs_grow_blocksize(zp, new_blksz, tx);
765168404Spjd			zfs_range_reduce(rl, woff, n);
766168404Spjd		}
767168404Spjd
768168404Spjd		/*
769168404Spjd		 * XXX - should we really limit each write to z_max_blksz?
770168404Spjd		 * Perhaps we should use SPA_MAXBLOCKSIZE chunks?
771168404Spjd		 */
772168404Spjd		nbytes = MIN(n, max_blksz - P2PHASE(woff, max_blksz));
773168404Spjd
774168404Spjd		if (woff + nbytes > zp->z_phys->zp_size)
775168404Spjd			vnode_pager_setsize(vp, woff + nbytes);
776168404Spjd
777169302Spjd		rw_enter(&zp->z_map_lock, RW_READER);
778169302Spjd
779168962Spjd		tx_bytes = uio->uio_resid;
780168404Spjd		if (vn_has_cached_data(vp)) {
781168404Spjd			rw_exit(&zp->z_map_lock);
782168404Spjd			error = mappedwrite(vp, nbytes, uio, tx);
783168404Spjd		} else {
784168404Spjd			error = dmu_write_uio(zfsvfs->z_os, zp->z_id,
785168404Spjd			    uio, nbytes, tx);
786168404Spjd			rw_exit(&zp->z_map_lock);
787168404Spjd		}
788168404Spjd		tx_bytes -= uio->uio_resid;
789168404Spjd
790168404Spjd		/*
791168404Spjd		 * If we made no progress, we're done.  If we made even
792168404Spjd		 * partial progress, update the znode and ZIL accordingly.
793168404Spjd		 */
794168404Spjd		if (tx_bytes == 0) {
795168404Spjd			dmu_tx_commit(tx);
796168404Spjd			ASSERT(error != 0);
797168404Spjd			break;
798168404Spjd		}
799168404Spjd
800168404Spjd		/*
801168404Spjd		 * Clear Set-UID/Set-GID bits on successful write if not
802168404Spjd		 * privileged and at least one of the excute bits is set.
803168404Spjd		 *
804168404Spjd		 * It would be nice to to this after all writes have
805168404Spjd		 * been done, but that would still expose the ISUID/ISGID
806168404Spjd		 * to another app after the partial write is committed.
807168404Spjd		 */
808168404Spjd		mutex_enter(&zp->z_acl_lock);
809168404Spjd		if ((zp->z_phys->zp_mode & (S_IXUSR | (S_IXUSR >> 3) |
810168404Spjd		    (S_IXUSR >> 6))) != 0 &&
811168404Spjd		    (zp->z_phys->zp_mode & (S_ISUID | S_ISGID)) != 0 &&
812168404Spjd		    secpolicy_vnode_setid_retain(cr,
813168404Spjd		    (zp->z_phys->zp_mode & S_ISUID) != 0 &&
814168404Spjd		    zp->z_phys->zp_uid == 0) != 0) {
815168404Spjd			    zp->z_phys->zp_mode &= ~(S_ISUID | S_ISGID);
816168404Spjd		}
817168404Spjd		mutex_exit(&zp->z_acl_lock);
818168404Spjd
819168404Spjd		/*
820168404Spjd		 * Update time stamp.  NOTE: This marks the bonus buffer as
821168404Spjd		 * dirty, so we don't have to do it again for zp_size.
822168404Spjd		 */
823168404Spjd		zfs_time_stamper(zp, CONTENT_MODIFIED, tx);
824168404Spjd
825168404Spjd		/*
826168404Spjd		 * Update the file size (zp_size) if it has changed;
827168404Spjd		 * account for possible concurrent updates.
828168404Spjd		 */
829168404Spjd		while ((end_size = zp->z_phys->zp_size) < uio->uio_loffset)
830168404Spjd			(void) atomic_cas_64(&zp->z_phys->zp_size, end_size,
831168404Spjd			    uio->uio_loffset);
832168404Spjd		zfs_log_write(zilog, tx, TX_WRITE, zp, woff, tx_bytes, ioflag);
833168404Spjd		dmu_tx_commit(tx);
834168404Spjd
835168404Spjd		if (error != 0)
836168404Spjd			break;
837168404Spjd		ASSERT(tx_bytes == nbytes);
838168404Spjd		n -= nbytes;
839168404Spjd	}
840168404Spjd
841168404Spjd	zfs_range_unlock(rl);
842168404Spjd
843168404Spjd	/*
844168404Spjd	 * If we're in replay mode, or we made no progress, return error.
845168404Spjd	 * Otherwise, it's at least a partial write, so it's successful.
846168404Spjd	 */
847168404Spjd	if (zfsvfs->z_assign >= TXG_INITIAL || uio->uio_resid == start_resid) {
848168404Spjd		ZFS_EXIT(zfsvfs);
849168404Spjd		return (error);
850168404Spjd	}
851168404Spjd
852168962Spjd	if (ioflag & (FSYNC | FDSYNC))
853168404Spjd		zil_commit(zilog, zp->z_last_itx, zp->z_id);
854168404Spjd
855168404Spjd	ZFS_EXIT(zfsvfs);
856168404Spjd	return (0);
857168404Spjd}
858168404Spjd
859168404Spjdvoid
860168404Spjdzfs_get_done(dmu_buf_t *db, void *vzgd)
861168404Spjd{
862168404Spjd	zgd_t *zgd = (zgd_t *)vzgd;
863168404Spjd	rl_t *rl = zgd->zgd_rl;
864168404Spjd	vnode_t *vp = ZTOV(rl->r_zp);
865168404Spjd	int vfslocked;
866168404Spjd
867168404Spjd	vfslocked = VFS_LOCK_GIANT(vp->v_vfsp);
868168404Spjd	dmu_buf_rele(db, vzgd);
869168404Spjd	zfs_range_unlock(rl);
870168404Spjd	VN_RELE(vp);
871168404Spjd	zil_add_vdev(zgd->zgd_zilog, DVA_GET_VDEV(BP_IDENTITY(zgd->zgd_bp)));
872168404Spjd	kmem_free(zgd, sizeof (zgd_t));
873168404Spjd	VFS_UNLOCK_GIANT(vfslocked);
874168404Spjd}
875168404Spjd
876168404Spjd/*
877168404Spjd * Get data to generate a TX_WRITE intent log record.
878168404Spjd */
879168404Spjdint
880168404Spjdzfs_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio)
881168404Spjd{
882168404Spjd	zfsvfs_t *zfsvfs = arg;
883168404Spjd	objset_t *os = zfsvfs->z_os;
884168404Spjd	znode_t *zp;
885168404Spjd	uint64_t off = lr->lr_offset;
886168404Spjd	dmu_buf_t *db;
887168404Spjd	rl_t *rl;
888168404Spjd	zgd_t *zgd;
889168404Spjd	int dlen = lr->lr_length;		/* length of user data */
890168404Spjd	int error = 0;
891168404Spjd
892168404Spjd	ASSERT(zio);
893168404Spjd	ASSERT(dlen != 0);
894168404Spjd
895168404Spjd	/*
896168404Spjd	 * Nothing to do if the file has been removed
897168404Spjd	 */
898168404Spjd	if (zfs_zget(zfsvfs, lr->lr_foid, &zp) != 0)
899168404Spjd		return (ENOENT);
900168404Spjd	if (zp->z_unlinked) {
901168404Spjd		VN_RELE(ZTOV(zp));
902168404Spjd		return (ENOENT);
903168404Spjd	}
904168404Spjd
905168404Spjd	/*
906168404Spjd	 * Write records come in two flavors: immediate and indirect.
907168404Spjd	 * For small writes it's cheaper to store the data with the
908168404Spjd	 * log record (immediate); for large writes it's cheaper to
909168404Spjd	 * sync the data and get a pointer to it (indirect) so that
910168404Spjd	 * we don't have to write the data twice.
911168404Spjd	 */
912168404Spjd	if (buf != NULL) { /* immediate write */
913168404Spjd		rl = zfs_range_lock(zp, off, dlen, RL_READER);
914168404Spjd		/* test for truncation needs to be done while range locked */
915168404Spjd		if (off >= zp->z_phys->zp_size) {
916168404Spjd			error = ENOENT;
917168404Spjd			goto out;
918168404Spjd		}
919168404Spjd		VERIFY(0 == dmu_read(os, lr->lr_foid, off, dlen, buf));
920168404Spjd	} else { /* indirect write */
921168404Spjd		uint64_t boff; /* block starting offset */
922168404Spjd
923168404Spjd		/*
924168404Spjd		 * Have to lock the whole block to ensure when it's
925168404Spjd		 * written out and it's checksum is being calculated
926168404Spjd		 * that no one can change the data. We need to re-check
927168404Spjd		 * blocksize after we get the lock in case it's changed!
928168404Spjd		 */
929168404Spjd		for (;;) {
930168404Spjd			if (ISP2(zp->z_blksz)) {
931168404Spjd				boff = P2ALIGN_TYPED(off, zp->z_blksz,
932168404Spjd				    uint64_t);
933168404Spjd			} else {
934168404Spjd				boff = 0;
935168404Spjd			}
936168404Spjd			dlen = zp->z_blksz;
937168404Spjd			rl = zfs_range_lock(zp, boff, dlen, RL_READER);
938168404Spjd			if (zp->z_blksz == dlen)
939168404Spjd				break;
940168404Spjd			zfs_range_unlock(rl);
941168404Spjd		}
942168404Spjd		/* test for truncation needs to be done while range locked */
943168404Spjd		if (off >= zp->z_phys->zp_size) {
944168404Spjd			error = ENOENT;
945168404Spjd			goto out;
946168404Spjd		}
947168404Spjd		zgd = (zgd_t *)kmem_alloc(sizeof (zgd_t), KM_SLEEP);
948168404Spjd		zgd->zgd_rl = rl;
949168404Spjd		zgd->zgd_zilog = zfsvfs->z_log;
950168404Spjd		zgd->zgd_bp = &lr->lr_blkptr;
951168404Spjd		VERIFY(0 == dmu_buf_hold(os, lr->lr_foid, boff, zgd, &db));
952168404Spjd		ASSERT(boff == db->db_offset);
953168404Spjd		lr->lr_blkoff = off - boff;
954168404Spjd		error = dmu_sync(zio, db, &lr->lr_blkptr,
955168404Spjd		    lr->lr_common.lrc_txg, zfs_get_done, zgd);
956168404Spjd		ASSERT(error == EEXIST || lr->lr_length <= zp->z_blksz);
957168404Spjd		if (error == 0) {
958168404Spjd			zil_add_vdev(zfsvfs->z_log,
959168404Spjd			    DVA_GET_VDEV(BP_IDENTITY(&lr->lr_blkptr)));
960168404Spjd		}
961168404Spjd		/*
962168404Spjd		 * If we get EINPROGRESS, then we need to wait for a
963168404Spjd		 * write IO initiated by dmu_sync() to complete before
964168404Spjd		 * we can release this dbuf.  We will finish everything
965168404Spjd		 * up in the zfs_get_done() callback.
966168404Spjd		 */
967168404Spjd		if (error == EINPROGRESS)
968168404Spjd			return (0);
969168404Spjd		dmu_buf_rele(db, zgd);
970168404Spjd		kmem_free(zgd, sizeof (zgd_t));
971168404Spjd	}
972168404Spjdout:
973168404Spjd	zfs_range_unlock(rl);
974168404Spjd	VN_RELE(ZTOV(zp));
975168404Spjd	return (error);
976168404Spjd}
977168404Spjd
978168404Spjd/*ARGSUSED*/
979168404Spjdstatic int
980168962Spjdzfs_access(vnode_t *vp, int mode, int flags, cred_t *cr)
981168404Spjd{
982168404Spjd	znode_t *zp = VTOZ(vp);
983168404Spjd	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
984168404Spjd	int error;
985168404Spjd
986168404Spjd	ZFS_ENTER(zfsvfs);
987168962Spjd	error = zfs_zaccess_rwx(zp, mode, cr);
988168404Spjd	ZFS_EXIT(zfsvfs);
989168404Spjd	return (error);
990168404Spjd}
991168404Spjd
992168404Spjd/*
993168404Spjd * Lookup an entry in a directory, or an extended attribute directory.
994168404Spjd * If it exists, return a held vnode reference for it.
995168404Spjd *
996168404Spjd *	IN:	dvp	- vnode of directory to search.
997168404Spjd *		nm	- name of entry to lookup.
998168404Spjd *		pnp	- full pathname to lookup [UNUSED].
999168404Spjd *		flags	- LOOKUP_XATTR set if looking for an attribute.
1000168404Spjd *		rdir	- root directory vnode [UNUSED].
1001168404Spjd *		cr	- credentials of caller.
1002168404Spjd *
1003168404Spjd *	OUT:	vpp	- vnode of located entry, NULL if not found.
1004168404Spjd *
1005168404Spjd *	RETURN:	0 if success
1006168404Spjd *		error code if failure
1007168404Spjd *
1008168404Spjd * Timestamps:
1009168404Spjd *	NA
1010168404Spjd */
1011168404Spjd/* ARGSUSED */
1012168962Spjdstatic int
1013168962Spjdzfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct componentname *cnp,
1014169170Spjd    int nameiop, cred_t *cr, kthread_t *td)
1015168404Spjd{
1016168404Spjd
1017168962Spjd	znode_t *zdp = VTOZ(dvp);
1018168962Spjd	zfsvfs_t *zfsvfs = zdp->z_zfsvfs;
1019168962Spjd	int	error;
1020168404Spjd
1021168404Spjd	ZFS_ENTER(zfsvfs);
1022168404Spjd
1023168404Spjd	*vpp = NULL;
1024168404Spjd
1025168404Spjd#ifdef TODO
1026168404Spjd	if (flags & LOOKUP_XATTR) {
1027168404Spjd		/*
1028168404Spjd		 * If the xattr property is off, refuse the lookup request.
1029168404Spjd		 */
1030168404Spjd		if (!(zfsvfs->z_vfs->vfs_flag & VFS_XATTR)) {
1031168404Spjd			ZFS_EXIT(zfsvfs);
1032168404Spjd			return (EINVAL);
1033168404Spjd		}
1034168404Spjd
1035168404Spjd		/*
1036168404Spjd		 * We don't allow recursive attributes..
1037168404Spjd		 * Maybe someday we will.
1038168404Spjd		 */
1039168404Spjd		if (zdp->z_phys->zp_flags & ZFS_XATTR) {
1040168404Spjd			ZFS_EXIT(zfsvfs);
1041168404Spjd			return (EINVAL);
1042168404Spjd		}
1043168404Spjd
1044168404Spjd		if (error = zfs_get_xattrdir(VTOZ(dvp), vpp, cr, flags)) {
1045168404Spjd			ZFS_EXIT(zfsvfs);
1046168404Spjd			return (error);
1047168404Spjd		}
1048168404Spjd
1049168404Spjd		/*
1050168404Spjd		 * Do we have permission to get into attribute directory?
1051168404Spjd		 */
1052168404Spjd
1053168404Spjd		if (error = zfs_zaccess(VTOZ(*vpp), ACE_EXECUTE, cr)) {
1054168404Spjd			VN_RELE(*vpp);
1055168404Spjd		}
1056168404Spjd
1057168404Spjd		ZFS_EXIT(zfsvfs);
1058168404Spjd		return (error);
1059168404Spjd	}
1060168404Spjd#endif	/* TODO */
1061168404Spjd
1062168404Spjd	if (dvp->v_type != VDIR) {
1063168404Spjd		ZFS_EXIT(zfsvfs);
1064168404Spjd		return (ENOTDIR);
1065168404Spjd	}
1066168404Spjd
1067168404Spjd	/*
1068168404Spjd	 * Check accessibility of directory.
1069168404Spjd	 */
1070168404Spjd
1071168404Spjd	if (error = zfs_zaccess(zdp, ACE_EXECUTE, cr)) {
1072168404Spjd		ZFS_EXIT(zfsvfs);
1073168404Spjd		return (error);
1074168404Spjd	}
1075168404Spjd
1076168962Spjd	if ((error = zfs_dirlook(zdp, nm, vpp)) == 0) {
1077168404Spjd
1078168962Spjd		/*
1079168962Spjd		 * Convert device special files
1080168962Spjd		 */
1081168962Spjd		if (IS_DEVVP(*vpp)) {
1082168962Spjd			vnode_t	*svp;
1083168962Spjd
1084168962Spjd			svp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type, cr);
1085168962Spjd			VN_RELE(*vpp);
1086168962Spjd			if (svp == NULL)
1087168962Spjd				error = ENOSYS;
1088168962Spjd			else
1089168962Spjd				*vpp = svp;
1090168962Spjd		}
1091168962Spjd	}
1092168962Spjd
1093168404Spjd	ZFS_EXIT(zfsvfs);
1094168404Spjd
1095168404Spjd	/* Translate errors and add SAVENAME when needed. */
1096168404Spjd	if (cnp->cn_flags & ISLASTCN) {
1097168404Spjd		switch (nameiop) {
1098168404Spjd		case CREATE:
1099168404Spjd		case RENAME:
1100168404Spjd			if (error == ENOENT) {
1101168404Spjd				error = EJUSTRETURN;
1102168404Spjd				cnp->cn_flags |= SAVENAME;
1103168404Spjd				break;
1104168404Spjd			}
1105168404Spjd			/* FALLTHROUGH */
1106168404Spjd		case DELETE:
1107168404Spjd			if (error == 0)
1108168404Spjd				cnp->cn_flags |= SAVENAME;
1109168404Spjd			break;
1110168404Spjd		}
1111168404Spjd	}
1112168404Spjd	if (error == 0 && (nm[0] != '.' || nm[1] != '\0')) {
1113169198Spjd		int ltype = 0;
1114169198Spjd
1115169198Spjd		if (cnp->cn_flags & ISDOTDOT) {
1116176559Sattilio			ltype = VOP_ISLOCKED(dvp);
1117175294Sattilio			VOP_UNLOCK(dvp, 0);
1118169198Spjd		}
1119175202Sattilio		error = vn_lock(*vpp, cnp->cn_lkflags);
1120168962Spjd		if (cnp->cn_flags & ISDOTDOT)
1121175202Sattilio			vn_lock(dvp, ltype | LK_RETRY);
1122169172Spjd		if (error != 0) {
1123169172Spjd			VN_RELE(*vpp);
1124169172Spjd			*vpp = NULL;
1125169172Spjd			return (error);
1126169172Spjd		}
1127168404Spjd	}
1128168404Spjd
1129168404Spjd#ifdef FREEBSD_NAMECACHE
1130168404Spjd	/*
1131168404Spjd	 * Insert name into cache (as non-existent) if appropriate.
1132168404Spjd	 */
1133168404Spjd	if (error == ENOENT && (cnp->cn_flags & MAKEENTRY) && nameiop != CREATE)
1134168404Spjd		cache_enter(dvp, *vpp, cnp);
1135169170Spjd	/*
1136169170Spjd	 * Insert name into cache if appropriate.
1137169170Spjd	 */
1138168404Spjd	if (error == 0 && (cnp->cn_flags & MAKEENTRY)) {
1139168404Spjd		if (!(cnp->cn_flags & ISLASTCN) ||
1140168404Spjd		    (nameiop != DELETE && nameiop != RENAME)) {
1141168404Spjd			cache_enter(dvp, *vpp, cnp);
1142168404Spjd		}
1143168404Spjd	}
1144168404Spjd#endif
1145168404Spjd
1146168404Spjd	return (error);
1147168404Spjd}
1148168404Spjd
1149168404Spjd/*
1150168404Spjd * Attempt to create a new entry in a directory.  If the entry
1151168404Spjd * already exists, truncate the file if permissible, else return
1152168404Spjd * an error.  Return the vp of the created or trunc'd file.
1153168404Spjd *
1154168404Spjd *	IN:	dvp	- vnode of directory to put new file entry in.
1155168404Spjd *		name	- name of new file entry.
1156168404Spjd *		vap	- attributes of new file.
1157168404Spjd *		excl	- flag indicating exclusive or non-exclusive mode.
1158168404Spjd *		mode	- mode to open file with.
1159168404Spjd *		cr	- credentials of caller.
1160168404Spjd *		flag	- large file flag [UNUSED].
1161168404Spjd *
1162168404Spjd *	OUT:	vpp	- vnode of created or trunc'd entry.
1163168404Spjd *
1164168404Spjd *	RETURN:	0 if success
1165168404Spjd *		error code if failure
1166168404Spjd *
1167168404Spjd * Timestamps:
1168168404Spjd *	dvp - ctime|mtime updated if new entry created
1169168404Spjd *	 vp - ctime|mtime always, atime if new
1170168404Spjd */
1171168404Spjd/* ARGSUSED */
1172168404Spjdstatic int
1173168962Spjdzfs_create(vnode_t *dvp, char *name, vattr_t *vap, int excl, int mode,
1174176559Sattilio    vnode_t **vpp, cred_t *cr)
1175168404Spjd{
1176168404Spjd	znode_t		*zp, *dzp = VTOZ(dvp);
1177168404Spjd	zfsvfs_t	*zfsvfs = dzp->z_zfsvfs;
1178168404Spjd	zilog_t		*zilog = zfsvfs->z_log;
1179168404Spjd	objset_t	*os = zfsvfs->z_os;
1180168404Spjd	zfs_dirlock_t	*dl;
1181168404Spjd	dmu_tx_t	*tx;
1182168404Spjd	int		error;
1183168404Spjd	uint64_t	zoid;
1184168404Spjd
1185168404Spjd	ZFS_ENTER(zfsvfs);
1186168404Spjd
1187168404Spjdtop:
1188168404Spjd	*vpp = NULL;
1189168404Spjd
1190168404Spjd	if ((vap->va_mode & VSVTX) && secpolicy_vnode_stky_modify(cr))
1191168404Spjd		vap->va_mode &= ~VSVTX;
1192168404Spjd
1193168404Spjd	if (*name == '\0') {
1194168404Spjd		/*
1195168404Spjd		 * Null component name refers to the directory itself.
1196168404Spjd		 */
1197168404Spjd		VN_HOLD(dvp);
1198168404Spjd		zp = dzp;
1199168404Spjd		dl = NULL;
1200168404Spjd		error = 0;
1201168404Spjd	} else {
1202168404Spjd		/* possible VN_HOLD(zp) */
1203168404Spjd		if (error = zfs_dirent_lock(&dl, dzp, name, &zp, 0)) {
1204168404Spjd			if (strcmp(name, "..") == 0)
1205168404Spjd				error = EISDIR;
1206168404Spjd			ZFS_EXIT(zfsvfs);
1207168404Spjd			return (error);
1208168404Spjd		}
1209168404Spjd	}
1210168404Spjd
1211168404Spjd	zoid = zp ? zp->z_id : -1ULL;
1212168404Spjd
1213168404Spjd	if (zp == NULL) {
1214168404Spjd		/*
1215168404Spjd		 * Create a new file object and update the directory
1216168404Spjd		 * to reference it.
1217168404Spjd		 */
1218168404Spjd		if (error = zfs_zaccess(dzp, ACE_ADD_FILE, cr)) {
1219168404Spjd			goto out;
1220168404Spjd		}
1221168404Spjd
1222168404Spjd		/*
1223168404Spjd		 * We only support the creation of regular files in
1224168404Spjd		 * extended attribute directories.
1225168404Spjd		 */
1226168404Spjd		if ((dzp->z_phys->zp_flags & ZFS_XATTR) &&
1227168404Spjd		    (vap->va_type != VREG)) {
1228168404Spjd			error = EINVAL;
1229168404Spjd			goto out;
1230168404Spjd		}
1231168404Spjd
1232168404Spjd		tx = dmu_tx_create(os);
1233168404Spjd		dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT);
1234168404Spjd		dmu_tx_hold_bonus(tx, dzp->z_id);
1235168404Spjd		dmu_tx_hold_zap(tx, dzp->z_id, TRUE, name);
1236168404Spjd		if (dzp->z_phys->zp_flags & ZFS_INHERIT_ACE)
1237168404Spjd			dmu_tx_hold_write(tx, DMU_NEW_OBJECT,
1238168404Spjd			    0, SPA_MAXBLOCKSIZE);
1239168404Spjd		error = dmu_tx_assign(tx, zfsvfs->z_assign);
1240168404Spjd		if (error) {
1241168404Spjd			zfs_dirent_unlock(dl);
1242168404Spjd			if (error == ERESTART &&
1243168404Spjd			    zfsvfs->z_assign == TXG_NOWAIT) {
1244168404Spjd				dmu_tx_wait(tx);
1245168404Spjd				dmu_tx_abort(tx);
1246168404Spjd				goto top;
1247168404Spjd			}
1248168404Spjd			dmu_tx_abort(tx);
1249168404Spjd			ZFS_EXIT(zfsvfs);
1250168404Spjd			return (error);
1251168404Spjd		}
1252168404Spjd		zfs_mknode(dzp, vap, &zoid, tx, cr, 0, &zp, 0);
1253168404Spjd		ASSERT(zp->z_id == zoid);
1254168404Spjd		(void) zfs_link_create(dl, zp, tx, ZNEW);
1255168404Spjd		zfs_log_create(zilog, tx, TX_CREATE, dzp, zp, name);
1256168404Spjd		dmu_tx_commit(tx);
1257168404Spjd	} else {
1258168404Spjd		/*
1259168404Spjd		 * A directory entry already exists for this name.
1260168404Spjd		 */
1261168404Spjd		/*
1262168962Spjd		 * Can't truncate an existing file if in exclusive mode.
1263168962Spjd		 */
1264168962Spjd		if (excl == EXCL) {
1265168962Spjd			error = EEXIST;
1266168962Spjd			goto out;
1267168962Spjd		}
1268168962Spjd		/*
1269168404Spjd		 * Can't open a directory for writing.
1270168404Spjd		 */
1271168404Spjd		if ((ZTOV(zp)->v_type == VDIR) && (mode & S_IWRITE)) {
1272168404Spjd			error = EISDIR;
1273168404Spjd			goto out;
1274168404Spjd		}
1275168404Spjd		/*
1276168404Spjd		 * Verify requested access to file.
1277168404Spjd		 */
1278168404Spjd		if (mode && (error = zfs_zaccess_rwx(zp, mode, cr))) {
1279168404Spjd			goto out;
1280168404Spjd		}
1281168404Spjd
1282168404Spjd		mutex_enter(&dzp->z_lock);
1283168404Spjd		dzp->z_seq++;
1284168404Spjd		mutex_exit(&dzp->z_lock);
1285168404Spjd
1286168404Spjd		/*
1287168404Spjd		 * Truncate regular files if requested.
1288168404Spjd		 */
1289168404Spjd		if ((ZTOV(zp)->v_type == VREG) &&
1290168404Spjd		    (vap->va_mask & AT_SIZE) && (vap->va_size == 0)) {
1291168404Spjd			error = zfs_freesp(zp, 0, 0, mode, TRUE);
1292168404Spjd			if (error == ERESTART &&
1293168404Spjd			    zfsvfs->z_assign == TXG_NOWAIT) {
1294168404Spjd				/* NB: we already did dmu_tx_wait() */
1295168404Spjd				zfs_dirent_unlock(dl);
1296168404Spjd				VN_RELE(ZTOV(zp));
1297168404Spjd				goto top;
1298168404Spjd			}
1299168404Spjd		}
1300168404Spjd	}
1301168404Spjdout:
1302168404Spjd
1303168404Spjd	if (error == 0) {
1304168404Spjd		*vpp = ZTOV(zp);
1305175202Sattilio		vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY);
1306168404Spjd	}
1307168404Spjd
1308168404Spjd	if (dl)
1309168404Spjd		zfs_dirent_unlock(dl);
1310168404Spjd
1311168404Spjd	if (error) {
1312168404Spjd		if (zp)
1313168404Spjd			VN_RELE(ZTOV(zp));
1314168962Spjd	} else {
1315168962Spjd		*vpp = ZTOV(zp);
1316168962Spjd		/*
1317168962Spjd		 * If vnode is for a device return a specfs vnode instead.
1318168962Spjd		 */
1319168962Spjd		if (IS_DEVVP(*vpp)) {
1320168962Spjd			struct vnode *svp;
1321168962Spjd
1322168962Spjd			svp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type, cr);
1323168962Spjd			VN_RELE(*vpp);
1324168962Spjd			if (svp == NULL) {
1325168962Spjd				error = ENOSYS;
1326168962Spjd			}
1327168962Spjd			*vpp = svp;
1328168962Spjd		}
1329168404Spjd	}
1330168404Spjd
1331168404Spjd	ZFS_EXIT(zfsvfs);
1332168404Spjd	return (error);
1333168404Spjd}
1334168404Spjd
1335168404Spjd/*
1336168404Spjd * Remove an entry from a directory.
1337168404Spjd *
1338168404Spjd *	IN:	dvp	- vnode of directory to remove entry from.
1339168404Spjd *		name	- name of entry to remove.
1340168404Spjd *		cr	- credentials of caller.
1341168404Spjd *
1342168404Spjd *	RETURN:	0 if success
1343168404Spjd *		error code if failure
1344168404Spjd *
1345168404Spjd * Timestamps:
1346168404Spjd *	dvp - ctime|mtime
1347168404Spjd *	 vp - ctime (if nlink > 0)
1348168404Spjd */
1349168404Spjdstatic int
1350168962Spjdzfs_remove(vnode_t *dvp, char *name, cred_t *cr)
1351168404Spjd{
1352168404Spjd	znode_t		*zp, *dzp = VTOZ(dvp);
1353168404Spjd	znode_t		*xzp = NULL;
1354168404Spjd	vnode_t		*vp;
1355168404Spjd	zfsvfs_t	*zfsvfs = dzp->z_zfsvfs;
1356168404Spjd	zilog_t		*zilog = zfsvfs->z_log;
1357168962Spjd	uint64_t	acl_obj, xattr_obj;
1358168404Spjd	zfs_dirlock_t	*dl;
1359168404Spjd	dmu_tx_t	*tx;
1360168962Spjd	boolean_t	may_delete_now, delete_now = FALSE;
1361168404Spjd	boolean_t	unlinked;
1362168404Spjd	int		error;
1363168404Spjd
1364168404Spjd	ZFS_ENTER(zfsvfs);
1365168404Spjd
1366168404Spjdtop:
1367168404Spjd	/*
1368168404Spjd	 * Attempt to lock directory; fail if entry doesn't exist.
1369168404Spjd	 */
1370168404Spjd	if (error = zfs_dirent_lock(&dl, dzp, name, &zp, ZEXISTS)) {
1371168404Spjd		ZFS_EXIT(zfsvfs);
1372168404Spjd		return (error);
1373168404Spjd	}
1374168404Spjd
1375168404Spjd	vp = ZTOV(zp);
1376168404Spjd
1377168962Spjd	if (error = zfs_zaccess_delete(dzp, zp, cr)) {
1378168404Spjd		goto out;
1379168962Spjd	}
1380168404Spjd
1381168962Spjd	/*
1382168962Spjd	 * Need to use rmdir for removing directories.
1383168962Spjd	 */
1384168962Spjd	if (vp->v_type == VDIR) {
1385168962Spjd		error = EPERM;
1386168962Spjd		goto out;
1387168962Spjd	}
1388168962Spjd
1389168962Spjd	vnevent_remove(vp);
1390168962Spjd
1391168404Spjd	dnlc_remove(dvp, name);
1392168404Spjd
1393168962Spjd	may_delete_now = FALSE;
1394168962Spjd
1395168404Spjd	/*
1396168404Spjd	 * We may delete the znode now, or we may put it in the unlinked set;
1397168404Spjd	 * it depends on whether we're the last link, and on whether there are
1398168404Spjd	 * other holds on the vnode.  So we dmu_tx_hold() the right things to
1399168404Spjd	 * allow for either case.
1400168404Spjd	 */
1401168404Spjd	tx = dmu_tx_create(zfsvfs->z_os);
1402168404Spjd	dmu_tx_hold_zap(tx, dzp->z_id, FALSE, name);
1403168404Spjd	dmu_tx_hold_bonus(tx, zp->z_id);
1404168962Spjd	if (may_delete_now)
1405168962Spjd		dmu_tx_hold_free(tx, zp->z_id, 0, DMU_OBJECT_END);
1406168404Spjd
1407168404Spjd	/* are there any extended attributes? */
1408168404Spjd	if ((xattr_obj = zp->z_phys->zp_xattr) != 0) {
1409168404Spjd		/* XXX - do we need this if we are deleting? */
1410168404Spjd		dmu_tx_hold_bonus(tx, xattr_obj);
1411168404Spjd	}
1412168404Spjd
1413168962Spjd	/* are there any additional acls */
1414168962Spjd	if ((acl_obj = zp->z_phys->zp_acl.z_acl_extern_obj) != 0 &&
1415168962Spjd	    may_delete_now)
1416168962Spjd		dmu_tx_hold_free(tx, acl_obj, 0, DMU_OBJECT_END);
1417168962Spjd
1418168404Spjd	/* charge as an update -- would be nice not to charge at all */
1419168404Spjd	dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL);
1420168404Spjd
1421168404Spjd	error = dmu_tx_assign(tx, zfsvfs->z_assign);
1422168404Spjd	if (error) {
1423168404Spjd		zfs_dirent_unlock(dl);
1424168962Spjd		VN_RELE(vp);
1425168404Spjd		if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) {
1426168404Spjd			dmu_tx_wait(tx);
1427168404Spjd			dmu_tx_abort(tx);
1428168404Spjd			goto top;
1429168404Spjd		}
1430168404Spjd		dmu_tx_abort(tx);
1431168404Spjd		ZFS_EXIT(zfsvfs);
1432168404Spjd		return (error);
1433168404Spjd	}
1434168404Spjd
1435168404Spjd	/*
1436168404Spjd	 * Remove the directory entry.
1437168404Spjd	 */
1438168404Spjd	error = zfs_link_destroy(dl, zp, tx, 0, &unlinked);
1439168404Spjd
1440168404Spjd	if (error) {
1441168404Spjd		dmu_tx_commit(tx);
1442168404Spjd		goto out;
1443168404Spjd	}
1444168404Spjd
1445168962Spjd	if (0 && unlinked) {
1446168962Spjd		VI_LOCK(vp);
1447168962Spjd		delete_now = may_delete_now &&
1448168962Spjd		    vp->v_count == 1 && !vn_has_cached_data(vp) &&
1449168962Spjd		    zp->z_phys->zp_xattr == xattr_obj &&
1450168962Spjd		    zp->z_phys->zp_acl.z_acl_extern_obj == acl_obj;
1451168962Spjd		VI_UNLOCK(vp);
1452168962Spjd	}
1453168962Spjd
1454168962Spjd	if (delete_now) {
1455168962Spjd		if (zp->z_phys->zp_xattr) {
1456168962Spjd			error = zfs_zget(zfsvfs, zp->z_phys->zp_xattr, &xzp);
1457168962Spjd			ASSERT3U(error, ==, 0);
1458168962Spjd			ASSERT3U(xzp->z_phys->zp_links, ==, 2);
1459168962Spjd			dmu_buf_will_dirty(xzp->z_dbuf, tx);
1460168962Spjd			mutex_enter(&xzp->z_lock);
1461168962Spjd			xzp->z_unlinked = 1;
1462168962Spjd			xzp->z_phys->zp_links = 0;
1463168962Spjd			mutex_exit(&xzp->z_lock);
1464168962Spjd			zfs_unlinked_add(xzp, tx);
1465168962Spjd			zp->z_phys->zp_xattr = 0; /* probably unnecessary */
1466168962Spjd		}
1467168962Spjd		mutex_enter(&zp->z_lock);
1468168962Spjd		VI_LOCK(vp);
1469168962Spjd		vp->v_count--;
1470168962Spjd		ASSERT3U(vp->v_count, ==, 0);
1471168962Spjd		VI_UNLOCK(vp);
1472168962Spjd		mutex_exit(&zp->z_lock);
1473168962Spjd		zfs_znode_delete(zp, tx);
1474168962Spjd		VFS_RELE(zfsvfs->z_vfs);
1475168962Spjd	} else if (unlinked) {
1476168404Spjd		zfs_unlinked_add(zp, tx);
1477168962Spjd	}
1478168404Spjd
1479168404Spjd	zfs_log_remove(zilog, tx, TX_REMOVE, dzp, name);
1480168404Spjd
1481168404Spjd	dmu_tx_commit(tx);
1482168404Spjdout:
1483168404Spjd	zfs_dirent_unlock(dl);
1484168404Spjd
1485168962Spjd	if (!delete_now) {
1486168962Spjd		VN_RELE(vp);
1487168962Spjd	} else if (xzp) {
1488168962Spjd		/* this rele delayed to prevent nesting transactions */
1489168962Spjd		VN_RELE(ZTOV(xzp));
1490168962Spjd	}
1491168962Spjd
1492168404Spjd	ZFS_EXIT(zfsvfs);
1493168404Spjd	return (error);
1494168404Spjd}
1495168404Spjd
1496168404Spjd/*
1497168404Spjd * Create a new directory and insert it into dvp using the name
1498168404Spjd * provided.  Return a pointer to the inserted directory.
1499168404Spjd *
1500168404Spjd *	IN:	dvp	- vnode of directory to add subdir to.
1501168404Spjd *		dirname	- name of new directory.
1502168404Spjd *		vap	- attributes of new directory.
1503168404Spjd *		cr	- credentials of caller.
1504168404Spjd *
1505168404Spjd *	OUT:	vpp	- vnode of created directory.
1506168404Spjd *
1507168404Spjd *	RETURN:	0 if success
1508168404Spjd *		error code if failure
1509168404Spjd *
1510168404Spjd * Timestamps:
1511168404Spjd *	dvp - ctime|mtime updated
1512168404Spjd *	 vp - ctime|mtime|atime updated
1513168404Spjd */
1514168404Spjdstatic int
1515168962Spjdzfs_mkdir(vnode_t *dvp, char *dirname, vattr_t *vap, vnode_t **vpp, cred_t *cr)
1516168404Spjd{
1517168404Spjd	znode_t		*zp, *dzp = VTOZ(dvp);
1518168404Spjd	zfsvfs_t	*zfsvfs = dzp->z_zfsvfs;
1519168404Spjd	zilog_t		*zilog = zfsvfs->z_log;
1520168404Spjd	zfs_dirlock_t	*dl;
1521168404Spjd	uint64_t	zoid = 0;
1522168404Spjd	dmu_tx_t	*tx;
1523168404Spjd	int		error;
1524168404Spjd
1525168404Spjd	ASSERT(vap->va_type == VDIR);
1526168404Spjd
1527168404Spjd	ZFS_ENTER(zfsvfs);
1528168404Spjd
1529168404Spjd	if (dzp->z_phys->zp_flags & ZFS_XATTR) {
1530168404Spjd		ZFS_EXIT(zfsvfs);
1531168404Spjd		return (EINVAL);
1532168404Spjd	}
1533168404Spjdtop:
1534168404Spjd	*vpp = NULL;
1535168404Spjd
1536168404Spjd	/*
1537168404Spjd	 * First make sure the new directory doesn't exist.
1538168404Spjd	 */
1539168404Spjd	if (error = zfs_dirent_lock(&dl, dzp, dirname, &zp, ZNEW)) {
1540168404Spjd		ZFS_EXIT(zfsvfs);
1541168404Spjd		return (error);
1542168404Spjd	}
1543168404Spjd
1544168404Spjd	if (error = zfs_zaccess(dzp, ACE_ADD_SUBDIRECTORY, cr)) {
1545168404Spjd		zfs_dirent_unlock(dl);
1546168404Spjd		ZFS_EXIT(zfsvfs);
1547168404Spjd		return (error);
1548168404Spjd	}
1549168404Spjd
1550168404Spjd	/*
1551168404Spjd	 * Add a new entry to the directory.
1552168404Spjd	 */
1553168404Spjd	tx = dmu_tx_create(zfsvfs->z_os);
1554168404Spjd	dmu_tx_hold_zap(tx, dzp->z_id, TRUE, dirname);
1555168404Spjd	dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, FALSE, NULL);
1556168404Spjd	if (dzp->z_phys->zp_flags & ZFS_INHERIT_ACE)
1557168404Spjd		dmu_tx_hold_write(tx, DMU_NEW_OBJECT,
1558168404Spjd		    0, SPA_MAXBLOCKSIZE);
1559168404Spjd	error = dmu_tx_assign(tx, zfsvfs->z_assign);
1560168404Spjd	if (error) {
1561168404Spjd		zfs_dirent_unlock(dl);
1562168404Spjd		if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) {
1563168404Spjd			dmu_tx_wait(tx);
1564168404Spjd			dmu_tx_abort(tx);
1565168404Spjd			goto top;
1566168404Spjd		}
1567168404Spjd		dmu_tx_abort(tx);
1568168404Spjd		ZFS_EXIT(zfsvfs);
1569168404Spjd		return (error);
1570168404Spjd	}
1571168404Spjd
1572168404Spjd	/*
1573168404Spjd	 * Create new node.
1574168404Spjd	 */
1575168404Spjd	zfs_mknode(dzp, vap, &zoid, tx, cr, 0, &zp, 0);
1576168404Spjd
1577168404Spjd	/*
1578168404Spjd	 * Now put new name in parent dir.
1579168404Spjd	 */
1580168404Spjd	(void) zfs_link_create(dl, zp, tx, ZNEW);
1581168404Spjd
1582168404Spjd	*vpp = ZTOV(zp);
1583168404Spjd
1584168404Spjd	zfs_log_create(zilog, tx, TX_MKDIR, dzp, zp, dirname);
1585168404Spjd	dmu_tx_commit(tx);
1586168404Spjd
1587175202Sattilio	vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY);
1588168404Spjd
1589168404Spjd	zfs_dirent_unlock(dl);
1590168404Spjd
1591168404Spjd	ZFS_EXIT(zfsvfs);
1592168404Spjd	return (0);
1593168404Spjd}
1594168404Spjd
1595168404Spjd/*
1596168404Spjd * Remove a directory subdir entry.  If the current working
1597168404Spjd * directory is the same as the subdir to be removed, the
1598168404Spjd * remove will fail.
1599168404Spjd *
1600168404Spjd *	IN:	dvp	- vnode of directory to remove from.
1601168404Spjd *		name	- name of directory to be removed.
1602168404Spjd *		cwd	- vnode of current working directory.
1603168404Spjd *		cr	- credentials of caller.
1604168404Spjd *
1605168404Spjd *	RETURN:	0 if success
1606168404Spjd *		error code if failure
1607168404Spjd *
1608168404Spjd * Timestamps:
1609168404Spjd *	dvp - ctime|mtime updated
1610168404Spjd */
1611168404Spjdstatic int
1612168962Spjdzfs_rmdir(vnode_t *dvp, char *name, vnode_t *cwd, cred_t *cr)
1613168404Spjd{
1614168404Spjd	znode_t		*dzp = VTOZ(dvp);
1615168404Spjd	znode_t		*zp;
1616168404Spjd	vnode_t		*vp;
1617168404Spjd	zfsvfs_t	*zfsvfs = dzp->z_zfsvfs;
1618168404Spjd	zilog_t		*zilog = zfsvfs->z_log;
1619168404Spjd	zfs_dirlock_t	*dl;
1620168404Spjd	dmu_tx_t	*tx;
1621168404Spjd	int		error;
1622168404Spjd
1623168962Spjd	ZFS_ENTER(zfsvfs);
1624168404Spjd
1625168404Spjdtop:
1626168404Spjd	zp = NULL;
1627168404Spjd
1628168404Spjd	/*
1629168404Spjd	 * Attempt to lock directory; fail if entry doesn't exist.
1630168404Spjd	 */
1631168404Spjd	if (error = zfs_dirent_lock(&dl, dzp, name, &zp, ZEXISTS)) {
1632168404Spjd		ZFS_EXIT(zfsvfs);
1633168404Spjd		return (error);
1634168404Spjd	}
1635168404Spjd
1636168404Spjd	vp = ZTOV(zp);
1637168404Spjd
1638168404Spjd	if (error = zfs_zaccess_delete(dzp, zp, cr)) {
1639168404Spjd		goto out;
1640168404Spjd	}
1641168404Spjd
1642168962Spjd	if (vp->v_type != VDIR) {
1643168962Spjd		error = ENOTDIR;
1644168962Spjd		goto out;
1645168962Spjd	}
1646168962Spjd
1647168962Spjd	if (vp == cwd) {
1648168962Spjd		error = EINVAL;
1649168962Spjd		goto out;
1650168962Spjd	}
1651168962Spjd
1652168962Spjd	vnevent_rmdir(vp);
1653168962Spjd
1654168404Spjd	/*
1655168404Spjd	 * Grab a lock on the directory to make sure that noone is
1656168404Spjd	 * trying to add (or lookup) entries while we are removing it.
1657168404Spjd	 */
1658168404Spjd	rw_enter(&zp->z_name_lock, RW_WRITER);
1659168404Spjd
1660168404Spjd	/*
1661168404Spjd	 * Grab a lock on the parent pointer to make sure we play well
1662168404Spjd	 * with the treewalk and directory rename code.
1663168404Spjd	 */
1664168404Spjd	rw_enter(&zp->z_parent_lock, RW_WRITER);
1665168404Spjd
1666168404Spjd	tx = dmu_tx_create(zfsvfs->z_os);
1667168404Spjd	dmu_tx_hold_zap(tx, dzp->z_id, FALSE, name);
1668168404Spjd	dmu_tx_hold_bonus(tx, zp->z_id);
1669168404Spjd	dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL);
1670168404Spjd	error = dmu_tx_assign(tx, zfsvfs->z_assign);
1671168404Spjd	if (error) {
1672168404Spjd		rw_exit(&zp->z_parent_lock);
1673168404Spjd		rw_exit(&zp->z_name_lock);
1674168404Spjd		zfs_dirent_unlock(dl);
1675168962Spjd		VN_RELE(vp);
1676168404Spjd		if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) {
1677168404Spjd			dmu_tx_wait(tx);
1678168404Spjd			dmu_tx_abort(tx);
1679168404Spjd			goto top;
1680168404Spjd		}
1681168404Spjd		dmu_tx_abort(tx);
1682168404Spjd		ZFS_EXIT(zfsvfs);
1683168404Spjd		return (error);
1684168404Spjd	}
1685168404Spjd
1686168404Spjd#ifdef FREEBSD_NAMECACHE
1687168404Spjd	cache_purge(dvp);
1688168404Spjd#endif
1689168404Spjd
1690168404Spjd	error = zfs_link_destroy(dl, zp, tx, 0, NULL);
1691168404Spjd
1692168404Spjd	if (error == 0)
1693168404Spjd		zfs_log_remove(zilog, tx, TX_RMDIR, dzp, name);
1694168404Spjd
1695168404Spjd	dmu_tx_commit(tx);
1696168404Spjd
1697168404Spjd	rw_exit(&zp->z_parent_lock);
1698168404Spjd	rw_exit(&zp->z_name_lock);
1699168404Spjd#ifdef FREEBSD_NAMECACHE
1700168404Spjd	cache_purge(vp);
1701168404Spjd#endif
1702168404Spjdout:
1703168404Spjd	zfs_dirent_unlock(dl);
1704168404Spjd
1705168962Spjd	VN_RELE(vp);
1706168962Spjd
1707168404Spjd	ZFS_EXIT(zfsvfs);
1708168404Spjd	return (error);
1709168404Spjd}
1710168404Spjd
1711168404Spjd/*
1712168404Spjd * Read as many directory entries as will fit into the provided
1713168404Spjd * buffer from the given directory cursor position (specified in
1714168404Spjd * the uio structure.
1715168404Spjd *
1716168404Spjd *	IN:	vp	- vnode of directory to read.
1717168404Spjd *		uio	- structure supplying read location, range info,
1718168404Spjd *			  and return buffer.
1719168404Spjd *		cr	- credentials of caller.
1720168404Spjd *
1721168404Spjd *	OUT:	uio	- updated offset and range, buffer filled.
1722168404Spjd *		eofp	- set to true if end-of-file detected.
1723168404Spjd *
1724168404Spjd *	RETURN:	0 if success
1725168404Spjd *		error code if failure
1726168404Spjd *
1727168404Spjd * Timestamps:
1728168404Spjd *	vp - atime updated
1729168404Spjd *
1730168404Spjd * Note that the low 4 bits of the cookie returned by zap is always zero.
1731168404Spjd * This allows us to use the low range for "special" directory entries:
1732168404Spjd * We use 0 for '.', and 1 for '..'.  If this is the root of the filesystem,
1733168404Spjd * we use the offset 2 for the '.zfs' directory.
1734168404Spjd */
1735168404Spjd/* ARGSUSED */
1736168404Spjdstatic int
1737168962Spjdzfs_readdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp, int *ncookies, u_long **cookies)
1738168404Spjd{
1739168404Spjd	znode_t		*zp = VTOZ(vp);
1740168404Spjd	iovec_t		*iovp;
1741168404Spjd	dirent64_t	*odp;
1742168404Spjd	zfsvfs_t	*zfsvfs = zp->z_zfsvfs;
1743168404Spjd	objset_t	*os;
1744168404Spjd	caddr_t		outbuf;
1745168404Spjd	size_t		bufsize;
1746168404Spjd	zap_cursor_t	zc;
1747168404Spjd	zap_attribute_t	zap;
1748168404Spjd	uint_t		bytes_wanted;
1749168404Spjd	uint64_t	offset; /* must be unsigned; checks for < 1 */
1750168404Spjd	int		local_eof;
1751168404Spjd	int		outcount;
1752168404Spjd	int		error;
1753168404Spjd	uint8_t		prefetch;
1754168404Spjd	uint8_t		type;
1755168962Spjd	int		ncooks;
1756168962Spjd	u_long		*cooks = NULL;
1757168404Spjd
1758168404Spjd	ZFS_ENTER(zfsvfs);
1759168404Spjd
1760168404Spjd	/*
1761168404Spjd	 * If we are not given an eof variable,
1762168404Spjd	 * use a local one.
1763168404Spjd	 */
1764168404Spjd	if (eofp == NULL)
1765168404Spjd		eofp = &local_eof;
1766168404Spjd
1767168404Spjd	/*
1768168404Spjd	 * Check for valid iov_len.
1769168404Spjd	 */
1770168404Spjd	if (uio->uio_iov->iov_len <= 0) {
1771168404Spjd		ZFS_EXIT(zfsvfs);
1772168404Spjd		return (EINVAL);
1773168404Spjd	}
1774168404Spjd
1775168404Spjd	/*
1776168404Spjd	 * Quit if directory has been removed (posix)
1777168404Spjd	 */
1778168404Spjd	if ((*eofp = zp->z_unlinked) != 0) {
1779168404Spjd		ZFS_EXIT(zfsvfs);
1780168404Spjd		return (0);
1781168404Spjd	}
1782168404Spjd
1783168404Spjd	error = 0;
1784168404Spjd	os = zfsvfs->z_os;
1785168404Spjd	offset = uio->uio_loffset;
1786168404Spjd	prefetch = zp->z_zn_prefetch;
1787168404Spjd
1788168404Spjd	/*
1789168404Spjd	 * Initialize the iterator cursor.
1790168404Spjd	 */
1791168404Spjd	if (offset <= 3) {
1792168404Spjd		/*
1793168404Spjd		 * Start iteration from the beginning of the directory.
1794168404Spjd		 */
1795168404Spjd		zap_cursor_init(&zc, os, zp->z_id);
1796168404Spjd	} else {
1797168404Spjd		/*
1798168404Spjd		 * The offset is a serialized cursor.
1799168404Spjd		 */
1800168404Spjd		zap_cursor_init_serialized(&zc, os, zp->z_id, offset);
1801168404Spjd	}
1802168404Spjd
1803168404Spjd	/*
1804168404Spjd	 * Get space to change directory entries into fs independent format.
1805168404Spjd	 */
1806168404Spjd	iovp = uio->uio_iov;
1807168404Spjd	bytes_wanted = iovp->iov_len;
1808168404Spjd	if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) {
1809168404Spjd		bufsize = bytes_wanted;
1810168404Spjd		outbuf = kmem_alloc(bufsize, KM_SLEEP);
1811168404Spjd		odp = (struct dirent64 *)outbuf;
1812168404Spjd	} else {
1813168404Spjd		bufsize = bytes_wanted;
1814168404Spjd		odp = (struct dirent64 *)iovp->iov_base;
1815168404Spjd	}
1816168404Spjd
1817169170Spjd	if (ncookies != NULL) {
1818168404Spjd		/*
1819168404Spjd		 * Minimum entry size is dirent size and 1 byte for a file name.
1820168404Spjd		 */
1821168962Spjd		ncooks = uio->uio_resid / (sizeof(struct dirent) - sizeof(((struct dirent *)NULL)->d_name) + 1);
1822168962Spjd		cooks = malloc(ncooks * sizeof(u_long), M_TEMP, M_WAITOK);
1823169170Spjd		*cookies = cooks;
1824168962Spjd		*ncookies = ncooks;
1825168404Spjd	}
1826168404Spjd
1827168404Spjd	/*
1828168404Spjd	 * Transform to file-system independent format
1829168404Spjd	 */
1830168404Spjd	outcount = 0;
1831168404Spjd	while (outcount < bytes_wanted) {
1832168404Spjd		ino64_t objnum;
1833168404Spjd		ushort_t reclen;
1834168404Spjd
1835168404Spjd		/*
1836168404Spjd		 * Special case `.', `..', and `.zfs'.
1837168404Spjd		 */
1838168404Spjd		if (offset == 0) {
1839168404Spjd			(void) strcpy(zap.za_name, ".");
1840168404Spjd			objnum = zp->z_id;
1841169108Spjd			type = DT_DIR;
1842168404Spjd		} else if (offset == 1) {
1843168404Spjd			(void) strcpy(zap.za_name, "..");
1844168404Spjd			objnum = zp->z_phys->zp_parent;
1845169108Spjd			type = DT_DIR;
1846168404Spjd		} else if (offset == 2 && zfs_show_ctldir(zp)) {
1847168404Spjd			(void) strcpy(zap.za_name, ZFS_CTLDIR_NAME);
1848168404Spjd			objnum = ZFSCTL_INO_ROOT;
1849169108Spjd			type = DT_DIR;
1850168404Spjd		} else {
1851168404Spjd			/*
1852168404Spjd			 * Grab next entry.
1853168404Spjd			 */
1854168404Spjd			if (error = zap_cursor_retrieve(&zc, &zap)) {
1855168404Spjd				if ((*eofp = (error == ENOENT)) != 0)
1856168404Spjd					break;
1857168404Spjd				else
1858168404Spjd					goto update;
1859168404Spjd			}
1860168404Spjd
1861168404Spjd			if (zap.za_integer_length != 8 ||
1862168404Spjd			    zap.za_num_integers != 1) {
1863168404Spjd				cmn_err(CE_WARN, "zap_readdir: bad directory "
1864168404Spjd				    "entry, obj = %lld, offset = %lld\n",
1865168404Spjd				    (u_longlong_t)zp->z_id,
1866168404Spjd				    (u_longlong_t)offset);
1867168404Spjd				error = ENXIO;
1868168404Spjd				goto update;
1869168404Spjd			}
1870168404Spjd
1871168404Spjd			objnum = ZFS_DIRENT_OBJ(zap.za_first_integer);
1872168404Spjd			/*
1873168404Spjd			 * MacOS X can extract the object type here such as:
1874168404Spjd			 * uint8_t type = ZFS_DIRENT_TYPE(zap.za_first_integer);
1875168404Spjd			 */
1876168404Spjd			type = ZFS_DIRENT_TYPE(zap.za_first_integer);
1877168404Spjd		}
1878168404Spjd		reclen = DIRENT64_RECLEN(strlen(zap.za_name));
1879168404Spjd
1880168404Spjd		/*
1881168404Spjd		 * Will this entry fit in the buffer?
1882168404Spjd		 */
1883168404Spjd		if (outcount + reclen > bufsize) {
1884168404Spjd			/*
1885168404Spjd			 * Did we manage to fit anything in the buffer?
1886168404Spjd			 */
1887168404Spjd			if (!outcount) {
1888168404Spjd				error = EINVAL;
1889168404Spjd				goto update;
1890168404Spjd			}
1891168404Spjd			break;
1892168404Spjd		}
1893168404Spjd		/*
1894168404Spjd		 * Add this entry:
1895168404Spjd		 */
1896168404Spjd		odp->d_ino = objnum;
1897168404Spjd		odp->d_reclen = reclen;
1898168404Spjd		odp->d_namlen = strlen(zap.za_name);
1899168404Spjd		(void) strlcpy(odp->d_name, zap.za_name, odp->d_namlen + 1);
1900168404Spjd		odp->d_type = type;
1901168404Spjd		outcount += reclen;
1902168404Spjd		odp = (dirent64_t *)((intptr_t)odp + reclen);
1903168404Spjd
1904168404Spjd		ASSERT(outcount <= bufsize);
1905168404Spjd
1906168404Spjd		/* Prefetch znode */
1907168404Spjd		if (prefetch)
1908168404Spjd			dmu_prefetch(os, objnum, 0, 0);
1909168404Spjd
1910168404Spjd		/*
1911168404Spjd		 * Move to the next entry, fill in the previous offset.
1912168404Spjd		 */
1913168404Spjd		if (offset > 2 || (offset == 2 && !zfs_show_ctldir(zp))) {
1914168404Spjd			zap_cursor_advance(&zc);
1915168404Spjd			offset = zap_cursor_serialize(&zc);
1916168404Spjd		} else {
1917168404Spjd			offset += 1;
1918168404Spjd		}
1919168404Spjd
1920168962Spjd		if (cooks != NULL) {
1921168962Spjd			*cooks++ = offset;
1922168962Spjd			ncooks--;
1923168962Spjd			KASSERT(ncooks >= 0, ("ncookies=%d", ncooks));
1924168404Spjd		}
1925168404Spjd	}
1926168404Spjd	zp->z_zn_prefetch = B_FALSE; /* a lookup will re-enable pre-fetching */
1927168404Spjd
1928168404Spjd	/* Subtract unused cookies */
1929168962Spjd	if (ncookies != NULL)
1930168962Spjd		*ncookies -= ncooks;
1931168404Spjd
1932168404Spjd	if (uio->uio_segflg == UIO_SYSSPACE && uio->uio_iovcnt == 1) {
1933168404Spjd		iovp->iov_base += outcount;
1934168404Spjd		iovp->iov_len -= outcount;
1935168404Spjd		uio->uio_resid -= outcount;
1936168404Spjd	} else if (error = uiomove(outbuf, (long)outcount, UIO_READ, uio)) {
1937168404Spjd		/*
1938168404Spjd		 * Reset the pointer.
1939168404Spjd		 */
1940168404Spjd		offset = uio->uio_loffset;
1941168404Spjd	}
1942168404Spjd
1943168404Spjdupdate:
1944168404Spjd	zap_cursor_fini(&zc);
1945168404Spjd	if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
1946168404Spjd		kmem_free(outbuf, bufsize);
1947168404Spjd
1948168404Spjd	if (error == ENOENT)
1949168404Spjd		error = 0;
1950168404Spjd
1951168404Spjd	ZFS_ACCESSTIME_STAMP(zfsvfs, zp);
1952168404Spjd
1953168404Spjd	uio->uio_loffset = offset;
1954168404Spjd	ZFS_EXIT(zfsvfs);
1955169107Spjd	if (error != 0 && cookies != NULL) {
1956168962Spjd		free(*cookies, M_TEMP);
1957168962Spjd		*cookies = NULL;
1958168962Spjd		*ncookies = 0;
1959168404Spjd	}
1960168404Spjd	return (error);
1961168404Spjd}
1962168404Spjd
1963168404Spjdstatic int
1964168962Spjdzfs_fsync(vnode_t *vp, int syncflag, cred_t *cr)
1965168404Spjd{
1966168962Spjd	znode_t	*zp = VTOZ(vp);
1967168962Spjd	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
1968168404Spjd
1969168404Spjd	ZFS_ENTER(zfsvfs);
1970168404Spjd	zil_commit(zfsvfs->z_log, zp->z_last_itx, zp->z_id);
1971168404Spjd	ZFS_EXIT(zfsvfs);
1972168404Spjd	return (0);
1973168404Spjd}
1974168404Spjd
1975168404Spjd/*
1976168404Spjd * Get the requested file attributes and place them in the provided
1977168404Spjd * vattr structure.
1978168404Spjd *
1979168404Spjd *	IN:	vp	- vnode of file.
1980168404Spjd *		vap	- va_mask identifies requested attributes.
1981168404Spjd *		flags	- [UNUSED]
1982168404Spjd *		cr	- credentials of caller.
1983168404Spjd *
1984168404Spjd *	OUT:	vap	- attribute values.
1985168404Spjd *
1986168404Spjd *	RETURN:	0 (always succeeds)
1987168404Spjd */
1988168404Spjd/* ARGSUSED */
1989168404Spjdstatic int
1990168962Spjdzfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr)
1991168404Spjd{
1992168962Spjd	znode_t *zp = VTOZ(vp);
1993168962Spjd	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
1994168962Spjd	znode_phys_t *pzp = zp->z_phys;
1995168962Spjd	uint32_t blksize;
1996168962Spjd	u_longlong_t nblocks;
1997168962Spjd	int	error;
1998168404Spjd
1999168404Spjd	ZFS_ENTER(zfsvfs);
2000168404Spjd
2001168404Spjd	/*
2002168404Spjd	 * Return all attributes.  It's cheaper to provide the answer
2003168404Spjd	 * than to determine whether we were asked the question.
2004168404Spjd	 */
2005168404Spjd	mutex_enter(&zp->z_lock);
2006168404Spjd
2007168404Spjd	vap->va_type = IFTOVT(pzp->zp_mode);
2008168404Spjd	vap->va_mode = pzp->zp_mode & ~S_IFMT;
2009168404Spjd	vap->va_uid = zp->z_phys->zp_uid;
2010168404Spjd	vap->va_gid = zp->z_phys->zp_gid;
2011168404Spjd	vap->va_nodeid = zp->z_id;
2012168404Spjd	vap->va_nlink = MIN(pzp->zp_links, UINT32_MAX);	/* nlink_t limit! */
2013168404Spjd	vap->va_size = pzp->zp_size;
2014168404Spjd	vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
2015168958Spjd	vap->va_rdev = zfs_cmpldev(pzp->zp_rdev);
2016168404Spjd	vap->va_seq = zp->z_seq;
2017168404Spjd	vap->va_flags = 0;	/* FreeBSD: Reset chflags(2) flags. */
2018168404Spjd
2019168404Spjd	ZFS_TIME_DECODE(&vap->va_atime, pzp->zp_atime);
2020168404Spjd	ZFS_TIME_DECODE(&vap->va_mtime, pzp->zp_mtime);
2021168404Spjd	ZFS_TIME_DECODE(&vap->va_ctime, pzp->zp_ctime);
2022168404Spjd	ZFS_TIME_DECODE(&vap->va_birthtime, pzp->zp_crtime);
2023168404Spjd
2024168404Spjd	/*
2025168404Spjd	 * If ACL is trivial don't bother looking for ACE_READ_ATTRIBUTES.
2026168404Spjd	 * Also, if we are the owner don't bother, since owner should
2027168404Spjd	 * always be allowed to read basic attributes of file.
2028168404Spjd	 */
2029168404Spjd	if (!(zp->z_phys->zp_flags & ZFS_ACL_TRIVIAL) &&
2030168404Spjd	    (zp->z_phys->zp_uid != crgetuid(cr))) {
2031168404Spjd		if (error = zfs_zaccess(zp, ACE_READ_ATTRIBUTES, cr)) {
2032168404Spjd			mutex_exit(&zp->z_lock);
2033168404Spjd			ZFS_EXIT(zfsvfs);
2034168404Spjd			return (error);
2035168404Spjd		}
2036168404Spjd	}
2037168404Spjd
2038168404Spjd	mutex_exit(&zp->z_lock);
2039168404Spjd
2040168404Spjd	dmu_object_size_from_db(zp->z_dbuf, &blksize, &nblocks);
2041168404Spjd	vap->va_blksize = blksize;
2042168404Spjd	vap->va_bytes = nblocks << 9;	/* nblocks * 512 */
2043168404Spjd
2044168404Spjd	if (zp->z_blksz == 0) {
2045168404Spjd		/*
2046168404Spjd		 * Block size hasn't been set; suggest maximal I/O transfers.
2047168404Spjd		 */
2048168404Spjd		vap->va_blksize = zfsvfs->z_max_blksz;
2049168404Spjd	}
2050168404Spjd
2051168404Spjd	ZFS_EXIT(zfsvfs);
2052168404Spjd	return (0);
2053168404Spjd}
2054168404Spjd
2055168404Spjd/*
2056168404Spjd * Set the file attributes to the values contained in the
2057168404Spjd * vattr structure.
2058168404Spjd *
2059168404Spjd *	IN:	vp	- vnode of file to be modified.
2060168404Spjd *		vap	- new attribute values.
2061168404Spjd *		flags	- ATTR_UTIME set if non-default time values provided.
2062168404Spjd *		cr	- credentials of caller.
2063168404Spjd *
2064168404Spjd *	RETURN:	0 if success
2065168404Spjd *		error code if failure
2066168404Spjd *
2067168404Spjd * Timestamps:
2068168404Spjd *	vp - ctime updated, mtime updated if size changed.
2069168404Spjd */
2070168404Spjd/* ARGSUSED */
2071168404Spjdstatic int
2072168962Spjdzfs_setattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
2073168962Spjd	caller_context_t *ct)
2074168404Spjd{
2075168962Spjd	struct znode	*zp = VTOZ(vp);
2076168404Spjd	znode_phys_t	*pzp = zp->z_phys;
2077168404Spjd	zfsvfs_t	*zfsvfs = zp->z_zfsvfs;
2078168404Spjd	zilog_t		*zilog = zfsvfs->z_log;
2079168404Spjd	dmu_tx_t	*tx;
2080168404Spjd	vattr_t		oldva;
2081168962Spjd	uint_t		mask = vap->va_mask;
2082168404Spjd	uint_t		saved_mask;
2083168404Spjd	int		trim_mask = 0;
2084168404Spjd	uint64_t	new_mode;
2085168404Spjd	znode_t		*attrzp;
2086168404Spjd	int		need_policy = FALSE;
2087168404Spjd	int		err;
2088168404Spjd
2089168404Spjd	if (mask == 0)
2090168404Spjd		return (0);
2091168404Spjd
2092168962Spjd	if (mask & AT_NOSET)
2093168962Spjd		return (EINVAL);
2094168962Spjd
2095168404Spjd	if (mask & AT_SIZE && vp->v_type == VDIR)
2096168404Spjd		return (EISDIR);
2097168404Spjd
2098168404Spjd	if (mask & AT_SIZE && vp->v_type != VREG && vp->v_type != VFIFO)
2099168404Spjd		return (EINVAL);
2100168404Spjd
2101168404Spjd	ZFS_ENTER(zfsvfs);
2102168404Spjd
2103168404Spjdtop:
2104168404Spjd	attrzp = NULL;
2105168404Spjd
2106168404Spjd	if (zfsvfs->z_vfs->vfs_flag & VFS_RDONLY) {
2107168404Spjd		ZFS_EXIT(zfsvfs);
2108168404Spjd		return (EROFS);
2109168404Spjd	}
2110168404Spjd
2111168404Spjd	/*
2112168404Spjd	 * First validate permissions
2113168404Spjd	 */
2114168404Spjd
2115168404Spjd	if (mask & AT_SIZE) {
2116168404Spjd		err = zfs_zaccess(zp, ACE_WRITE_DATA, cr);
2117168404Spjd		if (err) {
2118168404Spjd			ZFS_EXIT(zfsvfs);
2119168404Spjd			return (err);
2120168404Spjd		}
2121168404Spjd		/*
2122168404Spjd		 * XXX - Note, we are not providing any open
2123168404Spjd		 * mode flags here (like FNDELAY), so we may
2124168404Spjd		 * block if there are locks present... this
2125168404Spjd		 * should be addressed in openat().
2126168404Spjd		 */
2127168404Spjd		do {
2128168404Spjd			err = zfs_freesp(zp, vap->va_size, 0, 0, FALSE);
2129168404Spjd			/* NB: we already did dmu_tx_wait() if necessary */
2130168404Spjd		} while (err == ERESTART && zfsvfs->z_assign == TXG_NOWAIT);
2131168404Spjd		if (err) {
2132168404Spjd			ZFS_EXIT(zfsvfs);
2133168404Spjd			return (err);
2134168404Spjd		}
2135168404Spjd	}
2136168404Spjd
2137168404Spjd	if (mask & (AT_ATIME|AT_MTIME))
2138168404Spjd		need_policy = zfs_zaccess_v4_perm(zp, ACE_WRITE_ATTRIBUTES, cr);
2139168404Spjd
2140168404Spjd	if (mask & (AT_UID|AT_GID)) {
2141168404Spjd		int	idmask = (mask & (AT_UID|AT_GID));
2142168404Spjd		int	take_owner;
2143168404Spjd		int	take_group;
2144168404Spjd
2145168404Spjd		/*
2146168404Spjd		 * NOTE: even if a new mode is being set,
2147168404Spjd		 * we may clear S_ISUID/S_ISGID bits.
2148168404Spjd		 */
2149168404Spjd
2150168404Spjd		if (!(mask & AT_MODE))
2151168404Spjd			vap->va_mode = pzp->zp_mode;
2152168404Spjd
2153168404Spjd		/*
2154168404Spjd		 * Take ownership or chgrp to group we are a member of
2155168404Spjd		 */
2156168404Spjd
2157168404Spjd		take_owner = (mask & AT_UID) && (vap->va_uid == crgetuid(cr));
2158168404Spjd		take_group = (mask & AT_GID) && groupmember(vap->va_gid, cr);
2159168404Spjd
2160168404Spjd		/*
2161168404Spjd		 * If both AT_UID and AT_GID are set then take_owner and
2162168404Spjd		 * take_group must both be set in order to allow taking
2163168404Spjd		 * ownership.
2164168404Spjd		 *
2165168404Spjd		 * Otherwise, send the check through secpolicy_vnode_setattr()
2166168404Spjd		 *
2167168404Spjd		 */
2168168404Spjd
2169168404Spjd		if (((idmask == (AT_UID|AT_GID)) && take_owner && take_group) ||
2170168404Spjd		    ((idmask == AT_UID) && take_owner) ||
2171168404Spjd		    ((idmask == AT_GID) && take_group)) {
2172168404Spjd			if (zfs_zaccess_v4_perm(zp, ACE_WRITE_OWNER, cr) == 0) {
2173168404Spjd				/*
2174168404Spjd				 * Remove setuid/setgid for non-privileged users
2175168404Spjd				 */
2176168404Spjd				secpolicy_setid_clear(vap, cr);
2177168404Spjd				trim_mask = (mask & (AT_UID|AT_GID));
2178168404Spjd			} else {
2179168404Spjd				need_policy =  TRUE;
2180168404Spjd			}
2181168404Spjd		} else {
2182168404Spjd			need_policy =  TRUE;
2183168404Spjd		}
2184168404Spjd	}
2185168404Spjd
2186168404Spjd	mutex_enter(&zp->z_lock);
2187168404Spjd	oldva.va_mode = pzp->zp_mode;
2188168404Spjd	oldva.va_uid = zp->z_phys->zp_uid;
2189168404Spjd	oldva.va_gid = zp->z_phys->zp_gid;
2190168404Spjd	mutex_exit(&zp->z_lock);
2191168404Spjd
2192168404Spjd	if (mask & AT_MODE) {
2193168404Spjd		if (zfs_zaccess_v4_perm(zp, ACE_WRITE_ACL, cr) == 0) {
2194168962Spjd			err = secpolicy_setid_setsticky_clear(vp, vap,
2195168962Spjd			    &oldva, cr);
2196168962Spjd			if (err) {
2197168962Spjd				ZFS_EXIT(zfsvfs);
2198168962Spjd				return (err);
2199168962Spjd			}
2200168404Spjd			trim_mask |= AT_MODE;
2201168404Spjd		} else {
2202168404Spjd			need_policy = TRUE;
2203168404Spjd		}
2204168404Spjd	}
2205168404Spjd
2206168404Spjd	if (need_policy) {
2207168404Spjd		/*
2208168404Spjd		 * If trim_mask is set then take ownership
2209168404Spjd		 * has been granted or write_acl is present and user
2210168404Spjd		 * has the ability to modify mode.  In that case remove
2211168404Spjd		 * UID|GID and or MODE from mask so that
2212168404Spjd		 * secpolicy_vnode_setattr() doesn't revoke it.
2213168404Spjd		 */
2214168404Spjd
2215168404Spjd		if (trim_mask) {
2216168404Spjd			saved_mask = vap->va_mask;
2217168404Spjd			vap->va_mask &= ~trim_mask;
2218168404Spjd
2219168404Spjd		}
2220168404Spjd		err = secpolicy_vnode_setattr(cr, vp, vap, &oldva, flags,
2221168404Spjd		    (int (*)(void *, int, cred_t *))zfs_zaccess_rwx, zp);
2222168404Spjd		if (err) {
2223168404Spjd			ZFS_EXIT(zfsvfs);
2224168404Spjd			return (err);
2225168404Spjd		}
2226168404Spjd
2227168404Spjd		if (trim_mask)
2228168404Spjd			vap->va_mask |= saved_mask;
2229168404Spjd	}
2230168404Spjd
2231168404Spjd	/*
2232168404Spjd	 * secpolicy_vnode_setattr, or take ownership may have
2233168404Spjd	 * changed va_mask
2234168404Spjd	 */
2235168404Spjd	mask = vap->va_mask;
2236168404Spjd
2237168404Spjd	tx = dmu_tx_create(zfsvfs->z_os);
2238168404Spjd	dmu_tx_hold_bonus(tx, zp->z_id);
2239168404Spjd
2240168404Spjd	if (mask & AT_MODE) {
2241168404Spjd		uint64_t pmode = pzp->zp_mode;
2242168404Spjd
2243168404Spjd		new_mode = (pmode & S_IFMT) | (vap->va_mode & ~S_IFMT);
2244168404Spjd
2245168404Spjd		if (zp->z_phys->zp_acl.z_acl_extern_obj)
2246168404Spjd			dmu_tx_hold_write(tx,
2247168404Spjd			    pzp->zp_acl.z_acl_extern_obj, 0, SPA_MAXBLOCKSIZE);
2248168404Spjd		else
2249168404Spjd			dmu_tx_hold_write(tx, DMU_NEW_OBJECT,
2250168404Spjd			    0, ZFS_ACL_SIZE(MAX_ACL_SIZE));
2251168404Spjd	}
2252168404Spjd
2253168404Spjd	if ((mask & (AT_UID | AT_GID)) && zp->z_phys->zp_xattr != 0) {
2254168404Spjd		err = zfs_zget(zp->z_zfsvfs, zp->z_phys->zp_xattr, &attrzp);
2255168404Spjd		if (err) {
2256168404Spjd			dmu_tx_abort(tx);
2257168404Spjd			ZFS_EXIT(zfsvfs);
2258168404Spjd			return (err);
2259168404Spjd		}
2260168404Spjd		dmu_tx_hold_bonus(tx, attrzp->z_id);
2261168404Spjd	}
2262168404Spjd
2263168404Spjd	err = dmu_tx_assign(tx, zfsvfs->z_assign);
2264168404Spjd	if (err) {
2265168404Spjd		if (attrzp)
2266168404Spjd			VN_RELE(ZTOV(attrzp));
2267168404Spjd		if (err == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) {
2268168404Spjd			dmu_tx_wait(tx);
2269168404Spjd			dmu_tx_abort(tx);
2270168404Spjd			goto top;
2271168404Spjd		}
2272168404Spjd		dmu_tx_abort(tx);
2273168404Spjd		ZFS_EXIT(zfsvfs);
2274168404Spjd		return (err);
2275168404Spjd	}
2276168404Spjd
2277168404Spjd	dmu_buf_will_dirty(zp->z_dbuf, tx);
2278168404Spjd
2279168404Spjd	/*
2280168404Spjd	 * Set each attribute requested.
2281168404Spjd	 * We group settings according to the locks they need to acquire.
2282168404Spjd	 *
2283168404Spjd	 * Note: you cannot set ctime directly, although it will be
2284168404Spjd	 * updated as a side-effect of calling this function.
2285168404Spjd	 */
2286168404Spjd
2287168404Spjd	mutex_enter(&zp->z_lock);
2288168404Spjd
2289168404Spjd	if (mask & AT_MODE) {
2290168404Spjd		err = zfs_acl_chmod_setattr(zp, new_mode, tx);
2291168404Spjd		ASSERT3U(err, ==, 0);
2292168404Spjd	}
2293168404Spjd
2294168404Spjd	if (attrzp)
2295168404Spjd		mutex_enter(&attrzp->z_lock);
2296168404Spjd
2297168404Spjd	if (mask & AT_UID) {
2298168404Spjd		zp->z_phys->zp_uid = (uint64_t)vap->va_uid;
2299168404Spjd		if (attrzp) {
2300168404Spjd			attrzp->z_phys->zp_uid = (uint64_t)vap->va_uid;
2301168404Spjd		}
2302168404Spjd	}
2303168404Spjd
2304168404Spjd	if (mask & AT_GID) {
2305168404Spjd		zp->z_phys->zp_gid = (uint64_t)vap->va_gid;
2306168404Spjd		if (attrzp)
2307168404Spjd			attrzp->z_phys->zp_gid = (uint64_t)vap->va_gid;
2308168404Spjd	}
2309168404Spjd
2310168404Spjd	if (attrzp)
2311168404Spjd		mutex_exit(&attrzp->z_lock);
2312168404Spjd
2313168404Spjd	if (mask & AT_ATIME)
2314168404Spjd		ZFS_TIME_ENCODE(&vap->va_atime, pzp->zp_atime);
2315168404Spjd
2316168404Spjd	if (mask & AT_MTIME)
2317168404Spjd		ZFS_TIME_ENCODE(&vap->va_mtime, pzp->zp_mtime);
2318168404Spjd
2319168404Spjd	if (mask & AT_SIZE)
2320168404Spjd		zfs_time_stamper_locked(zp, CONTENT_MODIFIED, tx);
2321168404Spjd	else if (mask != 0)
2322168404Spjd		zfs_time_stamper_locked(zp, STATE_CHANGED, tx);
2323168404Spjd
2324168404Spjd	if (mask != 0)
2325168404Spjd		zfs_log_setattr(zilog, tx, TX_SETATTR, zp, vap, mask);
2326168404Spjd
2327168404Spjd	mutex_exit(&zp->z_lock);
2328168404Spjd
2329168404Spjd	if (attrzp)
2330168404Spjd		VN_RELE(ZTOV(attrzp));
2331168404Spjd
2332168404Spjd	dmu_tx_commit(tx);
2333168404Spjd
2334168404Spjd	ZFS_EXIT(zfsvfs);
2335168404Spjd	return (err);
2336168404Spjd}
2337168404Spjd
2338168404Spjdtypedef struct zfs_zlock {
2339168404Spjd	krwlock_t	*zl_rwlock;	/* lock we acquired */
2340168404Spjd	znode_t		*zl_znode;	/* znode we held */
2341168404Spjd	struct zfs_zlock *zl_next;	/* next in list */
2342168404Spjd} zfs_zlock_t;
2343168404Spjd
2344168404Spjd/*
2345168404Spjd * Drop locks and release vnodes that were held by zfs_rename_lock().
2346168404Spjd */
2347168404Spjdstatic void
2348168404Spjdzfs_rename_unlock(zfs_zlock_t **zlpp)
2349168404Spjd{
2350168404Spjd	zfs_zlock_t *zl;
2351168404Spjd
2352168404Spjd	while ((zl = *zlpp) != NULL) {
2353168404Spjd		if (zl->zl_znode != NULL)
2354168404Spjd			VN_RELE(ZTOV(zl->zl_znode));
2355168404Spjd		rw_exit(zl->zl_rwlock);
2356168404Spjd		*zlpp = zl->zl_next;
2357168404Spjd		kmem_free(zl, sizeof (*zl));
2358168404Spjd	}
2359168404Spjd}
2360168404Spjd
2361168404Spjd/*
2362168404Spjd * Search back through the directory tree, using the ".." entries.
2363168404Spjd * Lock each directory in the chain to prevent concurrent renames.
2364168404Spjd * Fail any attempt to move a directory into one of its own descendants.
2365168404Spjd * XXX - z_parent_lock can overlap with map or grow locks
2366168404Spjd */
2367168404Spjdstatic int
2368168404Spjdzfs_rename_lock(znode_t *szp, znode_t *tdzp, znode_t *sdzp, zfs_zlock_t **zlpp)
2369168404Spjd{
2370168404Spjd	zfs_zlock_t	*zl;
2371168404Spjd	znode_t		*zp = tdzp;
2372168404Spjd	uint64_t	rootid = zp->z_zfsvfs->z_root;
2373168404Spjd	uint64_t	*oidp = &zp->z_id;
2374168404Spjd	krwlock_t	*rwlp = &szp->z_parent_lock;
2375168404Spjd	krw_t		rw = RW_WRITER;
2376168404Spjd
2377168404Spjd	/*
2378168404Spjd	 * First pass write-locks szp and compares to zp->z_id.
2379168404Spjd	 * Later passes read-lock zp and compare to zp->z_parent.
2380168404Spjd	 */
2381168404Spjd	do {
2382168404Spjd		if (!rw_tryenter(rwlp, rw)) {
2383168404Spjd			/*
2384168404Spjd			 * Another thread is renaming in this path.
2385168404Spjd			 * Note that if we are a WRITER, we don't have any
2386168404Spjd			 * parent_locks held yet.
2387168404Spjd			 */
2388168404Spjd			if (rw == RW_READER && zp->z_id > szp->z_id) {
2389168404Spjd				/*
2390168404Spjd				 * Drop our locks and restart
2391168404Spjd				 */
2392168404Spjd				zfs_rename_unlock(&zl);
2393168404Spjd				*zlpp = NULL;
2394168404Spjd				zp = tdzp;
2395168404Spjd				oidp = &zp->z_id;
2396168404Spjd				rwlp = &szp->z_parent_lock;
2397168404Spjd				rw = RW_WRITER;
2398168404Spjd				continue;
2399168404Spjd			} else {
2400168404Spjd				/*
2401168404Spjd				 * Wait for other thread to drop its locks
2402168404Spjd				 */
2403168404Spjd				rw_enter(rwlp, rw);
2404168404Spjd			}
2405168404Spjd		}
2406168404Spjd
2407168404Spjd		zl = kmem_alloc(sizeof (*zl), KM_SLEEP);
2408168404Spjd		zl->zl_rwlock = rwlp;
2409168404Spjd		zl->zl_znode = NULL;
2410168404Spjd		zl->zl_next = *zlpp;
2411168404Spjd		*zlpp = zl;
2412168404Spjd
2413168404Spjd		if (*oidp == szp->z_id)		/* We're a descendant of szp */
2414168404Spjd			return (EINVAL);
2415168404Spjd
2416168404Spjd		if (*oidp == rootid)		/* We've hit the top */
2417168404Spjd			return (0);
2418168404Spjd
2419168404Spjd		if (rw == RW_READER) {		/* i.e. not the first pass */
2420168404Spjd			int error = zfs_zget(zp->z_zfsvfs, *oidp, &zp);
2421168404Spjd			if (error)
2422168404Spjd				return (error);
2423168404Spjd			zl->zl_znode = zp;
2424168404Spjd		}
2425168404Spjd		oidp = &zp->z_phys->zp_parent;
2426168404Spjd		rwlp = &zp->z_parent_lock;
2427168404Spjd		rw = RW_READER;
2428168404Spjd
2429168404Spjd	} while (zp->z_id != sdzp->z_id);
2430168404Spjd
2431168404Spjd	return (0);
2432168404Spjd}
2433168404Spjd
2434168404Spjd/*
2435168404Spjd * Move an entry from the provided source directory to the target
2436168404Spjd * directory.  Change the entry name as indicated.
2437168404Spjd *
2438168404Spjd *	IN:	sdvp	- Source directory containing the "old entry".
2439168404Spjd *		snm	- Old entry name.
2440168404Spjd *		tdvp	- Target directory to contain the "new entry".
2441168404Spjd *		tnm	- New entry name.
2442168404Spjd *		cr	- credentials of caller.
2443168404Spjd *
2444168404Spjd *	RETURN:	0 if success
2445168404Spjd *		error code if failure
2446168404Spjd *
2447168404Spjd * Timestamps:
2448168404Spjd *	sdvp,tdvp - ctime|mtime updated
2449168404Spjd */
2450168404Spjdstatic int
2451168962Spjdzfs_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm, cred_t *cr)
2452168404Spjd{
2453168404Spjd	znode_t		*tdzp, *szp, *tzp;
2454168404Spjd	znode_t		*sdzp = VTOZ(sdvp);
2455168404Spjd	zfsvfs_t	*zfsvfs = sdzp->z_zfsvfs;
2456168404Spjd	zilog_t		*zilog = zfsvfs->z_log;
2457168962Spjd	vnode_t		*realvp;
2458168404Spjd	zfs_dirlock_t	*sdl, *tdl;
2459168404Spjd	dmu_tx_t	*tx;
2460168404Spjd	zfs_zlock_t	*zl;
2461168962Spjd	int		cmp, serr, terr, error;
2462168404Spjd
2463168404Spjd	ZFS_ENTER(zfsvfs);
2464168404Spjd
2465168962Spjd	/*
2466168962Spjd	 * Make sure we have the real vp for the target directory.
2467168962Spjd	 */
2468168962Spjd	if (VOP_REALVP(tdvp, &realvp) == 0)
2469168962Spjd		tdvp = realvp;
2470168962Spjd
2471168404Spjd	if (tdvp->v_vfsp != sdvp->v_vfsp) {
2472168404Spjd		ZFS_EXIT(zfsvfs);
2473168962Spjd		return (EXDEV);
2474168404Spjd	}
2475168404Spjd
2476168404Spjd	tdzp = VTOZ(tdvp);
2477168404Spjdtop:
2478168404Spjd	szp = NULL;
2479168404Spjd	tzp = NULL;
2480168404Spjd	zl = NULL;
2481168404Spjd
2482168404Spjd	/*
2483168404Spjd	 * This is to prevent the creation of links into attribute space
2484168404Spjd	 * by renaming a linked file into/outof an attribute directory.
2485168404Spjd	 * See the comment in zfs_link() for why this is considered bad.
2486168404Spjd	 */
2487168404Spjd	if ((tdzp->z_phys->zp_flags & ZFS_XATTR) !=
2488168404Spjd	    (sdzp->z_phys->zp_flags & ZFS_XATTR)) {
2489168962Spjd		ZFS_EXIT(zfsvfs);
2490168962Spjd		return (EINVAL);
2491168404Spjd	}
2492168404Spjd
2493168404Spjd	/*
2494168404Spjd	 * Lock source and target directory entries.  To prevent deadlock,
2495168404Spjd	 * a lock ordering must be defined.  We lock the directory with
2496168404Spjd	 * the smallest object id first, or if it's a tie, the one with
2497168404Spjd	 * the lexically first name.
2498168404Spjd	 */
2499168404Spjd	if (sdzp->z_id < tdzp->z_id) {
2500168962Spjd		cmp = -1;
2501168962Spjd	} else if (sdzp->z_id > tdzp->z_id) {
2502168962Spjd		cmp = 1;
2503168962Spjd	} else {
2504168962Spjd		cmp = strcmp(snm, tnm);
2505168962Spjd		if (cmp == 0) {
2506168962Spjd			/*
2507168962Spjd			 * POSIX: "If the old argument and the new argument
2508168962Spjd			 * both refer to links to the same existing file,
2509168962Spjd			 * the rename() function shall return successfully
2510168962Spjd			 * and perform no other action."
2511168962Spjd			 */
2512168962Spjd			ZFS_EXIT(zfsvfs);
2513168962Spjd			return (0);
2514168962Spjd		}
2515168962Spjd	}
2516168962Spjd	if (cmp < 0) {
2517168404Spjd		serr = zfs_dirent_lock(&sdl, sdzp, snm, &szp, ZEXISTS);
2518168404Spjd		terr = zfs_dirent_lock(&tdl, tdzp, tnm, &tzp, 0);
2519168962Spjd	} else {
2520168404Spjd		terr = zfs_dirent_lock(&tdl, tdzp, tnm, &tzp, 0);
2521168404Spjd		serr = zfs_dirent_lock(&sdl, sdzp, snm, &szp, ZEXISTS);
2522168404Spjd	}
2523168404Spjd
2524168962Spjd	if (serr) {
2525168404Spjd		/*
2526168404Spjd		 * Source entry invalid or not there.
2527168404Spjd		 */
2528168962Spjd		if (!terr) {
2529168404Spjd			zfs_dirent_unlock(tdl);
2530168962Spjd			if (tzp)
2531168962Spjd				VN_RELE(ZTOV(tzp));
2532168962Spjd		}
2533168404Spjd		if (strcmp(snm, ".") == 0 || strcmp(snm, "..") == 0)
2534168404Spjd			serr = EINVAL;
2535168962Spjd		ZFS_EXIT(zfsvfs);
2536168962Spjd		return (serr);
2537168404Spjd	}
2538168404Spjd	if (terr) {
2539168404Spjd		zfs_dirent_unlock(sdl);
2540168962Spjd		VN_RELE(ZTOV(szp));
2541168404Spjd		if (strcmp(tnm, "..") == 0)
2542168404Spjd			terr = EINVAL;
2543168962Spjd		ZFS_EXIT(zfsvfs);
2544168962Spjd		return (terr);
2545168404Spjd	}
2546168404Spjd
2547168404Spjd	/*
2548168404Spjd	 * Must have write access at the source to remove the old entry
2549168404Spjd	 * and write access at the target to create the new entry.
2550168404Spjd	 * Note that if target and source are the same, this can be
2551168404Spjd	 * done in a single check.
2552168404Spjd	 */
2553168404Spjd
2554168404Spjd	if (error = zfs_zaccess_rename(sdzp, szp, tdzp, tzp, cr))
2555168404Spjd		goto out;
2556168404Spjd
2557168962Spjd	if (ZTOV(szp)->v_type == VDIR) {
2558168404Spjd		/*
2559168404Spjd		 * Check to make sure rename is valid.
2560168404Spjd		 * Can't do a move like this: /usr/a/b to /usr/a/b/c/d
2561168404Spjd		 */
2562168404Spjd		if (error = zfs_rename_lock(szp, tdzp, sdzp, &zl))
2563168404Spjd			goto out;
2564168404Spjd	}
2565168404Spjd
2566168404Spjd	/*
2567168404Spjd	 * Does target exist?
2568168404Spjd	 */
2569168404Spjd	if (tzp) {
2570168404Spjd		/*
2571168404Spjd		 * Source and target must be the same type.
2572168404Spjd		 */
2573168962Spjd		if (ZTOV(szp)->v_type == VDIR) {
2574168962Spjd			if (ZTOV(tzp)->v_type != VDIR) {
2575168404Spjd				error = ENOTDIR;
2576168404Spjd				goto out;
2577168404Spjd			}
2578168404Spjd		} else {
2579168962Spjd			if (ZTOV(tzp)->v_type == VDIR) {
2580168404Spjd				error = EISDIR;
2581168404Spjd				goto out;
2582168404Spjd			}
2583168404Spjd		}
2584168404Spjd		/*
2585168404Spjd		 * POSIX dictates that when the source and target
2586168404Spjd		 * entries refer to the same file object, rename
2587168404Spjd		 * must do nothing and exit without error.
2588168404Spjd		 */
2589168404Spjd		if (szp->z_id == tzp->z_id) {
2590168404Spjd			error = 0;
2591168404Spjd			goto out;
2592168404Spjd		}
2593168404Spjd	}
2594168404Spjd
2595168962Spjd	vnevent_rename_src(ZTOV(szp));
2596168962Spjd	if (tzp)
2597168962Spjd		vnevent_rename_dest(ZTOV(tzp));
2598168962Spjd
2599168404Spjd	tx = dmu_tx_create(zfsvfs->z_os);
2600168404Spjd	dmu_tx_hold_bonus(tx, szp->z_id);	/* nlink changes */
2601168404Spjd	dmu_tx_hold_bonus(tx, sdzp->z_id);	/* nlink changes */
2602168404Spjd	dmu_tx_hold_zap(tx, sdzp->z_id, FALSE, snm);
2603168404Spjd	dmu_tx_hold_zap(tx, tdzp->z_id, TRUE, tnm);
2604168404Spjd	if (sdzp != tdzp)
2605168404Spjd		dmu_tx_hold_bonus(tx, tdzp->z_id);	/* nlink changes */
2606168404Spjd	if (tzp)
2607168404Spjd		dmu_tx_hold_bonus(tx, tzp->z_id);	/* parent changes */
2608168404Spjd	dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL);
2609168404Spjd	error = dmu_tx_assign(tx, zfsvfs->z_assign);
2610168404Spjd	if (error) {
2611168404Spjd		if (zl != NULL)
2612168404Spjd			zfs_rename_unlock(&zl);
2613168404Spjd		zfs_dirent_unlock(sdl);
2614168404Spjd		zfs_dirent_unlock(tdl);
2615168962Spjd		VN_RELE(ZTOV(szp));
2616168962Spjd		if (tzp)
2617168962Spjd			VN_RELE(ZTOV(tzp));
2618168404Spjd		if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) {
2619168404Spjd			dmu_tx_wait(tx);
2620168404Spjd			dmu_tx_abort(tx);
2621168404Spjd			goto top;
2622168404Spjd		}
2623168404Spjd		dmu_tx_abort(tx);
2624168962Spjd		ZFS_EXIT(zfsvfs);
2625168962Spjd		return (error);
2626168404Spjd	}
2627168404Spjd
2628168404Spjd	if (tzp)	/* Attempt to remove the existing target */
2629168404Spjd		error = zfs_link_destroy(tdl, tzp, tx, 0, NULL);
2630168404Spjd
2631168404Spjd	if (error == 0) {
2632168404Spjd		error = zfs_link_create(tdl, szp, tx, ZRENAMING);
2633168404Spjd		if (error == 0) {
2634168404Spjd			error = zfs_link_destroy(sdl, szp, tx, ZRENAMING, NULL);
2635168404Spjd			ASSERT(error == 0);
2636168404Spjd			zfs_log_rename(zilog, tx, TX_RENAME, sdzp,
2637168404Spjd			    sdl->dl_name, tdzp, tdl->dl_name, szp);
2638168404Spjd		}
2639168404Spjd#ifdef FREEBSD_NAMECACHE
2640168404Spjd		if (error == 0) {
2641168404Spjd			cache_purge(sdvp);
2642168404Spjd			cache_purge(tdvp);
2643168404Spjd		}
2644168404Spjd#endif
2645168404Spjd	}
2646168404Spjd
2647168404Spjd	dmu_tx_commit(tx);
2648168404Spjdout:
2649168404Spjd	if (zl != NULL)
2650168404Spjd		zfs_rename_unlock(&zl);
2651168404Spjd
2652168404Spjd	zfs_dirent_unlock(sdl);
2653168404Spjd	zfs_dirent_unlock(tdl);
2654168404Spjd
2655168962Spjd	VN_RELE(ZTOV(szp));
2656168404Spjd	if (tzp)
2657168962Spjd		VN_RELE(ZTOV(tzp));
2658168404Spjd
2659168404Spjd	ZFS_EXIT(zfsvfs);
2660168404Spjd
2661168404Spjd	return (error);
2662168404Spjd}
2663168404Spjd
2664168404Spjd/*
2665168404Spjd * Insert the indicated symbolic reference entry into the directory.
2666168404Spjd *
2667168404Spjd *	IN:	dvp	- Directory to contain new symbolic link.
2668168404Spjd *		link	- Name for new symlink entry.
2669168404Spjd *		vap	- Attributes of new entry.
2670168404Spjd *		target	- Target path of new symlink.
2671168404Spjd *		cr	- credentials of caller.
2672168404Spjd *
2673168404Spjd *	RETURN:	0 if success
2674168404Spjd *		error code if failure
2675168404Spjd *
2676168404Spjd * Timestamps:
2677168404Spjd *	dvp - ctime|mtime updated
2678168404Spjd */
2679168404Spjdstatic int
2680168962Spjdzfs_symlink(vnode_t *dvp, vnode_t **vpp, char *name, vattr_t *vap, char *link, cred_t *cr, kthread_t *td)
2681168404Spjd{
2682168404Spjd	znode_t		*zp, *dzp = VTOZ(dvp);
2683168404Spjd	zfs_dirlock_t	*dl;
2684168404Spjd	dmu_tx_t	*tx;
2685168404Spjd	zfsvfs_t	*zfsvfs = dzp->z_zfsvfs;
2686168404Spjd	zilog_t		*zilog = zfsvfs->z_log;
2687168404Spjd	uint64_t	zoid;
2688168404Spjd	int		len = strlen(link);
2689168404Spjd	int		error;
2690168404Spjd
2691168962Spjd	ASSERT(vap->va_type == VLNK);
2692168404Spjd
2693168404Spjd	ZFS_ENTER(zfsvfs);
2694168404Spjdtop:
2695168404Spjd	if (error = zfs_zaccess(dzp, ACE_ADD_FILE, cr)) {
2696168404Spjd		ZFS_EXIT(zfsvfs);
2697168404Spjd		return (error);
2698168404Spjd	}
2699168404Spjd
2700168404Spjd	if (len > MAXPATHLEN) {
2701168404Spjd		ZFS_EXIT(zfsvfs);
2702168404Spjd		return (ENAMETOOLONG);
2703168404Spjd	}
2704168404Spjd
2705168404Spjd	/*
2706168404Spjd	 * Attempt to lock directory; fail if entry already exists.
2707168404Spjd	 */
2708168404Spjd	if (error = zfs_dirent_lock(&dl, dzp, name, &zp, ZNEW)) {
2709168404Spjd		ZFS_EXIT(zfsvfs);
2710168404Spjd		return (error);
2711168404Spjd	}
2712168404Spjd
2713168404Spjd	tx = dmu_tx_create(zfsvfs->z_os);
2714168404Spjd	dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, MAX(1, len));
2715168404Spjd	dmu_tx_hold_bonus(tx, dzp->z_id);
2716168404Spjd	dmu_tx_hold_zap(tx, dzp->z_id, TRUE, name);
2717168404Spjd	if (dzp->z_phys->zp_flags & ZFS_INHERIT_ACE)
2718168404Spjd		dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, SPA_MAXBLOCKSIZE);
2719168404Spjd	error = dmu_tx_assign(tx, zfsvfs->z_assign);
2720168404Spjd	if (error) {
2721168404Spjd		zfs_dirent_unlock(dl);
2722168404Spjd		if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) {
2723168404Spjd			dmu_tx_wait(tx);
2724168404Spjd			dmu_tx_abort(tx);
2725168404Spjd			goto top;
2726168404Spjd		}
2727168404Spjd		dmu_tx_abort(tx);
2728168404Spjd		ZFS_EXIT(zfsvfs);
2729168404Spjd		return (error);
2730168404Spjd	}
2731168404Spjd
2732168404Spjd	dmu_buf_will_dirty(dzp->z_dbuf, tx);
2733168404Spjd
2734168404Spjd	/*
2735168404Spjd	 * Create a new object for the symlink.
2736168404Spjd	 * Put the link content into bonus buffer if it will fit;
2737168404Spjd	 * otherwise, store it just like any other file data.
2738168404Spjd	 */
2739168404Spjd	zoid = 0;
2740168404Spjd	if (sizeof (znode_phys_t) + len <= dmu_bonus_max()) {
2741168404Spjd		zfs_mknode(dzp, vap, &zoid, tx, cr, 0, &zp, len);
2742168404Spjd		if (len != 0)
2743168404Spjd			bcopy(link, zp->z_phys + 1, len);
2744168404Spjd	} else {
2745168404Spjd		dmu_buf_t *dbp;
2746168404Spjd
2747168404Spjd		zfs_mknode(dzp, vap, &zoid, tx, cr, 0, &zp, 0);
2748168404Spjd
2749168404Spjd		/*
2750168404Spjd		 * Nothing can access the znode yet so no locking needed
2751168404Spjd		 * for growing the znode's blocksize.
2752168404Spjd		 */
2753168404Spjd		zfs_grow_blocksize(zp, len, tx);
2754168404Spjd
2755168404Spjd		VERIFY(0 == dmu_buf_hold(zfsvfs->z_os, zoid, 0, FTAG, &dbp));
2756168404Spjd		dmu_buf_will_dirty(dbp, tx);
2757168404Spjd
2758168404Spjd		ASSERT3U(len, <=, dbp->db_size);
2759168404Spjd		bcopy(link, dbp->db_data, len);
2760168404Spjd		dmu_buf_rele(dbp, FTAG);
2761168404Spjd	}
2762168404Spjd	zp->z_phys->zp_size = len;
2763168404Spjd
2764168404Spjd	/*
2765168404Spjd	 * Insert the new object into the directory.
2766168404Spjd	 */
2767168404Spjd	(void) zfs_link_create(dl, zp, tx, ZNEW);
2768168962Spjdout:
2769168404Spjd	if (error == 0) {
2770168404Spjd		zfs_log_symlink(zilog, tx, TX_SYMLINK, dzp, zp, name, link);
2771168962Spjd		*vpp = ZTOV(zp);
2772175202Sattilio		vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY);
2773168404Spjd	}
2774168404Spjd
2775168404Spjd	dmu_tx_commit(tx);
2776168404Spjd
2777168404Spjd	zfs_dirent_unlock(dl);
2778168404Spjd
2779168404Spjd	ZFS_EXIT(zfsvfs);
2780168404Spjd	return (error);
2781168404Spjd}
2782168404Spjd
2783168404Spjd/*
2784168404Spjd * Return, in the buffer contained in the provided uio structure,
2785168404Spjd * the symbolic path referred to by vp.
2786168404Spjd *
2787168404Spjd *	IN:	vp	- vnode of symbolic link.
2788168404Spjd *		uoip	- structure to contain the link path.
2789168404Spjd *		cr	- credentials of caller.
2790168404Spjd *
2791168404Spjd *	OUT:	uio	- structure to contain the link path.
2792168404Spjd *
2793168404Spjd *	RETURN:	0 if success
2794168404Spjd *		error code if failure
2795168404Spjd *
2796168404Spjd * Timestamps:
2797168404Spjd *	vp - atime updated
2798168404Spjd */
2799168404Spjd/* ARGSUSED */
2800168404Spjdstatic int
2801168962Spjdzfs_readlink(vnode_t *vp, uio_t *uio, cred_t *cr)
2802168404Spjd{
2803168404Spjd	znode_t		*zp = VTOZ(vp);
2804168404Spjd	zfsvfs_t	*zfsvfs = zp->z_zfsvfs;
2805168404Spjd	size_t		bufsz;
2806168404Spjd	int		error;
2807168404Spjd
2808168404Spjd	ZFS_ENTER(zfsvfs);
2809168404Spjd
2810168404Spjd	bufsz = (size_t)zp->z_phys->zp_size;
2811168404Spjd	if (bufsz + sizeof (znode_phys_t) <= zp->z_dbuf->db_size) {
2812168404Spjd		error = uiomove(zp->z_phys + 1,
2813168404Spjd		    MIN((size_t)bufsz, uio->uio_resid), UIO_READ, uio);
2814168404Spjd	} else {
2815168404Spjd		dmu_buf_t *dbp;
2816168404Spjd		error = dmu_buf_hold(zfsvfs->z_os, zp->z_id, 0, FTAG, &dbp);
2817168404Spjd		if (error) {
2818168404Spjd			ZFS_EXIT(zfsvfs);
2819168404Spjd			return (error);
2820168404Spjd		}
2821168404Spjd		error = uiomove(dbp->db_data,
2822168404Spjd		    MIN((size_t)bufsz, uio->uio_resid), UIO_READ, uio);
2823168404Spjd		dmu_buf_rele(dbp, FTAG);
2824168404Spjd	}
2825168404Spjd
2826168404Spjd	ZFS_ACCESSTIME_STAMP(zfsvfs, zp);
2827168404Spjd	ZFS_EXIT(zfsvfs);
2828168404Spjd	return (error);
2829168404Spjd}
2830168404Spjd
2831168404Spjd/*
2832168404Spjd * Insert a new entry into directory tdvp referencing svp.
2833168404Spjd *
2834168404Spjd *	IN:	tdvp	- Directory to contain new entry.
2835168404Spjd *		svp	- vnode of new entry.
2836168404Spjd *		name	- name of new entry.
2837168404Spjd *		cr	- credentials of caller.
2838168404Spjd *
2839168404Spjd *	RETURN:	0 if success
2840168404Spjd *		error code if failure
2841168404Spjd *
2842168404Spjd * Timestamps:
2843168404Spjd *	tdvp - ctime|mtime updated
2844168404Spjd *	 svp - ctime updated
2845168404Spjd */
2846168404Spjd/* ARGSUSED */
2847168404Spjdstatic int
2848168962Spjdzfs_link(vnode_t *tdvp, vnode_t *svp, char *name, cred_t *cr)
2849168404Spjd{
2850168404Spjd	znode_t		*dzp = VTOZ(tdvp);
2851168404Spjd	znode_t		*tzp, *szp;
2852168404Spjd	zfsvfs_t	*zfsvfs = dzp->z_zfsvfs;
2853168404Spjd	zilog_t		*zilog = zfsvfs->z_log;
2854168404Spjd	zfs_dirlock_t	*dl;
2855168404Spjd	dmu_tx_t	*tx;
2856168962Spjd	vnode_t		*realvp;
2857168404Spjd	int		error;
2858168404Spjd
2859168404Spjd	ASSERT(tdvp->v_type == VDIR);
2860168404Spjd
2861168404Spjd	ZFS_ENTER(zfsvfs);
2862168404Spjd
2863168962Spjd	if (VOP_REALVP(svp, &realvp) == 0)
2864168962Spjd		svp = realvp;
2865168962Spjd
2866168404Spjd	if (svp->v_vfsp != tdvp->v_vfsp) {
2867168404Spjd		ZFS_EXIT(zfsvfs);
2868168404Spjd		return (EXDEV);
2869168404Spjd	}
2870168404Spjd
2871168404Spjd	szp = VTOZ(svp);
2872168404Spjdtop:
2873168404Spjd	/*
2874168404Spjd	 * We do not support links between attributes and non-attributes
2875168404Spjd	 * because of the potential security risk of creating links
2876168404Spjd	 * into "normal" file space in order to circumvent restrictions
2877168404Spjd	 * imposed in attribute space.
2878168404Spjd	 */
2879168404Spjd	if ((szp->z_phys->zp_flags & ZFS_XATTR) !=
2880168404Spjd	    (dzp->z_phys->zp_flags & ZFS_XATTR)) {
2881168404Spjd		ZFS_EXIT(zfsvfs);
2882168404Spjd		return (EINVAL);
2883168404Spjd	}
2884168404Spjd
2885168404Spjd	/*
2886168404Spjd	 * POSIX dictates that we return EPERM here.
2887168404Spjd	 * Better choices include ENOTSUP or EISDIR.
2888168404Spjd	 */
2889168404Spjd	if (svp->v_type == VDIR) {
2890168404Spjd		ZFS_EXIT(zfsvfs);
2891168404Spjd		return (EPERM);
2892168404Spjd	}
2893168404Spjd
2894168404Spjd	if ((uid_t)szp->z_phys->zp_uid != crgetuid(cr) &&
2895168404Spjd	    secpolicy_basic_link(cr) != 0) {
2896168404Spjd		ZFS_EXIT(zfsvfs);
2897168404Spjd		return (EPERM);
2898168404Spjd	}
2899168404Spjd
2900168404Spjd	if (error = zfs_zaccess(dzp, ACE_ADD_FILE, cr)) {
2901168404Spjd		ZFS_EXIT(zfsvfs);
2902168404Spjd		return (error);
2903168404Spjd	}
2904168404Spjd
2905168404Spjd	/*
2906168404Spjd	 * Attempt to lock directory; fail if entry already exists.
2907168404Spjd	 */
2908168404Spjd	if (error = zfs_dirent_lock(&dl, dzp, name, &tzp, ZNEW)) {
2909168404Spjd		ZFS_EXIT(zfsvfs);
2910168404Spjd		return (error);
2911168404Spjd	}
2912168404Spjd
2913168404Spjd	tx = dmu_tx_create(zfsvfs->z_os);
2914168404Spjd	dmu_tx_hold_bonus(tx, szp->z_id);
2915168404Spjd	dmu_tx_hold_zap(tx, dzp->z_id, TRUE, name);
2916168404Spjd	error = dmu_tx_assign(tx, zfsvfs->z_assign);
2917168404Spjd	if (error) {
2918168404Spjd		zfs_dirent_unlock(dl);
2919168404Spjd		if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) {
2920168404Spjd			dmu_tx_wait(tx);
2921168404Spjd			dmu_tx_abort(tx);
2922168404Spjd			goto top;
2923168404Spjd		}
2924168404Spjd		dmu_tx_abort(tx);
2925168404Spjd		ZFS_EXIT(zfsvfs);
2926168404Spjd		return (error);
2927168404Spjd	}
2928168404Spjd
2929168404Spjd	error = zfs_link_create(dl, szp, tx, 0);
2930168404Spjd
2931168404Spjd	if (error == 0)
2932168404Spjd		zfs_log_link(zilog, tx, TX_LINK, dzp, szp, name);
2933168404Spjd
2934168404Spjd	dmu_tx_commit(tx);
2935168404Spjd
2936168404Spjd	zfs_dirent_unlock(dl);
2937168404Spjd
2938168404Spjd	ZFS_EXIT(zfsvfs);
2939168404Spjd	return (error);
2940168404Spjd}
2941168404Spjd
2942168962Spjdvoid
2943168962Spjdzfs_inactive(vnode_t *vp, cred_t *cr)
2944168404Spjd{
2945168962Spjd	znode_t	*zp = VTOZ(vp);
2946168962Spjd	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
2947168962Spjd	int error;
2948168404Spjd
2949168404Spjd	rw_enter(&zfsvfs->z_um_lock, RW_READER);
2950168404Spjd	if (zfsvfs->z_unmounted2) {
2951168404Spjd		ASSERT(zp->z_dbuf_held == 0);
2952168404Spjd
2953168404Spjd		mutex_enter(&zp->z_lock);
2954168404Spjd		VI_LOCK(vp);
2955168404Spjd		vp->v_count = 0; /* count arrives as 1 */
2956168404Spjd		VI_UNLOCK(vp);
2957168404Spjd		if (zp->z_dbuf == NULL) {
2958168404Spjd			mutex_exit(&zp->z_lock);
2959168404Spjd			zfs_znode_free(zp);
2960168404Spjd		} else {
2961168404Spjd			mutex_exit(&zp->z_lock);
2962168404Spjd		}
2963168404Spjd		rw_exit(&zfsvfs->z_um_lock);
2964168404Spjd		VFS_RELE(zfsvfs->z_vfs);
2965168962Spjd		return;
2966168404Spjd	}
2967168404Spjd
2968168404Spjd	if (zp->z_atime_dirty && zp->z_unlinked == 0) {
2969168404Spjd		dmu_tx_t *tx = dmu_tx_create(zfsvfs->z_os);
2970168404Spjd
2971168404Spjd		dmu_tx_hold_bonus(tx, zp->z_id);
2972168404Spjd		error = dmu_tx_assign(tx, TXG_WAIT);
2973168404Spjd		if (error) {
2974168404Spjd			dmu_tx_abort(tx);
2975168404Spjd		} else {
2976168404Spjd			dmu_buf_will_dirty(zp->z_dbuf, tx);
2977168404Spjd			mutex_enter(&zp->z_lock);
2978168404Spjd			zp->z_atime_dirty = 0;
2979168404Spjd			mutex_exit(&zp->z_lock);
2980168404Spjd			dmu_tx_commit(tx);
2981168404Spjd		}
2982168404Spjd	}
2983168404Spjd
2984168404Spjd	zfs_zinactive(zp);
2985168404Spjd	rw_exit(&zfsvfs->z_um_lock);
2986168404Spjd}
2987168404Spjd
2988168404SpjdCTASSERT(sizeof(struct zfid_short) <= sizeof(struct fid));
2989168404SpjdCTASSERT(sizeof(struct zfid_long) <= sizeof(struct fid));
2990168404Spjd
2991168404Spjdstatic int
2992168962Spjdzfs_fid(vnode_t *vp, fid_t *fidp)
2993168404Spjd{
2994168404Spjd	znode_t		*zp = VTOZ(vp);
2995168404Spjd	zfsvfs_t	*zfsvfs = zp->z_zfsvfs;
2996168404Spjd	uint32_t	gen = (uint32_t)zp->z_phys->zp_gen;
2997168404Spjd	uint64_t	object = zp->z_id;
2998168404Spjd	zfid_short_t	*zfid;
2999168404Spjd	int		size, i;
3000168404Spjd
3001168404Spjd	ZFS_ENTER(zfsvfs);
3002168404Spjd
3003168404Spjd	size = (zfsvfs->z_parent != zfsvfs) ? LONG_FID_LEN : SHORT_FID_LEN;
3004168404Spjd	fidp->fid_len = size;
3005168404Spjd
3006168404Spjd	zfid = (zfid_short_t *)fidp;
3007168404Spjd
3008168404Spjd	zfid->zf_len = size;
3009168404Spjd
3010168404Spjd	for (i = 0; i < sizeof (zfid->zf_object); i++)
3011168404Spjd		zfid->zf_object[i] = (uint8_t)(object >> (8 * i));
3012168404Spjd
3013168404Spjd	/* Must have a non-zero generation number to distinguish from .zfs */
3014168404Spjd	if (gen == 0)
3015168404Spjd		gen = 1;
3016168404Spjd	for (i = 0; i < sizeof (zfid->zf_gen); i++)
3017168404Spjd		zfid->zf_gen[i] = (uint8_t)(gen >> (8 * i));
3018168404Spjd
3019168404Spjd	if (size == LONG_FID_LEN) {
3020168404Spjd		uint64_t	objsetid = dmu_objset_id(zfsvfs->z_os);
3021169023Spjd		zfid_long_t	*zlfid;
3022168404Spjd
3023168404Spjd		zlfid = (zfid_long_t *)fidp;
3024168404Spjd
3025168404Spjd		for (i = 0; i < sizeof (zlfid->zf_setid); i++)
3026168404Spjd			zlfid->zf_setid[i] = (uint8_t)(objsetid >> (8 * i));
3027168404Spjd
3028168404Spjd		/* XXX - this should be the generation number for the objset */
3029168404Spjd		for (i = 0; i < sizeof (zlfid->zf_setgen); i++)
3030168404Spjd			zlfid->zf_setgen[i] = 0;
3031168404Spjd	}
3032168404Spjd
3033168404Spjd	ZFS_EXIT(zfsvfs);
3034168404Spjd	return (0);
3035168404Spjd}
3036168404Spjd
3037168404Spjdstatic int
3038168962Spjdzfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr)
3039168404Spjd{
3040168404Spjd	znode_t		*zp, *xzp;
3041168404Spjd	zfsvfs_t	*zfsvfs;
3042168404Spjd	zfs_dirlock_t	*dl;
3043168404Spjd	int		error;
3044168404Spjd
3045168404Spjd	switch (cmd) {
3046168404Spjd	case _PC_LINK_MAX:
3047168404Spjd		*valp = INT_MAX;
3048168404Spjd		return (0);
3049168404Spjd
3050168404Spjd	case _PC_FILESIZEBITS:
3051168404Spjd		*valp = 64;
3052168404Spjd		return (0);
3053168404Spjd
3054168404Spjd#if 0
3055168404Spjd	case _PC_XATTR_EXISTS:
3056168404Spjd		zp = VTOZ(vp);
3057168404Spjd		zfsvfs = zp->z_zfsvfs;
3058168404Spjd		ZFS_ENTER(zfsvfs);
3059168404Spjd		*valp = 0;
3060168404Spjd		error = zfs_dirent_lock(&dl, zp, "", &xzp,
3061168404Spjd		    ZXATTR | ZEXISTS | ZSHARED);
3062168404Spjd		if (error == 0) {
3063168404Spjd			zfs_dirent_unlock(dl);
3064168404Spjd			if (!zfs_dirempty(xzp))
3065168404Spjd				*valp = 1;
3066168404Spjd			VN_RELE(ZTOV(xzp));
3067168404Spjd		} else if (error == ENOENT) {
3068168404Spjd			/*
3069168404Spjd			 * If there aren't extended attributes, it's the
3070168404Spjd			 * same as having zero of them.
3071168404Spjd			 */
3072168404Spjd			error = 0;
3073168404Spjd		}
3074168404Spjd		ZFS_EXIT(zfsvfs);
3075168404Spjd		return (error);
3076168404Spjd#endif
3077168404Spjd
3078168404Spjd	case _PC_ACL_EXTENDED:
3079168404Spjd		*valp = 0;	/* TODO */
3080168404Spjd		return (0);
3081168404Spjd
3082168404Spjd	case _PC_MIN_HOLE_SIZE:
3083168404Spjd		*valp = (int)SPA_MINBLOCKSIZE;
3084168404Spjd		return (0);
3085168404Spjd
3086168404Spjd	default:
3087168962Spjd		return (EOPNOTSUPP);
3088168404Spjd	}
3089168404Spjd}
3090168404Spjd
3091168404Spjd#ifdef TODO
3092168404Spjd/*ARGSUSED*/
3093168404Spjdstatic int
3094168404Spjdzfs_getsecattr(vnode_t *vp, vsecattr_t *vsecp, int flag, cred_t *cr)
3095168404Spjd{
3096168404Spjd	znode_t *zp = VTOZ(vp);
3097168404Spjd	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
3098168404Spjd	int error;
3099168404Spjd
3100168404Spjd	ZFS_ENTER(zfsvfs);
3101168404Spjd	error = zfs_getacl(zp, vsecp, cr);
3102168404Spjd	ZFS_EXIT(zfsvfs);
3103168404Spjd
3104168404Spjd	return (error);
3105168404Spjd}
3106168404Spjd#endif	/* TODO */
3107168404Spjd
3108168404Spjd#ifdef TODO
3109168404Spjd/*ARGSUSED*/
3110168404Spjdstatic int
3111168404Spjdzfs_setsecattr(vnode_t *vp, vsecattr_t *vsecp, int flag, cred_t *cr)
3112168404Spjd{
3113168404Spjd	znode_t *zp = VTOZ(vp);
3114168404Spjd	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
3115168404Spjd	int error;
3116168404Spjd
3117168404Spjd	ZFS_ENTER(zfsvfs);
3118168404Spjd	error = zfs_setacl(zp, vsecp, cr);
3119168404Spjd	ZFS_EXIT(zfsvfs);
3120168404Spjd	return (error);
3121168404Spjd}
3122168404Spjd#endif	/* TODO */
3123168404Spjd
3124168962Spjdstatic int
3125168962Spjdzfs_freebsd_open(ap)
3126168962Spjd	struct vop_open_args /* {
3127168962Spjd		struct vnode *a_vp;
3128168962Spjd		int a_mode;
3129168962Spjd		struct ucred *a_cred;
3130168962Spjd		struct thread *a_td;
3131168962Spjd	} */ *ap;
3132168962Spjd{
3133168962Spjd	vnode_t	*vp = ap->a_vp;
3134168962Spjd	znode_t *zp = VTOZ(vp);
3135168962Spjd	int error;
3136168962Spjd
3137168962Spjd	error = zfs_open(&vp, ap->a_mode, ap->a_cred);
3138168962Spjd	if (error == 0)
3139168962Spjd		vnode_create_vobject(vp, zp->z_phys->zp_size, ap->a_td);
3140168962Spjd	return (error);
3141168962Spjd}
3142168962Spjd
3143168962Spjdstatic int
3144168962Spjdzfs_freebsd_close(ap)
3145168962Spjd	struct vop_close_args /* {
3146168962Spjd		struct vnode *a_vp;
3147168962Spjd		int  a_fflag;
3148168962Spjd		struct ucred *a_cred;
3149168962Spjd		struct thread *a_td;
3150168962Spjd	} */ *ap;
3151168962Spjd{
3152168962Spjd
3153168962Spjd	return (zfs_close(ap->a_vp, ap->a_fflag, 0, 0, ap->a_cred));
3154168962Spjd}
3155168962Spjd
3156168962Spjdstatic int
3157168962Spjdzfs_freebsd_ioctl(ap)
3158168962Spjd	struct vop_ioctl_args /* {
3159168962Spjd		struct vnode *a_vp;
3160168962Spjd		u_long a_command;
3161168962Spjd		caddr_t a_data;
3162168962Spjd		int a_fflag;
3163168962Spjd		struct ucred *cred;
3164168962Spjd		struct thread *td;
3165168962Spjd	} */ *ap;
3166168962Spjd{
3167168962Spjd
3168168978Spjd	return (zfs_ioctl(ap->a_vp, ap->a_command, (intptr_t)ap->a_data,
3169168962Spjd	    ap->a_fflag, ap->a_cred, NULL));
3170168962Spjd}
3171168962Spjd
3172168962Spjdstatic int
3173168962Spjdzfs_freebsd_read(ap)
3174168962Spjd	struct vop_read_args /* {
3175168962Spjd		struct vnode *a_vp;
3176168962Spjd		struct uio *a_uio;
3177168962Spjd		int a_ioflag;
3178168962Spjd		struct ucred *a_cred;
3179168962Spjd	} */ *ap;
3180168962Spjd{
3181168962Spjd
3182168962Spjd	return (zfs_read(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred, NULL));
3183168962Spjd}
3184168962Spjd
3185168962Spjdstatic int
3186168962Spjdzfs_freebsd_write(ap)
3187168962Spjd	struct vop_write_args /* {
3188168962Spjd		struct vnode *a_vp;
3189168962Spjd		struct uio *a_uio;
3190168962Spjd		int a_ioflag;
3191168962Spjd		struct ucred *a_cred;
3192168962Spjd	} */ *ap;
3193168962Spjd{
3194168962Spjd
3195168962Spjd	return (zfs_write(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred, NULL));
3196168962Spjd}
3197168962Spjd
3198168962Spjdstatic int
3199168962Spjdzfs_freebsd_access(ap)
3200168962Spjd	struct vop_access_args /* {
3201168962Spjd		struct vnode *a_vp;
3202168962Spjd		int  a_mode;
3203168962Spjd		struct ucred *a_cred;
3204168962Spjd		struct thread *a_td;
3205168962Spjd	} */ *ap;
3206168962Spjd{
3207168962Spjd
3208168962Spjd	return (zfs_access(ap->a_vp, ap->a_mode, 0, ap->a_cred));
3209168962Spjd}
3210168962Spjd
3211168962Spjdstatic int
3212168962Spjdzfs_freebsd_lookup(ap)
3213168962Spjd	struct vop_lookup_args /* {
3214168962Spjd		struct vnode *a_dvp;
3215168962Spjd		struct vnode **a_vpp;
3216168962Spjd		struct componentname *a_cnp;
3217168962Spjd	} */ *ap;
3218168962Spjd{
3219168962Spjd	struct componentname *cnp = ap->a_cnp;
3220168962Spjd	char nm[NAME_MAX + 1];
3221168962Spjd
3222168962Spjd	ASSERT(cnp->cn_namelen < sizeof(nm));
3223168962Spjd	strlcpy(nm, cnp->cn_nameptr, MIN(cnp->cn_namelen + 1, sizeof(nm)));
3224168962Spjd
3225168962Spjd	return (zfs_lookup(ap->a_dvp, nm, ap->a_vpp, cnp, cnp->cn_nameiop,
3226168962Spjd	    cnp->cn_cred, cnp->cn_thread));
3227168962Spjd}
3228168962Spjd
3229168962Spjdstatic int
3230168962Spjdzfs_freebsd_create(ap)
3231168962Spjd	struct vop_create_args /* {
3232168962Spjd		struct vnode *a_dvp;
3233168962Spjd		struct vnode **a_vpp;
3234168962Spjd		struct componentname *a_cnp;
3235168962Spjd		struct vattr *a_vap;
3236168962Spjd	} */ *ap;
3237168962Spjd{
3238168962Spjd	struct componentname *cnp = ap->a_cnp;
3239168962Spjd	vattr_t *vap = ap->a_vap;
3240168962Spjd	int mode;
3241168962Spjd
3242168962Spjd	ASSERT(cnp->cn_flags & SAVENAME);
3243168962Spjd
3244168962Spjd	vattr_init_mask(vap);
3245168962Spjd	mode = vap->va_mode & ALLPERMS;
3246168962Spjd
3247168962Spjd	return (zfs_create(ap->a_dvp, cnp->cn_nameptr, vap, !EXCL, mode,
3248176559Sattilio	    ap->a_vpp, cnp->cn_cred));
3249168962Spjd}
3250168962Spjd
3251168962Spjdstatic int
3252168962Spjdzfs_freebsd_remove(ap)
3253168962Spjd	struct vop_remove_args /* {
3254168962Spjd		struct vnode *a_dvp;
3255168962Spjd		struct vnode *a_vp;
3256168962Spjd		struct componentname *a_cnp;
3257168962Spjd	} */ *ap;
3258168962Spjd{
3259168962Spjd
3260168962Spjd	ASSERT(ap->a_cnp->cn_flags & SAVENAME);
3261168962Spjd
3262168962Spjd	return (zfs_remove(ap->a_dvp, ap->a_cnp->cn_nameptr,
3263168962Spjd	    ap->a_cnp->cn_cred));
3264168962Spjd}
3265168962Spjd
3266168962Spjdstatic int
3267168962Spjdzfs_freebsd_mkdir(ap)
3268168962Spjd	struct vop_mkdir_args /* {
3269168962Spjd		struct vnode *a_dvp;
3270168962Spjd		struct vnode **a_vpp;
3271168962Spjd		struct componentname *a_cnp;
3272168962Spjd		struct vattr *a_vap;
3273168962Spjd	} */ *ap;
3274168962Spjd{
3275168962Spjd	vattr_t *vap = ap->a_vap;
3276168962Spjd
3277168962Spjd	ASSERT(ap->a_cnp->cn_flags & SAVENAME);
3278168962Spjd
3279168962Spjd	vattr_init_mask(vap);
3280168962Spjd
3281168962Spjd	return (zfs_mkdir(ap->a_dvp, ap->a_cnp->cn_nameptr, vap, ap->a_vpp,
3282168962Spjd	    ap->a_cnp->cn_cred));
3283168962Spjd}
3284168962Spjd
3285168962Spjdstatic int
3286168962Spjdzfs_freebsd_rmdir(ap)
3287168962Spjd	struct vop_rmdir_args /* {
3288168962Spjd		struct vnode *a_dvp;
3289168962Spjd		struct vnode *a_vp;
3290168962Spjd		struct componentname *a_cnp;
3291168962Spjd	} */ *ap;
3292168962Spjd{
3293168962Spjd	struct componentname *cnp = ap->a_cnp;
3294168962Spjd
3295168962Spjd	ASSERT(cnp->cn_flags & SAVENAME);
3296168962Spjd
3297168962Spjd	return (zfs_rmdir(ap->a_dvp, cnp->cn_nameptr, NULL, cnp->cn_cred));
3298168962Spjd}
3299168962Spjd
3300168962Spjdstatic int
3301168962Spjdzfs_freebsd_readdir(ap)
3302168962Spjd	struct vop_readdir_args /* {
3303168962Spjd		struct vnode *a_vp;
3304168962Spjd		struct uio *a_uio;
3305168962Spjd		struct ucred *a_cred;
3306168962Spjd		int *a_eofflag;
3307168962Spjd		int *a_ncookies;
3308168962Spjd		u_long **a_cookies;
3309168962Spjd	} */ *ap;
3310168962Spjd{
3311168962Spjd
3312168962Spjd	return (zfs_readdir(ap->a_vp, ap->a_uio, ap->a_cred, ap->a_eofflag,
3313168962Spjd	    ap->a_ncookies, ap->a_cookies));
3314168962Spjd}
3315168962Spjd
3316168962Spjdstatic int
3317168962Spjdzfs_freebsd_fsync(ap)
3318168962Spjd	struct vop_fsync_args /* {
3319168962Spjd		struct vnode *a_vp;
3320168962Spjd		int a_waitfor;
3321168962Spjd		struct thread *a_td;
3322168962Spjd	} */ *ap;
3323168962Spjd{
3324168962Spjd
3325168962Spjd	vop_stdfsync(ap);
3326168962Spjd	return (zfs_fsync(ap->a_vp, 0, ap->a_td->td_ucred));
3327168962Spjd}
3328168962Spjd
3329168962Spjdstatic int
3330168962Spjdzfs_freebsd_getattr(ap)
3331168962Spjd	struct vop_getattr_args /* {
3332168962Spjd		struct vnode *a_vp;
3333168962Spjd		struct vattr *a_vap;
3334168962Spjd		struct ucred *a_cred;
3335168962Spjd		struct thread *a_td;
3336168962Spjd	} */ *ap;
3337168962Spjd{
3338168962Spjd
3339168962Spjd	return (zfs_getattr(ap->a_vp, ap->a_vap, 0, ap->a_cred));
3340168962Spjd}
3341168962Spjd
3342168962Spjdstatic int
3343168962Spjdzfs_freebsd_setattr(ap)
3344168962Spjd	struct vop_setattr_args /* {
3345168962Spjd		struct vnode *a_vp;
3346168962Spjd		struct vattr *a_vap;
3347168962Spjd		struct ucred *a_cred;
3348168962Spjd		struct thread *a_td;
3349168962Spjd	} */ *ap;
3350168962Spjd{
3351168962Spjd	vattr_t *vap = ap->a_vap;
3352168962Spjd
3353168962Spjd	/* No support for FreeBSD's chflags(2). */
3354168962Spjd	if (vap->va_flags != VNOVAL)
3355168962Spjd		return (EOPNOTSUPP);
3356168962Spjd
3357168962Spjd	vattr_init_mask(vap);
3358170044Spjd	vap->va_mask &= ~AT_NOSET;
3359168962Spjd
3360168962Spjd	return (zfs_setattr(ap->a_vp, vap, 0, ap->a_cred, NULL));
3361168962Spjd}
3362168962Spjd
3363168962Spjdstatic int
3364168962Spjdzfs_freebsd_rename(ap)
3365168962Spjd	struct vop_rename_args  /* {
3366168962Spjd		struct vnode *a_fdvp;
3367168962Spjd		struct vnode *a_fvp;
3368168962Spjd		struct componentname *a_fcnp;
3369168962Spjd		struct vnode *a_tdvp;
3370168962Spjd		struct vnode *a_tvp;
3371168962Spjd		struct componentname *a_tcnp;
3372168962Spjd	} */ *ap;
3373168962Spjd{
3374168962Spjd	vnode_t *fdvp = ap->a_fdvp;
3375168962Spjd	vnode_t *fvp = ap->a_fvp;
3376168962Spjd	vnode_t *tdvp = ap->a_tdvp;
3377168962Spjd	vnode_t *tvp = ap->a_tvp;
3378168962Spjd	int error;
3379168962Spjd
3380168962Spjd	ASSERT(ap->a_fcnp->cn_flags & SAVENAME);
3381168962Spjd	ASSERT(ap->a_tcnp->cn_flags & SAVENAME);
3382168962Spjd
3383168962Spjd	error = zfs_rename(fdvp, ap->a_fcnp->cn_nameptr, tdvp,
3384168962Spjd	    ap->a_tcnp->cn_nameptr, ap->a_fcnp->cn_cred);
3385168962Spjd
3386168962Spjd	if (tdvp == tvp)
3387168962Spjd		VN_RELE(tdvp);
3388168962Spjd	else
3389168962Spjd		VN_URELE(tdvp);
3390168962Spjd	if (tvp)
3391168962Spjd		VN_URELE(tvp);
3392168962Spjd	VN_RELE(fdvp);
3393168962Spjd	VN_RELE(fvp);
3394168962Spjd
3395168962Spjd	return (error);
3396168962Spjd}
3397168962Spjd
3398168962Spjdstatic int
3399168962Spjdzfs_freebsd_symlink(ap)
3400168962Spjd	struct vop_symlink_args /* {
3401168962Spjd		struct vnode *a_dvp;
3402168962Spjd		struct vnode **a_vpp;
3403168962Spjd		struct componentname *a_cnp;
3404168962Spjd		struct vattr *a_vap;
3405168962Spjd		char *a_target;
3406168962Spjd	} */ *ap;
3407168962Spjd{
3408168962Spjd	struct componentname *cnp = ap->a_cnp;
3409168962Spjd	vattr_t *vap = ap->a_vap;
3410168962Spjd
3411168962Spjd	ASSERT(cnp->cn_flags & SAVENAME);
3412168962Spjd
3413168962Spjd	vap->va_type = VLNK;	/* FreeBSD: Syscall only sets va_mode. */
3414168962Spjd	vattr_init_mask(vap);
3415168962Spjd
3416168962Spjd	return (zfs_symlink(ap->a_dvp, ap->a_vpp, cnp->cn_nameptr, vap,
3417168962Spjd	    ap->a_target, cnp->cn_cred, cnp->cn_thread));
3418168962Spjd}
3419168962Spjd
3420168962Spjdstatic int
3421168962Spjdzfs_freebsd_readlink(ap)
3422168962Spjd	struct vop_readlink_args /* {
3423168962Spjd		struct vnode *a_vp;
3424168962Spjd		struct uio *a_uio;
3425168962Spjd		struct ucred *a_cred;
3426168962Spjd	} */ *ap;
3427168962Spjd{
3428168962Spjd
3429168962Spjd	return (zfs_readlink(ap->a_vp, ap->a_uio, ap->a_cred));
3430168962Spjd}
3431168962Spjd
3432168962Spjdstatic int
3433168962Spjdzfs_freebsd_link(ap)
3434168962Spjd	struct vop_link_args /* {
3435168962Spjd		struct vnode *a_tdvp;
3436168962Spjd		struct vnode *a_vp;
3437168962Spjd		struct componentname *a_cnp;
3438168962Spjd	} */ *ap;
3439168962Spjd{
3440168962Spjd	struct componentname *cnp = ap->a_cnp;
3441168962Spjd
3442168962Spjd	ASSERT(cnp->cn_flags & SAVENAME);
3443168962Spjd
3444168962Spjd	return (zfs_link(ap->a_tdvp, ap->a_vp, cnp->cn_nameptr, cnp->cn_cred));
3445168962Spjd}
3446168962Spjd
3447168962Spjdstatic int
3448168962Spjdzfs_freebsd_inactive(ap)
3449169170Spjd	struct vop_inactive_args /* {
3450169170Spjd		struct vnode *a_vp;
3451169170Spjd		struct thread *a_td;
3452169170Spjd	} */ *ap;
3453168962Spjd{
3454168962Spjd	vnode_t *vp = ap->a_vp;
3455168962Spjd
3456168962Spjd	zfs_inactive(vp, ap->a_td->td_ucred);
3457168962Spjd	return (0);
3458168962Spjd}
3459168962Spjd
3460168962Spjdstatic int
3461168962Spjdzfs_freebsd_reclaim(ap)
3462168962Spjd	struct vop_reclaim_args /* {
3463168962Spjd		struct vnode *a_vp;
3464168962Spjd		struct thread *a_td;
3465168962Spjd	} */ *ap;
3466168962Spjd{
3467169170Spjd	vnode_t	*vp = ap->a_vp;
3468168962Spjd	znode_t	*zp = VTOZ(vp);
3469169025Spjd	zfsvfs_t *zfsvfs;
3470169025Spjd	int rele = 1;
3471168962Spjd
3472169025Spjd	ASSERT(zp != NULL);
3473169025Spjd
3474168962Spjd	/*
3475168962Spjd	 * Destroy the vm object and flush associated pages.
3476168962Spjd	 */
3477168962Spjd	vnode_destroy_vobject(vp);
3478169025Spjd
3479169025Spjd	mutex_enter(&zp->z_lock);
3480169025Spjd	ASSERT(zp->z_phys);
3481169025Spjd	ASSERT(zp->z_dbuf_held);
3482169025Spjd	zfsvfs = zp->z_zfsvfs;
3483169025Spjd	if (!zp->z_unlinked) {
3484169025Spjd		zp->z_dbuf_held = 0;
3485169025Spjd		ZTOV(zp) = NULL;
3486169025Spjd		mutex_exit(&zp->z_lock);
3487169025Spjd		dmu_buf_rele(zp->z_dbuf, NULL);
3488169025Spjd	} else {
3489169025Spjd		mutex_exit(&zp->z_lock);
3490169025Spjd	}
3491168962Spjd	VI_LOCK(vp);
3492169025Spjd	if (vp->v_count > 0)
3493169025Spjd		rele = 0;
3494168962Spjd	vp->v_data = NULL;
3495171567Spjd	ASSERT(vp->v_holdcnt >= 1);
3496171316Sdfr	VI_UNLOCK(vp);
3497169025Spjd	if (!zp->z_unlinked && rele)
3498169025Spjd		VFS_RELE(zfsvfs->z_vfs);
3499168962Spjd	return (0);
3500168962Spjd}
3501168962Spjd
3502168962Spjdstatic int
3503168962Spjdzfs_freebsd_fid(ap)
3504168962Spjd	struct vop_fid_args /* {
3505168962Spjd		struct vnode *a_vp;
3506168962Spjd		struct fid *a_fid;
3507168962Spjd	} */ *ap;
3508168962Spjd{
3509168962Spjd
3510168962Spjd	return (zfs_fid(ap->a_vp, (void *)ap->a_fid));
3511168962Spjd}
3512168962Spjd
3513168962Spjdstatic int
3514168962Spjdzfs_freebsd_pathconf(ap)
3515168962Spjd	struct vop_pathconf_args /* {
3516168962Spjd		struct vnode *a_vp;
3517168962Spjd		int a_name;
3518168962Spjd		register_t *a_retval;
3519168962Spjd	} */ *ap;
3520168962Spjd{
3521168962Spjd	ulong_t val;
3522168962Spjd	int error;
3523168962Spjd
3524168962Spjd	error = zfs_pathconf(ap->a_vp, ap->a_name, &val, curthread->td_ucred);
3525168962Spjd	if (error == 0)
3526168962Spjd		*ap->a_retval = val;
3527168962Spjd	else if (error == EOPNOTSUPP)
3528168962Spjd		error = vop_stdpathconf(ap);
3529168962Spjd	return (error);
3530168962Spjd}
3531168962Spjd
3532168404Spjd/*
3533168404Spjd * Advisory record locking support
3534168404Spjd */
3535168404Spjdstatic int
3536168962Spjdzfs_freebsd_advlock(ap)
3537168404Spjd	struct vop_advlock_args /* {
3538168404Spjd		struct vnode *a_vp;
3539168404Spjd		caddr_t  a_id;
3540168404Spjd		int  a_op;
3541168404Spjd		struct flock *a_fl;
3542168404Spjd		int  a_flags;
3543168404Spjd	} */ *ap;
3544168404Spjd{
3545168404Spjd	znode_t	*zp = VTOZ(ap->a_vp);
3546168404Spjd
3547168404Spjd	return (lf_advlock(ap, &(zp->z_lockf), zp->z_phys->zp_size));
3548168404Spjd}
3549168404Spjd
3550168404Spjdstruct vop_vector zfs_vnodeops;
3551168404Spjdstruct vop_vector zfs_fifoops;
3552168404Spjd
3553168404Spjdstruct vop_vector zfs_vnodeops = {
3554168404Spjd	.vop_default =	&default_vnodeops,
3555168962Spjd	.vop_inactive =	zfs_freebsd_inactive,
3556168962Spjd	.vop_reclaim =	zfs_freebsd_reclaim,
3557168962Spjd	.vop_access =	zfs_freebsd_access,
3558168404Spjd#ifdef FREEBSD_NAMECACHE
3559168404Spjd	.vop_lookup =	vfs_cache_lookup,
3560168962Spjd	.vop_cachedlookup = zfs_freebsd_lookup,
3561168404Spjd#else
3562168962Spjd	.vop_lookup =	zfs_freebsd_lookup,
3563168404Spjd#endif
3564168962Spjd	.vop_getattr =	zfs_freebsd_getattr,
3565168962Spjd	.vop_setattr =	zfs_freebsd_setattr,
3566168962Spjd	.vop_create =	zfs_freebsd_create,
3567168962Spjd	.vop_mknod =	zfs_freebsd_create,
3568168962Spjd	.vop_mkdir =	zfs_freebsd_mkdir,
3569168962Spjd	.vop_readdir =	zfs_freebsd_readdir,
3570168962Spjd	.vop_fsync =	zfs_freebsd_fsync,
3571168962Spjd	.vop_open =	zfs_freebsd_open,
3572168962Spjd	.vop_close =	zfs_freebsd_close,
3573168962Spjd	.vop_rmdir =	zfs_freebsd_rmdir,
3574168962Spjd	.vop_ioctl =	zfs_freebsd_ioctl,
3575168962Spjd	.vop_link =	zfs_freebsd_link,
3576168962Spjd	.vop_symlink =	zfs_freebsd_symlink,
3577168962Spjd	.vop_readlink =	zfs_freebsd_readlink,
3578168962Spjd	.vop_read =	zfs_freebsd_read,
3579168962Spjd	.vop_write =	zfs_freebsd_write,
3580168962Spjd	.vop_remove =	zfs_freebsd_remove,
3581168962Spjd	.vop_rename =	zfs_freebsd_rename,
3582168962Spjd	.vop_advlock =	zfs_freebsd_advlock,
3583168962Spjd	.vop_pathconf =	zfs_freebsd_pathconf,
3584168404Spjd	.vop_bmap =	VOP_EOPNOTSUPP,
3585168962Spjd	.vop_fid =	zfs_freebsd_fid,
3586168404Spjd};
3587168404Spjd
3588169170Spjdstruct vop_vector zfs_fifoops = {
3589168404Spjd	.vop_default =	&fifo_specops,
3590168404Spjd	.vop_fsync =	VOP_PANIC,
3591168962Spjd	.vop_access =	zfs_freebsd_access,
3592168962Spjd	.vop_getattr =	zfs_freebsd_getattr,
3593168962Spjd	.vop_inactive =	zfs_freebsd_inactive,
3594168404Spjd	.vop_read =	VOP_PANIC,
3595168962Spjd	.vop_reclaim =	zfs_freebsd_reclaim,
3596168962Spjd	.vop_setattr =	zfs_freebsd_setattr,
3597168404Spjd	.vop_write =	VOP_PANIC,
3598168962Spjd	.vop_fid =	zfs_freebsd_fid,
3599168404Spjd};
3600