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