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
ufs_create(void * v)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
ufs_mknod(void * v)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
ufs_open(void * v)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
ufs_close(void * v)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
ufs_check_possible(struct vnode * vp,struct inode * ip,accmode_t accmode,kauth_cred_t cred)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
ufs_check_permitted(struct vnode * vp,struct inode * ip,struct acl * acl,accmode_t accmode,kauth_cred_t cred,int (* func)(struct vnode *,kauth_cred_t,uid_t,gid_t,mode_t,struct acl *,accmode_t))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
ufs_accessx(void * v)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
ufs_getattr(void * v)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
ufs_setattr(void * v)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
ufs_update_nfs4_acl_after_mode_change(struct vnode * vp,int mode,int file_owner_id,kauth_cred_t cred,struct lwp * l)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
ufs_chmod(struct vnode * vp,int mode,kauth_cred_t cred,struct lwp * l)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
ufs_chown(struct vnode * vp,uid_t uid,gid_t gid,kauth_cred_t cred,struct lwp * l)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
ufs_remove(void * v)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
ufs_link(void * v)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
ufs_whiteout(void * v)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
ufs_do_posix1e_acl_inheritance_dir(struct vnode * dvp,struct vnode * tvp,mode_t dmode,kauth_cred_t cred,struct lwp * l)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
ufs_do_posix1e_acl_inheritance_file(struct vnode * dvp,struct vnode * tvp,mode_t mode,kauth_cred_t cred,struct lwp * l)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
ufs_do_nfs4_acl_inheritance(struct vnode * dvp,struct vnode * tvp,mode_t child_mode,kauth_cred_t cred,struct lwp * l)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
ufs_mkdir(void * v)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
ufs_rmdir(void * v)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
ufs_symlink(void * v)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
ufs_readdir(void * v)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
ufs_readlink(void * v)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
ufs_strategy(void * v)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
ufs_print(void * v)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
ufsspec_read(void * v)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
ufsspec_write(void * v)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
ufsspec_close(void * v)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
ufsfifo_read(void * v)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
ufsfifo_write(void * v)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
ufsfifo_close(void * v)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
ufs_pathconf(void * v)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
ufs_advlock(void * v)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
ufs_vinit(struct mount * mntp,int (** specops)(void *),int (** fifoops)(void *),struct vnode ** vpp)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
ufs_makeinode(struct vattr * vap,struct vnode * dvp,const struct ufs_lookup_results * ulr,struct vnode ** vpp,struct componentname * cnp)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
ufs_gop_alloc(struct vnode * vp,off_t off,off_t len,int flags,kauth_cred_t cred)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
ufs_gop_markupdate(struct vnode * vp,int flags)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
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)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