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