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