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