xref: /netbsd-src/sys/ufs/ufs/ufs_vnops.c (revision 56bb44cae5b13a6b74792381ba1e6d930b26aa67)
1 /*	$NetBSD: ufs_vnops.c,v 1.186 2011/01/02 05:09:32 dholland Exp $	*/
2 
3 /*-
4  * Copyright (c) 2008 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Wasabi Systems, Inc.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /*
33  * Copyright (c) 1982, 1986, 1989, 1993, 1995
34  *	The Regents of the University of California.  All rights reserved.
35  * (c) UNIX System Laboratories, Inc.
36  * All or some portions of this file are derived from material licensed
37  * to the University of California by American Telephone and Telegraph
38  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
39  * the permission of UNIX System Laboratories, Inc.
40  *
41  * Redistribution and use in source and binary forms, with or without
42  * modification, are permitted provided that the following conditions
43  * are met:
44  * 1. Redistributions of source code must retain the above copyright
45  *    notice, this list of conditions and the following disclaimer.
46  * 2. Redistributions in binary form must reproduce the above copyright
47  *    notice, this list of conditions and the following disclaimer in the
48  *    documentation and/or other materials provided with the distribution.
49  * 3. Neither the name of the University nor the names of its contributors
50  *    may be used to endorse or promote products derived from this software
51  *    without specific prior written permission.
52  *
53  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63  * SUCH DAMAGE.
64  *
65  *	@(#)ufs_vnops.c	8.28 (Berkeley) 7/31/95
66  */
67 
68 #include <sys/cdefs.h>
69 __KERNEL_RCSID(0, "$NetBSD: ufs_vnops.c,v 1.186 2011/01/02 05:09:32 dholland Exp $");
70 
71 #if defined(_KERNEL_OPT)
72 #include "opt_ffs.h"
73 #include "opt_quota.h"
74 #endif
75 
76 #include <sys/param.h>
77 #include <sys/systm.h>
78 #include <sys/namei.h>
79 #include <sys/resourcevar.h>
80 #include <sys/kernel.h>
81 #include <sys/file.h>
82 #include <sys/stat.h>
83 #include <sys/buf.h>
84 #include <sys/proc.h>
85 #include <sys/mount.h>
86 #include <sys/vnode.h>
87 #include <sys/malloc.h>
88 #include <sys/dirent.h>
89 #include <sys/lockf.h>
90 #include <sys/kauth.h>
91 #include <sys/wapbl.h>
92 #include <sys/fstrans.h>
93 
94 #include <miscfs/specfs/specdev.h>
95 #include <miscfs/fifofs/fifo.h>
96 #include <miscfs/genfs/genfs.h>
97 
98 #include <ufs/ufs/inode.h>
99 #include <ufs/ufs/dir.h>
100 #include <ufs/ufs/ufsmount.h>
101 #include <ufs/ufs/ufs_bswap.h>
102 #include <ufs/ufs/ufs_extern.h>
103 #include <ufs/ufs/ufs_wapbl.h>
104 #ifdef UFS_DIRHASH
105 #include <ufs/ufs/dirhash.h>
106 #endif
107 #include <ufs/ext2fs/ext2fs_extern.h>
108 #include <ufs/ffs/ffs_extern.h>
109 #include <ufs/lfs/lfs_extern.h>
110 
111 #include <uvm/uvm.h>
112 
113 static int ufs_chmod(struct vnode *, int, kauth_cred_t, struct lwp *);
114 static int ufs_chown(struct vnode *, uid_t, gid_t, kauth_cred_t,
115     struct lwp *);
116 
117 /*
118  * A virgin directory (no blushing please).
119  */
120 static const struct dirtemplate mastertemplate = {
121 	0,	12,		DT_DIR,	1,	".",
122 	0,	DIRBLKSIZ - 12,	DT_DIR,	2,	".."
123 };
124 
125 /*
126  * Create a regular file
127  */
128 int
129 ufs_create(void *v)
130 {
131 	struct vop_create_args /* {
132 		struct vnode		*a_dvp;
133 		struct vnode		**a_vpp;
134 		struct componentname	*a_cnp;
135 		struct vattr		*a_vap;
136 	} */ *ap = v;
137 	int	error;
138 
139 	/*
140 	 * UFS_WAPBL_BEGIN1(dvp->v_mount, dvp) performed by successful
141 	 * ufs_makeinode
142 	 */
143 	fstrans_start(ap->a_dvp->v_mount, FSTRANS_SHARED);
144 	error =
145 	    ufs_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode),
146 			  ap->a_dvp, ap->a_vpp, ap->a_cnp);
147 	if (error) {
148 		fstrans_done(ap->a_dvp->v_mount);
149 		return (error);
150 	}
151 	UFS_WAPBL_END1(ap->a_dvp->v_mount, ap->a_dvp);
152 	fstrans_done(ap->a_dvp->v_mount);
153 	VN_KNOTE(ap->a_dvp, NOTE_WRITE);
154 	return (0);
155 }
156 
157 /*
158  * Mknod vnode call
159  */
160 /* ARGSUSED */
161 int
162 ufs_mknod(void *v)
163 {
164 	struct vop_mknod_args /* {
165 		struct vnode		*a_dvp;
166 		struct vnode		**a_vpp;
167 		struct componentname	*a_cnp;
168 		struct vattr		*a_vap;
169 	} */ *ap = v;
170 	struct vattr	*vap;
171 	struct vnode	**vpp;
172 	struct inode	*ip;
173 	int		error;
174 	struct mount	*mp;
175 	ino_t		ino;
176 
177 	vap = ap->a_vap;
178 	vpp = ap->a_vpp;
179 
180 	/*
181 	 * UFS_WAPBL_BEGIN1(dvp->v_mount, dvp) performed by successful
182 	 * ufs_makeinode
183 	 */
184 	fstrans_start(ap->a_dvp->v_mount, FSTRANS_SHARED);
185 	if ((error =
186 	    ufs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode),
187 	    ap->a_dvp, vpp, ap->a_cnp)) != 0)
188 		goto out;
189 	VN_KNOTE(ap->a_dvp, NOTE_WRITE);
190 	ip = VTOI(*vpp);
191 	mp  = (*vpp)->v_mount;
192 	ino = ip->i_number;
193 	ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
194 	if (vap->va_rdev != VNOVAL) {
195 		struct ufsmount *ump = ip->i_ump;
196 		/*
197 		 * Want to be able to use this to make badblock
198 		 * inodes, so don't truncate the dev number.
199 		 */
200 		if (ump->um_fstype == UFS1)
201 			ip->i_ffs1_rdev = ufs_rw32(vap->va_rdev,
202 			    UFS_MPNEEDSWAP(ump));
203 		else
204 			ip->i_ffs2_rdev = ufs_rw64(vap->va_rdev,
205 			    UFS_MPNEEDSWAP(ump));
206 	}
207 	UFS_WAPBL_UPDATE(*vpp, NULL, NULL, 0);
208 	UFS_WAPBL_END1(ap->a_dvp->v_mount, ap->a_dvp);
209 	/*
210 	 * Remove inode so that it will be reloaded by VFS_VGET and
211 	 * checked to see if it is an alias of an existing entry in
212 	 * the inode cache.
213 	 */
214 	VOP_UNLOCK(*vpp);
215 	(*vpp)->v_type = VNON;
216 	vgone(*vpp);
217 	error = VFS_VGET(mp, ino, vpp);
218 out:
219 	fstrans_done(ap->a_dvp->v_mount);
220 	if (error != 0) {
221 		*vpp = NULL;
222 		return (error);
223 	}
224 	return (0);
225 }
226 
227 /*
228  * Open called.
229  *
230  * Nothing to do.
231  */
232 /* ARGSUSED */
233 int
234 ufs_open(void *v)
235 {
236 	struct vop_open_args /* {
237 		struct vnode	*a_vp;
238 		int		a_mode;
239 		kauth_cred_t	a_cred;
240 	} */ *ap = v;
241 
242 	/*
243 	 * Files marked append-only must be opened for appending.
244 	 */
245 	if ((VTOI(ap->a_vp)->i_flags & APPEND) &&
246 	    (ap->a_mode & (FWRITE | O_APPEND)) == FWRITE)
247 		return (EPERM);
248 	return (0);
249 }
250 
251 /*
252  * Close called.
253  *
254  * Update the times on the inode.
255  */
256 /* ARGSUSED */
257 int
258 ufs_close(void *v)
259 {
260 	struct vop_close_args /* {
261 		struct vnode	*a_vp;
262 		int		a_fflag;
263 		kauth_cred_t	a_cred;
264 	} */ *ap = v;
265 	struct vnode	*vp;
266 	struct inode	*ip;
267 
268 	vp = ap->a_vp;
269 	ip = VTOI(vp);
270 	fstrans_start(vp->v_mount, FSTRANS_SHARED);
271 	if (vp->v_usecount > 1)
272 		UFS_ITIMES(vp, NULL, NULL, NULL);
273 	fstrans_done(vp->v_mount);
274 	return (0);
275 }
276 
277 static int
278 ufs_check_possible(struct vnode *vp, struct inode *ip, mode_t mode)
279 {
280 #ifdef QUOTA
281 	int error;
282 #endif /* QUOTA */
283 
284 	/*
285 	 * Disallow write attempts on read-only file systems;
286 	 * unless the file is a socket, fifo, or a block or
287 	 * character device resident on the file system.
288 	 */
289 	if (mode & VWRITE) {
290 		switch (vp->v_type) {
291 		case VDIR:
292 		case VLNK:
293 		case VREG:
294 			if (vp->v_mount->mnt_flag & MNT_RDONLY)
295 				return (EROFS);
296 #ifdef QUOTA
297 			fstrans_start(vp->v_mount, FSTRANS_SHARED);
298 			error = getinoquota(ip);
299 			fstrans_done(vp->v_mount);
300 			if (error != 0)
301 				return error;
302 #endif
303 			break;
304 		case VBAD:
305 		case VBLK:
306 		case VCHR:
307 		case VSOCK:
308 		case VFIFO:
309 		case VNON:
310 		default:
311 			break;
312 		}
313 	}
314 
315 	/* If it is a snapshot, nobody gets access to it. */
316 	if ((ip->i_flags & SF_SNAPSHOT))
317 		return (EPERM);
318 	/* If immutable bit set, nobody gets to write it. */
319 	if ((mode & VWRITE) && (ip->i_flags & IMMUTABLE))
320 		return (EPERM);
321 
322 	return 0;
323 }
324 
325 static int
326 ufs_check_permitted(struct vnode *vp, struct inode *ip, mode_t mode,
327     kauth_cred_t cred)
328 {
329 
330 	return genfs_can_access(vp->v_type, ip->i_mode & ALLPERMS, ip->i_uid,
331 	    ip->i_gid, mode, cred);
332 }
333 
334 int
335 ufs_access(void *v)
336 {
337 	struct vop_access_args /* {
338 		struct vnode	*a_vp;
339 		int		a_mode;
340 		kauth_cred_t	a_cred;
341 	} */ *ap = v;
342 	struct vnode	*vp;
343 	struct inode	*ip;
344 	mode_t		mode;
345 	int		error;
346 
347 	vp = ap->a_vp;
348 	ip = VTOI(vp);
349 	mode = ap->a_mode;
350 
351 	error = ufs_check_possible(vp, ip, mode);
352 	if (error)
353 		return error;
354 
355 	error = ufs_check_permitted(vp, ip, mode, ap->a_cred);
356 
357 	return error;
358 }
359 
360 /* ARGSUSED */
361 int
362 ufs_getattr(void *v)
363 {
364 	struct vop_getattr_args /* {
365 		struct vnode	*a_vp;
366 		struct vattr	*a_vap;
367 		kauth_cred_t	a_cred;
368 	} */ *ap = v;
369 	struct vnode	*vp;
370 	struct inode	*ip;
371 	struct vattr	*vap;
372 
373 	vp = ap->a_vp;
374 	ip = VTOI(vp);
375 	vap = ap->a_vap;
376 	fstrans_start(vp->v_mount, FSTRANS_SHARED);
377 	UFS_ITIMES(vp, NULL, NULL, NULL);
378 
379 	/*
380 	 * Copy from inode table
381 	 */
382 	vap->va_fsid = ip->i_dev;
383 	vap->va_fileid = ip->i_number;
384 	vap->va_mode = ip->i_mode & ALLPERMS;
385 	vap->va_nlink = ip->i_nlink;
386 	vap->va_uid = ip->i_uid;
387 	vap->va_gid = ip->i_gid;
388 	vap->va_size = vp->v_size;
389 	if (ip->i_ump->um_fstype == UFS1) {
390 		vap->va_rdev = (dev_t)ufs_rw32(ip->i_ffs1_rdev,
391 		    UFS_MPNEEDSWAP(ip->i_ump));
392 		vap->va_atime.tv_sec = ip->i_ffs1_atime;
393 		vap->va_atime.tv_nsec = ip->i_ffs1_atimensec;
394 		vap->va_mtime.tv_sec = ip->i_ffs1_mtime;
395 		vap->va_mtime.tv_nsec = ip->i_ffs1_mtimensec;
396 		vap->va_ctime.tv_sec = ip->i_ffs1_ctime;
397 		vap->va_ctime.tv_nsec = ip->i_ffs1_ctimensec;
398 		vap->va_birthtime.tv_sec = 0;
399 		vap->va_birthtime.tv_nsec = 0;
400 		vap->va_bytes = dbtob((u_quad_t)ip->i_ffs1_blocks);
401 	} else {
402 		vap->va_rdev = (dev_t)ufs_rw64(ip->i_ffs2_rdev,
403 		    UFS_MPNEEDSWAP(ip->i_ump));
404 		vap->va_atime.tv_sec = ip->i_ffs2_atime;
405 		vap->va_atime.tv_nsec = ip->i_ffs2_atimensec;
406 		vap->va_mtime.tv_sec = ip->i_ffs2_mtime;
407 		vap->va_mtime.tv_nsec = ip->i_ffs2_mtimensec;
408 		vap->va_ctime.tv_sec = ip->i_ffs2_ctime;
409 		vap->va_ctime.tv_nsec = ip->i_ffs2_ctimensec;
410 		vap->va_birthtime.tv_sec = ip->i_ffs2_birthtime;
411 		vap->va_birthtime.tv_nsec = ip->i_ffs2_birthnsec;
412 		vap->va_bytes = dbtob(ip->i_ffs2_blocks);
413 	}
414 	vap->va_gen = ip->i_gen;
415 	vap->va_flags = ip->i_flags;
416 
417 	/* this doesn't belong here */
418 	if (vp->v_type == VBLK)
419 		vap->va_blocksize = BLKDEV_IOSIZE;
420 	else if (vp->v_type == VCHR)
421 		vap->va_blocksize = MAXBSIZE;
422 	else
423 		vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize;
424 	vap->va_type = vp->v_type;
425 	vap->va_filerev = ip->i_modrev;
426 	fstrans_done(vp->v_mount);
427 	return (0);
428 }
429 
430 /*
431  * Set attribute vnode op. called from several syscalls
432  */
433 int
434 ufs_setattr(void *v)
435 {
436 	struct vop_setattr_args /* {
437 		struct vnode	*a_vp;
438 		struct vattr	*a_vap;
439 		kauth_cred_t	a_cred;
440 	} */ *ap = v;
441 	struct vattr	*vap;
442 	struct vnode	*vp;
443 	struct inode	*ip;
444 	kauth_cred_t	cred;
445 	struct lwp	*l;
446 	int		error;
447 
448 	vap = ap->a_vap;
449 	vp = ap->a_vp;
450 	ip = VTOI(vp);
451 	cred = ap->a_cred;
452 	l = curlwp;
453 
454 	/*
455 	 * Check for unsettable attributes.
456 	 */
457 	if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
458 	    (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
459 	    (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
460 	    ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
461 		return (EINVAL);
462 	}
463 
464 	fstrans_start(vp->v_mount, FSTRANS_SHARED);
465 
466 	if (vap->va_flags != VNOVAL) {
467 		if (vp->v_mount->mnt_flag & MNT_RDONLY) {
468 			error = EROFS;
469 			goto out;
470 		}
471 		if (kauth_cred_geteuid(cred) != ip->i_uid &&
472 		    (error = kauth_authorize_generic(cred,
473 		    KAUTH_GENERIC_ISSUSER, NULL)))
474 			goto out;
475 		if (kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER,
476 		    NULL) == 0) {
477 			if ((ip->i_flags & (SF_IMMUTABLE | SF_APPEND)) &&
478 			    kauth_authorize_system(l->l_cred,
479 			     KAUTH_SYSTEM_CHSYSFLAGS, 0, NULL, NULL, NULL)) {
480 				error = EPERM;
481 				goto out;
482 			}
483 			/* Snapshot flag cannot be set or cleared */
484 			if ((vap->va_flags & SF_SNAPSHOT) !=
485 			    (ip->i_flags & SF_SNAPSHOT)) {
486 				error = EPERM;
487 				goto out;
488 			}
489 			error = UFS_WAPBL_BEGIN(vp->v_mount);
490 			if (error)
491 				goto out;
492 			ip->i_flags = vap->va_flags;
493 			DIP_ASSIGN(ip, flags, ip->i_flags);
494 		} else {
495 			if ((ip->i_flags & (SF_IMMUTABLE | SF_APPEND)) ||
496 			    (vap->va_flags & UF_SETTABLE) != vap->va_flags) {
497 				error = EPERM;
498 				goto out;
499 			}
500 			if ((ip->i_flags & SF_SETTABLE) !=
501 			    (vap->va_flags & SF_SETTABLE)) {
502 				error = EPERM;
503 				goto out;
504 			}
505 			error = UFS_WAPBL_BEGIN(vp->v_mount);
506 			if (error)
507 				goto out;
508 			ip->i_flags &= SF_SETTABLE;
509 			ip->i_flags |= (vap->va_flags & UF_SETTABLE);
510 			DIP_ASSIGN(ip, flags, ip->i_flags);
511 		}
512 		ip->i_flag |= IN_CHANGE;
513 		UFS_WAPBL_UPDATE(vp, NULL, NULL, 0);
514 		UFS_WAPBL_END(vp->v_mount);
515 		if (vap->va_flags & (IMMUTABLE | APPEND)) {
516 			error = 0;
517 			goto out;
518 		}
519 	}
520 	if (ip->i_flags & (IMMUTABLE | APPEND)) {
521 		error = EPERM;
522 		goto out;
523 	}
524 	/*
525 	 * Go through the fields and update iff not VNOVAL.
526 	 */
527 	if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) {
528 		if (vp->v_mount->mnt_flag & MNT_RDONLY) {
529 			error = EROFS;
530 			goto out;
531 		}
532 		error = UFS_WAPBL_BEGIN(vp->v_mount);
533 		if (error)
534 			goto out;
535 		error = ufs_chown(vp, vap->va_uid, vap->va_gid, cred, l);
536 		UFS_WAPBL_END(vp->v_mount);
537 		if (error)
538 			goto out;
539 	}
540 	if (vap->va_size != VNOVAL) {
541 		/*
542 		 * Disallow write attempts on read-only file systems;
543 		 * unless the file is a socket, fifo, or a block or
544 		 * character device resident on the file system.
545 		 */
546 		switch (vp->v_type) {
547 		case VDIR:
548 			error = EISDIR;
549 			goto out;
550 		case VCHR:
551 		case VBLK:
552 		case VFIFO:
553 			break;
554 		case VREG:
555 			if (vp->v_mount->mnt_flag & MNT_RDONLY) {
556 				error = EROFS;
557 				goto out;
558 			}
559 			if ((ip->i_flags & SF_SNAPSHOT) != 0) {
560 				error = EPERM;
561 				goto out;
562 			}
563 			error = UFS_WAPBL_BEGIN(vp->v_mount);
564 			if (error)
565 				goto out;
566 			/*
567 			 * When journaling, only truncate one indirect block
568 			 * at a time.
569 			 */
570 			if (vp->v_mount->mnt_wapbl) {
571 				uint64_t incr = MNINDIR(ip->i_ump) <<
572 				    vp->v_mount->mnt_fs_bshift; /* Power of 2 */
573 				uint64_t base = NDADDR <<
574 				    vp->v_mount->mnt_fs_bshift;
575 				while (!error && ip->i_size > base + incr &&
576 				    ip->i_size > vap->va_size + incr) {
577 					/*
578 					 * round down to next full indirect
579 					 * block boundary.
580 					 */
581 					uint64_t nsize = base +
582 					    ((ip->i_size - base - 1) &
583 					    ~(incr - 1));
584 					error = UFS_TRUNCATE(vp, nsize, 0,
585 					    cred);
586 					if (error == 0) {
587 						UFS_WAPBL_END(vp->v_mount);
588 						error =
589 						   UFS_WAPBL_BEGIN(vp->v_mount);
590 					}
591 				}
592 			}
593 			if (!error)
594 				error = UFS_TRUNCATE(vp, vap->va_size, 0, cred);
595 			UFS_WAPBL_END(vp->v_mount);
596 			if (error)
597 				goto out;
598 			break;
599 		default:
600 			error = EOPNOTSUPP;
601 			goto out;
602 		}
603 	}
604 	ip = VTOI(vp);
605 	if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL ||
606 	    vap->va_birthtime.tv_sec != VNOVAL) {
607 		if (vp->v_mount->mnt_flag & MNT_RDONLY) {
608 			error = EROFS;
609 			goto out;
610 		}
611 		if ((ip->i_flags & SF_SNAPSHOT) != 0) {
612 			error = EPERM;
613 			goto out;
614 		}
615 		error = genfs_can_chtimes(vp, vap->va_vaflags, ip->i_uid, cred);
616 		if (error)
617 			goto out;
618 		error = UFS_WAPBL_BEGIN(vp->v_mount);
619 		if (error)
620 			goto out;
621 		if (vap->va_atime.tv_sec != VNOVAL)
622 			if (!(vp->v_mount->mnt_flag & MNT_NOATIME))
623 				ip->i_flag |= IN_ACCESS;
624 		if (vap->va_mtime.tv_sec != VNOVAL)
625 			ip->i_flag |= IN_CHANGE | IN_UPDATE;
626 		if (vap->va_birthtime.tv_sec != VNOVAL &&
627 		    ip->i_ump->um_fstype == UFS2) {
628 			ip->i_ffs2_birthtime = vap->va_birthtime.tv_sec;
629 			ip->i_ffs2_birthnsec = vap->va_birthtime.tv_nsec;
630 		}
631 		error = UFS_UPDATE(vp, &vap->va_atime, &vap->va_mtime, 0);
632 		UFS_WAPBL_END(vp->v_mount);
633 		if (error)
634 			goto out;
635 	}
636 	error = 0;
637 	if (vap->va_mode != (mode_t)VNOVAL) {
638 		if (vp->v_mount->mnt_flag & MNT_RDONLY) {
639 			error = EROFS;
640 			goto out;
641 		}
642 		if ((ip->i_flags & SF_SNAPSHOT) != 0 &&
643 		    (vap->va_mode & (S_IXUSR | S_IWUSR | S_IXGRP | S_IWGRP |
644 		     S_IXOTH | S_IWOTH))) {
645 			error = EPERM;
646 			goto out;
647 		}
648 		error = UFS_WAPBL_BEGIN(vp->v_mount);
649 		if (error)
650 			goto out;
651 		error = ufs_chmod(vp, (int)vap->va_mode, cred, l);
652 		UFS_WAPBL_END(vp->v_mount);
653 	}
654 	VN_KNOTE(vp, NOTE_ATTRIB);
655 out:
656 	fstrans_done(vp->v_mount);
657 	return (error);
658 }
659 
660 /*
661  * Change the mode on a file.
662  * Inode must be locked before calling.
663  */
664 static int
665 ufs_chmod(struct vnode *vp, int mode, kauth_cred_t cred, struct lwp *l)
666 {
667 	struct inode	*ip;
668 	int		error;
669 
670 	UFS_WAPBL_JLOCK_ASSERT(vp->v_mount);
671 
672 	ip = VTOI(vp);
673 
674 	error = genfs_can_chmod(vp, cred, ip->i_uid, ip->i_gid, mode);
675 	if (error)
676 		return (error);
677 
678 	fstrans_start(vp->v_mount, FSTRANS_SHARED);
679 	ip->i_mode &= ~ALLPERMS;
680 	ip->i_mode |= (mode & ALLPERMS);
681 	ip->i_flag |= IN_CHANGE;
682 	DIP_ASSIGN(ip, mode, ip->i_mode);
683 	UFS_WAPBL_UPDATE(vp, NULL, NULL, 0);
684 	fstrans_done(vp->v_mount);
685 	return (0);
686 }
687 
688 /*
689  * Perform chown operation on inode ip;
690  * inode must be locked prior to call.
691  */
692 static int
693 ufs_chown(struct vnode *vp, uid_t uid, gid_t gid, kauth_cred_t cred,
694     	struct lwp *l)
695 {
696 	struct inode	*ip;
697 	int		error = 0;
698 #ifdef QUOTA
699 	uid_t		ouid;
700 	gid_t		ogid;
701 	int64_t		change;
702 #endif
703 	ip = VTOI(vp);
704 	error = 0;
705 
706 	if (uid == (uid_t)VNOVAL)
707 		uid = ip->i_uid;
708 	if (gid == (gid_t)VNOVAL)
709 		gid = ip->i_gid;
710 
711 	error = genfs_can_chown(vp, cred, ip->i_uid, ip->i_gid, uid, gid);
712 	if (error)
713 		return (error);
714 
715 	fstrans_start(vp->v_mount, FSTRANS_SHARED);
716 #ifdef QUOTA
717 	ogid = ip->i_gid;
718 	ouid = ip->i_uid;
719 	change = DIP(ip, blocks);
720 	(void) chkdq(ip, -change, cred, 0);
721 	(void) chkiq(ip, -1, cred, 0);
722 #endif
723 	ip->i_gid = gid;
724 	DIP_ASSIGN(ip, gid, gid);
725 	ip->i_uid = uid;
726 	DIP_ASSIGN(ip, uid, uid);
727 #ifdef QUOTA
728 	if ((error = chkdq(ip, change, cred, 0)) == 0) {
729 		if ((error = chkiq(ip, 1, cred, 0)) == 0)
730 			goto good;
731 		else
732 			(void) chkdq(ip, -change, cred, FORCE);
733 	}
734 	ip->i_gid = ogid;
735 	DIP_ASSIGN(ip, gid, ogid);
736 	ip->i_uid = ouid;
737 	DIP_ASSIGN(ip, uid, ouid);
738 	(void) chkdq(ip, change, cred, FORCE);
739 	(void) chkiq(ip, 1, cred, FORCE);
740 	fstrans_done(vp->v_mount);
741 	return (error);
742  good:
743 #endif /* QUOTA */
744 	ip->i_flag |= IN_CHANGE;
745 	UFS_WAPBL_UPDATE(vp, NULL, NULL, 0);
746 	fstrans_done(vp->v_mount);
747 	return (0);
748 }
749 
750 int
751 ufs_remove(void *v)
752 {
753 	struct vop_remove_args /* {
754 		struct vnode		*a_dvp;
755 		struct vnode		*a_vp;
756 		struct componentname	*a_cnp;
757 	} */ *ap = v;
758 	struct vnode	*vp, *dvp;
759 	struct inode	*ip;
760 	int		error;
761 
762 	vp = ap->a_vp;
763 	dvp = ap->a_dvp;
764 	ip = VTOI(vp);
765 	fstrans_start(dvp->v_mount, FSTRANS_SHARED);
766 	if (vp->v_type == VDIR || (ip->i_flags & (IMMUTABLE | APPEND)) ||
767 	    (VTOI(dvp)->i_flags & APPEND))
768 		error = EPERM;
769 	else {
770 		error = UFS_WAPBL_BEGIN(dvp->v_mount);
771 		if (error == 0) {
772 			error = ufs_dirremove(dvp, ip, ap->a_cnp->cn_flags, 0);
773 			UFS_WAPBL_END(dvp->v_mount);
774 		}
775 	}
776 	VN_KNOTE(vp, NOTE_DELETE);
777 	VN_KNOTE(dvp, NOTE_WRITE);
778 	if (dvp == vp)
779 		vrele(vp);
780 	else
781 		vput(vp);
782 	vput(dvp);
783 	fstrans_done(dvp->v_mount);
784 	return (error);
785 }
786 
787 /*
788  * link vnode call
789  */
790 int
791 ufs_link(void *v)
792 {
793 	struct vop_link_args /* {
794 		struct vnode *a_dvp;
795 		struct vnode *a_vp;
796 		struct componentname *a_cnp;
797 	} */ *ap = v;
798 	struct vnode		*vp, *dvp;
799 	struct componentname	*cnp;
800 	struct inode		*ip;
801 	struct direct		*newdir;
802 	int			error;
803 
804 	dvp = ap->a_dvp;
805 	vp = ap->a_vp;
806 	cnp = ap->a_cnp;
807 
808 	fstrans_start(dvp->v_mount, FSTRANS_SHARED);
809 	if (vp->v_type == VDIR) {
810 		VOP_ABORTOP(dvp, cnp);
811 		error = EPERM;
812 		goto out2;
813 	}
814 	if (dvp->v_mount != vp->v_mount) {
815 		VOP_ABORTOP(dvp, cnp);
816 		error = EXDEV;
817 		goto out2;
818 	}
819 	if (dvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE))) {
820 		VOP_ABORTOP(dvp, cnp);
821 		goto out2;
822 	}
823 	ip = VTOI(vp);
824 	if ((nlink_t)ip->i_nlink >= LINK_MAX) {
825 		VOP_ABORTOP(dvp, cnp);
826 		error = EMLINK;
827 		goto out1;
828 	}
829 	if (ip->i_flags & (IMMUTABLE | APPEND)) {
830 		VOP_ABORTOP(dvp, cnp);
831 		error = EPERM;
832 		goto out1;
833 	}
834 	error = UFS_WAPBL_BEGIN(vp->v_mount);
835 	if (error) {
836 		VOP_ABORTOP(dvp, cnp);
837 		goto out1;
838 	}
839 	ip->i_nlink++;
840 	DIP_ASSIGN(ip, nlink, ip->i_nlink);
841 	ip->i_flag |= IN_CHANGE;
842 	error = UFS_UPDATE(vp, NULL, NULL, UPDATE_DIROP);
843 	if (!error) {
844 		newdir = pool_cache_get(ufs_direct_cache, PR_WAITOK);
845 		ufs_makedirentry(ip, cnp, newdir);
846 		error = ufs_direnter(dvp, vp, newdir, cnp, NULL);
847 		pool_cache_put(ufs_direct_cache, newdir);
848 	}
849 	if (error) {
850 		ip->i_nlink--;
851 		DIP_ASSIGN(ip, nlink, ip->i_nlink);
852 		ip->i_flag |= IN_CHANGE;
853 		UFS_WAPBL_UPDATE(vp, NULL, NULL, UPDATE_DIROP);
854 	}
855 	UFS_WAPBL_END(vp->v_mount);
856  out1:
857 	if (dvp != vp)
858 		VOP_UNLOCK(vp);
859  out2:
860 	VN_KNOTE(vp, NOTE_LINK);
861 	VN_KNOTE(dvp, NOTE_WRITE);
862 	vput(dvp);
863 	fstrans_done(dvp->v_mount);
864 	return (error);
865 }
866 
867 /*
868  * whiteout vnode call
869  */
870 int
871 ufs_whiteout(void *v)
872 {
873 	struct vop_whiteout_args /* {
874 		struct vnode		*a_dvp;
875 		struct componentname	*a_cnp;
876 		int			a_flags;
877 	} */ *ap = v;
878 	struct vnode		*dvp = ap->a_dvp;
879 	struct componentname	*cnp = ap->a_cnp;
880 	struct direct		*newdir;
881 	int			error;
882 	struct ufsmount		*ump = VFSTOUFS(dvp->v_mount);
883 
884 	error = 0;
885 	switch (ap->a_flags) {
886 	case LOOKUP:
887 		/* 4.4 format directories support whiteout operations */
888 		if (ump->um_maxsymlinklen > 0)
889 			return (0);
890 		return (EOPNOTSUPP);
891 
892 	case CREATE:
893 		/* create a new directory whiteout */
894 		fstrans_start(dvp->v_mount, FSTRANS_SHARED);
895 #ifdef DIAGNOSTIC
896 		if (ump->um_maxsymlinklen <= 0)
897 			panic("ufs_whiteout: old format filesystem");
898 #endif
899 
900 		newdir = pool_cache_get(ufs_direct_cache, PR_WAITOK);
901 		newdir->d_ino = WINO;
902 		newdir->d_namlen = cnp->cn_namelen;
903 		memcpy(newdir->d_name, cnp->cn_nameptr,
904 		    (size_t)cnp->cn_namelen);
905 		newdir->d_name[cnp->cn_namelen] = '\0';
906 		newdir->d_type = DT_WHT;
907 		error = ufs_direnter(dvp, NULL, newdir, cnp, NULL);
908 		pool_cache_put(ufs_direct_cache, newdir);
909 		break;
910 
911 	case DELETE:
912 		/* remove an existing directory whiteout */
913 		fstrans_start(dvp->v_mount, FSTRANS_SHARED);
914 #ifdef DIAGNOSTIC
915 		if (ump->um_maxsymlinklen <= 0)
916 			panic("ufs_whiteout: old format filesystem");
917 #endif
918 
919 		cnp->cn_flags &= ~DOWHITEOUT;
920 		error = ufs_dirremove(dvp, NULL, cnp->cn_flags, 0);
921 		break;
922 	default:
923 		panic("ufs_whiteout: unknown op");
924 		/* NOTREACHED */
925 	}
926 	fstrans_done(dvp->v_mount);
927 	return (error);
928 }
929 
930 
931 /*
932  * Rename vnode operation
933  * 	rename("foo", "bar");
934  * is essentially
935  *	unlink("bar");
936  *	link("foo", "bar");
937  *	unlink("foo");
938  * but ``atomically''.  Can't do full commit without saving state in the
939  * inode on disk which isn't feasible at this time.  Best we can do is
940  * always guarantee the target exists.
941  *
942  * Basic algorithm is:
943  *
944  * 1) Bump link count on source while we're linking it to the
945  *    target.  This also ensure the inode won't be deleted out
946  *    from underneath us while we work (it may be truncated by
947  *    a concurrent `trunc' or `open' for creation).
948  * 2) Link source to destination.  If destination already exists,
949  *    delete it first.
950  * 3) Unlink source reference to inode if still around. If a
951  *    directory was moved and the parent of the destination
952  *    is different from the source, patch the ".." entry in the
953  *    directory.
954  */
955 int
956 ufs_rename(void *v)
957 {
958 	struct vop_rename_args  /* {
959 		struct vnode		*a_fdvp;
960 		struct vnode		*a_fvp;
961 		struct componentname	*a_fcnp;
962 		struct vnode		*a_tdvp;
963 		struct vnode		*a_tvp;
964 		struct componentname	*a_tcnp;
965 	} */ *ap = v;
966 	struct vnode		*tvp, *tdvp, *fvp, *fdvp;
967 	struct componentname	*tcnp, *fcnp;
968 	struct inode		*ip, *xp, *dp;
969 	struct mount		*mp;
970 	struct direct		*newdir;
971 	int			doingdirectory, oldparent, newparent, error;
972 
973 #ifdef WAPBL
974 	if (ap->a_tdvp->v_mount->mnt_wapbl)
975 		return wapbl_ufs_rename(v);
976 #endif
977 
978 	tvp = ap->a_tvp;
979 	tdvp = ap->a_tdvp;
980 	fvp = ap->a_fvp;
981 	fdvp = ap->a_fdvp;
982 	tcnp = ap->a_tcnp;
983 	fcnp = ap->a_fcnp;
984 	doingdirectory = oldparent = newparent = error = 0;
985 
986 	/*
987 	 * Check for cross-device rename.
988 	 */
989 	if ((fvp->v_mount != tdvp->v_mount) ||
990 	    (tvp && (fvp->v_mount != tvp->v_mount))) {
991 		error = EXDEV;
992  abortit:
993 		VOP_ABORTOP(tdvp, tcnp); /* XXX, why not in NFS? */
994 		if (tdvp == tvp)
995 			vrele(tdvp);
996 		else
997 			vput(tdvp);
998 		if (tvp)
999 			vput(tvp);
1000 		VOP_ABORTOP(fdvp, fcnp); /* XXX, why not in NFS? */
1001 		vrele(fdvp);
1002 		vrele(fvp);
1003 		return (error);
1004 	}
1005 
1006 	/*
1007 	 * Check if just deleting a link name.
1008 	 */
1009 	if (tvp && ((VTOI(tvp)->i_flags & (IMMUTABLE | APPEND)) ||
1010 	    (VTOI(tdvp)->i_flags & APPEND))) {
1011 		error = EPERM;
1012 		goto abortit;
1013 	}
1014 	if (fvp == tvp) {
1015 		if (fvp->v_type == VDIR) {
1016 			error = EINVAL;
1017 			goto abortit;
1018 		}
1019 
1020 		/* Release destination completely. */
1021 		VOP_ABORTOP(tdvp, tcnp);
1022 		vput(tdvp);
1023 		vput(tvp);
1024 
1025 		/* Delete source. */
1026 		vrele(fvp);
1027 		fcnp->cn_flags &= ~(MODMASK);
1028 		fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
1029 		fcnp->cn_nameiop = DELETE;
1030 		vn_lock(fdvp, LK_EXCLUSIVE | LK_RETRY);
1031 		if ((error = relookup(fdvp, &fvp, fcnp, 0))) {
1032 			vput(fdvp);
1033 			return (error);
1034 		}
1035 		return (VOP_REMOVE(fdvp, fvp, fcnp));
1036 	}
1037 	if ((error = vn_lock(fvp, LK_EXCLUSIVE)) != 0)
1038 		goto abortit;
1039 	dp = VTOI(fdvp);
1040 	ip = VTOI(fvp);
1041 	if ((nlink_t) ip->i_nlink >= LINK_MAX) {
1042 		VOP_UNLOCK(fvp);
1043 		error = EMLINK;
1044 		goto abortit;
1045 	}
1046 	if ((ip->i_flags & (IMMUTABLE | APPEND)) ||
1047 		(dp->i_flags & APPEND)) {
1048 		VOP_UNLOCK(fvp);
1049 		error = EPERM;
1050 		goto abortit;
1051 	}
1052 	if ((ip->i_mode & IFMT) == IFDIR) {
1053 		/*
1054 		 * Avoid ".", "..", and aliases of "." for obvious reasons.
1055 		 */
1056 		if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') ||
1057 		    dp == ip ||
1058 		    (fcnp->cn_flags & ISDOTDOT) ||
1059 		    (tcnp->cn_flags & ISDOTDOT) ||
1060 		    (ip->i_flag & IN_RENAME)) {
1061 			VOP_UNLOCK(fvp);
1062 			error = EINVAL;
1063 			goto abortit;
1064 		}
1065 		ip->i_flag |= IN_RENAME;
1066 		oldparent = dp->i_number;
1067 		doingdirectory = 1;
1068 	}
1069 	VN_KNOTE(fdvp, NOTE_WRITE);		/* XXXLUKEM/XXX: right place? */
1070 
1071 	/*
1072 	 * When the target exists, both the directory
1073 	 * and target vnodes are returned locked.
1074 	 */
1075 	dp = VTOI(tdvp);
1076 	xp = NULL;
1077 	if (tvp)
1078 		xp = VTOI(tvp);
1079 
1080 	mp = fdvp->v_mount;
1081 	fstrans_start(mp, FSTRANS_SHARED);
1082 
1083 	/*
1084 	 * 1) Bump link count while we're moving stuff
1085 	 *    around.  If we crash somewhere before
1086 	 *    completing our work, the link count
1087 	 *    may be wrong, but correctable.
1088 	 */
1089 	ip->i_nlink++;
1090 	DIP_ASSIGN(ip, nlink, ip->i_nlink);
1091 	ip->i_flag |= IN_CHANGE;
1092 	if ((error = UFS_UPDATE(fvp, NULL, NULL, UPDATE_DIROP)) != 0) {
1093 		VOP_UNLOCK(fvp);
1094 		goto bad;
1095 	}
1096 
1097 	/*
1098 	 * If ".." must be changed (ie the directory gets a new
1099 	 * parent) then the source directory must not be in the
1100 	 * directory hierarchy above the target, as this would
1101 	 * orphan everything below the source directory. Also
1102 	 * the user must have write permission in the source so
1103 	 * as to be able to change "..". We must repeat the call
1104 	 * to namei, as the parent directory is unlocked by the
1105 	 * call to checkpath().
1106 	 */
1107 	error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred);
1108 	VOP_UNLOCK(fvp);
1109 	if (oldparent != dp->i_number)
1110 		newparent = dp->i_number;
1111 	if (doingdirectory && newparent) {
1112 		if (error)	/* write access check above */
1113 			goto bad;
1114 		if (xp != NULL)
1115 			vput(tvp);
1116 		vref(tdvp);	/* compensate for the ref checkpath loses */
1117 		if ((error = ufs_checkpath(ip, dp, tcnp->cn_cred)) != 0) {
1118 			vrele(tdvp);
1119 			goto out;
1120 		}
1121 		vn_lock(tdvp, LK_EXCLUSIVE | LK_RETRY);
1122 		error = relookup(tdvp, &tvp, tcnp, 0);
1123 		if (error != 0) {
1124 			vput(tdvp);
1125 			goto out;
1126 		}
1127 		dp = VTOI(tdvp);
1128 		xp = NULL;
1129 		if (tvp)
1130 			xp = VTOI(tvp);
1131 	}
1132 	/*
1133 	 * 2) If target doesn't exist, link the target
1134 	 *    to the source and unlink the source.
1135 	 *    Otherwise, rewrite the target directory
1136 	 *    entry to reference the source inode and
1137 	 *    expunge the original entry's existence.
1138 	 */
1139 	if (xp == NULL) {
1140 		if (dp->i_dev != ip->i_dev)
1141 			panic("rename: EXDEV");
1142 		/*
1143 		 * Account for ".." in new directory.
1144 		 * When source and destination have the same
1145 		 * parent we don't fool with the link count.
1146 		 */
1147 		if (doingdirectory && newparent) {
1148 			if ((nlink_t)dp->i_nlink >= LINK_MAX) {
1149 				error = EMLINK;
1150 				goto bad;
1151 			}
1152 			dp->i_nlink++;
1153 			DIP_ASSIGN(dp, nlink, dp->i_nlink);
1154 			dp->i_flag |= IN_CHANGE;
1155 			if ((error = UFS_UPDATE(tdvp, NULL, NULL,
1156 			    UPDATE_DIROP)) != 0) {
1157 				dp->i_nlink--;
1158 				DIP_ASSIGN(dp, nlink, dp->i_nlink);
1159 				dp->i_flag |= IN_CHANGE;
1160 				goto bad;
1161 			}
1162 		}
1163 		newdir = pool_cache_get(ufs_direct_cache, PR_WAITOK);
1164 		ufs_makedirentry(ip, tcnp, newdir);
1165 		error = ufs_direnter(tdvp, NULL, newdir, tcnp, NULL);
1166 		pool_cache_put(ufs_direct_cache, newdir);
1167 		if (error != 0) {
1168 			if (doingdirectory && newparent) {
1169 				dp->i_nlink--;
1170 				DIP_ASSIGN(dp, nlink, dp->i_nlink);
1171 				dp->i_flag |= IN_CHANGE;
1172 				(void)UFS_UPDATE(tdvp, NULL, NULL,
1173 						 UPDATE_WAIT|UPDATE_DIROP);
1174 			}
1175 			goto bad;
1176 		}
1177 		VN_KNOTE(tdvp, NOTE_WRITE);
1178 		vput(tdvp);
1179 	} else {
1180 		if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev)
1181 			panic("rename: EXDEV");
1182 		/*
1183 		 * Short circuit rename(foo, foo).
1184 		 */
1185 		if (xp->i_number == ip->i_number)
1186 			panic("rename: same file");
1187 		/*
1188 		 * If the parent directory is "sticky", then the user must
1189 		 * own the parent directory, or the destination of the rename,
1190 		 * otherwise the destination may not be changed (except by
1191 		 * root). This implements append-only directories.
1192 		 */
1193 		if ((dp->i_mode & S_ISTXT) &&
1194 		    kauth_authorize_generic(tcnp->cn_cred,
1195 		     KAUTH_GENERIC_ISSUSER, NULL) != 0 &&
1196 		    kauth_cred_geteuid(tcnp->cn_cred) != dp->i_uid &&
1197 		    xp->i_uid != kauth_cred_geteuid(tcnp->cn_cred)) {
1198 			error = EPERM;
1199 			goto bad;
1200 		}
1201 		/*
1202 		 * Target must be empty if a directory and have no links
1203 		 * to it. Also, ensure source and target are compatible
1204 		 * (both directories, or both not directories).
1205 		 */
1206 		if ((xp->i_mode & IFMT) == IFDIR) {
1207 			if (xp->i_nlink > 2 ||
1208 			    !ufs_dirempty(xp, dp->i_number, tcnp->cn_cred)) {
1209 				error = ENOTEMPTY;
1210 				goto bad;
1211 			}
1212 			if (!doingdirectory) {
1213 				error = ENOTDIR;
1214 				goto bad;
1215 			}
1216 			cache_purge(tdvp);
1217 		} else if (doingdirectory) {
1218 			error = EISDIR;
1219 			goto bad;
1220 		}
1221 		if ((error = ufs_dirrewrite(dp, xp, ip->i_number,
1222 		    IFTODT(ip->i_mode), doingdirectory && newparent ?
1223 		    newparent : doingdirectory, IN_CHANGE | IN_UPDATE)) != 0)
1224 			goto bad;
1225 		if (doingdirectory) {
1226 			/*
1227 			 * Truncate inode. The only stuff left in the directory
1228 			 * is "." and "..". The "." reference is inconsequential
1229 			 * since we are quashing it. We have removed the "."
1230 			 * reference and the reference in the parent directory,
1231 			 * but there may be other hard links.
1232 			 */
1233 			if (!newparent) {
1234 				dp->i_nlink--;
1235 				DIP_ASSIGN(dp, nlink, dp->i_nlink);
1236 				dp->i_flag |= IN_CHANGE;
1237 			}
1238 			xp->i_nlink--;
1239 			DIP_ASSIGN(xp, nlink, xp->i_nlink);
1240 			xp->i_flag |= IN_CHANGE;
1241 			if ((error = UFS_TRUNCATE(tvp, (off_t)0, IO_SYNC,
1242 			    tcnp->cn_cred)))
1243 				goto bad;
1244 		}
1245 		VN_KNOTE(tdvp, NOTE_WRITE);
1246 		vput(tdvp);
1247 		VN_KNOTE(tvp, NOTE_DELETE);
1248 		vput(tvp);
1249 		xp = NULL;
1250 	}
1251 
1252 	/*
1253 	 * 3) Unlink the source.
1254 	 */
1255 	fcnp->cn_flags &= ~(MODMASK);
1256 	fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
1257 	vn_lock(fdvp, LK_EXCLUSIVE | LK_RETRY);
1258 	if ((error = relookup(fdvp, &fvp, fcnp, 0))) {
1259 		vput(fdvp);
1260 		vrele(ap->a_fvp);
1261 		goto out2;
1262 	}
1263 	if (fvp != NULL) {
1264 		xp = VTOI(fvp);
1265 		dp = VTOI(fdvp);
1266 	} else {
1267 		/*
1268 		 * From name has disappeared.
1269 		 */
1270 		if (doingdirectory)
1271 			panic("rename: lost dir entry");
1272 		vrele(ap->a_fvp);
1273 		error = 0;
1274 		goto out2;
1275 	}
1276 	/*
1277 	 * Ensure that the directory entry still exists and has not
1278 	 * changed while the new name has been entered. If the source is
1279 	 * a file then the entry may have been unlinked or renamed. In
1280 	 * either case there is no further work to be done. If the source
1281 	 * is a directory then it cannot have been rmdir'ed; The IRENAME
1282 	 * flag ensures that it cannot be moved by another rename or removed
1283 	 * by a rmdir.
1284 	 */
1285 	if (xp != ip) {
1286 		if (doingdirectory)
1287 			panic("rename: lost dir entry");
1288 	} else {
1289 		/*
1290 		 * If the source is a directory with a
1291 		 * new parent, the link count of the old
1292 		 * parent directory must be decremented
1293 		 * and ".." set to point to the new parent.
1294 		 */
1295 		if (doingdirectory && newparent) {
1296 			KASSERT(dp != NULL);
1297 			xp->i_offset = mastertemplate.dot_reclen;
1298 			ufs_dirrewrite(xp, dp, newparent, DT_DIR, 0, IN_CHANGE);
1299 			cache_purge(fdvp);
1300 		}
1301 		error = ufs_dirremove(fdvp, xp, fcnp->cn_flags, 0);
1302 		xp->i_flag &= ~IN_RENAME;
1303 	}
1304 	VN_KNOTE(fvp, NOTE_RENAME);
1305 	if (dp)
1306 		vput(fdvp);
1307 	if (xp)
1308 		vput(fvp);
1309 	vrele(ap->a_fvp);
1310 	goto out2;
1311 
1312 	/* exit routines from steps 1 & 2 */
1313  bad:
1314 	if (xp)
1315 		vput(ITOV(xp));
1316 	vput(ITOV(dp));
1317  out:
1318 	if (doingdirectory)
1319 		ip->i_flag &= ~IN_RENAME;
1320 	if (vn_lock(fvp, LK_EXCLUSIVE) == 0) {
1321 		ip->i_nlink--;
1322 		DIP_ASSIGN(ip, nlink, ip->i_nlink);
1323 		ip->i_flag |= IN_CHANGE;
1324 		ip->i_flag &= ~IN_RENAME;
1325 		vput(fvp);
1326 	} else
1327 		vrele(fvp);
1328 	vrele(fdvp);
1329 
1330 	/* exit routines from step 3 */
1331  out2:
1332 	fstrans_done(mp);
1333 	return (error);
1334 }
1335 
1336 int
1337 ufs_mkdir(void *v)
1338 {
1339 	struct vop_mkdir_args /* {
1340 		struct vnode		*a_dvp;
1341 		struct vnode		**a_vpp;
1342 		struct componentname	*a_cnp;
1343 		struct vattr		*a_vap;
1344 	} */ *ap = v;
1345 	struct vnode		*dvp = ap->a_dvp, *tvp;
1346 	struct vattr		*vap = ap->a_vap;
1347 	struct componentname	*cnp = ap->a_cnp;
1348 	struct inode		*ip, *dp = VTOI(dvp);
1349 	struct buf		*bp;
1350 	struct dirtemplate	dirtemplate;
1351 	struct direct		*newdir;
1352 	int			error, dmode;
1353 	struct ufsmount		*ump = dp->i_ump;
1354 	int			dirblksiz = ump->um_dirblksiz;
1355 
1356 	fstrans_start(dvp->v_mount, FSTRANS_SHARED);
1357 
1358 	if ((nlink_t)dp->i_nlink >= LINK_MAX) {
1359 		error = EMLINK;
1360 		goto out;
1361 	}
1362 	dmode = vap->va_mode & ACCESSPERMS;
1363 	dmode |= IFDIR;
1364 	/*
1365 	 * Must simulate part of ufs_makeinode here to acquire the inode,
1366 	 * but not have it entered in the parent directory. The entry is
1367 	 * made later after writing "." and ".." entries.
1368 	 */
1369 	if ((error = UFS_VALLOC(dvp, dmode, cnp->cn_cred, ap->a_vpp)) != 0)
1370 		goto out;
1371 	error = UFS_WAPBL_BEGIN(ap->a_dvp->v_mount);
1372 	if (error)
1373 		goto out;
1374 	tvp = *ap->a_vpp;
1375 	ip = VTOI(tvp);
1376 	ip->i_uid = kauth_cred_geteuid(cnp->cn_cred);
1377 	DIP_ASSIGN(ip, uid, ip->i_uid);
1378 	ip->i_gid = dp->i_gid;
1379 	DIP_ASSIGN(ip, gid, ip->i_gid);
1380 #ifdef QUOTA
1381 	if ((error = chkiq(ip, 1, cnp->cn_cred, 0))) {
1382 		UFS_VFREE(tvp, ip->i_number, dmode);
1383 		UFS_WAPBL_END(dvp->v_mount);
1384 		fstrans_done(dvp->v_mount);
1385 		vput(tvp);
1386 		vput(dvp);
1387 		return (error);
1388 	}
1389 #endif
1390 	ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
1391 	ip->i_mode = dmode;
1392 	DIP_ASSIGN(ip, mode, dmode);
1393 	tvp->v_type = VDIR;	/* Rest init'd in getnewvnode(). */
1394 	ip->i_nlink = 2;
1395 	DIP_ASSIGN(ip, nlink, 2);
1396 	if (cnp->cn_flags & ISWHITEOUT) {
1397 		ip->i_flags |= UF_OPAQUE;
1398 		DIP_ASSIGN(ip, flags, ip->i_flags);
1399 	}
1400 
1401 	/*
1402 	 * Bump link count in parent directory to reflect work done below.
1403 	 * Should be done before reference is created so cleanup is
1404 	 * possible if we crash.
1405 	 */
1406 	dp->i_nlink++;
1407 	DIP_ASSIGN(dp, nlink, dp->i_nlink);
1408 	dp->i_flag |= IN_CHANGE;
1409 	if ((error = UFS_UPDATE(dvp, NULL, NULL, UPDATE_DIROP)) != 0)
1410 		goto bad;
1411 
1412 	/*
1413 	 * Initialize directory with "." and ".." from static template.
1414 	 */
1415 	dirtemplate = mastertemplate;
1416 	dirtemplate.dotdot_reclen = dirblksiz - dirtemplate.dot_reclen;
1417 	dirtemplate.dot_ino = ufs_rw32(ip->i_number, UFS_MPNEEDSWAP(ump));
1418 	dirtemplate.dotdot_ino = ufs_rw32(dp->i_number, UFS_MPNEEDSWAP(ump));
1419 	dirtemplate.dot_reclen = ufs_rw16(dirtemplate.dot_reclen,
1420 	    UFS_MPNEEDSWAP(ump));
1421 	dirtemplate.dotdot_reclen = ufs_rw16(dirtemplate.dotdot_reclen,
1422 	    UFS_MPNEEDSWAP(ump));
1423 	if (ump->um_maxsymlinklen <= 0) {
1424 #if BYTE_ORDER == LITTLE_ENDIAN
1425 		if (UFS_MPNEEDSWAP(ump) == 0)
1426 #else
1427 		if (UFS_MPNEEDSWAP(ump) != 0)
1428 #endif
1429 		{
1430 			dirtemplate.dot_type = dirtemplate.dot_namlen;
1431 			dirtemplate.dotdot_type = dirtemplate.dotdot_namlen;
1432 			dirtemplate.dot_namlen = dirtemplate.dotdot_namlen = 0;
1433 		} else
1434 			dirtemplate.dot_type = dirtemplate.dotdot_type = 0;
1435 	}
1436 	if ((error = UFS_BALLOC(tvp, (off_t)0, dirblksiz, cnp->cn_cred,
1437 	    B_CLRBUF, &bp)) != 0)
1438 		goto bad;
1439 	ip->i_size = dirblksiz;
1440 	DIP_ASSIGN(ip, size, dirblksiz);
1441 	ip->i_flag |= IN_CHANGE | IN_UPDATE;
1442 	uvm_vnp_setsize(tvp, ip->i_size);
1443 	memcpy((void *)bp->b_data, (void *)&dirtemplate, sizeof dirtemplate);
1444 
1445 	/*
1446 	 * Directory set up, now install it's entry in the parent directory.
1447 	 * We must write out the buffer containing the new directory body
1448 	 * before entering the new name in the parent.
1449 	 */
1450 	if ((error = VOP_BWRITE(bp)) != 0)
1451 		goto bad;
1452 	if ((error = UFS_UPDATE(tvp, NULL, NULL, UPDATE_DIROP)) != 0) {
1453 		goto bad;
1454 	}
1455 	newdir = pool_cache_get(ufs_direct_cache, PR_WAITOK);
1456 	ufs_makedirentry(ip, cnp, newdir);
1457 	error = ufs_direnter(dvp, tvp, newdir, cnp, bp);
1458 	pool_cache_put(ufs_direct_cache, newdir);
1459  bad:
1460 	if (error == 0) {
1461 		VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
1462 		UFS_WAPBL_END(dvp->v_mount);
1463 	} else {
1464 		dp->i_nlink--;
1465 		DIP_ASSIGN(dp, nlink, dp->i_nlink);
1466 		dp->i_flag |= IN_CHANGE;
1467 		UFS_WAPBL_UPDATE(dvp, NULL, NULL, UPDATE_DIROP);
1468 		/*
1469 		 * No need to do an explicit UFS_TRUNCATE here, vrele will
1470 		 * do this for us because we set the link count to 0.
1471 		 */
1472 		ip->i_nlink = 0;
1473 		DIP_ASSIGN(ip, nlink, 0);
1474 		ip->i_flag |= IN_CHANGE;
1475 		/* If IN_ADIROP, account for it */
1476 		UFS_UNMARK_VNODE(tvp);
1477 		UFS_WAPBL_UPDATE(tvp, NULL, NULL, UPDATE_DIROP);
1478 		UFS_WAPBL_END(dvp->v_mount);
1479 		vput(tvp);
1480 	}
1481  out:
1482 	fstrans_done(dvp->v_mount);
1483 	vput(dvp);
1484 	return (error);
1485 }
1486 
1487 int
1488 ufs_rmdir(void *v)
1489 {
1490 	struct vop_rmdir_args /* {
1491 		struct vnode		*a_dvp;
1492 		struct vnode		*a_vp;
1493 		struct componentname	*a_cnp;
1494 	} */ *ap = v;
1495 	struct vnode		*vp, *dvp;
1496 	struct componentname	*cnp;
1497 	struct inode		*ip, *dp;
1498 	int			error;
1499 
1500 	vp = ap->a_vp;
1501 	dvp = ap->a_dvp;
1502 	cnp = ap->a_cnp;
1503 	ip = VTOI(vp);
1504 	dp = VTOI(dvp);
1505 	/*
1506 	 * No rmdir "." or of mounted directories please.
1507 	 */
1508 	if (dp == ip || vp->v_mountedhere != NULL) {
1509 		if (dp == ip)
1510 			vrele(vp);
1511 		else
1512 			vput(vp);
1513 		vput(vp);
1514 		return (EINVAL);
1515 	}
1516 
1517 	fstrans_start(dvp->v_mount, FSTRANS_SHARED);
1518 
1519 	/*
1520 	 * Do not remove a directory that is in the process of being renamed.
1521 	 * Verify that the directory is empty (and valid). (Rmdir ".." won't
1522 	 * be valid since ".." will contain a reference to the current
1523 	 * directory and thus be non-empty.)
1524 	 */
1525 	error = 0;
1526 	if (ip->i_flag & IN_RENAME) {
1527 		error = EINVAL;
1528 		goto out;
1529 	}
1530 	if (ip->i_nlink != 2 ||
1531 	    !ufs_dirempty(ip, dp->i_number, cnp->cn_cred)) {
1532 		error = ENOTEMPTY;
1533 		goto out;
1534 	}
1535 	if ((dp->i_flags & APPEND) ||
1536 		(ip->i_flags & (IMMUTABLE | APPEND))) {
1537 		error = EPERM;
1538 		goto out;
1539 	}
1540 	error = UFS_WAPBL_BEGIN(dvp->v_mount);
1541 	if (error)
1542 		goto out;
1543 	/*
1544 	 * Delete reference to directory before purging
1545 	 * inode.  If we crash in between, the directory
1546 	 * will be reattached to lost+found,
1547 	 */
1548 	error = ufs_dirremove(dvp, ip, cnp->cn_flags, 1);
1549 	if (error) {
1550 		UFS_WAPBL_END(dvp->v_mount);
1551 		goto out;
1552 	}
1553 	VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
1554 	cache_purge(dvp);
1555 	/*
1556 	 * Truncate inode.  The only stuff left in the directory is "." and
1557 	 * "..".  The "." reference is inconsequential since we're quashing
1558 	 * it.
1559 	 */
1560 	dp->i_nlink--;
1561 	DIP_ASSIGN(dp, nlink, dp->i_nlink);
1562 	dp->i_flag |= IN_CHANGE;
1563 	UFS_WAPBL_UPDATE(dvp, NULL, NULL, UPDATE_DIROP);
1564 	ip->i_nlink--;
1565 	DIP_ASSIGN(ip, nlink, ip->i_nlink);
1566 	ip->i_flag |= IN_CHANGE;
1567 	error = UFS_TRUNCATE(vp, (off_t)0, IO_SYNC, cnp->cn_cred);
1568 	cache_purge(vp);
1569 	/*
1570 	 * Unlock the log while we still have reference to unlinked
1571 	 * directory vp so that it will not get locked for recycling
1572 	 */
1573 	UFS_WAPBL_END(dvp->v_mount);
1574 #ifdef UFS_DIRHASH
1575 	if (ip->i_dirhash != NULL)
1576 		ufsdirhash_free(ip);
1577 #endif
1578  out:
1579 	VN_KNOTE(vp, NOTE_DELETE);
1580 	vput(dvp);
1581 	vput(vp);
1582 	fstrans_done(dvp->v_mount);
1583 	return (error);
1584 }
1585 
1586 /*
1587  * symlink -- make a symbolic link
1588  */
1589 int
1590 ufs_symlink(void *v)
1591 {
1592 	struct vop_symlink_args /* {
1593 		struct vnode		*a_dvp;
1594 		struct vnode		**a_vpp;
1595 		struct componentname	*a_cnp;
1596 		struct vattr		*a_vap;
1597 		char			*a_target;
1598 	} */ *ap = v;
1599 	struct vnode	*vp, **vpp;
1600 	struct inode	*ip;
1601 	int		len, error;
1602 
1603 	vpp = ap->a_vpp;
1604 	/*
1605 	 * UFS_WAPBL_BEGIN1(dvp->v_mount, dvp) performed by successful
1606 	 * ufs_makeinode
1607 	 */
1608 	fstrans_start(ap->a_dvp->v_mount, FSTRANS_SHARED);
1609 	error = ufs_makeinode(IFLNK | ap->a_vap->va_mode, ap->a_dvp,
1610 			      vpp, ap->a_cnp);
1611 	if (error)
1612 		goto out;
1613 	VN_KNOTE(ap->a_dvp, NOTE_WRITE);
1614 	vp = *vpp;
1615 	len = strlen(ap->a_target);
1616 	ip = VTOI(vp);
1617 	if (len < ip->i_ump->um_maxsymlinklen) {
1618 		memcpy((char *)SHORTLINK(ip), ap->a_target, len);
1619 		ip->i_size = len;
1620 		DIP_ASSIGN(ip, size, len);
1621 		uvm_vnp_setsize(vp, ip->i_size);
1622 		ip->i_flag |= IN_CHANGE | IN_UPDATE;
1623 		UFS_WAPBL_UPDATE(vp, NULL, NULL, 0);
1624 	} else
1625 		error = vn_rdwr(UIO_WRITE, vp, ap->a_target, len, (off_t)0,
1626 		    UIO_SYSSPACE, IO_NODELOCKED | IO_JOURNALLOCKED,
1627 		    ap->a_cnp->cn_cred, NULL, NULL);
1628 	UFS_WAPBL_END1(ap->a_dvp->v_mount, ap->a_dvp);
1629 	if (error)
1630 		vput(vp);
1631 out:
1632 	fstrans_done(ap->a_dvp->v_mount);
1633 	return (error);
1634 }
1635 
1636 /*
1637  * Vnode op for reading directories.
1638  *
1639  * This routine handles converting from the on-disk directory format
1640  * "struct direct" to the in-memory format "struct dirent" as well as
1641  * byte swapping the entries if necessary.
1642  */
1643 int
1644 ufs_readdir(void *v)
1645 {
1646 	struct vop_readdir_args /* {
1647 		struct vnode	*a_vp;
1648 		struct uio	*a_uio;
1649 		kauth_cred_t	a_cred;
1650 		int		*a_eofflag;
1651 		off_t		**a_cookies;
1652 		int		*ncookies;
1653 	} */ *ap = v;
1654 	struct vnode	*vp = ap->a_vp;
1655 	struct direct	*cdp, *ecdp;
1656 	struct dirent	*ndp;
1657 	char		*cdbuf, *ndbuf, *endp;
1658 	struct uio	auio, *uio;
1659 	struct iovec	aiov;
1660 	int		error;
1661 	size_t		count, ccount, rcount;
1662 	off_t		off, *ccp;
1663 	off_t		startoff;
1664 	size_t		skipbytes;
1665 	struct ufsmount	*ump = VFSTOUFS(vp->v_mount);
1666 	int nswap = UFS_MPNEEDSWAP(ump);
1667 #if BYTE_ORDER == LITTLE_ENDIAN
1668 	int needswap = ump->um_maxsymlinklen <= 0 && nswap == 0;
1669 #else
1670 	int needswap = ump->um_maxsymlinklen <= 0 && nswap != 0;
1671 #endif
1672 	uio = ap->a_uio;
1673 	count = uio->uio_resid;
1674 	rcount = count - ((uio->uio_offset + count) & (ump->um_dirblksiz - 1));
1675 
1676 	if (rcount < _DIRENT_MINSIZE(cdp) || count < _DIRENT_MINSIZE(ndp))
1677 		return EINVAL;
1678 
1679 	startoff = uio->uio_offset & ~(ump->um_dirblksiz - 1);
1680 	skipbytes = uio->uio_offset - startoff;
1681 	rcount += skipbytes;
1682 
1683 	auio.uio_iov = &aiov;
1684 	auio.uio_iovcnt = 1;
1685 	auio.uio_offset = startoff;
1686 	auio.uio_resid = rcount;
1687 	UIO_SETUP_SYSSPACE(&auio);
1688 	auio.uio_rw = UIO_READ;
1689 	cdbuf = malloc(rcount, M_TEMP, M_WAITOK);
1690 	aiov.iov_base = cdbuf;
1691 	aiov.iov_len = rcount;
1692 	error = VOP_READ(vp, &auio, 0, ap->a_cred);
1693 	if (error != 0) {
1694 		free(cdbuf, M_TEMP);
1695 		return error;
1696 	}
1697 
1698 	rcount -= auio.uio_resid;
1699 
1700 	cdp = (struct direct *)(void *)cdbuf;
1701 	ecdp = (struct direct *)(void *)&cdbuf[rcount];
1702 
1703 	ndbuf = malloc(count, M_TEMP, M_WAITOK);
1704 	ndp = (struct dirent *)(void *)ndbuf;
1705 	endp = &ndbuf[count];
1706 
1707 	off = uio->uio_offset;
1708 	if (ap->a_cookies) {
1709 		ccount = rcount / _DIRENT_RECLEN(cdp, 1);
1710 		ccp = *(ap->a_cookies) = malloc(ccount * sizeof(*ccp),
1711 		    M_TEMP, M_WAITOK);
1712 	} else {
1713 		/* XXX: GCC */
1714 		ccount = 0;
1715 		ccp = NULL;
1716 	}
1717 
1718 	while (cdp < ecdp) {
1719 		cdp->d_reclen = ufs_rw16(cdp->d_reclen, nswap);
1720 		if (skipbytes > 0) {
1721 			if (cdp->d_reclen <= skipbytes) {
1722 				skipbytes -= cdp->d_reclen;
1723 				cdp = _DIRENT_NEXT(cdp);
1724 				continue;
1725 			}
1726 			/*
1727 			 * invalid cookie.
1728 			 */
1729 			error = EINVAL;
1730 			goto out;
1731 		}
1732 		if (cdp->d_reclen == 0) {
1733 			struct dirent *ondp = ndp;
1734 			ndp->d_reclen = _DIRENT_MINSIZE(ndp);
1735 			ndp = _DIRENT_NEXT(ndp);
1736 			ondp->d_reclen = 0;
1737 			cdp = ecdp;
1738 			break;
1739 		}
1740 		if (needswap) {
1741 			ndp->d_type = cdp->d_namlen;
1742 			ndp->d_namlen = cdp->d_type;
1743 		} else {
1744 			ndp->d_type = cdp->d_type;
1745 			ndp->d_namlen = cdp->d_namlen;
1746 		}
1747 		ndp->d_reclen = _DIRENT_RECLEN(ndp, ndp->d_namlen);
1748 		if ((char *)(void *)ndp + ndp->d_reclen +
1749 		    _DIRENT_MINSIZE(ndp) > endp)
1750 			break;
1751 		ndp->d_fileno = ufs_rw32(cdp->d_ino, nswap);
1752 		(void)memcpy(ndp->d_name, cdp->d_name, ndp->d_namlen);
1753 		memset(&ndp->d_name[ndp->d_namlen], 0,
1754 		    ndp->d_reclen - _DIRENT_NAMEOFF(ndp) - ndp->d_namlen);
1755 		off += cdp->d_reclen;
1756 		if (ap->a_cookies) {
1757 			KASSERT(ccp - *(ap->a_cookies) < ccount);
1758 			*(ccp++) = off;
1759 		}
1760 		ndp = _DIRENT_NEXT(ndp);
1761 		cdp = _DIRENT_NEXT(cdp);
1762 	}
1763 
1764 	count = ((char *)(void *)ndp - ndbuf);
1765 	error = uiomove(ndbuf, count, uio);
1766 out:
1767 	if (ap->a_cookies) {
1768 		if (error) {
1769 			free(*(ap->a_cookies), M_TEMP);
1770 			*(ap->a_cookies) = NULL;
1771 			*(ap->a_ncookies) = 0;
1772 		} else {
1773 			*ap->a_ncookies = ccp - *(ap->a_cookies);
1774 		}
1775 	}
1776 	uio->uio_offset = off;
1777 	free(ndbuf, M_TEMP);
1778 	free(cdbuf, M_TEMP);
1779 	*ap->a_eofflag = VTOI(vp)->i_size <= uio->uio_offset;
1780 	return error;
1781 }
1782 
1783 /*
1784  * Return target name of a symbolic link
1785  */
1786 int
1787 ufs_readlink(void *v)
1788 {
1789 	struct vop_readlink_args /* {
1790 		struct vnode	*a_vp;
1791 		struct uio	*a_uio;
1792 		kauth_cred_t	a_cred;
1793 	} */ *ap = v;
1794 	struct vnode	*vp = ap->a_vp;
1795 	struct inode	*ip = VTOI(vp);
1796 	struct ufsmount	*ump = VFSTOUFS(vp->v_mount);
1797 	int		isize;
1798 
1799 	isize = ip->i_size;
1800 	if (isize < ump->um_maxsymlinklen ||
1801 	    (ump->um_maxsymlinklen == 0 && DIP(ip, blocks) == 0)) {
1802 		uiomove((char *)SHORTLINK(ip), isize, ap->a_uio);
1803 		return (0);
1804 	}
1805 	return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred));
1806 }
1807 
1808 /*
1809  * Calculate the logical to physical mapping if not done already,
1810  * then call the device strategy routine.
1811  */
1812 int
1813 ufs_strategy(void *v)
1814 {
1815 	struct vop_strategy_args /* {
1816 		struct vnode *a_vp;
1817 		struct buf *a_bp;
1818 	} */ *ap = v;
1819 	struct buf	*bp;
1820 	struct vnode	*vp;
1821 	struct inode	*ip;
1822 	struct mount	*mp;
1823 	int		error;
1824 
1825 	bp = ap->a_bp;
1826 	vp = ap->a_vp;
1827 	ip = VTOI(vp);
1828 	if (vp->v_type == VBLK || vp->v_type == VCHR)
1829 		panic("ufs_strategy: spec");
1830 	KASSERT(bp->b_bcount != 0);
1831 	if (bp->b_blkno == bp->b_lblkno) {
1832 		error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno,
1833 				 NULL);
1834 		if (error) {
1835 			bp->b_error = error;
1836 			biodone(bp);
1837 			return (error);
1838 		}
1839 		if (bp->b_blkno == -1) /* no valid data */
1840 			clrbuf(bp);
1841 	}
1842 	if (bp->b_blkno < 0) { /* block is not on disk */
1843 		biodone(bp);
1844 		return (0);
1845 	}
1846 	vp = ip->i_devvp;
1847 
1848 	error = VOP_STRATEGY(vp, bp);
1849 	if (error)
1850 		return error;
1851 
1852 	if (!BUF_ISREAD(bp))
1853 		return 0;
1854 
1855 	mp = wapbl_vptomp(vp);
1856 	if (mp == NULL || mp->mnt_wapbl_replay == NULL ||
1857 	    !WAPBL_REPLAY_ISOPEN(mp) ||
1858 	    !WAPBL_REPLAY_CAN_READ(mp, bp->b_blkno, bp->b_bcount))
1859 		return 0;
1860 
1861 	error = biowait(bp);
1862 	if (error)
1863 		return error;
1864 
1865 	error = WAPBL_REPLAY_READ(mp, bp->b_data, bp->b_blkno, bp->b_bcount);
1866 	if (error) {
1867 		mutex_enter(&bufcache_lock);
1868 		SET(bp->b_cflags, BC_INVAL);
1869 		mutex_exit(&bufcache_lock);
1870 	}
1871 	return error;
1872 }
1873 
1874 /*
1875  * Print out the contents of an inode.
1876  */
1877 int
1878 ufs_print(void *v)
1879 {
1880 	struct vop_print_args /* {
1881 		struct vnode	*a_vp;
1882 	} */ *ap = v;
1883 	struct vnode	*vp;
1884 	struct inode	*ip;
1885 
1886 	vp = ap->a_vp;
1887 	ip = VTOI(vp);
1888 	printf("tag VT_UFS, ino %llu, on dev %llu, %llu",
1889 	    (unsigned long long)ip->i_number,
1890 	    (unsigned long long)major(ip->i_dev),
1891 	    (unsigned long long)minor(ip->i_dev));
1892 	printf(" flags 0x%x, nlink %d\n",
1893 	    ip->i_flag, ip->i_nlink);
1894 	printf("\tmode 0%o, owner %d, group %d, size %qd",
1895 	    ip->i_mode, ip->i_uid, ip->i_gid,
1896 	    (long long)ip->i_size);
1897 	if (vp->v_type == VFIFO)
1898 		VOCALL(fifo_vnodeop_p, VOFFSET(vop_print), v);
1899 	printf("\n");
1900 	return (0);
1901 }
1902 
1903 /*
1904  * Read wrapper for special devices.
1905  */
1906 int
1907 ufsspec_read(void *v)
1908 {
1909 	struct vop_read_args /* {
1910 		struct vnode	*a_vp;
1911 		struct uio	*a_uio;
1912 		int		a_ioflag;
1913 		kauth_cred_t	a_cred;
1914 	} */ *ap = v;
1915 
1916 	/*
1917 	 * Set access flag.
1918 	 */
1919 	if ((ap->a_vp->v_mount->mnt_flag & MNT_NODEVMTIME) == 0)
1920 		VTOI(ap->a_vp)->i_flag |= IN_ACCESS;
1921 	return (VOCALL (spec_vnodeop_p, VOFFSET(vop_read), ap));
1922 }
1923 
1924 /*
1925  * Write wrapper for special devices.
1926  */
1927 int
1928 ufsspec_write(void *v)
1929 {
1930 	struct vop_write_args /* {
1931 		struct vnode	*a_vp;
1932 		struct uio	*a_uio;
1933 		int		a_ioflag;
1934 		kauth_cred_t	a_cred;
1935 	} */ *ap = v;
1936 
1937 	/*
1938 	 * Set update and change flags.
1939 	 */
1940 	if ((ap->a_vp->v_mount->mnt_flag & MNT_NODEVMTIME) == 0)
1941 		VTOI(ap->a_vp)->i_flag |= IN_MODIFY;
1942 	return (VOCALL (spec_vnodeop_p, VOFFSET(vop_write), ap));
1943 }
1944 
1945 /*
1946  * Close wrapper for special devices.
1947  *
1948  * Update the times on the inode then do device close.
1949  */
1950 int
1951 ufsspec_close(void *v)
1952 {
1953 	struct vop_close_args /* {
1954 		struct vnode	*a_vp;
1955 		int		a_fflag;
1956 		kauth_cred_t	a_cred;
1957 	} */ *ap = v;
1958 	struct vnode	*vp;
1959 	struct inode	*ip;
1960 
1961 	vp = ap->a_vp;
1962 	ip = VTOI(vp);
1963 	if (vp->v_usecount > 1)
1964 		UFS_ITIMES(vp, NULL, NULL, NULL);
1965 	return (VOCALL (spec_vnodeop_p, VOFFSET(vop_close), ap));
1966 }
1967 
1968 /*
1969  * Read wrapper for fifo's
1970  */
1971 int
1972 ufsfifo_read(void *v)
1973 {
1974 	struct vop_read_args /* {
1975 		struct vnode	*a_vp;
1976 		struct uio	*a_uio;
1977 		int		a_ioflag;
1978 		kauth_cred_t	a_cred;
1979 	} */ *ap = v;
1980 
1981 	/*
1982 	 * Set access flag.
1983 	 */
1984 	VTOI(ap->a_vp)->i_flag |= IN_ACCESS;
1985 	return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_read), ap));
1986 }
1987 
1988 /*
1989  * Write wrapper for fifo's.
1990  */
1991 int
1992 ufsfifo_write(void *v)
1993 {
1994 	struct vop_write_args /* {
1995 		struct vnode	*a_vp;
1996 		struct uio	*a_uio;
1997 		int		a_ioflag;
1998 		kauth_cred_t	a_cred;
1999 	} */ *ap = v;
2000 
2001 	/*
2002 	 * Set update and change flags.
2003 	 */
2004 	VTOI(ap->a_vp)->i_flag |= IN_MODIFY;
2005 	return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_write), ap));
2006 }
2007 
2008 /*
2009  * Close wrapper for fifo's.
2010  *
2011  * Update the times on the inode then do device close.
2012  */
2013 int
2014 ufsfifo_close(void *v)
2015 {
2016 	struct vop_close_args /* {
2017 		struct vnode	*a_vp;
2018 		int		a_fflag;
2019 		kauth_cred_t	a_cred;
2020 	} */ *ap = v;
2021 	struct vnode	*vp;
2022 	struct inode	*ip;
2023 
2024 	vp = ap->a_vp;
2025 	ip = VTOI(vp);
2026 	if (ap->a_vp->v_usecount > 1)
2027 		UFS_ITIMES(vp, NULL, NULL, NULL);
2028 	return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_close), ap));
2029 }
2030 
2031 /*
2032  * Return POSIX pathconf information applicable to ufs filesystems.
2033  */
2034 int
2035 ufs_pathconf(void *v)
2036 {
2037 	struct vop_pathconf_args /* {
2038 		struct vnode	*a_vp;
2039 		int		a_name;
2040 		register_t	*a_retval;
2041 	} */ *ap = v;
2042 
2043 	switch (ap->a_name) {
2044 	case _PC_LINK_MAX:
2045 		*ap->a_retval = LINK_MAX;
2046 		return (0);
2047 	case _PC_NAME_MAX:
2048 		*ap->a_retval = NAME_MAX;
2049 		return (0);
2050 	case _PC_PATH_MAX:
2051 		*ap->a_retval = PATH_MAX;
2052 		return (0);
2053 	case _PC_PIPE_BUF:
2054 		*ap->a_retval = PIPE_BUF;
2055 		return (0);
2056 	case _PC_CHOWN_RESTRICTED:
2057 		*ap->a_retval = 1;
2058 		return (0);
2059 	case _PC_NO_TRUNC:
2060 		*ap->a_retval = 1;
2061 		return (0);
2062 	case _PC_SYNC_IO:
2063 		*ap->a_retval = 1;
2064 		return (0);
2065 	case _PC_FILESIZEBITS:
2066 		*ap->a_retval = 42;
2067 		return (0);
2068 	case _PC_SYMLINK_MAX:
2069 		*ap->a_retval = MAXPATHLEN;
2070 		return (0);
2071 	case _PC_2_SYMLINKS:
2072 		*ap->a_retval = 1;
2073 		return (0);
2074 	default:
2075 		return (EINVAL);
2076 	}
2077 	/* NOTREACHED */
2078 }
2079 
2080 /*
2081  * Advisory record locking support
2082  */
2083 int
2084 ufs_advlock(void *v)
2085 {
2086 	struct vop_advlock_args /* {
2087 		struct vnode	*a_vp;
2088 		void *		a_id;
2089 		int		a_op;
2090 		struct flock	*a_fl;
2091 		int		a_flags;
2092 	} */ *ap = v;
2093 	struct inode *ip;
2094 
2095 	ip = VTOI(ap->a_vp);
2096 	return lf_advlock(ap, &ip->i_lockf, ip->i_size);
2097 }
2098 
2099 /*
2100  * Initialize the vnode associated with a new inode, handle aliased
2101  * vnodes.
2102  */
2103 void
2104 ufs_vinit(struct mount *mntp, int (**specops)(void *), int (**fifoops)(void *),
2105 	struct vnode **vpp)
2106 {
2107 	struct timeval	tv;
2108 	struct inode	*ip;
2109 	struct vnode	*vp;
2110 	dev_t		rdev;
2111 	struct ufsmount	*ump;
2112 
2113 	vp = *vpp;
2114 	ip = VTOI(vp);
2115 	switch(vp->v_type = IFTOVT(ip->i_mode)) {
2116 	case VCHR:
2117 	case VBLK:
2118 		vp->v_op = specops;
2119 		ump = ip->i_ump;
2120 		if (ump->um_fstype == UFS1)
2121 			rdev = (dev_t)ufs_rw32(ip->i_ffs1_rdev,
2122 			    UFS_MPNEEDSWAP(ump));
2123 		else
2124 			rdev = (dev_t)ufs_rw64(ip->i_ffs2_rdev,
2125 			    UFS_MPNEEDSWAP(ump));
2126 		spec_node_init(vp, rdev);
2127 		break;
2128 	case VFIFO:
2129 		vp->v_op = fifoops;
2130 		break;
2131 	case VNON:
2132 	case VBAD:
2133 	case VSOCK:
2134 	case VLNK:
2135 	case VDIR:
2136 	case VREG:
2137 		break;
2138 	}
2139 	if (ip->i_number == ROOTINO)
2140                 vp->v_vflag |= VV_ROOT;
2141 	/*
2142 	 * Initialize modrev times
2143 	 */
2144 	getmicrouptime(&tv);
2145 	ip->i_modrev = (uint64_t)(uint)tv.tv_sec << 32
2146 			| tv.tv_usec * 4294u;
2147 	*vpp = vp;
2148 }
2149 
2150 /*
2151  * Allocate a new inode.
2152  */
2153 int
2154 ufs_makeinode(int mode, struct vnode *dvp, struct vnode **vpp,
2155 	struct componentname *cnp)
2156 {
2157 	struct inode	*ip, *pdir;
2158 	struct direct	*newdir;
2159 	struct vnode	*tvp;
2160 	int		error, ismember = 0;
2161 
2162 	UFS_WAPBL_JUNLOCK_ASSERT(dvp->v_mount);
2163 
2164 	pdir = VTOI(dvp);
2165 
2166 	if ((mode & IFMT) == 0)
2167 		mode |= IFREG;
2168 
2169 	if ((error = UFS_VALLOC(dvp, mode, cnp->cn_cred, vpp)) != 0) {
2170 		vput(dvp);
2171 		return (error);
2172 	}
2173 	tvp = *vpp;
2174 	ip = VTOI(tvp);
2175 	ip->i_gid = pdir->i_gid;
2176 	DIP_ASSIGN(ip, gid, ip->i_gid);
2177 	ip->i_uid = kauth_cred_geteuid(cnp->cn_cred);
2178 	DIP_ASSIGN(ip, uid, ip->i_uid);
2179 	error = UFS_WAPBL_BEGIN1(dvp->v_mount, dvp);
2180 	if (error) {
2181 		/*
2182 		 * Note, we can't VOP_VFREE(tvp) here like we should
2183 		 * because we can't write to the disk.  Instead, we leave
2184 		 * the vnode dangling from the journal.
2185 		 */
2186 		vput(tvp);
2187 		vput(dvp);
2188 		return (error);
2189 	}
2190 #ifdef QUOTA
2191 	if ((error = chkiq(ip, 1, cnp->cn_cred, 0))) {
2192 		UFS_VFREE(tvp, ip->i_number, mode);
2193 		UFS_WAPBL_END1(dvp->v_mount, dvp);
2194 		vput(tvp);
2195 		vput(dvp);
2196 		return (error);
2197 	}
2198 #endif
2199 	ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
2200 	ip->i_mode = mode;
2201 	DIP_ASSIGN(ip, mode, mode);
2202 	tvp->v_type = IFTOVT(mode);	/* Rest init'd in getnewvnode(). */
2203 	ip->i_nlink = 1;
2204 	DIP_ASSIGN(ip, nlink, 1);
2205 	if ((ip->i_mode & ISGID) && (kauth_cred_ismember_gid(cnp->cn_cred,
2206 	    ip->i_gid, &ismember) != 0 || !ismember) &&
2207 	    kauth_authorize_generic(cnp->cn_cred, KAUTH_GENERIC_ISSUSER, NULL)) {
2208 		ip->i_mode &= ~ISGID;
2209 		DIP_ASSIGN(ip, mode, ip->i_mode);
2210 	}
2211 
2212 	if (cnp->cn_flags & ISWHITEOUT) {
2213 		ip->i_flags |= UF_OPAQUE;
2214 		DIP_ASSIGN(ip, flags, ip->i_flags);
2215 	}
2216 
2217 	/*
2218 	 * Make sure inode goes to disk before directory entry.
2219 	 */
2220 	if ((error = UFS_UPDATE(tvp, NULL, NULL, UPDATE_DIROP)) != 0)
2221 		goto bad;
2222 	newdir = pool_cache_get(ufs_direct_cache, PR_WAITOK);
2223 	ufs_makedirentry(ip, cnp, newdir);
2224 	error = ufs_direnter(dvp, tvp, newdir, cnp, NULL);
2225 	pool_cache_put(ufs_direct_cache, newdir);
2226 	if (error)
2227 		goto bad;
2228 	vput(dvp);
2229 	*vpp = tvp;
2230 	return (0);
2231 
2232  bad:
2233 	/*
2234 	 * Write error occurred trying to update the inode
2235 	 * or the directory so must deallocate the inode.
2236 	 */
2237 	ip->i_nlink = 0;
2238 	DIP_ASSIGN(ip, nlink, 0);
2239 	ip->i_flag |= IN_CHANGE;
2240 	/* If IN_ADIROP, account for it */
2241 	UFS_UNMARK_VNODE(tvp);
2242 	UFS_WAPBL_UPDATE(tvp, NULL, NULL, 0);
2243 	tvp->v_type = VNON;		/* explodes later if VBLK */
2244 	UFS_WAPBL_END1(dvp->v_mount, dvp);
2245 	vput(tvp);
2246 	vput(dvp);
2247 	return (error);
2248 }
2249 
2250 /*
2251  * Allocate len bytes at offset off.
2252  */
2253 int
2254 ufs_gop_alloc(struct vnode *vp, off_t off, off_t len, int flags,
2255     kauth_cred_t cred)
2256 {
2257         struct inode *ip = VTOI(vp);
2258         int error, delta, bshift, bsize;
2259         UVMHIST_FUNC("ufs_gop_alloc"); UVMHIST_CALLED(ubchist);
2260 
2261         error = 0;
2262         bshift = vp->v_mount->mnt_fs_bshift;
2263         bsize = 1 << bshift;
2264 
2265         delta = off & (bsize - 1);
2266         off -= delta;
2267         len += delta;
2268 
2269         while (len > 0) {
2270                 bsize = MIN(bsize, len);
2271 
2272                 error = UFS_BALLOC(vp, off, bsize, cred, flags, NULL);
2273                 if (error) {
2274                         goto out;
2275                 }
2276 
2277                 /*
2278                  * increase file size now, UFS_BALLOC() requires that
2279                  * EOF be up-to-date before each call.
2280                  */
2281 
2282                 if (ip->i_size < off + bsize) {
2283                         UVMHIST_LOG(ubchist, "vp %p old 0x%x new 0x%x",
2284                             vp, ip->i_size, off + bsize, 0);
2285                         ip->i_size = off + bsize;
2286 			DIP_ASSIGN(ip, size, ip->i_size);
2287                 }
2288 
2289                 off += bsize;
2290                 len -= bsize;
2291         }
2292 
2293 out:
2294 	UFS_WAPBL_UPDATE(vp, NULL, NULL, 0);
2295 	return error;
2296 }
2297 
2298 void
2299 ufs_gop_markupdate(struct vnode *vp, int flags)
2300 {
2301 	u_int32_t mask = 0;
2302 
2303 	if ((flags & GOP_UPDATE_ACCESSED) != 0) {
2304 		mask = IN_ACCESS;
2305 	}
2306 	if ((flags & GOP_UPDATE_MODIFIED) != 0) {
2307 		if (vp->v_type == VREG) {
2308 			mask |= IN_CHANGE | IN_UPDATE;
2309 		} else {
2310 			mask |= IN_MODIFY;
2311 		}
2312 	}
2313 	if (mask) {
2314 		struct inode *ip = VTOI(vp);
2315 
2316 		ip->i_flag |= mask;
2317 	}
2318 }
2319