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