Home | History | Annotate | Line # | Download | only in ufs
      1 /*	$NetBSD: ufs_vnops.c,v 1.262 2022/03/27 16:24:59 christos Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2008, 2020 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.262 2022/03/27 16:24:59 christos Exp $");
     70 
     71 #if defined(_KERNEL_OPT)
     72 #include "opt_ffs.h"
     73 #include "opt_quota.h"
     74 #include "opt_uvmhist.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/fstrans.h>
     89 #include <sys/kmem.h>
     90 #include <sys/malloc.h>
     91 #include <sys/dirent.h>
     92 #include <sys/lockf.h>
     93 #include <sys/kauth.h>
     94 #include <sys/wapbl.h>
     95 
     96 #include <miscfs/specfs/specdev.h>
     97 #include <miscfs/fifofs/fifo.h>
     98 #include <miscfs/genfs/genfs.h>
     99 
    100 #include <ufs/ufs/acl.h>
    101 #include <ufs/ufs/inode.h>
    102 #include <ufs/ufs/dir.h>
    103 #include <ufs/ufs/ufsmount.h>
    104 #include <ufs/ufs/ufs_bswap.h>
    105 #include <ufs/ufs/ufs_extern.h>
    106 #include <ufs/ufs/ufs_wapbl.h>
    107 #ifdef UFS_DIRHASH
    108 #include <ufs/ufs/dirhash.h>
    109 #endif
    110 #include <ufs/ext2fs/ext2fs_extern.h>
    111 #include <ufs/ext2fs/ext2fs_dir.h>
    112 #include <ufs/ffs/ffs_extern.h>
    113 #include <ufs/lfs/lfs_extern.h>
    114 #include <ufs/lfs/lfs.h>
    115 
    116 #ifdef UVMHIST
    117 #include <uvm/uvm.h>
    118 #endif
    119 #include <uvm/uvm_extern.h>
    120 #include <uvm/uvm_stat.h>
    121 
    122 __CTASSERT(EXT2FS_MAXNAMLEN == FFS_MAXNAMLEN);
    123 __CTASSERT(LFS_MAXNAMLEN == FFS_MAXNAMLEN);
    124 
    125 static int ufs_chmod(struct vnode *, int, kauth_cred_t, struct lwp *);
    126 static int ufs_chown(struct vnode *, uid_t, gid_t, kauth_cred_t,
    127     struct lwp *);
    128 static int ufs_makeinode(struct vattr *, struct vnode *,
    129     const struct ufs_lookup_results *, struct vnode **, struct componentname *);
    130 
    131 /*
    132  * A virgin directory (no blushing please).
    133  */
    134 static const struct dirtemplate mastertemplate = {
    135 	0,	12,			DT_DIR,	1,	".",
    136 	0,	UFS_DIRBLKSIZ - 12,	DT_DIR,	2,	".."
    137 };
    138 
    139 /*
    140  * Create a regular file
    141  */
    142 int
    143 ufs_create(void *v)
    144 {
    145 	struct vop_create_v3_args /* {
    146 		struct vnode		*a_dvp;
    147 		struct vnode		**a_vpp;
    148 		struct componentname	*a_cnp;
    149 		struct vattr		*a_vap;
    150 	} */ *ap = v;
    151 	int	error;
    152 	struct vnode *dvp = ap->a_dvp;
    153 	struct ufs_lookup_results *ulr;
    154 
    155 	/* XXX should handle this material another way */
    156 	ulr = &VTOI(dvp)->i_crap;
    157 	UFS_CHECK_CRAPCOUNTER(VTOI(dvp));
    158 
    159 	/*
    160 	 * UFS_WAPBL_BEGIN(dvp->v_mount) performed by successful
    161 	 * ufs_makeinode
    162 	 */
    163 	error = ufs_makeinode(ap->a_vap, dvp, ulr, ap->a_vpp, ap->a_cnp);
    164 	if (error) {
    165 		return (error);
    166 	}
    167 	UFS_WAPBL_END(dvp->v_mount);
    168 	VOP_UNLOCK(*ap->a_vpp);
    169 	return (0);
    170 }
    171 
    172 /*
    173  * Mknod vnode call
    174  */
    175 /* ARGSUSED */
    176 int
    177 ufs_mknod(void *v)
    178 {
    179 	struct vop_mknod_v3_args /* {
    180 		struct vnode		*a_dvp;
    181 		struct vnode		**a_vpp;
    182 		struct componentname	*a_cnp;
    183 		struct vattr		*a_vap;
    184 	} */ *ap = v;
    185 	struct vattr	*vap;
    186 	struct vnode	**vpp;
    187 	struct inode	*ip;
    188 	int		error;
    189 	struct ufs_lookup_results *ulr;
    190 
    191 	vap = ap->a_vap;
    192 	vpp = ap->a_vpp;
    193 
    194 	/* XXX should handle this material another way */
    195 	ulr = &VTOI(ap->a_dvp)->i_crap;
    196 	UFS_CHECK_CRAPCOUNTER(VTOI(ap->a_dvp));
    197 
    198 	/*
    199 	 * UFS_WAPBL_BEGIN(dvp->v_mount) performed by successful
    200 	 * ufs_makeinode
    201 	 */
    202 	if ((error = ufs_makeinode(vap, ap->a_dvp, ulr, vpp, ap->a_cnp)) != 0)
    203 		goto out;
    204 	ip = VTOI(*vpp);
    205 	ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
    206 	UFS_WAPBL_UPDATE(*vpp, NULL, NULL, 0);
    207 	UFS_WAPBL_END(ap->a_dvp->v_mount);
    208 	VOP_UNLOCK(*vpp);
    209 out:
    210 	if (error != 0) {
    211 		*vpp = NULL;
    212 		return (error);
    213 	}
    214 	return (0);
    215 }
    216 
    217 /*
    218  * Open called.
    219  *
    220  * Nothing to do.
    221  */
    222 /* ARGSUSED */
    223 int
    224 ufs_open(void *v)
    225 {
    226 	struct vop_open_args /* {
    227 		struct vnode	*a_vp;
    228 		int		a_mode;
    229 		kauth_cred_t	a_cred;
    230 	} */ *ap = v;
    231 
    232 	/*
    233 	 * Files marked append-only must be opened for appending.
    234 	 */
    235 	if ((VTOI(ap->a_vp)->i_flags & APPEND) &&
    236 	    (ap->a_mode & (FWRITE | O_APPEND)) == FWRITE)
    237 		return (EPERM);
    238 	return (0);
    239 }
    240 
    241 /*
    242  * Close called.
    243  *
    244  * Update the times on the inode.
    245  */
    246 /* ARGSUSED */
    247 int
    248 ufs_close(void *v)
    249 {
    250 	struct vop_close_args /* {
    251 		struct vnode	*a_vp;
    252 		int		a_fflag;
    253 		kauth_cred_t	a_cred;
    254 	} */ *ap = v;
    255 	struct vnode	*vp;
    256 
    257 	vp = ap->a_vp;
    258 	if (vrefcnt(vp) > 1)
    259 		UFS_ITIMES(vp, NULL, NULL, NULL);
    260 	return (0);
    261 }
    262 
    263 static int
    264 ufs_check_possible(struct vnode *vp, struct inode *ip, accmode_t accmode,
    265     kauth_cred_t cred)
    266 {
    267 #if defined(QUOTA) || defined(QUOTA2)
    268 	int error;
    269 #endif
    270 
    271 	/*
    272 	 * Disallow write attempts on read-only file systems;
    273 	 * unless the file is a socket, fifo, or a block or
    274 	 * character device resident on the file system.
    275 	 */
    276 	if (accmode & VMODIFY_PERMS) {
    277 		switch (vp->v_type) {
    278 		case VDIR:
    279 		case VLNK:
    280 		case VREG:
    281 			if (vp->v_mount->mnt_flag & MNT_RDONLY)
    282 				return EROFS;
    283 #if defined(QUOTA) || defined(QUOTA2)
    284 			error = chkdq(ip, 0, cred, 0);
    285 			if (error != 0)
    286 				return error;
    287 #endif
    288 			break;
    289 		case VBAD:
    290 		case VBLK:
    291 		case VCHR:
    292 		case VSOCK:
    293 		case VFIFO:
    294 		case VNON:
    295 		default:
    296 			break;
    297 		}
    298 	}
    299 
    300 	/* If it is a snapshot, nobody gets access to it. */
    301 	if ((ip->i_flags & SF_SNAPSHOT))
    302 		return EPERM;
    303 	/*
    304 	 * If immutable bit set, nobody gets to write it.  "& ~VADMIN_PERMS"
    305 	 * permits the owner of the file to remove the IMMUTABLE flag.
    306 	 */
    307 	if ((accmode & (VMODIFY_PERMS & ~VADMIN_PERMS)) &&
    308 	    (ip->i_flags & IMMUTABLE))
    309 		return EPERM;
    310 
    311 	return 0;
    312 }
    313 
    314 static int
    315 ufs_check_permitted(struct vnode *vp, struct inode *ip,
    316     struct acl *acl, accmode_t accmode, kauth_cred_t cred,
    317     int (*func)(struct vnode *, kauth_cred_t, uid_t, gid_t, mode_t,
    318     struct acl *, accmode_t))
    319 {
    320 
    321 	return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode,
    322 	    vp->v_type, ip->i_mode & ALLPERMS), vp, NULL, (*func)(vp, cred,
    323 	    ip->i_uid, ip->i_gid, ip->i_mode & ALLPERMS, acl, accmode));
    324 }
    325 
    326 int
    327 ufs_accessx(void *v)
    328 {
    329 	struct vop_accessx_args /* {
    330 		struct vnode *a_vp;
    331 		accmode_t a_accmode;
    332 		kauth_cred_t a_cred;
    333 	} */ *ap = v;
    334 	struct vnode *vp = ap->a_vp;
    335 	struct inode *ip = VTOI(vp);
    336 	accmode_t accmode = ap->a_accmode;
    337 	int error;
    338 #ifdef UFS_ACL
    339 	struct acl *acl;
    340 	acl_type_t type;
    341 #endif
    342 
    343 	error = ufs_check_possible(vp, ip, accmode, ap->a_cred);
    344 	if (error)
    345 		return error;
    346 
    347 #ifdef UFS_ACL
    348 	if ((vp->v_mount->mnt_flag & (MNT_POSIX1EACLS | MNT_NFS4ACLS)) != 0) {
    349 		if (vp->v_mount->mnt_flag & MNT_NFS4ACLS)
    350 			type = ACL_TYPE_NFS4;
    351 		else
    352 			type = ACL_TYPE_ACCESS;
    353 
    354 		acl = acl_alloc(KM_SLEEP);
    355 		if (type == ACL_TYPE_NFS4)
    356 			error = ufs_getacl_nfs4_internal(vp, acl, curlwp);
    357 		else
    358 			error = VOP_GETACL(vp, type, acl, ap->a_cred);
    359 		if (!error) {
    360 			if (type == ACL_TYPE_NFS4) {
    361 				error = ufs_check_permitted(vp,
    362 				    ip, acl, accmode, ap->a_cred,
    363 				    genfs_can_access_acl_nfs4);
    364 			} else {
    365 				error = vfs_unixify_accmode(&accmode);
    366 				if (error == 0)
    367 					error = ufs_check_permitted(vp,
    368 					    ip, acl, accmode, ap->a_cred,
    369 					    genfs_can_access_acl_posix1e);
    370 			}
    371 			acl_free(acl);
    372 			return error;
    373 		}
    374 		if (error != EOPNOTSUPP)
    375 			printf("%s: Error retrieving ACL: %d\n",
    376 			    __func__, error);
    377 		/*
    378 		 * XXX: Fall back until debugged.  Should
    379 		 * eventually possibly log an error, and return
    380 		 * EPERM for safety.
    381 		 */
    382 		acl_free(acl);
    383 	}
    384 #endif /* !UFS_ACL */
    385 	error = vfs_unixify_accmode(&accmode);
    386 	if (error)
    387 		return error;
    388 	return ufs_check_permitted(vp, ip,
    389 	    NULL, accmode, ap->a_cred, genfs_can_access);
    390 }
    391 
    392 /* ARGSUSED */
    393 int
    394 ufs_getattr(void *v)
    395 {
    396 	struct vop_getattr_args /* {
    397 		struct vnode	*a_vp;
    398 		struct vattr	*a_vap;
    399 		kauth_cred_t	a_cred;
    400 	} */ *ap = v;
    401 	struct vnode	*vp;
    402 	struct inode	*ip;
    403 	struct vattr	*vap;
    404 
    405 	vp = ap->a_vp;
    406 	ip = VTOI(vp);
    407 	vap = ap->a_vap;
    408 	UFS_ITIMES(vp, NULL, NULL, NULL);
    409 
    410 	/*
    411 	 * Copy from inode table
    412 	 */
    413 	vap->va_fsid = ip->i_dev;
    414 	vap->va_fileid = ip->i_number;
    415 	vap->va_mode = ip->i_mode & ALLPERMS;
    416 	vap->va_nlink = ip->i_nlink;
    417 	vap->va_uid = ip->i_uid;
    418 	vap->va_gid = ip->i_gid;
    419 	vap->va_size = vp->v_size;
    420 	if (ip->i_ump->um_fstype == UFS1) {
    421 		switch (vp->v_type) {
    422 		    case VBLK:
    423 		    case VCHR:
    424 			vap->va_rdev = (dev_t)ufs_rw32(ip->i_ffs1_rdev,
    425 			    UFS_MPNEEDSWAP(ip->i_ump));
    426 			break;
    427 		    default:
    428 			vap->va_rdev = NODEV;
    429 			break;
    430 		}
    431 		vap->va_atime.tv_sec = ip->i_ffs1_atime;
    432 		vap->va_atime.tv_nsec = ip->i_ffs1_atimensec;
    433 		vap->va_mtime.tv_sec = ip->i_ffs1_mtime;
    434 		vap->va_mtime.tv_nsec = ip->i_ffs1_mtimensec;
    435 		vap->va_ctime.tv_sec = ip->i_ffs1_ctime;
    436 		vap->va_ctime.tv_nsec = ip->i_ffs1_ctimensec;
    437 		vap->va_birthtime.tv_sec = 0;
    438 		vap->va_birthtime.tv_nsec = 0;
    439 		vap->va_bytes = dbtob((u_quad_t)ip->i_ffs1_blocks);
    440 	} else {
    441 		switch (vp->v_type) {
    442 		    case VBLK:
    443 		    case VCHR:
    444 			vap->va_rdev = (dev_t)ufs_rw64(ip->i_ffs2_rdev,
    445 			    UFS_MPNEEDSWAP(ip->i_ump));
    446 			break;
    447 		    default:
    448 			vap->va_rdev = NODEV;
    449 			break;
    450 		}
    451 		vap->va_atime.tv_sec = ip->i_ffs2_atime;
    452 		vap->va_atime.tv_nsec = ip->i_ffs2_atimensec;
    453 		vap->va_mtime.tv_sec = ip->i_ffs2_mtime;
    454 		vap->va_mtime.tv_nsec = ip->i_ffs2_mtimensec;
    455 		vap->va_ctime.tv_sec = ip->i_ffs2_ctime;
    456 		vap->va_ctime.tv_nsec = ip->i_ffs2_ctimensec;
    457 		vap->va_birthtime.tv_sec = ip->i_ffs2_birthtime;
    458 		vap->va_birthtime.tv_nsec = ip->i_ffs2_birthnsec;
    459 		vap->va_bytes = dbtob(ip->i_ffs2_blocks);
    460 	}
    461 	vap->va_gen = ip->i_gen;
    462 	vap->va_flags = ip->i_flags;
    463 
    464 	/* this doesn't belong here */
    465 	if (vp->v_type == VBLK)
    466 		vap->va_blocksize = BLKDEV_IOSIZE;
    467 	else if (vp->v_type == VCHR)
    468 		vap->va_blocksize = MAXBSIZE;
    469 	else
    470 		vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize;
    471 	vap->va_type = vp->v_type;
    472 	vap->va_filerev = ip->i_modrev;
    473 	return (0);
    474 }
    475 
    476 /*
    477  * Set attribute vnode op. called from several syscalls
    478  */
    479 int
    480 ufs_setattr(void *v)
    481 {
    482 	struct vop_setattr_args /* {
    483 		struct vnode	*a_vp;
    484 		struct vattr	*a_vap;
    485 		kauth_cred_t	a_cred;
    486 	} */ *ap = v;
    487 	struct vattr	*vap;
    488 	struct vnode	*vp;
    489 	struct inode	*ip;
    490 	kauth_cred_t	cred;
    491 	struct lwp	*l;
    492 	int		error;
    493 	kauth_action_t	action;
    494 	bool		changing_sysflags;
    495 
    496 	vap = ap->a_vap;
    497 	vp = ap->a_vp;
    498 	ip = VTOI(vp);
    499 	cred = ap->a_cred;
    500 	l = curlwp;
    501 	action = KAUTH_VNODE_WRITE_FLAGS;
    502 	changing_sysflags = false;
    503 
    504 	/*
    505 	 * Check for unsettable attributes.
    506 	 */
    507 	if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
    508 	    (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
    509 	    (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
    510 	    ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
    511 		return (EINVAL);
    512 	}
    513 
    514 	UFS_WAPBL_JUNLOCK_ASSERT(vp->v_mount);
    515 
    516 	if (vap->va_flags != VNOVAL) {
    517 		if (vp->v_mount->mnt_flag & MNT_RDONLY) {
    518 			error = EROFS;
    519 			goto out;
    520 		}
    521 
    522 		/* Snapshot flag cannot be set or cleared */
    523 		if ((vap->va_flags & (SF_SNAPSHOT | SF_SNAPINVAL)) !=
    524 		    (ip->i_flags & (SF_SNAPSHOT | SF_SNAPINVAL))) {
    525 			error = EPERM;
    526 			goto out;
    527 		}
    528 
    529 		if (ip->i_flags & (SF_IMMUTABLE | SF_APPEND)) {
    530 			action |= KAUTH_VNODE_HAS_SYSFLAGS;
    531 		}
    532 
    533 		if ((vap->va_flags & SF_SETTABLE) !=
    534 		    (ip->i_flags & SF_SETTABLE)) {
    535 			action |= KAUTH_VNODE_WRITE_SYSFLAGS;
    536 			changing_sysflags = true;
    537 		}
    538 
    539 		error = kauth_authorize_vnode(cred, action, vp, NULL,
    540 		    genfs_can_chflags(vp, cred, ip->i_uid, changing_sysflags));
    541 		if (error)
    542 			goto out;
    543 
    544 		if (changing_sysflags) {
    545 			error = UFS_WAPBL_BEGIN(vp->v_mount);
    546 			if (error)
    547 				goto out;
    548 			ip->i_flags = vap->va_flags;
    549 			DIP_ASSIGN(ip, flags, ip->i_flags);
    550 		} else {
    551 			error = UFS_WAPBL_BEGIN(vp->v_mount);
    552 			if (error)
    553 				goto out;
    554 			ip->i_flags &= SF_SETTABLE;
    555 			ip->i_flags |= (vap->va_flags & UF_SETTABLE);
    556 			DIP_ASSIGN(ip, flags, ip->i_flags);
    557 		}
    558 		ip->i_flag |= IN_CHANGE;
    559 		UFS_WAPBL_UPDATE(vp, NULL, NULL, 0);
    560 		UFS_WAPBL_END(vp->v_mount);
    561 		if (vap->va_flags & (IMMUTABLE | APPEND)) {
    562 			error = 0;
    563 			goto out;
    564 		}
    565 	}
    566 	if (ip->i_flags & (IMMUTABLE | APPEND)) {
    567 		error = EPERM;
    568 		goto out;
    569 	}
    570 	/*
    571 	 * Go through the fields and update iff not VNOVAL.
    572 	 */
    573 	if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) {
    574 		if (vp->v_mount->mnt_flag & MNT_RDONLY) {
    575 			error = EROFS;
    576 			goto out;
    577 		}
    578 		error = UFS_WAPBL_BEGIN(vp->v_mount);
    579 		if (error)
    580 			goto out;
    581 		error = ufs_chown(vp, vap->va_uid, vap->va_gid, cred, l);
    582 		UFS_WAPBL_END(vp->v_mount);
    583 		if (error)
    584 			goto out;
    585 	}
    586 	if (vap->va_size != VNOVAL) {
    587 		/*
    588 		 * Disallow write attempts on read-only file systems;
    589 		 * unless the file is a socket, fifo, or a block or
    590 		 * character device resident on the file system.
    591 		 */
    592 		switch (vp->v_type) {
    593 		case VDIR:
    594 			error = EISDIR;
    595 			goto out;
    596 		case VCHR:
    597 		case VBLK:
    598 		case VFIFO:
    599 			break;
    600 		case VREG:
    601 			if (vp->v_mount->mnt_flag & MNT_RDONLY) {
    602 				error = EROFS;
    603 				goto out;
    604 			}
    605 			if ((ip->i_flags & SF_SNAPSHOT) != 0) {
    606 				error = EPERM;
    607 				goto out;
    608 			}
    609 			error = ufs_truncate_retry(vp, 0, vap->va_size, cred);
    610 			if (error)
    611 				goto out;
    612 			break;
    613 		default:
    614 			error = EOPNOTSUPP;
    615 			goto out;
    616 		}
    617 	}
    618 	ip = VTOI(vp);
    619 	if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL ||
    620 	    vap->va_birthtime.tv_sec != VNOVAL) {
    621 		if (vp->v_mount->mnt_flag & MNT_RDONLY) {
    622 			error = EROFS;
    623 			goto out;
    624 		}
    625 		if ((ip->i_flags & SF_SNAPSHOT) != 0) {
    626 			error = EPERM;
    627 			goto out;
    628 		}
    629 		error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, vp,
    630 		    NULL, genfs_can_chtimes(vp, cred, ip->i_uid,
    631 		    vap->va_vaflags));
    632 		if (error)
    633 			goto out;
    634 		error = UFS_WAPBL_BEGIN(vp->v_mount);
    635 		if (error)
    636 			goto out;
    637 		if (vap->va_atime.tv_sec != VNOVAL)
    638 			if (!(vp->v_mount->mnt_flag & MNT_NOATIME))
    639 				ip->i_flag |= IN_ACCESS;
    640 		if (vap->va_mtime.tv_sec != VNOVAL) {
    641 			ip->i_flag |= IN_CHANGE | IN_UPDATE;
    642 			if (vp->v_mount->mnt_flag & MNT_RELATIME)
    643 				ip->i_flag |= IN_ACCESS;
    644 		}
    645 		if (vap->va_birthtime.tv_sec != VNOVAL &&
    646 		    ip->i_ump->um_fstype == UFS2) {
    647 			ip->i_ffs2_birthtime = vap->va_birthtime.tv_sec;
    648 			ip->i_ffs2_birthnsec = vap->va_birthtime.tv_nsec;
    649 		}
    650 		error = UFS_UPDATE(vp, &vap->va_atime, &vap->va_mtime, 0);
    651 		UFS_WAPBL_END(vp->v_mount);
    652 		if (error)
    653 			goto out;
    654 	}
    655 	error = 0;
    656 	if (vap->va_mode != (mode_t)VNOVAL) {
    657 		if (vp->v_mount->mnt_flag & MNT_RDONLY) {
    658 			error = EROFS;
    659 			goto out;
    660 		}
    661 		if ((ip->i_flags & SF_SNAPSHOT) != 0 &&
    662 		    (vap->va_mode & (S_IXUSR | S_IWUSR | S_IXGRP | S_IWGRP |
    663 		     S_IXOTH | S_IWOTH))) {
    664 			error = EPERM;
    665 			goto out;
    666 		}
    667 		error = UFS_WAPBL_BEGIN(vp->v_mount);
    668 		if (error)
    669 			goto out;
    670 		error = ufs_chmod(vp, (int)vap->va_mode, cred, l);
    671 		UFS_WAPBL_END(vp->v_mount);
    672 	}
    673 out:
    674 	cache_enter_id(vp, ip->i_mode, ip->i_uid, ip->i_gid, !HAS_ACLS(ip));
    675 	return (error);
    676 }
    677 
    678 #ifdef UFS_ACL
    679 static int
    680 ufs_update_nfs4_acl_after_mode_change(struct vnode *vp, int mode,
    681     int file_owner_id, kauth_cred_t cred, struct lwp *l)
    682 {
    683 	int error;
    684 	struct acl *aclp;
    685 
    686 	aclp = acl_alloc(KM_SLEEP);
    687 	error = ufs_getacl_nfs4_internal(vp, aclp, l);
    688 	/*
    689 	 * We don't have to handle EOPNOTSUPP here, as the filesystem claims
    690 	 * it supports ACLs.
    691 	 */
    692 	if (error)
    693 		goto out;
    694 
    695 	acl_nfs4_sync_acl_from_mode(aclp, mode, file_owner_id);
    696 	error = ufs_setacl_nfs4_internal(vp, aclp, l, false);
    697 
    698 out:
    699 	acl_free(aclp);
    700 	return (error);
    701 }
    702 #endif /* UFS_ACL */
    703 
    704 /*
    705  * Change the mode on a file.
    706  * Inode must be locked before calling.
    707  */
    708 static int
    709 ufs_chmod(struct vnode *vp, int mode, kauth_cred_t cred, struct lwp *l)
    710 {
    711 	struct inode	*ip;
    712 	int		error;
    713 
    714 	UFS_WAPBL_JLOCK_ASSERT(vp->v_mount);
    715 
    716 	ip = VTOI(vp);
    717 
    718 #ifdef UFS_ACL
    719 	/*
    720 	 * To modify the permissions on a file, must possess VADMIN
    721 	 * for that file.
    722 	 */
    723 	if ((error = VOP_ACCESSX(vp, VWRITE_ACL, cred)) != 0)
    724 		return error;
    725 #endif
    726 
    727 	error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_SECURITY, vp,
    728 	    NULL, genfs_can_chmod(vp, cred, ip->i_uid, ip->i_gid, mode));
    729 	if (error)
    730 		return (error);
    731 
    732 #ifdef UFS_ACL
    733 	if ((vp->v_mount->mnt_flag & MNT_NFS4ACLS) != 0) {
    734 		error = ufs_update_nfs4_acl_after_mode_change(vp, mode,
    735 		    ip->i_uid, cred, l);
    736 		if (error)
    737 			return error;
    738 	}
    739 #endif
    740 	ip->i_mode &= ~ALLPERMS;
    741 	ip->i_mode |= (mode & ALLPERMS);
    742 	ip->i_flag |= IN_CHANGE;
    743 	DIP_ASSIGN(ip, mode, ip->i_mode);
    744 	UFS_WAPBL_UPDATE(vp, NULL, NULL, 0);
    745 	cache_enter_id(vp, ip->i_mode, ip->i_uid, ip->i_gid, !HAS_ACLS(ip));
    746 	return (0);
    747 }
    748 
    749 /*
    750  * Perform chown operation on inode ip;
    751  * inode must be locked prior to call.
    752  */
    753 static int
    754 ufs_chown(struct vnode *vp, uid_t uid, gid_t gid, kauth_cred_t cred,
    755     	struct lwp *l)
    756 {
    757 	struct inode	*ip;
    758 	int		error = 0;
    759 #if defined(QUOTA) || defined(QUOTA2)
    760 	uid_t		ouid;
    761 	gid_t		ogid;
    762 	int64_t		change;
    763 #endif
    764 	ip = VTOI(vp);
    765 	error = 0;
    766 
    767 	if (uid == (uid_t)VNOVAL)
    768 		uid = ip->i_uid;
    769 	if (gid == (gid_t)VNOVAL)
    770 		gid = ip->i_gid;
    771 
    772 #ifdef UFS_ACL
    773 	/*
    774 	 * To modify the ownership of a file, must possess VADMIN for that
    775 	 * file.
    776 	 */
    777 	if ((error = VOP_ACCESSX(vp, VWRITE_OWNER, cred)) != 0)
    778 		return error;
    779 #endif
    780 
    781 	error = kauth_authorize_vnode(cred, KAUTH_VNODE_CHANGE_OWNERSHIP, vp,
    782 	    NULL, genfs_can_chown(vp, cred, ip->i_uid, ip->i_gid, uid, gid));
    783 	if (error)
    784 		return (error);
    785 
    786 #if defined(QUOTA) || defined(QUOTA2)
    787 	ogid = ip->i_gid;
    788 	ouid = ip->i_uid;
    789 	change = DIP(ip, blocks);
    790 	(void) chkdq(ip, -change, cred, 0);
    791 	(void) chkiq(ip, -1, cred, 0);
    792 #endif
    793 	ip->i_gid = gid;
    794 	DIP_ASSIGN(ip, gid, gid);
    795 	ip->i_uid = uid;
    796 	DIP_ASSIGN(ip, uid, uid);
    797 #if defined(QUOTA) || defined(QUOTA2)
    798 	if ((error = chkdq(ip, change, cred, 0)) == 0) {
    799 		if ((error = chkiq(ip, 1, cred, 0)) == 0)
    800 			goto good;
    801 		else
    802 			(void) chkdq(ip, -change, cred, FORCE);
    803 	}
    804 	ip->i_gid = ogid;
    805 	DIP_ASSIGN(ip, gid, ogid);
    806 	ip->i_uid = ouid;
    807 	DIP_ASSIGN(ip, uid, ouid);
    808 	(void) chkdq(ip, change, cred, FORCE);
    809 	(void) chkiq(ip, 1, cred, FORCE);
    810 	return (error);
    811  good:
    812 #endif /* QUOTA || QUOTA2 */
    813 	ip->i_flag |= IN_CHANGE;
    814 	UFS_WAPBL_UPDATE(vp, NULL, NULL, 0);
    815 	cache_enter_id(vp, ip->i_mode, ip->i_uid, ip->i_gid, !HAS_ACLS(ip));
    816 	return (0);
    817 }
    818 
    819 int
    820 ufs_remove(void *v)
    821 {
    822 	struct vop_remove_v3_args /* {
    823 		struct vnode		*a_dvp;
    824 		struct vnode		*a_vp;
    825 		struct componentname	*a_cnp;
    826 		nlink_t 		 ctx_vp_new_nlink;
    827 	} */ *ap = v;
    828 	struct vnode	*vp, *dvp;
    829 	struct inode	*ip;
    830 	struct mount	*mp;
    831 	int		error;
    832 	struct ufs_lookup_results *ulr;
    833 
    834 	vp = ap->a_vp;
    835 	dvp = ap->a_dvp;
    836 	ip = VTOI(vp);
    837 	mp = dvp->v_mount;
    838 	KASSERT(mp == vp->v_mount); /* XXX Not stable without lock.  */
    839 
    840 #ifdef UFS_ACL
    841 #ifdef notyet
    842 	/* We don't do this because if the filesystem is mounted without ACLs
    843 	 * this goes through vfs_unixify_accmode() and we get EPERM.
    844 	 */
    845 	error = VOP_ACCESSX(vp, VDELETE, ap->a_cnp->cn_cred);
    846 	if (error)
    847 		goto err;
    848 #endif
    849 #endif
    850 
    851 	/* XXX should handle this material another way */
    852 	ulr = &VTOI(dvp)->i_crap;
    853 	UFS_CHECK_CRAPCOUNTER(VTOI(dvp));
    854 
    855 	if (vp->v_type == VDIR || (ip->i_flags & (IMMUTABLE | APPEND)) ||
    856 	    (VTOI(dvp)->i_flags & APPEND))
    857 		error = EPERM;
    858 	else {
    859 		error = UFS_WAPBL_BEGIN(mp);
    860 		if (error == 0) {
    861 			error = ufs_dirremove(dvp, ulr,
    862 					      ip, ap->a_cnp->cn_flags, 0);
    863 			UFS_WAPBL_END(mp);
    864 			if (error == 0) {
    865 				ap->ctx_vp_new_nlink = ip->i_nlink;
    866 			}
    867 		}
    868 	}
    869 #ifdef notyet
    870 err:
    871 #endif
    872 	if (dvp == vp)
    873 		vrele(vp);
    874 	else
    875 		vput(vp);
    876 	return (error);
    877 }
    878 
    879 /*
    880  * ufs_link: create hard link.
    881  */
    882 int
    883 ufs_link(void *v)
    884 {
    885 	struct vop_link_v2_args /* {
    886 		struct vnode *a_dvp;
    887 		struct vnode *a_vp;
    888 		struct componentname *a_cnp;
    889 	} */ *ap = v;
    890 	struct vnode *dvp = ap->a_dvp;
    891 	struct vnode *vp = ap->a_vp;
    892 	struct componentname *cnp = ap->a_cnp;
    893 	struct mount *mp = dvp->v_mount;
    894 	struct inode *ip;
    895 	struct direct *newdir;
    896 	int error, abrt = 1;
    897 	struct ufs_lookup_results *ulr;
    898 
    899 	KASSERT(dvp != vp);
    900 	KASSERT(vp->v_type != VDIR);
    901 	KASSERT(mp == vp->v_mount); /* XXX Not stable without lock.  */
    902 
    903 	/* XXX should handle this material another way */
    904 	ulr = &VTOI(dvp)->i_crap;
    905 	UFS_CHECK_CRAPCOUNTER(VTOI(dvp));
    906 
    907 	error = vn_lock(vp, LK_EXCLUSIVE);
    908 	if (error)
    909 		goto out2;
    910 
    911 	ip = VTOI(vp);
    912 	if ((nlink_t)ip->i_nlink >= LINK_MAX) {
    913 		error = EMLINK;
    914 		goto out1;
    915 	}
    916 	if (ip->i_flags & (IMMUTABLE | APPEND)) {
    917 		error = EPERM;
    918 		goto out1;
    919 	}
    920 
    921 	error = kauth_authorize_vnode(cnp->cn_cred, KAUTH_VNODE_ADD_LINK, vp,
    922 	    dvp, 0);
    923 	if (error)
    924 		goto out1;
    925 
    926 	error = UFS_WAPBL_BEGIN(mp);
    927 	if (error)
    928 		goto out1;
    929 
    930 	ip->i_nlink++;
    931 	DIP_ASSIGN(ip, nlink, ip->i_nlink);
    932 	ip->i_flag |= IN_CHANGE;
    933 	abrt = 0;
    934 	error = UFS_UPDATE(vp, NULL, NULL, UPDATE_DIROP);
    935 	if (!error) {
    936 		newdir = pool_cache_get(ufs_direct_cache, PR_WAITOK);
    937 		ufs_makedirentry(ip, cnp, newdir);
    938 		error = ufs_direnter(dvp, ulr, vp, newdir, cnp, NULL);
    939 		pool_cache_put(ufs_direct_cache, newdir);
    940 	}
    941 	if (error) {
    942 		ip->i_nlink--;
    943 		DIP_ASSIGN(ip, nlink, ip->i_nlink);
    944 		ip->i_flag |= IN_CHANGE;
    945 		UFS_WAPBL_UPDATE(vp, NULL, NULL, UPDATE_DIROP);
    946 	}
    947 	UFS_WAPBL_END(mp);
    948  out1:
    949 	VOP_UNLOCK(vp);
    950  out2:
    951 	if (abrt)
    952 		VOP_ABORTOP(dvp, cnp);
    953 	return (error);
    954 }
    955 
    956 /*
    957  * whiteout vnode call
    958  */
    959 int
    960 ufs_whiteout(void *v)
    961 {
    962 	struct vop_whiteout_args /* {
    963 		struct vnode		*a_dvp;
    964 		struct componentname	*a_cnp;
    965 		int			a_flags;
    966 	} */ *ap = v;
    967 	struct vnode		*dvp = ap->a_dvp;
    968 	struct componentname	*cnp = ap->a_cnp;
    969 	struct direct		*newdir;
    970 	int			error;
    971 	struct ufsmount		*ump = VFSTOUFS(dvp->v_mount);
    972 	struct ufs_lookup_results *ulr;
    973 
    974 	/* XXX should handle this material another way */
    975 	ulr = &VTOI(dvp)->i_crap;
    976 	UFS_CHECK_CRAPCOUNTER(VTOI(dvp));
    977 
    978 	error = 0;
    979 	switch (ap->a_flags) {
    980 	case LOOKUP:
    981 		/* 4.4 format directories support whiteout operations */
    982 		if (ump->um_maxsymlinklen > 0)
    983 			return (0);
    984 		return (EOPNOTSUPP);
    985 
    986 	case CREATE:
    987 		/* create a new directory whiteout */
    988 		error = UFS_WAPBL_BEGIN(dvp->v_mount);
    989 		if (error)
    990 			break;
    991 
    992 		KASSERTMSG((ump->um_maxsymlinklen > 0),
    993 		    "ufs_whiteout: old format filesystem");
    994 
    995 		newdir = pool_cache_get(ufs_direct_cache, PR_WAITOK);
    996 		newdir->d_ino = UFS_WINO;
    997 		newdir->d_namlen = cnp->cn_namelen;
    998 		memcpy(newdir->d_name, cnp->cn_nameptr,
    999 		    (size_t)cnp->cn_namelen);
   1000 
   1001 		/* NUL terminate and zero out padding */
   1002 		memset(&newdir->d_name[cnp->cn_namelen], 0,
   1003 		    UFS_NAMEPAD(cnp->cn_namelen));
   1004 
   1005 		newdir->d_type = DT_WHT;
   1006 		error = ufs_direnter(dvp, ulr, NULL, newdir, cnp, NULL);
   1007 		pool_cache_put(ufs_direct_cache, newdir);
   1008 		break;
   1009 
   1010 	case DELETE:
   1011 		/* remove an existing directory whiteout */
   1012 		error = UFS_WAPBL_BEGIN(dvp->v_mount);
   1013 		if (error)
   1014 			break;
   1015 
   1016 		KASSERTMSG((ump->um_maxsymlinklen > 0),
   1017 		    "ufs_whiteout: old format filesystem");
   1018 
   1019 		cnp->cn_flags &= ~DOWHITEOUT;
   1020 		error = ufs_dirremove(dvp, ulr, NULL, cnp->cn_flags, 0);
   1021 		break;
   1022 	default:
   1023 		panic("ufs_whiteout: unknown op");
   1024 		/* NOTREACHED */
   1025 	}
   1026 	UFS_WAPBL_END(dvp->v_mount);
   1027 	return (error);
   1028 }
   1029 
   1030 #ifdef UFS_ACL
   1031 static int
   1032 ufs_do_posix1e_acl_inheritance_dir(struct vnode *dvp, struct vnode *tvp,
   1033     mode_t dmode, kauth_cred_t cred, struct lwp *l)
   1034 {
   1035 	int error;
   1036 	struct inode *ip = VTOI(tvp);
   1037 	struct acl *dacl, *acl;
   1038 
   1039 	acl = acl_alloc(KM_SLEEP);
   1040 	dacl = acl_alloc(KM_SLEEP);
   1041 
   1042 	/*
   1043 	 * Retrieve default ACL from parent, if any.
   1044 	 */
   1045 	error = VOP_GETACL(dvp, ACL_TYPE_DEFAULT, acl, cred);
   1046 	switch (error) {
   1047 	case 0:
   1048 		/*
   1049 		 * Retrieved a default ACL, so merge mode and ACL if
   1050 		 * necessary.  If the ACL is empty, fall through to
   1051 		 * the "not defined or available" case.
   1052 		 */
   1053 		if (acl->acl_cnt != 0) {
   1054 			dmode = acl_posix1e_newfilemode(dmode, acl);
   1055 			ip->i_mode = dmode;
   1056 			DIP_ASSIGN(ip, mode, dmode);
   1057 			*dacl = *acl;
   1058 			ufs_sync_acl_from_inode(ip, acl);
   1059 			break;
   1060 		}
   1061 		/* FALLTHROUGH */
   1062 
   1063 	case EOPNOTSUPP:
   1064 		/*
   1065 		 * Just use the mode as-is.
   1066 		 */
   1067 		ip->i_mode = dmode;
   1068 		DIP_ASSIGN(ip, mode, dmode);
   1069 		error = 0;
   1070 		goto out;
   1071 
   1072 	default:
   1073 		goto out;
   1074 	}
   1075 
   1076 	/*
   1077 	 * XXX: If we abort now, will Soft Updates notify the extattr
   1078 	 * code that the EAs for the file need to be released?
   1079 	 */
   1080 	UFS_WAPBL_END(tvp->v_mount);
   1081 	error = ufs_setacl_posix1e(tvp, ACL_TYPE_ACCESS, acl, cred, l);
   1082 	if (error == 0)
   1083 		error = ufs_setacl_posix1e(tvp, ACL_TYPE_DEFAULT, dacl, cred,
   1084 		    l);
   1085 	UFS_WAPBL_BEGIN(tvp->v_mount);
   1086 	switch (error) {
   1087 	case 0:
   1088 		break;
   1089 
   1090 	case EOPNOTSUPP:
   1091 		/*
   1092 		 * XXX: This should not happen, as EOPNOTSUPP above
   1093 		 * was supposed to free acl.
   1094 		 */
   1095 		printf("ufs_mkdir: VOP_GETACL() but no VOP_SETACL()\n");
   1096 		/*
   1097 		panic("ufs_mkdir: VOP_GETACL() but no VOP_SETACL()");
   1098 		 */
   1099 		break;
   1100 
   1101 	default:
   1102 		goto out;
   1103 	}
   1104 
   1105 out:
   1106 	acl_free(acl);
   1107 	acl_free(dacl);
   1108 
   1109 	return (error);
   1110 }
   1111 
   1112 static int
   1113 ufs_do_posix1e_acl_inheritance_file(struct vnode *dvp, struct vnode *tvp,
   1114     mode_t mode, kauth_cred_t cred, struct lwp *l)
   1115 {
   1116 	int error;
   1117 	struct inode *ip = VTOI(tvp);
   1118 	struct acl *acl;
   1119 
   1120 	acl = acl_alloc(KM_SLEEP);
   1121 
   1122 	/*
   1123 	 * Retrieve default ACL for parent, if any.
   1124 	 */
   1125 	error = VOP_GETACL(dvp, ACL_TYPE_DEFAULT, acl, cred);
   1126 	switch (error) {
   1127 	case 0:
   1128 		/*
   1129 		 * Retrieved a default ACL, so merge mode and ACL if
   1130 		 * necessary.
   1131 		 */
   1132 		if (acl->acl_cnt != 0) {
   1133 			/*
   1134 			 * Two possible ways for default ACL to not
   1135 			 * be present.  First, the EA can be
   1136 			 * undefined, or second, the default ACL can
   1137 			 * be blank.  If it's blank, fall through to
   1138 			 * the it's not defined case.
   1139 			 */
   1140 			mode = acl_posix1e_newfilemode(mode, acl);
   1141 			ip->i_mode = mode;
   1142 			DIP_ASSIGN(ip, mode, mode);
   1143 			ufs_sync_acl_from_inode(ip, acl);
   1144 			break;
   1145 		}
   1146 		/* FALLTHROUGH */
   1147 
   1148 	case EOPNOTSUPP:
   1149 		/*
   1150 		 * Just use the mode as-is.
   1151 		 */
   1152 		ip->i_mode = mode;
   1153 		DIP_ASSIGN(ip, mode, mode);
   1154 		error = 0;
   1155 		goto out;
   1156 
   1157 	default:
   1158 		goto out;
   1159 	}
   1160 
   1161 	UFS_WAPBL_END(tvp->v_mount);
   1162 	/*
   1163 	 * XXX: If we abort now, will Soft Updates notify the extattr
   1164 	 * code that the EAs for the file need to be released?
   1165 	 */
   1166 	error = VOP_SETACL(tvp, ACL_TYPE_ACCESS, acl, cred);
   1167 	UFS_WAPBL_BEGIN(tvp->v_mount);
   1168 	switch (error) {
   1169 	case 0:
   1170 		break;
   1171 
   1172 	case EOPNOTSUPP:
   1173 		/*
   1174 		 * XXX: This should not happen, as EOPNOTSUPP above was
   1175 		 * supposed to free acl.
   1176 		 */
   1177 		printf("%s: VOP_GETACL() but no VOP_SETACL()\n", __func__);
   1178 		/* panic("%s: VOP_GETACL() but no VOP_SETACL()", __func__); */
   1179 		break;
   1180 
   1181 	default:
   1182 		goto out;
   1183 	}
   1184 
   1185 out:
   1186 	acl_free(acl);
   1187 
   1188 	return (error);
   1189 }
   1190 
   1191 static int
   1192 ufs_do_nfs4_acl_inheritance(struct vnode *dvp, struct vnode *tvp,
   1193     mode_t child_mode, kauth_cred_t cred, struct lwp *l)
   1194 {
   1195 	int error;
   1196 	struct acl *parent_aclp, *child_aclp;
   1197 
   1198 	parent_aclp = acl_alloc(KM_SLEEP);
   1199 	child_aclp = acl_alloc(KM_SLEEP);
   1200 
   1201 	error = ufs_getacl_nfs4_internal(dvp, parent_aclp, l);
   1202 	if (error)
   1203 		goto out;
   1204 	acl_nfs4_compute_inherited_acl(parent_aclp, child_aclp,
   1205 	    child_mode, VTOI(tvp)->i_uid, tvp->v_type == VDIR);
   1206 	error = ufs_setacl_nfs4_internal(tvp, child_aclp, l, false);
   1207 	if (error)
   1208 		goto out;
   1209 out:
   1210 	acl_free(parent_aclp);
   1211 	acl_free(child_aclp);
   1212 
   1213 	return (error);
   1214 }
   1215 #endif
   1216 
   1217 int
   1218 ufs_mkdir(void *v)
   1219 {
   1220 	struct vop_mkdir_v3_args /* {
   1221 		struct vnode		*a_dvp;
   1222 		struct vnode		**a_vpp;
   1223 		struct componentname	*a_cnp;
   1224 		struct vattr		*a_vap;
   1225 	} */ *ap = v;
   1226 	struct vnode		*dvp = ap->a_dvp, *tvp;
   1227 	struct vattr		*vap = ap->a_vap;
   1228 	struct componentname	*cnp = ap->a_cnp;
   1229 	struct inode		*ip, *dp = VTOI(dvp);
   1230 	struct buf		*bp;
   1231 	struct dirtemplate	dirtemplate;
   1232 	struct direct		*newdir;
   1233 	int			error;
   1234 	struct ufsmount		*ump = dp->i_ump;
   1235 	int			dirblksiz = ump->um_dirblksiz;
   1236 	struct ufs_lookup_results *ulr;
   1237 
   1238 	/* XXX should handle this material another way */
   1239 	ulr = &dp->i_crap;
   1240 	UFS_CHECK_CRAPCOUNTER(dp);
   1241 
   1242 	KASSERT(vap->va_type == VDIR);
   1243 
   1244 	if ((nlink_t)dp->i_nlink >= LINK_MAX) {
   1245 		error = EMLINK;
   1246 		goto out;
   1247 	}
   1248 	/*
   1249 	 * Must simulate part of ufs_makeinode here to acquire the inode,
   1250 	 * but not have it entered in the parent directory. The entry is
   1251 	 * made later after writing "." and ".." entries.
   1252 	 */
   1253 	error = vcache_new(dvp->v_mount, dvp, vap, cnp->cn_cred, NULL,
   1254 	    ap->a_vpp);
   1255 	if (error)
   1256 		goto out;
   1257 	error = vn_lock(*ap->a_vpp, LK_EXCLUSIVE);
   1258 	if (error) {
   1259 		vrele(*ap->a_vpp);
   1260 		*ap->a_vpp = NULL;
   1261 		goto out;
   1262 	}
   1263 	error = UFS_WAPBL_BEGIN(ap->a_dvp->v_mount);
   1264 	if (error) {
   1265 		vput(*ap->a_vpp);
   1266 		goto out;
   1267 	}
   1268 
   1269 	tvp = *ap->a_vpp;
   1270 	ip = VTOI(tvp);
   1271 	ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
   1272 	ip->i_nlink = 2;
   1273 	DIP_ASSIGN(ip, nlink, 2);
   1274 	if (cnp->cn_flags & ISWHITEOUT) {
   1275 		ip->i_flags |= UF_OPAQUE;
   1276 		DIP_ASSIGN(ip, flags, ip->i_flags);
   1277 	}
   1278 
   1279 	/*
   1280 	 * Bump link count in parent directory to reflect work done below.
   1281 	 * Should be done before reference is created so cleanup is
   1282 	 * possible if we crash.
   1283 	 */
   1284 	dp->i_nlink++;
   1285 	DIP_ASSIGN(dp, nlink, dp->i_nlink);
   1286 	dp->i_flag |= IN_CHANGE;
   1287 	if ((error = UFS_UPDATE(dvp, NULL, NULL, UPDATE_DIROP)) != 0)
   1288 		goto bad;
   1289 
   1290 #ifdef UFS_ACL
   1291 	mode_t dmode = (vap->va_mode & 0777) | IFDIR;
   1292 	struct lwp *l = curlwp;
   1293 	if (dvp->v_mount->mnt_flag & MNT_POSIX1EACLS) {
   1294 
   1295 		error = ufs_do_posix1e_acl_inheritance_dir(dvp, tvp, dmode,
   1296 		    cnp->cn_cred, l);
   1297 		if (error)
   1298 			goto bad;
   1299 	} else if (dvp->v_mount->mnt_flag & MNT_NFS4ACLS) {
   1300 		error = ufs_do_nfs4_acl_inheritance(dvp, tvp, dmode,
   1301 		    cnp->cn_cred, l);
   1302 		if (error)
   1303 			goto bad;
   1304 	}
   1305 #endif /* !UFS_ACL */
   1306 
   1307 	/*
   1308 	 * Initialize directory with "." and ".." from static template.
   1309 	 */
   1310 	dirtemplate = mastertemplate;
   1311 	dirtemplate.dotdot_reclen = dirblksiz - dirtemplate.dot_reclen;
   1312 	dirtemplate.dot_ino = ufs_rw32(ip->i_number, UFS_MPNEEDSWAP(ump));
   1313 	dirtemplate.dotdot_ino = ufs_rw32(dp->i_number, UFS_MPNEEDSWAP(ump));
   1314 	dirtemplate.dot_reclen = ufs_rw16(dirtemplate.dot_reclen,
   1315 	    UFS_MPNEEDSWAP(ump));
   1316 	dirtemplate.dotdot_reclen = ufs_rw16(dirtemplate.dotdot_reclen,
   1317 	    UFS_MPNEEDSWAP(ump));
   1318 	if (ump->um_maxsymlinklen <= 0) {
   1319 #if BYTE_ORDER == LITTLE_ENDIAN
   1320 		if (UFS_MPNEEDSWAP(ump) == 0)
   1321 #else
   1322 		if (UFS_MPNEEDSWAP(ump) != 0)
   1323 #endif
   1324 		{
   1325 			dirtemplate.dot_type = dirtemplate.dot_namlen;
   1326 			dirtemplate.dotdot_type = dirtemplate.dotdot_namlen;
   1327 			dirtemplate.dot_namlen = dirtemplate.dotdot_namlen = 0;
   1328 		} else
   1329 			dirtemplate.dot_type = dirtemplate.dotdot_type = 0;
   1330 	}
   1331 	if ((error = UFS_BALLOC(tvp, (off_t)0, dirblksiz, cnp->cn_cred,
   1332 	    B_CLRBUF, &bp)) != 0)
   1333 		goto bad;
   1334 	ip->i_size = dirblksiz;
   1335 	DIP_ASSIGN(ip, size, dirblksiz);
   1336 	ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
   1337 	uvm_vnp_setsize(tvp, ip->i_size);
   1338 	memcpy((void *)bp->b_data, (void *)&dirtemplate, sizeof dirtemplate);
   1339 
   1340 	/*
   1341 	 * Directory set up, now install its entry in the parent directory.
   1342 	 * We must write out the buffer containing the new directory body
   1343 	 * before entering the new name in the parent.
   1344 	 */
   1345 	if ((error = VOP_BWRITE(bp->b_vp, bp)) != 0)
   1346 		goto bad;
   1347 	if ((error = UFS_UPDATE(tvp, NULL, NULL, UPDATE_DIROP)) != 0) {
   1348 		goto bad;
   1349 	}
   1350 	newdir = pool_cache_get(ufs_direct_cache, PR_WAITOK);
   1351 	ufs_makedirentry(ip, cnp, newdir);
   1352 	error = ufs_direnter(dvp, ulr, tvp, newdir, cnp, bp);
   1353 	pool_cache_put(ufs_direct_cache, newdir);
   1354  bad:
   1355 	if (error == 0) {
   1356 		VOP_UNLOCK(tvp);
   1357 		UFS_WAPBL_END(dvp->v_mount);
   1358 	} else {
   1359 		dp->i_nlink--;
   1360 		DIP_ASSIGN(dp, nlink, dp->i_nlink);
   1361 		dp->i_flag |= IN_CHANGE;
   1362 		UFS_WAPBL_UPDATE(dvp, NULL, NULL, UPDATE_DIROP);
   1363 		/*
   1364 		 * No need to do an explicit UFS_TRUNCATE here, vrele will
   1365 		 * do this for us because we set the link count to 0.
   1366 		 */
   1367 		ip->i_nlink = 0;
   1368 		DIP_ASSIGN(ip, nlink, 0);
   1369 		ip->i_flag |= IN_CHANGE;
   1370 		UFS_WAPBL_UPDATE(tvp, NULL, NULL, UPDATE_DIROP);
   1371 		UFS_WAPBL_END(dvp->v_mount);
   1372 		vput(tvp);
   1373 	}
   1374  out:
   1375 	return (error);
   1376 }
   1377 
   1378 int
   1379 ufs_rmdir(void *v)
   1380 {
   1381 	struct vop_rmdir_v2_args /* {
   1382 		struct vnode		*a_dvp;
   1383 		struct vnode		*a_vp;
   1384 		struct componentname	*a_cnp;
   1385 	} */ *ap = v;
   1386 	struct vnode		*vp, *dvp;
   1387 	struct componentname	*cnp;
   1388 	struct inode		*ip, *dp;
   1389 	int			error;
   1390 	struct ufs_lookup_results *ulr;
   1391 
   1392 	vp = ap->a_vp;
   1393 	dvp = ap->a_dvp;
   1394 	cnp = ap->a_cnp;
   1395 	ip = VTOI(vp);
   1396 	dp = VTOI(dvp);
   1397 
   1398 #ifdef UFS_ACL
   1399 #ifdef notyet
   1400 	/* We don't do this because if the filesystem is mounted without ACLs
   1401 	 * this goes through vfs_unixify_accmode() and we get EPERM.
   1402 	 */
   1403 	error = VOP_ACCESSX(vp, VDELETE, cnp->cn_cred);
   1404 	if (error)
   1405 		goto err;
   1406 #endif
   1407 #endif
   1408 
   1409 	/* XXX should handle this material another way */
   1410 	ulr = &dp->i_crap;
   1411 	UFS_CHECK_CRAPCOUNTER(dp);
   1412 
   1413 	/*
   1414 	 * No rmdir "." or of mounted directories please.
   1415 	 */
   1416 	if (dp == ip || vp->v_mountedhere != NULL) {
   1417 		error = EINVAL;
   1418 		goto err;
   1419 	}
   1420 
   1421 	/*
   1422 	 * Do not remove a directory that is in the process of being renamed.
   1423 	 * Verify that the directory is empty (and valid). (Rmdir ".." won't
   1424 	 * be valid since ".." will contain a reference to the current
   1425 	 * directory and thus be non-empty.)
   1426 	 */
   1427 	error = 0;
   1428 	if (ip->i_nlink != 2 ||
   1429 	    !ufs_dirempty(ip, dp->i_number, cnp->cn_cred)) {
   1430 		error = ENOTEMPTY;
   1431 		goto out;
   1432 	}
   1433 	if ((dp->i_flags & APPEND) ||
   1434 		(ip->i_flags & (IMMUTABLE | APPEND))) {
   1435 		error = EPERM;
   1436 		goto out;
   1437 	}
   1438 	error = UFS_WAPBL_BEGIN(dvp->v_mount);
   1439 	if (error)
   1440 		goto out;
   1441 	/*
   1442 	 * Delete reference to directory before purging
   1443 	 * inode.  If we crash in between, the directory
   1444 	 * will be reattached to lost+found,
   1445 	 */
   1446 	error = ufs_dirremove(dvp, ulr, ip, cnp->cn_flags, 1);
   1447 	if (error) {
   1448 		UFS_WAPBL_END(dvp->v_mount);
   1449 		goto out;
   1450 	}
   1451 	cache_purge(dvp);
   1452 	/*
   1453 	 * Truncate inode.  The only stuff left in the directory is "." and
   1454 	 * "..".  The "." reference is inconsequential since we're quashing
   1455 	 * it.
   1456 	 */
   1457 	dp->i_nlink--;
   1458 	DIP_ASSIGN(dp, nlink, dp->i_nlink);
   1459 	dp->i_flag |= IN_CHANGE;
   1460 	UFS_WAPBL_UPDATE(dvp, NULL, NULL, UPDATE_DIROP);
   1461 	ip->i_nlink--;
   1462 	DIP_ASSIGN(ip, nlink, ip->i_nlink);
   1463 	ip->i_flag |= IN_CHANGE;
   1464 	(void) UFS_TRUNCATE(vp, (off_t)0, IO_SYNC, cnp->cn_cred);
   1465 	cache_purge(vp);
   1466 	/*
   1467 	 * Unlock the log while we still have reference to unlinked
   1468 	 * directory vp so that it will not get locked for recycling
   1469 	 */
   1470 	UFS_WAPBL_END(dvp->v_mount);
   1471 #ifdef UFS_DIRHASH
   1472 	if (ip->i_dirhash != NULL)
   1473 		ufsdirhash_free(ip);
   1474 #endif
   1475  out:
   1476 	vput(vp);
   1477 	return error;
   1478  err:
   1479 	if (dp == ip)
   1480 		vrele(vp);
   1481 	else
   1482 		vput(vp);
   1483 	return error;
   1484 }
   1485 
   1486 /*
   1487  * symlink -- make a symbolic link
   1488  */
   1489 int
   1490 ufs_symlink(void *v)
   1491 {
   1492 	struct vop_symlink_v3_args /* {
   1493 		struct vnode		*a_dvp;
   1494 		struct vnode		**a_vpp;
   1495 		struct componentname	*a_cnp;
   1496 		struct vattr		*a_vap;
   1497 		char			*a_target;
   1498 	} */ *ap = v;
   1499 	struct vnode	*vp, **vpp;
   1500 	struct inode	*ip;
   1501 	int		len, error;
   1502 	struct ufs_lookup_results *ulr;
   1503 
   1504 	vpp = ap->a_vpp;
   1505 
   1506 	/* XXX should handle this material another way */
   1507 	ulr = &VTOI(ap->a_dvp)->i_crap;
   1508 	UFS_CHECK_CRAPCOUNTER(VTOI(ap->a_dvp));
   1509 
   1510 	/*
   1511 	 * UFS_WAPBL_BEGIN(dvp->v_mount) performed by successful
   1512 	 * ufs_makeinode
   1513 	 */
   1514 	KASSERT(ap->a_vap->va_type == VLNK);
   1515 	error = ufs_makeinode(ap->a_vap, ap->a_dvp, ulr, vpp, ap->a_cnp);
   1516 	if (error)
   1517 		goto out;
   1518 	vp = *vpp;
   1519 	len = strlen(ap->a_target);
   1520 	ip = VTOI(vp);
   1521 	/*
   1522 	 * This test is off by one. um_maxsymlinklen contains the
   1523 	 * number of bytes available, and we aren't storing a \0, so
   1524 	 * the test should properly be <=. However, it cannot be
   1525 	 * changed as this would break compatibility with existing fs
   1526 	 * images -- see the way ufs_readlink() works.
   1527 	 */
   1528 	if (len < ip->i_ump->um_maxsymlinklen) {
   1529 		memcpy((char *)SHORTLINK(ip), ap->a_target, len);
   1530 		ip->i_size = len;
   1531 		DIP_ASSIGN(ip, size, len);
   1532 		uvm_vnp_setsize(vp, ip->i_size);
   1533 		ip->i_flag |= IN_CHANGE | IN_UPDATE;
   1534 		if (vp->v_mount->mnt_flag & MNT_RELATIME)
   1535 			ip->i_flag |= IN_ACCESS;
   1536 		UFS_WAPBL_UPDATE(vp, NULL, NULL, 0);
   1537 	} else
   1538 		error = ufs_bufio(UIO_WRITE, vp, ap->a_target, len, (off_t)0,
   1539 		    IO_NODELOCKED | IO_JOURNALLOCKED, ap->a_cnp->cn_cred, NULL,
   1540 		    NULL);
   1541 	UFS_WAPBL_END(ap->a_dvp->v_mount);
   1542 	VOP_UNLOCK(vp);
   1543 	if (error)
   1544 		vrele(vp);
   1545 out:
   1546 	return (error);
   1547 }
   1548 
   1549 /*
   1550  * Vnode op for reading directories.
   1551  *
   1552  * This routine handles converting from the on-disk directory format
   1553  * "struct direct" to the in-memory format "struct dirent" as well as
   1554  * byte swapping the entries if necessary.
   1555  */
   1556 int
   1557 ufs_readdir(void *v)
   1558 {
   1559 	struct vop_readdir_args /* {
   1560 		struct vnode	*a_vp;
   1561 		struct uio	*a_uio;
   1562 		kauth_cred_t	a_cred;
   1563 		int		*a_eofflag;
   1564 		off_t		**a_cookies;
   1565 		int		*a_ncookies;
   1566 	} */ *ap = v;
   1567 
   1568 	/* vnode and fs */
   1569 	struct vnode	*vp = ap->a_vp;
   1570 	struct ufsmount	*ump = VFSTOUFS(vp->v_mount);
   1571 	int nswap = UFS_MPNEEDSWAP(ump);
   1572 #if BYTE_ORDER == LITTLE_ENDIAN
   1573 	int needswap = ump->um_maxsymlinklen <= 0 && nswap == 0;
   1574 #else
   1575 	int needswap = ump->um_maxsymlinklen <= 0 && nswap != 0;
   1576 #endif
   1577 	/* caller's buffer */
   1578 	struct uio	*calleruio = ap->a_uio;
   1579 	off_t		startoffset, endoffset;
   1580 	size_t		callerbytes;
   1581 	off_t		curoffset;
   1582 	/* dirent production buffer */
   1583 	char		*direntbuf;
   1584 	size_t		direntbufmax;
   1585 	struct dirent	*dirent, *stopdirent;
   1586 	/* output cookies array */
   1587 	off_t		*cookies;
   1588 	size_t		numcookies, maxcookies;
   1589 	/* disk buffer */
   1590 	off_t		physstart, physend;
   1591 	size_t		skipstart, dropend;
   1592 	char		*rawbuf;
   1593 	size_t		rawbufmax, rawbytes;
   1594 	struct uio	rawuio;
   1595 	struct iovec	rawiov;
   1596 	struct direct	*rawdp, *stoprawdp;
   1597 	/* general */
   1598 	int		error;
   1599 
   1600 	KASSERT(VOP_ISLOCKED(vp));
   1601 
   1602 	/*
   1603 	 * Figure out where the user wants us to read and how much.
   1604 	 *
   1605 	 * XXX: there should probably be an upper bound on callerbytes
   1606 	 * to avoid silliness trying to do large kernel allocations.
   1607 	 */
   1608 	callerbytes = calleruio->uio_resid;
   1609 	startoffset = calleruio->uio_offset;
   1610 	endoffset = startoffset + callerbytes;
   1611 
   1612 	if (callerbytes < _DIRENT_MINSIZE(dirent)) {
   1613 		/* no room for even one struct dirent */
   1614 		return EINVAL;
   1615 	}
   1616 
   1617 	/*
   1618 	 * Now figure out where to actually start reading. Round the
   1619 	 * start down to a block boundary: we need to start at the
   1620 	 * beginning of a block in order to read the directory
   1621 	 * correctly.
   1622 	 *
   1623 	 * We also want to always read a whole number of blocks so
   1624 	 * that the copying code below doesn't have to worry about
   1625 	 * partial entries. (It used to try at one point, and was a
   1626 	 * horrible mess.)
   1627 	 *
   1628 	 * Furthermore, since blocks have to be scanned from the
   1629 	 * beginning, if we go partially into another block now we'll
   1630 	 * just have to rescan it on the next readdir call, which
   1631 	 * doesn't really serve any useful purpose.
   1632 	 *
   1633 	 * So, round down the end as well. It's ok to underpopulate
   1634 	 * the transfer buffer, as long as we send back at least one
   1635 	 * dirent so as to avoid giving a bogus EOF indication.
   1636 	 *
   1637 	 * Note that because dirents are larger than ffs struct
   1638 	 * directs, despite the rounding down we may not be able to
   1639 	 * send all the entries in the blocks we read and may have to
   1640 	 * rescan some of them on the next call anyway. Alternatively
   1641 	 * if there's empty space on disk we might have actually been
   1642 	 * able to fit the next block in, and so forth. None of this
   1643 	 * actually matters that much in practice.
   1644 	 *
   1645 	 * XXX: what does ffs do if a directory block becomes
   1646 	 * completely empty, and what happens if all the blocks we
   1647 	 * read are completely empty even though we aren't at EOF? As
   1648 	 * of this writing I (dholland) can't remember the details.
   1649 	 */
   1650 	physstart = rounddown2(startoffset, ump->um_dirblksiz);
   1651 	physend = rounddown2(endoffset, ump->um_dirblksiz);
   1652 
   1653 	if (physstart >= physend) {
   1654 		/* Need at least one block */
   1655 		return EINVAL;
   1656 	}
   1657 
   1658 	/*
   1659 	 * skipstart is the number of bytes we need to read in
   1660 	 * (because we need to start at the beginning of a block) but
   1661 	 * not transfer to the user.
   1662 	 *
   1663 	 * dropend is the number of bytes to ignore at the end of the
   1664 	 * user's buffer.
   1665 	 */
   1666 	skipstart = startoffset - physstart;
   1667 	dropend = endoffset - physend;
   1668 
   1669 	/*
   1670 	 * Make a transfer buffer.
   1671 	 *
   1672 	 * Note: rawbufmax = physend - physstart. Proof:
   1673 	 *
   1674 	 * physend - physstart = physend - physstart
   1675 	 *   = physend - physstart + startoffset - startoffset
   1676 	 *   = physend + (startoffset - physstart) - startoffset
   1677 	 *   = physend + skipstart - startoffset
   1678 	 *   = physend + skipstart - startoffset + endoffset - endoffset
   1679 	 *   = skipstart - startoffset + endoffset - (endoffset - physend)
   1680 	 *   = skipstart - startoffset + endoffset - dropend
   1681 	 *   = skipstart - startoffset + (startoffset + callerbytes) - dropend
   1682 	 *   = skipstart + callerbytes - dropend
   1683 	 *   = rawbufmax
   1684 	 * Qed.
   1685 	 *
   1686 	 * XXX: this should just use physend - physstart.
   1687 	 *
   1688 	 * XXX: this should be rewritten to read the directs straight
   1689 	 * out of bufferio buffers instead of copying twice. This would
   1690 	 * also let us adapt better to the user's buffer size.
   1691 	 */
   1692 
   1693 	/* Base buffer space for CALLERBYTES of new data */
   1694 	rawbufmax = callerbytes + skipstart;
   1695 	if (rawbufmax < callerbytes)
   1696 		return EINVAL;
   1697 	rawbufmax -= dropend;
   1698 
   1699 	if (rawbufmax < _DIRENT_MINSIZE(rawdp)) {
   1700 		/* no room for even one struct direct */
   1701 		return EINVAL;
   1702 	}
   1703 
   1704 	/* read it */
   1705 	rawbuf = kmem_alloc(rawbufmax, KM_SLEEP);
   1706 	rawiov.iov_base = rawbuf;
   1707 	rawiov.iov_len = rawbufmax;
   1708 	rawuio.uio_iov = &rawiov;
   1709 	rawuio.uio_iovcnt = 1;
   1710 	rawuio.uio_offset = physstart;
   1711 	rawuio.uio_resid = rawbufmax;
   1712 	UIO_SETUP_SYSSPACE(&rawuio);
   1713 	rawuio.uio_rw = UIO_READ;
   1714 	error = UFS_BUFRD(vp, &rawuio, 0, ap->a_cred);
   1715 	if (error != 0) {
   1716 		kmem_free(rawbuf, rawbufmax);
   1717 		return error;
   1718 	}
   1719 	rawbytes = rawbufmax - rawuio.uio_resid;
   1720 
   1721 	/* the raw entries to iterate over */
   1722 	rawdp = (struct direct *)(void *)rawbuf;
   1723 	stoprawdp = (struct direct *)(void *)&rawbuf[rawbytes];
   1724 
   1725 	/* allocate space to produce dirents into */
   1726 	direntbufmax = callerbytes;
   1727 	direntbuf = kmem_alloc(direntbufmax, KM_SLEEP);
   1728 
   1729 	/* the dirents to iterate over */
   1730 	dirent = (struct dirent *)(void *)direntbuf;
   1731 	stopdirent = (struct dirent *)(void *)&direntbuf[direntbufmax];
   1732 
   1733 	/* the output "cookies" (seek positions of directory entries) */
   1734 	if (ap->a_cookies) {
   1735 		numcookies = 0;
   1736 		maxcookies = rawbytes / _DIRENT_RECLEN(rawdp, 1);
   1737 		cookies = malloc(maxcookies * sizeof(*cookies),
   1738 		    M_TEMP, M_WAITOK);
   1739 	} else {
   1740 		/* XXX: GCC */
   1741 		maxcookies = 0;
   1742 		cookies = NULL;
   1743 	}
   1744 
   1745 	/* now produce the dirents */
   1746 	curoffset = calleruio->uio_offset;
   1747 	while (rawdp < stoprawdp) {
   1748 		rawdp->d_reclen = ufs_rw16(rawdp->d_reclen, nswap);
   1749 		if (skipstart > 0) {
   1750 			/* drain skipstart */
   1751 			if (rawdp->d_reclen <= skipstart) {
   1752 				skipstart -= rawdp->d_reclen;
   1753 				rawdp = _DIRENT_NEXT(rawdp);
   1754 				continue;
   1755 			}
   1756 			/* caller's start position wasn't on an entry */
   1757 			error = EINVAL;
   1758 			goto out;
   1759 		}
   1760 		if (rawdp->d_reclen == 0) {
   1761 			struct dirent *save = dirent;
   1762 			dirent->d_reclen = _DIRENT_MINSIZE(dirent);
   1763 			dirent = _DIRENT_NEXT(dirent);
   1764 			save->d_reclen = 0;
   1765 			rawdp = stoprawdp;
   1766 			break;
   1767 		}
   1768 
   1769 		/* copy the header */
   1770 		if (needswap) {
   1771 			dirent->d_type = rawdp->d_namlen;
   1772 			dirent->d_namlen = rawdp->d_type;
   1773 		} else {
   1774 			dirent->d_type = rawdp->d_type;
   1775 			dirent->d_namlen = rawdp->d_namlen;
   1776 		}
   1777 		dirent->d_reclen = _DIRENT_RECLEN(dirent, dirent->d_namlen);
   1778 
   1779 		/* stop if there isn't room for the name AND another header */
   1780 		if ((char *)(void *)dirent + dirent->d_reclen +
   1781 		    _DIRENT_MINSIZE(dirent) > (char *)(void *)stopdirent)
   1782 			break;
   1783 
   1784 		/* copy the name (and inode (XXX: why after the test?)) */
   1785 		dirent->d_fileno = ufs_rw32(rawdp->d_ino, nswap);
   1786 		(void)memcpy(dirent->d_name, rawdp->d_name, dirent->d_namlen);
   1787 		memset(&dirent->d_name[dirent->d_namlen], 0,
   1788 		    dirent->d_reclen - _DIRENT_NAMEOFF(dirent)
   1789 		    - dirent->d_namlen);
   1790 
   1791 		/* onward */
   1792 		curoffset += rawdp->d_reclen;
   1793 		if (ap->a_cookies) {
   1794 			KASSERT(numcookies < maxcookies);
   1795 			cookies[numcookies++] = curoffset;
   1796 		}
   1797 		dirent = _DIRENT_NEXT(dirent);
   1798 		rawdp = _DIRENT_NEXT(rawdp);
   1799 	}
   1800 
   1801 	/* transfer the dirents to the caller's buffer */
   1802 	callerbytes = ((char *)(void *)dirent - direntbuf);
   1803 	error = uiomove(direntbuf, callerbytes, calleruio);
   1804 
   1805 out:
   1806 	calleruio->uio_offset = curoffset;
   1807 	if (ap->a_cookies) {
   1808 		if (error) {
   1809 			free(cookies, M_TEMP);
   1810 			*ap->a_cookies = NULL;
   1811 			*ap->a_ncookies = 0;
   1812 		} else {
   1813 			*ap->a_cookies = cookies;
   1814 			*ap->a_ncookies = numcookies;
   1815 		}
   1816 	}
   1817 	kmem_free(direntbuf, direntbufmax);
   1818 	kmem_free(rawbuf, rawbufmax);
   1819 	*ap->a_eofflag = VTOI(vp)->i_size <= calleruio->uio_offset;
   1820 	return error;
   1821 }
   1822 
   1823 /*
   1824  * Return target name of a symbolic link
   1825  */
   1826 int
   1827 ufs_readlink(void *v)
   1828 {
   1829 	struct vop_readlink_args /* {
   1830 		struct vnode	*a_vp;
   1831 		struct uio	*a_uio;
   1832 		kauth_cred_t	a_cred;
   1833 	} */ *ap = v;
   1834 	struct vnode	*vp = ap->a_vp;
   1835 	struct inode	*ip = VTOI(vp);
   1836 	struct ufsmount	*ump = VFSTOUFS(vp->v_mount);
   1837 	int		isize;
   1838 
   1839 	/*
   1840 	 * The test against um_maxsymlinklen is off by one; it should
   1841 	 * theoretically be <=, not <. However, it cannot be changed
   1842 	 * as that would break compatibility with existing fs images.
   1843 	 */
   1844 
   1845 	isize = ip->i_size;
   1846 	if (isize < ump->um_maxsymlinklen ||
   1847 	    (ump->um_maxsymlinklen == 0 && DIP(ip, blocks) == 0)) {
   1848 		uiomove((char *)SHORTLINK(ip), isize, ap->a_uio);
   1849 		return (0);
   1850 	}
   1851 	return (UFS_BUFRD(vp, ap->a_uio, 0, ap->a_cred));
   1852 }
   1853 
   1854 /*
   1855  * Calculate the logical to physical mapping if not done already,
   1856  * then call the device strategy routine.
   1857  */
   1858 int
   1859 ufs_strategy(void *v)
   1860 {
   1861 	struct vop_strategy_args /* {
   1862 		struct vnode *a_vp;
   1863 		struct buf *a_bp;
   1864 	} */ *ap = v;
   1865 	struct buf	*bp;
   1866 	struct vnode	*vp;
   1867 	struct inode	*ip;
   1868 	struct mount	*mp;
   1869 	int		error;
   1870 
   1871 	bp = ap->a_bp;
   1872 	vp = ap->a_vp;
   1873 	ip = VTOI(vp);
   1874 	if (vp->v_type == VBLK || vp->v_type == VCHR)
   1875 		panic("ufs_strategy: spec");
   1876 	KASSERT(fstrans_held(vp->v_mount));
   1877 	KASSERT(bp->b_bcount != 0);
   1878 	if (bp->b_blkno == bp->b_lblkno) {
   1879 		error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno,
   1880 				 NULL);
   1881 		if (error) {
   1882 			bp->b_error = error;
   1883 			biodone(bp);
   1884 			return (error);
   1885 		}
   1886 		if (bp->b_blkno == -1) /* no valid data */
   1887 			clrbuf(bp);
   1888 	}
   1889 	if (bp->b_blkno < 0) { /* block is not on disk */
   1890 		biodone(bp);
   1891 		return (0);
   1892 	}
   1893 	vp = ip->i_devvp;
   1894 
   1895 	error = VOP_STRATEGY(vp, bp);
   1896 	if (error)
   1897 		return error;
   1898 
   1899 	if (!BUF_ISREAD(bp))
   1900 		return 0;
   1901 
   1902 	mp = wapbl_vptomp(vp);
   1903 	if (mp == NULL || mp->mnt_wapbl_replay == NULL ||
   1904 	    !WAPBL_REPLAY_ISOPEN(mp) ||
   1905 	    !WAPBL_REPLAY_CAN_READ(mp, bp->b_blkno, bp->b_bcount))
   1906 		return 0;
   1907 
   1908 	error = biowait(bp);
   1909 	if (error)
   1910 		return error;
   1911 
   1912 	error = WAPBL_REPLAY_READ(mp, bp->b_data, bp->b_blkno, bp->b_bcount);
   1913 	if (error) {
   1914 		mutex_enter(&bufcache_lock);
   1915 		SET(bp->b_cflags, BC_INVAL);
   1916 		mutex_exit(&bufcache_lock);
   1917 	}
   1918 	return error;
   1919 }
   1920 
   1921 /*
   1922  * Print out the contents of an inode.
   1923  */
   1924 int
   1925 ufs_print(void *v)
   1926 {
   1927 	struct vop_print_args /* {
   1928 		struct vnode	*a_vp;
   1929 	} */ *ap = v;
   1930 	struct vnode	*vp;
   1931 	struct inode	*ip;
   1932 
   1933 	vp = ap->a_vp;
   1934 	ip = VTOI(vp);
   1935 	printf("tag VT_UFS, ino %llu, on dev %llu, %llu",
   1936 	    (unsigned long long)ip->i_number,
   1937 	    (unsigned long long)major(ip->i_dev),
   1938 	    (unsigned long long)minor(ip->i_dev));
   1939 	printf(" flags 0x%x, nlink %d\n",
   1940 	    ip->i_flag, ip->i_nlink);
   1941 	printf("\tmode 0%o, owner %d, group %d, size %qd",
   1942 	    ip->i_mode, ip->i_uid, ip->i_gid,
   1943 	    (long long)ip->i_size);
   1944 	if (vp->v_type == VFIFO)
   1945 		VOCALL(fifo_vnodeop_p, VOFFSET(vop_print), v);
   1946 	printf("\n");
   1947 	return (0);
   1948 }
   1949 
   1950 /*
   1951  * Read wrapper for special devices.
   1952  */
   1953 int
   1954 ufsspec_read(void *v)
   1955 {
   1956 	struct vop_read_args /* {
   1957 		struct vnode	*a_vp;
   1958 		struct uio	*a_uio;
   1959 		int		a_ioflag;
   1960 		kauth_cred_t	a_cred;
   1961 	} */ *ap = v;
   1962 
   1963 	/*
   1964 	 * Set access flag.
   1965 	 */
   1966 	if ((ap->a_vp->v_mount->mnt_flag & MNT_NODEVMTIME) == 0)
   1967 		VTOI(ap->a_vp)->i_flag |= IN_ACCESS;
   1968 	return (VOCALL (spec_vnodeop_p, VOFFSET(vop_read), ap));
   1969 }
   1970 
   1971 /*
   1972  * Write wrapper for special devices.
   1973  */
   1974 int
   1975 ufsspec_write(void *v)
   1976 {
   1977 	struct vop_write_args /* {
   1978 		struct vnode	*a_vp;
   1979 		struct uio	*a_uio;
   1980 		int		a_ioflag;
   1981 		kauth_cred_t	a_cred;
   1982 	} */ *ap = v;
   1983 
   1984 	/*
   1985 	 * Set update and change flags.
   1986 	 */
   1987 	if ((ap->a_vp->v_mount->mnt_flag & MNT_NODEVMTIME) == 0)
   1988 		VTOI(ap->a_vp)->i_flag |= IN_MODIFY;
   1989 	return (VOCALL (spec_vnodeop_p, VOFFSET(vop_write), ap));
   1990 }
   1991 
   1992 /*
   1993  * Close wrapper for special devices.
   1994  *
   1995  * Update the times on the inode then do device close.
   1996  */
   1997 int
   1998 ufsspec_close(void *v)
   1999 {
   2000 	struct vop_close_args /* {
   2001 		struct vnode	*a_vp;
   2002 		int		a_fflag;
   2003 		kauth_cred_t	a_cred;
   2004 	} */ *ap = v;
   2005 	struct vnode	*vp;
   2006 
   2007 	vp = ap->a_vp;
   2008 	if (vrefcnt(vp) > 1)
   2009 		UFS_ITIMES(vp, NULL, NULL, NULL);
   2010 	return (VOCALL (spec_vnodeop_p, VOFFSET(vop_close), ap));
   2011 }
   2012 
   2013 /*
   2014  * Read wrapper for fifo's
   2015  */
   2016 int
   2017 ufsfifo_read(void *v)
   2018 {
   2019 	struct vop_read_args /* {
   2020 		struct vnode	*a_vp;
   2021 		struct uio	*a_uio;
   2022 		int		a_ioflag;
   2023 		kauth_cred_t	a_cred;
   2024 	} */ *ap = v;
   2025 
   2026 	/*
   2027 	 * Set access flag.
   2028 	 */
   2029 	VTOI(ap->a_vp)->i_flag |= IN_ACCESS;
   2030 	return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_read), ap));
   2031 }
   2032 
   2033 /*
   2034  * Write wrapper for fifo's.
   2035  */
   2036 int
   2037 ufsfifo_write(void *v)
   2038 {
   2039 	struct vop_write_args /* {
   2040 		struct vnode	*a_vp;
   2041 		struct uio	*a_uio;
   2042 		int		a_ioflag;
   2043 		kauth_cred_t	a_cred;
   2044 	} */ *ap = v;
   2045 
   2046 	/*
   2047 	 * Set update and change flags.
   2048 	 */
   2049 	VTOI(ap->a_vp)->i_flag |= IN_MODIFY;
   2050 	return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_write), ap));
   2051 }
   2052 
   2053 /*
   2054  * Close wrapper for fifo's.
   2055  *
   2056  * Update the times on the inode then do device close.
   2057  */
   2058 int
   2059 ufsfifo_close(void *v)
   2060 {
   2061 	struct vop_close_args /* {
   2062 		struct vnode	*a_vp;
   2063 		int		a_fflag;
   2064 		kauth_cred_t	a_cred;
   2065 	} */ *ap = v;
   2066 	struct vnode	*vp;
   2067 
   2068 	vp = ap->a_vp;
   2069 	if (vrefcnt(ap->a_vp) > 1)
   2070 		UFS_ITIMES(vp, NULL, NULL, NULL);
   2071 	return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_close), ap));
   2072 }
   2073 
   2074 /*
   2075  * Return POSIX pathconf information applicable to ufs filesystems.
   2076  */
   2077 int
   2078 ufs_pathconf(void *v)
   2079 {
   2080 	struct vop_pathconf_args /* {
   2081 		struct vnode	*a_vp;
   2082 		int		a_name;
   2083 		register_t	*a_retval;
   2084 	} */ *ap = v;
   2085 
   2086 	switch (ap->a_name) {
   2087 	case _PC_LINK_MAX:
   2088 		*ap->a_retval = LINK_MAX;
   2089 		return (0);
   2090 	case _PC_NAME_MAX:
   2091 		*ap->a_retval = FFS_MAXNAMLEN;
   2092 		return (0);
   2093 	case _PC_PATH_MAX:
   2094 		*ap->a_retval = PATH_MAX;
   2095 		return (0);
   2096 	case _PC_PIPE_BUF:
   2097 		*ap->a_retval = PIPE_BUF;
   2098 		return (0);
   2099 	case _PC_CHOWN_RESTRICTED:
   2100 		*ap->a_retval = 1;
   2101 		return (0);
   2102 	case _PC_NO_TRUNC:
   2103 		*ap->a_retval = 1;
   2104 		return (0);
   2105 #ifdef UFS_ACL
   2106 	case _PC_ACL_EXTENDED:
   2107 		if (ap->a_vp->v_mount->mnt_flag & MNT_POSIX1EACLS)
   2108 			*ap->a_retval = 1;
   2109 		else
   2110 			*ap->a_retval = 0;
   2111 		return 0;
   2112 	case _PC_ACL_NFS4:
   2113 		if (ap->a_vp->v_mount->mnt_flag & MNT_NFS4ACLS)
   2114 			*ap->a_retval = 1;
   2115 		else
   2116 			*ap->a_retval = 0;
   2117 		return 0;
   2118 #endif
   2119 	case _PC_ACL_PATH_MAX:
   2120 #ifdef UFS_ACL
   2121 		if (ap->a_vp->v_mount->mnt_flag & (MNT_POSIX1EACLS | MNT_NFS4ACLS))
   2122 			*ap->a_retval = ACL_MAX_ENTRIES;
   2123 		else
   2124 			*ap->a_retval = 3;
   2125 #else
   2126 		*ap->a_retval = 3;
   2127 #endif
   2128 		return 0;
   2129 	case _PC_SYNC_IO:
   2130 		*ap->a_retval = 1;
   2131 		return (0);
   2132 	case _PC_FILESIZEBITS:
   2133 		*ap->a_retval = 42;
   2134 		return (0);
   2135 	case _PC_SYMLINK_MAX:
   2136 		*ap->a_retval = MAXPATHLEN;
   2137 		return (0);
   2138 	case _PC_2_SYMLINKS:
   2139 		*ap->a_retval = 1;
   2140 		return (0);
   2141 	default:
   2142 		return (EINVAL);
   2143 	}
   2144 	/* NOTREACHED */
   2145 }
   2146 
   2147 /*
   2148  * Advisory record locking support
   2149  */
   2150 int
   2151 ufs_advlock(void *v)
   2152 {
   2153 	struct vop_advlock_args /* {
   2154 		struct vnode	*a_vp;
   2155 		void *		a_id;
   2156 		int		a_op;
   2157 		struct flock	*a_fl;
   2158 		int		a_flags;
   2159 	} */ *ap = v;
   2160 	struct inode *ip;
   2161 
   2162 	ip = VTOI(ap->a_vp);
   2163 	return lf_advlock(ap, &ip->i_lockf, ip->i_size);
   2164 }
   2165 
   2166 /*
   2167  * Initialize the vnode associated with a new inode, handle aliased
   2168  * vnodes.
   2169  */
   2170 void
   2171 ufs_vinit(struct mount *mntp, int (**specops)(void *), int (**fifoops)(void *),
   2172 	struct vnode **vpp)
   2173 {
   2174 	struct timeval	tv;
   2175 	struct inode	*ip;
   2176 	struct vnode	*vp;
   2177 	dev_t		rdev;
   2178 	struct ufsmount	*ump;
   2179 
   2180 	vp = *vpp;
   2181 	ip = VTOI(vp);
   2182 	switch(vp->v_type = IFTOVT(ip->i_mode)) {
   2183 	case VCHR:
   2184 	case VBLK:
   2185 		vp->v_op = specops;
   2186 		ump = ip->i_ump;
   2187 		if (ump->um_fstype == UFS1)
   2188 			rdev = (dev_t)ufs_rw32(ip->i_ffs1_rdev,
   2189 			    UFS_MPNEEDSWAP(ump));
   2190 		else
   2191 			rdev = (dev_t)ufs_rw64(ip->i_ffs2_rdev,
   2192 			    UFS_MPNEEDSWAP(ump));
   2193 		spec_node_init(vp, rdev);
   2194 		break;
   2195 	case VFIFO:
   2196 		vp->v_op = fifoops;
   2197 		break;
   2198 	case VNON:
   2199 	case VBAD:
   2200 	case VSOCK:
   2201 	case VLNK:
   2202 	case VDIR:
   2203 	case VREG:
   2204 		break;
   2205 	}
   2206 	if (ip->i_number == UFS_ROOTINO)
   2207                 vp->v_vflag |= VV_ROOT;
   2208 	/*
   2209 	 * Initialize modrev times
   2210 	 */
   2211 	getmicrouptime(&tv);
   2212 	ip->i_modrev = (uint64_t)(uint)tv.tv_sec << 32
   2213 			| tv.tv_usec * 4294u;
   2214 	*vpp = vp;
   2215 }
   2216 
   2217 /*
   2218  * Allocate a new inode.
   2219  */
   2220 static int
   2221 ufs_makeinode(struct vattr *vap, struct vnode *dvp,
   2222 	const struct ufs_lookup_results *ulr,
   2223 	struct vnode **vpp, struct componentname *cnp)
   2224 {
   2225 	struct inode	*ip;
   2226 	struct direct	*newdir;
   2227 	struct vnode	*tvp;
   2228 	int		error;
   2229 
   2230 	UFS_WAPBL_JUNLOCK_ASSERT(dvp->v_mount);
   2231 
   2232 	error = vcache_new(dvp->v_mount, dvp, vap, cnp->cn_cred, NULL, &tvp);
   2233 	if (error)
   2234 		return error;
   2235 	error = vn_lock(tvp, LK_EXCLUSIVE);
   2236 	if (error) {
   2237 		vrele(tvp);
   2238 		return error;
   2239 	}
   2240 	*vpp = tvp;
   2241 	ip = VTOI(tvp);
   2242 	error = UFS_WAPBL_BEGIN(dvp->v_mount);
   2243 	if (error) {
   2244 		vput(tvp);
   2245 		return (error);
   2246 	}
   2247 	ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
   2248 	ip->i_nlink = 1;
   2249 	DIP_ASSIGN(ip, nlink, 1);
   2250 
   2251 	/* Authorize setting SGID if needed. */
   2252 	if (ip->i_mode & ISGID) {
   2253 		error = kauth_authorize_vnode(cnp->cn_cred,
   2254 		    KAUTH_VNODE_WRITE_SECURITY,
   2255 		    tvp, NULL, genfs_can_chmod(tvp, cnp->cn_cred, ip->i_uid,
   2256 		    ip->i_gid, MAKEIMODE(vap->va_type, vap->va_mode)));
   2257 		if (error) {
   2258 			ip->i_mode &= ~ISGID;
   2259 			DIP_ASSIGN(ip, mode, ip->i_mode);
   2260 		}
   2261 	}
   2262 
   2263 	if (cnp->cn_flags & ISWHITEOUT) {
   2264 		ip->i_flags |= UF_OPAQUE;
   2265 		DIP_ASSIGN(ip, flags, ip->i_flags);
   2266 	}
   2267 
   2268 	/*
   2269 	 * Make sure inode goes to disk before directory entry.
   2270 	 */
   2271 	if ((error = UFS_UPDATE(tvp, NULL, NULL, UPDATE_DIROP)) != 0)
   2272 		goto bad;
   2273 #ifdef UFS_ACL
   2274 	struct lwp *l = curlwp;
   2275 	if (dvp->v_mount->mnt_flag & MNT_POSIX1EACLS) {
   2276 		error = ufs_do_posix1e_acl_inheritance_file(dvp, tvp,
   2277 		    ip->i_mode, cnp->cn_cred, l);
   2278 		if (error)
   2279 			goto bad;
   2280 	} else if (dvp->v_mount->mnt_flag & MNT_NFS4ACLS) {
   2281 		error = ufs_do_nfs4_acl_inheritance(dvp, tvp, ip->i_mode,
   2282 		    cnp->cn_cred, l);
   2283 		if (error)
   2284 			goto bad;
   2285 	}
   2286 #endif /* !UFS_ACL */
   2287 	newdir = pool_cache_get(ufs_direct_cache, PR_WAITOK);
   2288 	ufs_makedirentry(ip, cnp, newdir);
   2289 	error = ufs_direnter(dvp, ulr, tvp, newdir, cnp, NULL);
   2290 	pool_cache_put(ufs_direct_cache, newdir);
   2291 	if (error)
   2292 		goto bad;
   2293 	*vpp = tvp;
   2294 	cache_enter(dvp, *vpp, cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_flags);
   2295 	return (0);
   2296 
   2297  bad:
   2298 	/*
   2299 	 * Write error occurred trying to update the inode
   2300 	 * or the directory so must deallocate the inode.
   2301 	 */
   2302 	ip->i_nlink = 0;
   2303 	DIP_ASSIGN(ip, nlink, 0);
   2304 	ip->i_flag |= IN_CHANGE;
   2305 	UFS_WAPBL_UPDATE(tvp, NULL, NULL, 0);
   2306 	UFS_WAPBL_END(dvp->v_mount);
   2307 	vput(tvp);
   2308 	return (error);
   2309 }
   2310 
   2311 /*
   2312  * Allocate len bytes at offset off.
   2313  */
   2314 int
   2315 ufs_gop_alloc(struct vnode *vp, off_t off, off_t len, int flags,
   2316     kauth_cred_t cred)
   2317 {
   2318         struct inode *ip = VTOI(vp);
   2319         int error, delta, bshift, bsize;
   2320         UVMHIST_FUNC("ufs_gop_alloc"); UVMHIST_CALLED(ubchist);
   2321 
   2322         error = 0;
   2323         bshift = vp->v_mount->mnt_fs_bshift;
   2324         bsize = 1 << bshift;
   2325 
   2326         delta = off & (bsize - 1);
   2327         off -= delta;
   2328         len += delta;
   2329 
   2330         while (len > 0) {
   2331                 bsize = MIN(bsize, len);
   2332 
   2333                 error = UFS_BALLOC(vp, off, bsize, cred, flags, NULL);
   2334                 if (error) {
   2335                         goto out;
   2336                 }
   2337 
   2338                 /*
   2339                  * increase file size now, UFS_BALLOC() requires that
   2340                  * EOF be up-to-date before each call.
   2341                  */
   2342 
   2343                 if (ip->i_size < off + bsize) {
   2344                         UVMHIST_LOG(ubchist, "vp %#jx old 0x%jx new 0x%x",
   2345                             (uintptr_t)vp, ip->i_size, off + bsize, 0);
   2346                         ip->i_size = off + bsize;
   2347 			DIP_ASSIGN(ip, size, ip->i_size);
   2348                 }
   2349 
   2350                 off += bsize;
   2351                 len -= bsize;
   2352         }
   2353 
   2354 out:
   2355 	UFS_WAPBL_UPDATE(vp, NULL, NULL, 0);
   2356 	return error;
   2357 }
   2358 
   2359 void
   2360 ufs_gop_markupdate(struct vnode *vp, int flags)
   2361 {
   2362 	u_int32_t mask = 0;
   2363 
   2364 	if ((flags & GOP_UPDATE_ACCESSED) != 0) {
   2365 		mask = IN_ACCESS;
   2366 	}
   2367 	if ((flags & GOP_UPDATE_MODIFIED) != 0) {
   2368 		if (vp->v_type == VREG) {
   2369 			mask |= IN_CHANGE | IN_UPDATE;
   2370 		} else {
   2371 			mask |= IN_MODIFY;
   2372 		}
   2373 	}
   2374 	if (mask) {
   2375 		struct inode *ip = VTOI(vp);
   2376 
   2377 		ip->i_flag |= mask;
   2378 	}
   2379 }
   2380 
   2381 int
   2382 ufs_bufio(enum uio_rw rw, struct vnode *vp, void *buf, size_t len, off_t off,
   2383     int ioflg, kauth_cred_t cred, size_t *aresid, struct lwp *l)
   2384 {
   2385 	struct iovec iov;
   2386 	struct uio uio;
   2387 	int error;
   2388 
   2389 	KASSERT(ISSET(ioflg, IO_NODELOCKED));
   2390 	KASSERT(VOP_ISLOCKED(vp));
   2391 	KASSERT(rw != UIO_WRITE || VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
   2392 	KASSERT(rw != UIO_WRITE || vp->v_mount->mnt_wapbl == NULL ||
   2393 	    ISSET(ioflg, IO_JOURNALLOCKED));
   2394 
   2395 	iov.iov_base = buf;
   2396 	iov.iov_len = len;
   2397 	uio.uio_iov = &iov;
   2398 	uio.uio_iovcnt = 1;
   2399 	uio.uio_resid = len;
   2400 	uio.uio_offset = off;
   2401 	uio.uio_rw = rw;
   2402 	UIO_SETUP_SYSSPACE(&uio);
   2403 
   2404 	switch (rw) {
   2405 	case UIO_READ:
   2406 		error = UFS_BUFRD(vp, &uio, ioflg, cred);
   2407 		break;
   2408 	case UIO_WRITE:
   2409 		error = UFS_BUFWR(vp, &uio, ioflg, cred);
   2410 		break;
   2411 	default:
   2412 		panic("invalid uio rw: %d", (int)rw);
   2413 	}
   2414 
   2415 	if (aresid)
   2416 		*aresid = uio.uio_resid;
   2417 	else if (uio.uio_resid && error == 0)
   2418 		error = EIO;
   2419 
   2420 	KASSERT(VOP_ISLOCKED(vp));
   2421 	KASSERT(rw != UIO_WRITE || VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
   2422 	return error;
   2423 }
   2424