ufs_vnops.c revision 76132
1/* 2 * Copyright (c) 1982, 1986, 1989, 1993, 1995 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, 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 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)ufs_vnops.c 8.27 (Berkeley) 5/27/95 39 * $FreeBSD: head/sys/ufs/ufs/ufs_vnops.c 76132 2001-04-29 12:36:52Z phk $ 40 */ 41 42#include "opt_quota.h" 43#include "opt_suiddir.h" 44#include "opt_ufs.h" 45 46#include <sys/param.h> 47#include <sys/systm.h> 48#include <sys/namei.h> 49#include <sys/kernel.h> 50#include <sys/fcntl.h> 51#include <sys/stat.h> 52#include <sys/bio.h> 53#include <sys/buf.h> 54#include <sys/mount.h> 55#include <sys/unistd.h> 56#include <sys/malloc.h> 57#include <sys/vnode.h> 58#include <sys/dirent.h> 59#include <sys/lockf.h> 60#include <sys/event.h> 61#include <sys/conf.h> 62#include <sys/acl.h> 63 64#include <machine/mutex.h> 65 66#include <sys/file.h> /* XXX */ 67 68#include <vm/vm.h> 69#include <vm/vm_extern.h> 70 71#include <miscfs/fifofs/fifo.h> 72 73#include <ufs/ufs/acl.h> 74#include <ufs/ufs/extattr.h> 75#include <ufs/ufs/quota.h> 76#include <ufs/ufs/inode.h> 77#include <ufs/ufs/dir.h> 78#include <ufs/ufs/ufsmount.h> 79#include <ufs/ufs/ufs_extern.h> 80 81static int ufs_access __P((struct vop_access_args *)); 82static int ufs_advlock __P((struct vop_advlock_args *)); 83static int ufs_chmod __P((struct vnode *, int, struct ucred *, struct proc *)); 84static int ufs_chown __P((struct vnode *, uid_t, gid_t, struct ucred *, struct proc *)); 85static int ufs_close __P((struct vop_close_args *)); 86static int ufs_create __P((struct vop_create_args *)); 87static int ufs_getattr __P((struct vop_getattr_args *)); 88static int ufs_link __P((struct vop_link_args *)); 89static int ufs_makeinode __P((int mode, struct vnode *, struct vnode **, struct componentname *)); 90static int ufs_missingop __P((struct vop_generic_args *ap)); 91static int ufs_mkdir __P((struct vop_mkdir_args *)); 92static int ufs_mknod __P((struct vop_mknod_args *)); 93static int ufs_open __P((struct vop_open_args *)); 94static int ufs_pathconf __P((struct vop_pathconf_args *)); 95static int ufs_print __P((struct vop_print_args *)); 96static int ufs_readlink __P((struct vop_readlink_args *)); 97static int ufs_remove __P((struct vop_remove_args *)); 98static int ufs_rename __P((struct vop_rename_args *)); 99static int ufs_rmdir __P((struct vop_rmdir_args *)); 100static int ufs_setattr __P((struct vop_setattr_args *)); 101static int ufs_strategy __P((struct vop_strategy_args *)); 102static int ufs_symlink __P((struct vop_symlink_args *)); 103static int ufs_whiteout __P((struct vop_whiteout_args *)); 104static int ufsfifo_close __P((struct vop_close_args *)); 105static int ufsfifo_read __P((struct vop_read_args *)); 106static int ufsfifo_write __P((struct vop_write_args *)); 107static int ufsspec_close __P((struct vop_close_args *)); 108static int ufsspec_read __P((struct vop_read_args *)); 109static int ufsspec_write __P((struct vop_write_args *)); 110static int filt_ufsread __P((struct knote *kn, long hint)); 111static int filt_ufsvnode __P((struct knote *kn, long hint)); 112static void filt_ufsdetach __P((struct knote *kn)); 113static int ufs_kqfilter __P((struct vop_kqfilter_args *ap)); 114 115union _qcvt { 116 int64_t qcvt; 117 int32_t val[2]; 118}; 119#define SETHIGH(q, h) { \ 120 union _qcvt tmp; \ 121 tmp.qcvt = (q); \ 122 tmp.val[_QUAD_HIGHWORD] = (h); \ 123 (q) = tmp.qcvt; \ 124} 125#define SETLOW(q, l) { \ 126 union _qcvt tmp; \ 127 tmp.qcvt = (q); \ 128 tmp.val[_QUAD_LOWWORD] = (l); \ 129 (q) = tmp.qcvt; \ 130} 131#define VN_KNOTE(vp, b) \ 132 KNOTE(&vp->v_pollinfo.vpi_selinfo.si_note, (b)) 133 134/* 135 * A virgin directory (no blushing please). 136 */ 137static struct dirtemplate mastertemplate = { 138 0, 12, DT_DIR, 1, ".", 139 0, DIRBLKSIZ - 12, DT_DIR, 2, ".." 140}; 141static struct odirtemplate omastertemplate = { 142 0, 12, 1, ".", 143 0, DIRBLKSIZ - 12, 2, ".." 144}; 145 146void 147ufs_itimes(vp) 148 struct vnode *vp; 149{ 150 struct inode *ip; 151 struct timespec ts; 152 153 ip = VTOI(vp); 154 if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE)) == 0) 155 return; 156 if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 157 vfs_timestamp(&ts); 158 if ((vp->v_type == VBLK || vp->v_type == VCHR) && 159 !DOINGSOFTDEP(vp)) 160 ip->i_flag |= IN_LAZYMOD; 161 else 162 ip->i_flag |= IN_MODIFIED; 163 if (ip->i_flag & IN_ACCESS) { 164 ip->i_atime = ts.tv_sec; 165 ip->i_atimensec = ts.tv_nsec; 166 } 167 if (ip->i_flag & IN_UPDATE) { 168 ip->i_mtime = ts.tv_sec; 169 ip->i_mtimensec = ts.tv_nsec; 170 ip->i_modrev++; 171 } 172 if (ip->i_flag & IN_CHANGE) { 173 ip->i_ctime = ts.tv_sec; 174 ip->i_ctimensec = ts.tv_nsec; 175 } 176 } 177 ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE); 178} 179 180/* 181 * Create a regular file 182 */ 183int 184ufs_create(ap) 185 struct vop_create_args /* { 186 struct vnode *a_dvp; 187 struct vnode **a_vpp; 188 struct componentname *a_cnp; 189 struct vattr *a_vap; 190 } */ *ap; 191{ 192 int error; 193 194 error = 195 ufs_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode), 196 ap->a_dvp, ap->a_vpp, ap->a_cnp); 197 if (error) 198 return (error); 199 VN_KNOTE(ap->a_dvp, NOTE_WRITE); 200 return (0); 201} 202 203/* 204 * Mknod vnode call 205 */ 206/* ARGSUSED */ 207int 208ufs_mknod(ap) 209 struct vop_mknod_args /* { 210 struct vnode *a_dvp; 211 struct vnode **a_vpp; 212 struct componentname *a_cnp; 213 struct vattr *a_vap; 214 } */ *ap; 215{ 216 struct vattr *vap = ap->a_vap; 217 struct vnode **vpp = ap->a_vpp; 218 struct inode *ip; 219 ino_t ino; 220 int error; 221 222 error = ufs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode), 223 ap->a_dvp, vpp, ap->a_cnp); 224 if (error) 225 return (error); 226 VN_KNOTE(ap->a_dvp, NOTE_WRITE); 227 ip = VTOI(*vpp); 228 ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE; 229 if (vap->va_rdev != VNOVAL) { 230 /* 231 * Want to be able to use this to make badblock 232 * inodes, so don't truncate the dev number. 233 */ 234 ip->i_rdev = vap->va_rdev; 235 } 236 /* 237 * Remove inode, then reload it through VFS_VGET so it is 238 * checked to see if it is an alias of an existing entry in 239 * the inode cache. 240 */ 241 vput(*vpp); 242 (*vpp)->v_type = VNON; 243 ino = ip->i_number; /* Save this before vgone() invalidates ip. */ 244 vgone(*vpp); 245 error = VFS_VGET(ap->a_dvp->v_mount, ino, vpp); 246 if (error) { 247 *vpp = NULL; 248 return (error); 249 } 250 return (0); 251} 252 253/* 254 * Open called. 255 * 256 * Nothing to do. 257 */ 258/* ARGSUSED */ 259int 260ufs_open(ap) 261 struct vop_open_args /* { 262 struct vnode *a_vp; 263 int a_mode; 264 struct ucred *a_cred; 265 struct proc *a_p; 266 } */ *ap; 267{ 268 269 /* 270 * Files marked append-only must be opened for appending. 271 */ 272 if ((VTOI(ap->a_vp)->i_flags & APPEND) && 273 (ap->a_mode & (FWRITE | O_APPEND)) == FWRITE) 274 return (EPERM); 275 return (0); 276} 277 278/* 279 * Close called. 280 * 281 * Update the times on the inode. 282 */ 283/* ARGSUSED */ 284int 285ufs_close(ap) 286 struct vop_close_args /* { 287 struct vnode *a_vp; 288 int a_fflag; 289 struct ucred *a_cred; 290 struct proc *a_p; 291 } */ *ap; 292{ 293 struct vnode *vp = ap->a_vp; 294 struct mount *mp; 295 296 mtx_lock(&vp->v_interlock); 297 if (vp->v_usecount > 1) { 298 ufs_itimes(vp); 299 mtx_unlock(&vp->v_interlock); 300 } else { 301 mtx_unlock(&vp->v_interlock); 302 /* 303 * If we are closing the last reference to an unlinked 304 * file, then it will be freed by the inactive routine. 305 * Because the freeing causes a the filesystem to be 306 * modified, it must be held up during periods when the 307 * filesystem is suspended. 308 * 309 * XXX - EAGAIN is returned to prevent vn_close from 310 * repeating the vrele operation. 311 */ 312 if (vp->v_type == VREG && VTOI(vp)->i_effnlink == 0) { 313 (void) vn_start_write(vp, &mp, V_WAIT); 314 vrele(vp); 315 vn_finished_write(mp); 316 return (EAGAIN); 317 } 318 } 319 return (0); 320} 321 322int 323ufs_access(ap) 324 struct vop_access_args /* { 325 struct vnode *a_vp; 326 int a_mode; 327 struct ucred *a_cred; 328 struct proc *a_p; 329 } */ *ap; 330{ 331 struct vnode *vp = ap->a_vp; 332 struct inode *ip = VTOI(vp); 333 mode_t mode = ap->a_mode; 334 int error; 335#ifdef UFS_ACL 336 struct acl *acl; 337 int len; 338#endif 339 340 /* 341 * Disallow write attempts on read-only file systems; 342 * unless the file is a socket, fifo, or a block or 343 * character device resident on the file system. 344 */ 345 if (mode & VWRITE) { 346 switch (vp->v_type) { 347 case VDIR: 348 case VLNK: 349 case VREG: 350 if (vp->v_mount->mnt_flag & MNT_RDONLY) 351 return (EROFS); 352#ifdef QUOTA 353 if ((error = getinoquota(ip)) != 0) 354 return (error); 355#endif 356 break; 357 default: 358 break; 359 } 360 } 361 362 /* If immutable bit set, nobody gets to write it. */ 363 if ((mode & VWRITE) && (ip->i_flags & (IMMUTABLE | SF_SNAPSHOT))) 364 return (EPERM); 365 366#ifdef UFS_ACL 367 MALLOC(acl, struct acl *, sizeof(*acl), M_ACL, M_WAITOK); 368 len = sizeof(*acl); 369 error = VOP_GETACL(vp, ACL_TYPE_ACCESS, acl, ap->a_cred, ap->a_p); 370 switch (error) { 371 case EOPNOTSUPP: 372 error = vaccess(vp->v_type, ip->i_mode, ip->i_uid, ip->i_gid, 373 ap->a_mode, ap->a_cred, NULL); 374 break; 375 case 0: 376 error = vaccess_acl_posix1e(vp->v_type, ip->i_uid, ip->i_gid, 377 acl, ap->a_mode, ap->a_cred, NULL); 378 break; 379 default: 380 printf("ufs_access(): Error retrieving ACL on object (%d).\n", 381 error); 382 /* 383 * XXX: Fall back until debugged. Should eventually 384 * possibly log an error, and return EPERM for safety. 385 */ 386 error = vaccess(vp->v_type, ip->i_mode, ip->i_uid, ip->i_gid, 387 ap->a_mode, ap->a_cred, NULL); 388 } 389 FREE(acl, M_ACL); 390#else 391 error = vaccess(vp->v_type, ip->i_mode, ip->i_uid, ip->i_gid, 392 ap->a_mode, ap->a_cred, NULL); 393#endif 394 return (error); 395} 396 397/* ARGSUSED */ 398int 399ufs_getattr(ap) 400 struct vop_getattr_args /* { 401 struct vnode *a_vp; 402 struct vattr *a_vap; 403 struct ucred *a_cred; 404 struct proc *a_p; 405 } */ *ap; 406{ 407 register struct vnode *vp = ap->a_vp; 408 register struct inode *ip = VTOI(vp); 409 register struct vattr *vap = ap->a_vap; 410 411 ufs_itimes(vp); 412 /* 413 * Copy from inode table 414 */ 415 vap->va_fsid = dev2udev(ip->i_dev); 416 vap->va_fileid = ip->i_number; 417 vap->va_mode = ip->i_mode & ~IFMT; 418 vap->va_nlink = VFSTOUFS(vp->v_mount)->um_i_effnlink_valid ? 419 ip->i_effnlink : ip->i_nlink; 420 vap->va_uid = ip->i_uid; 421 vap->va_gid = ip->i_gid; 422 vap->va_rdev = ip->i_rdev; 423 vap->va_size = ip->i_din.di_size; 424 vap->va_atime.tv_sec = ip->i_atime; 425 vap->va_atime.tv_nsec = ip->i_atimensec; 426 vap->va_mtime.tv_sec = ip->i_mtime; 427 vap->va_mtime.tv_nsec = ip->i_mtimensec; 428 vap->va_ctime.tv_sec = ip->i_ctime; 429 vap->va_ctime.tv_nsec = ip->i_ctimensec; 430 vap->va_flags = ip->i_flags; 431 vap->va_gen = ip->i_gen; 432 vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize; 433 vap->va_bytes = dbtob((u_quad_t)ip->i_blocks); 434 vap->va_type = IFTOVT(ip->i_mode); 435 vap->va_filerev = ip->i_modrev; 436 return (0); 437} 438 439/* 440 * Set attribute vnode op. called from several syscalls 441 */ 442int 443ufs_setattr(ap) 444 struct vop_setattr_args /* { 445 struct vnode *a_vp; 446 struct vattr *a_vap; 447 struct ucred *a_cred; 448 struct proc *a_p; 449 } */ *ap; 450{ 451 struct vattr *vap = ap->a_vap; 452 struct vnode *vp = ap->a_vp; 453 struct inode *ip = VTOI(vp); 454 struct ucred *cred = ap->a_cred; 455 struct proc *p = ap->a_p; 456 int error; 457 458 /* 459 * Check for unsettable attributes. 460 */ 461 if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) || 462 (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) || 463 (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) || 464 ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) { 465 return (EINVAL); 466 } 467 if (vap->va_flags != VNOVAL) { 468 if (vp->v_mount->mnt_flag & MNT_RDONLY) 469 return (EROFS); 470 /* 471 * Callers may only modify the file flags on objects they 472 * have VADMIN rights for. 473 */ 474 if ((error = VOP_ACCESS(vp, VADMIN, cred, p))) 475 return (error); 476 /* 477 * Unprivileged processes and privileged processes in 478 * jail() are not permitted to set system flags. 479 * Privileged processes not in jail() may only set system 480 * flags if the securelevel <= 0. 481 */ 482 if (!suser_xxx(cred, NULL, 0)) { 483 if ((ip->i_flags 484 & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) && 485 securelevel > 0) 486 return (EPERM); 487 /* Snapshot flag cannot be set or cleared */ 488 if (((vap->va_flags & SF_SNAPSHOT) != 0 && 489 (ip->i_flags & SF_SNAPSHOT) == 0) || 490 ((vap->va_flags & SF_SNAPSHOT) == 0 && 491 (ip->i_flags & SF_SNAPSHOT) != 0)) 492 return (EPERM); 493 ip->i_flags = vap->va_flags; 494 } else { 495 if (ip->i_flags 496 & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND) || 497 (vap->va_flags & UF_SETTABLE) != vap->va_flags) 498 return (EPERM); 499 ip->i_flags &= SF_SETTABLE; 500 ip->i_flags |= (vap->va_flags & UF_SETTABLE); 501 } 502 ip->i_flag |= IN_CHANGE; 503 if (vap->va_flags & (IMMUTABLE | APPEND)) 504 return (0); 505 } 506 if (ip->i_flags & (IMMUTABLE | APPEND)) 507 return (EPERM); 508 /* 509 * Go through the fields and update iff not VNOVAL. 510 */ 511 if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) { 512 if (vp->v_mount->mnt_flag & MNT_RDONLY) 513 return (EROFS); 514 if ((error = ufs_chown(vp, vap->va_uid, vap->va_gid, cred, 515 p)) != 0) 516 return (error); 517 } 518 if (vap->va_size != VNOVAL) { 519 /* 520 * Disallow write attempts on read-only file systems; 521 * unless the file is a socket, fifo, or a block or 522 * character device resident on the file system. 523 */ 524 switch (vp->v_type) { 525 case VDIR: 526 return (EISDIR); 527 case VLNK: 528 case VREG: 529 if (vp->v_mount->mnt_flag & MNT_RDONLY) 530 return (EROFS); 531 if ((ip->i_flags & SF_SNAPSHOT) != 0) 532 return (EPERM); 533 break; 534 default: 535 break; 536 } 537 if ((error = UFS_TRUNCATE(vp, vap->va_size, 0, cred, p)) != 0) 538 return (error); 539 } 540 if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) { 541 if (vp->v_mount->mnt_flag & MNT_RDONLY) 542 return (EROFS); 543 if ((ip->i_flags & SF_SNAPSHOT) != 0) 544 return (EPERM); 545 /* 546 * From utimes(2): 547 * If times is NULL, ... The caller must be the owner of 548 * the file, have permission to write the file, or be the 549 * super-user. 550 * If times is non-NULL, ... The caller must be the owner of 551 * the file or be the super-user. 552 */ 553 if ((error = VOP_ACCESS(vp, VADMIN, cred, p)) && 554 ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || 555 (error = VOP_ACCESS(vp, VWRITE, cred, p)))) 556 return (error); 557 if (vap->va_atime.tv_sec != VNOVAL) 558 ip->i_flag |= IN_ACCESS; 559 if (vap->va_mtime.tv_sec != VNOVAL) 560 ip->i_flag |= IN_CHANGE | IN_UPDATE; 561 ufs_itimes(vp); 562 if (vap->va_atime.tv_sec != VNOVAL) { 563 ip->i_atime = vap->va_atime.tv_sec; 564 ip->i_atimensec = vap->va_atime.tv_nsec; 565 } 566 if (vap->va_mtime.tv_sec != VNOVAL) { 567 ip->i_mtime = vap->va_mtime.tv_sec; 568 ip->i_mtimensec = vap->va_mtime.tv_nsec; 569 } 570 error = UFS_UPDATE(vp, 0); 571 if (error) 572 return (error); 573 } 574 error = 0; 575 if (vap->va_mode != (mode_t)VNOVAL) { 576 if (vp->v_mount->mnt_flag & MNT_RDONLY) 577 return (EROFS); 578 if ((ip->i_flags & SF_SNAPSHOT) != 0 && (vap->va_mode & 579 (S_IXUSR | S_IWUSR | S_IXGRP | S_IWGRP | S_IXOTH | S_IWOTH))) 580 return (EPERM); 581 error = ufs_chmod(vp, (int)vap->va_mode, cred, p); 582 } 583 VN_KNOTE(vp, NOTE_ATTRIB); 584 return (error); 585} 586 587/* 588 * Change the mode on a file. 589 * Inode must be locked before calling. 590 */ 591static int 592ufs_chmod(vp, mode, cred, p) 593 register struct vnode *vp; 594 register int mode; 595 register struct ucred *cred; 596 struct proc *p; 597{ 598 register struct inode *ip = VTOI(vp); 599 int error; 600 601 /* 602 * To modify the permissions on a file, must possess VADMIN 603 * for that file. 604 */ 605 if ((error = VOP_ACCESS(vp, VADMIN, cred, p))) 606 return (error); 607 /* 608 * Privileged processes may set the sticky bit on non-directories, 609 * as well as set the setgid bit on a file with a group that the 610 * process is not a member of. 611 */ 612 if (suser_xxx(cred, NULL, PRISON_ROOT)) { 613 if (vp->v_type != VDIR && (mode & S_ISTXT)) 614 return (EFTYPE); 615 if (!groupmember(ip->i_gid, cred) && (mode & ISGID)) 616 return (EPERM); 617 } 618 ip->i_mode &= ~ALLPERMS; 619 ip->i_mode |= (mode & ALLPERMS); 620 ip->i_flag |= IN_CHANGE; 621 return (0); 622} 623 624/* 625 * Perform chown operation on inode ip; 626 * inode must be locked prior to call. 627 */ 628static int 629ufs_chown(vp, uid, gid, cred, p) 630 register struct vnode *vp; 631 uid_t uid; 632 gid_t gid; 633 struct ucred *cred; 634 struct proc *p; 635{ 636 register struct inode *ip = VTOI(vp); 637 uid_t ouid; 638 gid_t ogid; 639 int error = 0; 640#ifdef QUOTA 641 register int i; 642 long change; 643#endif 644 645 if (uid == (uid_t)VNOVAL) 646 uid = ip->i_uid; 647 if (gid == (gid_t)VNOVAL) 648 gid = ip->i_gid; 649 /* 650 * To modify the ownership of a file, must possess VADMIN 651 * for that file. 652 */ 653 if ((error = VOP_ACCESS(vp, VADMIN, cred, p))) 654 return (error); 655 /* 656 * To change the owner of a file, or change the group of a file 657 * to a group of which we are not a member, the caller must 658 * have privilege. 659 */ 660 if ((uid != ip->i_uid || 661 (gid != ip->i_gid && !groupmember(gid, cred))) && 662 (error = suser_xxx(cred, p, PRISON_ROOT))) 663 return (error); 664 ogid = ip->i_gid; 665 ouid = ip->i_uid; 666#ifdef QUOTA 667 if ((error = getinoquota(ip)) != 0) 668 return (error); 669 if (ouid == uid) { 670 dqrele(vp, ip->i_dquot[USRQUOTA]); 671 ip->i_dquot[USRQUOTA] = NODQUOT; 672 } 673 if (ogid == gid) { 674 dqrele(vp, ip->i_dquot[GRPQUOTA]); 675 ip->i_dquot[GRPQUOTA] = NODQUOT; 676 } 677 change = ip->i_blocks; 678 (void) chkdq(ip, -change, cred, CHOWN); 679 (void) chkiq(ip, -1, cred, CHOWN); 680 for (i = 0; i < MAXQUOTAS; i++) { 681 dqrele(vp, ip->i_dquot[i]); 682 ip->i_dquot[i] = NODQUOT; 683 } 684#endif 685 ip->i_gid = gid; 686 ip->i_uid = uid; 687#ifdef QUOTA 688 if ((error = getinoquota(ip)) == 0) { 689 if (ouid == uid) { 690 dqrele(vp, ip->i_dquot[USRQUOTA]); 691 ip->i_dquot[USRQUOTA] = NODQUOT; 692 } 693 if (ogid == gid) { 694 dqrele(vp, ip->i_dquot[GRPQUOTA]); 695 ip->i_dquot[GRPQUOTA] = NODQUOT; 696 } 697 if ((error = chkdq(ip, change, cred, CHOWN)) == 0) { 698 if ((error = chkiq(ip, 1, cred, CHOWN)) == 0) 699 goto good; 700 else 701 (void) chkdq(ip, -change, cred, CHOWN|FORCE); 702 } 703 for (i = 0; i < MAXQUOTAS; i++) { 704 dqrele(vp, ip->i_dquot[i]); 705 ip->i_dquot[i] = NODQUOT; 706 } 707 } 708 ip->i_gid = ogid; 709 ip->i_uid = ouid; 710 if (getinoquota(ip) == 0) { 711 if (ouid == uid) { 712 dqrele(vp, ip->i_dquot[USRQUOTA]); 713 ip->i_dquot[USRQUOTA] = NODQUOT; 714 } 715 if (ogid == gid) { 716 dqrele(vp, ip->i_dquot[GRPQUOTA]); 717 ip->i_dquot[GRPQUOTA] = NODQUOT; 718 } 719 (void) chkdq(ip, change, cred, FORCE|CHOWN); 720 (void) chkiq(ip, 1, cred, FORCE|CHOWN); 721 (void) getinoquota(ip); 722 } 723 return (error); 724good: 725 if (getinoquota(ip)) 726 panic("ufs_chown: lost quota"); 727#endif /* QUOTA */ 728 ip->i_flag |= IN_CHANGE; 729 if (suser_xxx(cred, NULL, PRISON_ROOT) && (ouid != uid || ogid != gid)) 730 ip->i_mode &= ~(ISUID | ISGID); 731 return (0); 732} 733 734int 735ufs_remove(ap) 736 struct vop_remove_args /* { 737 struct vnode *a_dvp; 738 struct vnode *a_vp; 739 struct componentname *a_cnp; 740 } */ *ap; 741{ 742 struct inode *ip; 743 struct vnode *vp = ap->a_vp; 744 struct vnode *dvp = ap->a_dvp; 745 int error; 746 747 ip = VTOI(vp); 748 if ((ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND)) || 749 (VTOI(dvp)->i_flags & APPEND)) { 750 error = EPERM; 751 goto out; 752 } 753 error = ufs_dirremove(dvp, ip, ap->a_cnp->cn_flags, 0); 754 VN_KNOTE(vp, NOTE_DELETE); 755 VN_KNOTE(dvp, NOTE_WRITE); 756out: 757 return (error); 758} 759 760/* 761 * link vnode call 762 */ 763int 764ufs_link(ap) 765 struct vop_link_args /* { 766 struct vnode *a_tdvp; 767 struct vnode *a_vp; 768 struct componentname *a_cnp; 769 } */ *ap; 770{ 771 struct vnode *vp = ap->a_vp; 772 struct vnode *tdvp = ap->a_tdvp; 773 struct componentname *cnp = ap->a_cnp; 774 struct proc *p = cnp->cn_proc; 775 struct inode *ip; 776 struct direct newdir; 777 int error; 778 779#ifdef DIAGNOSTIC 780 if ((cnp->cn_flags & HASBUF) == 0) 781 panic("ufs_link: no name"); 782#endif 783 if (tdvp->v_mount != vp->v_mount) { 784 error = EXDEV; 785 goto out2; 786 } 787 if (tdvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE, p))) { 788 goto out2; 789 } 790 ip = VTOI(vp); 791 if ((nlink_t)ip->i_nlink >= LINK_MAX) { 792 error = EMLINK; 793 goto out1; 794 } 795 if (ip->i_flags & (IMMUTABLE | APPEND)) { 796 error = EPERM; 797 goto out1; 798 } 799 ip->i_effnlink++; 800 ip->i_nlink++; 801 ip->i_flag |= IN_CHANGE; 802 if (DOINGSOFTDEP(vp)) 803 softdep_change_linkcnt(ip); 804 error = UFS_UPDATE(vp, !(DOINGSOFTDEP(vp) | DOINGASYNC(vp))); 805 if (!error) { 806 ufs_makedirentry(ip, cnp, &newdir); 807 error = ufs_direnter(tdvp, vp, &newdir, cnp, NULL); 808 } 809 810 if (error) { 811 ip->i_effnlink--; 812 ip->i_nlink--; 813 ip->i_flag |= IN_CHANGE; 814 if (DOINGSOFTDEP(vp)) 815 softdep_change_linkcnt(ip); 816 } 817out1: 818 if (tdvp != vp) 819 VOP_UNLOCK(vp, 0, p); 820out2: 821 VN_KNOTE(vp, NOTE_LINK); 822 VN_KNOTE(tdvp, NOTE_WRITE); 823 return (error); 824} 825 826/* 827 * whiteout vnode call 828 */ 829int 830ufs_whiteout(ap) 831 struct vop_whiteout_args /* { 832 struct vnode *a_dvp; 833 struct componentname *a_cnp; 834 int a_flags; 835 } */ *ap; 836{ 837 struct vnode *dvp = ap->a_dvp; 838 struct componentname *cnp = ap->a_cnp; 839 struct direct newdir; 840 int error = 0; 841 842 switch (ap->a_flags) { 843 case LOOKUP: 844 /* 4.4 format directories support whiteout operations */ 845 if (dvp->v_mount->mnt_maxsymlinklen > 0) 846 return (0); 847 return (EOPNOTSUPP); 848 849 case CREATE: 850 /* create a new directory whiteout */ 851#ifdef DIAGNOSTIC 852 if ((cnp->cn_flags & SAVENAME) == 0) 853 panic("ufs_whiteout: missing name"); 854 if (dvp->v_mount->mnt_maxsymlinklen <= 0) 855 panic("ufs_whiteout: old format filesystem"); 856#endif 857 858 newdir.d_ino = WINO; 859 newdir.d_namlen = cnp->cn_namelen; 860 bcopy(cnp->cn_nameptr, newdir.d_name, (unsigned)cnp->cn_namelen + 1); 861 newdir.d_type = DT_WHT; 862 error = ufs_direnter(dvp, NULL, &newdir, cnp, NULL); 863 break; 864 865 case DELETE: 866 /* remove an existing directory whiteout */ 867#ifdef DIAGNOSTIC 868 if (dvp->v_mount->mnt_maxsymlinklen <= 0) 869 panic("ufs_whiteout: old format filesystem"); 870#endif 871 872 cnp->cn_flags &= ~DOWHITEOUT; 873 error = ufs_dirremove(dvp, NULL, cnp->cn_flags, 0); 874 break; 875 default: 876 panic("ufs_whiteout: unknown op"); 877 } 878 return (error); 879} 880 881/* 882 * Rename system call. 883 * rename("foo", "bar"); 884 * is essentially 885 * unlink("bar"); 886 * link("foo", "bar"); 887 * unlink("foo"); 888 * but ``atomically''. Can't do full commit without saving state in the 889 * inode on disk which isn't feasible at this time. Best we can do is 890 * always guarantee the target exists. 891 * 892 * Basic algorithm is: 893 * 894 * 1) Bump link count on source while we're linking it to the 895 * target. This also ensure the inode won't be deleted out 896 * from underneath us while we work (it may be truncated by 897 * a concurrent `trunc' or `open' for creation). 898 * 2) Link source to destination. If destination already exists, 899 * delete it first. 900 * 3) Unlink source reference to inode if still around. If a 901 * directory was moved and the parent of the destination 902 * is different from the source, patch the ".." entry in the 903 * directory. 904 */ 905int 906ufs_rename(ap) 907 struct vop_rename_args /* { 908 struct vnode *a_fdvp; 909 struct vnode *a_fvp; 910 struct componentname *a_fcnp; 911 struct vnode *a_tdvp; 912 struct vnode *a_tvp; 913 struct componentname *a_tcnp; 914 } */ *ap; 915{ 916 struct vnode *tvp = ap->a_tvp; 917 register struct vnode *tdvp = ap->a_tdvp; 918 struct vnode *fvp = ap->a_fvp; 919 struct vnode *fdvp = ap->a_fdvp; 920 struct componentname *tcnp = ap->a_tcnp; 921 struct componentname *fcnp = ap->a_fcnp; 922 struct proc *p = fcnp->cn_proc; 923 struct inode *ip, *xp, *dp; 924 struct direct newdir; 925 int doingdirectory = 0, oldparent = 0, newparent = 0; 926 int error = 0, ioflag; 927 928#ifdef DIAGNOSTIC 929 if ((tcnp->cn_flags & HASBUF) == 0 || 930 (fcnp->cn_flags & HASBUF) == 0) 931 panic("ufs_rename: no name"); 932#endif 933 /* 934 * Check for cross-device rename. 935 */ 936 if ((fvp->v_mount != tdvp->v_mount) || 937 (tvp && (fvp->v_mount != tvp->v_mount))) { 938 error = EXDEV; 939abortit: 940 if (tdvp == tvp) 941 vrele(tdvp); 942 else 943 vput(tdvp); 944 if (tvp) 945 vput(tvp); 946 vrele(fdvp); 947 vrele(fvp); 948 return (error); 949 } 950 951 if (tvp && ((VTOI(tvp)->i_flags & (NOUNLINK | IMMUTABLE | APPEND)) || 952 (VTOI(tdvp)->i_flags & APPEND))) { 953 error = EPERM; 954 goto abortit; 955 } 956 957 /* 958 * Check if just deleting a link name or if we've lost a race. 959 * If another process completes the same rename after we've looked 960 * up the source and have blocked looking up the target, then the 961 * source and target inodes may be identical now although the 962 * names were never linked. 963 */ 964 if (fvp == tvp) { 965 if (fvp->v_type == VDIR) { 966 /* 967 * Linked directories are impossible, so we must 968 * have lost the race. Pretend that the rename 969 * completed before the lookup. 970 */ 971#ifdef UFS_RENAME_DEBUG 972 printf("ufs_rename: fvp == tvp for directories\n"); 973#endif 974 error = ENOENT; 975 goto abortit; 976 } 977 978 /* Release destination completely. */ 979 vput(tdvp); 980 vput(tvp); 981 982 /* 983 * Delete source. There is another race now that everything 984 * is unlocked, but this doesn't cause any new complications. 985 * Relookup() may find a file that is unrelated to the 986 * original one, or it may fail. Too bad. 987 */ 988 vrele(fdvp); 989 vrele(fvp); 990 fcnp->cn_flags &= ~MODMASK; 991 fcnp->cn_flags |= LOCKPARENT | LOCKLEAF; 992 if ((fcnp->cn_flags & SAVESTART) == 0) 993 panic("ufs_rename: lost from startdir"); 994 fcnp->cn_nameiop = DELETE; 995 VREF(fdvp); 996 error = relookup(fdvp, &fvp, fcnp); 997 if (error == 0) 998 vrele(fdvp); 999 if (fvp == NULL) { 1000#ifdef UFS_RENAME_DEBUG 1001 printf("ufs_rename: from name disappeared\n"); 1002#endif 1003 return (ENOENT); 1004 } 1005 error = VOP_REMOVE(fdvp, fvp, fcnp); 1006 if (fdvp == fvp) 1007 vrele(fdvp); 1008 else 1009 vput(fdvp); 1010 vput(fvp); 1011 return (error); 1012 } 1013 if ((error = vn_lock(fvp, LK_EXCLUSIVE, p)) != 0) 1014 goto abortit; 1015 dp = VTOI(fdvp); 1016 ip = VTOI(fvp); 1017 if (ip->i_nlink >= LINK_MAX) { 1018 VOP_UNLOCK(fvp, 0, p); 1019 error = EMLINK; 1020 goto abortit; 1021 } 1022 if ((ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND)) 1023 || (dp->i_flags & APPEND)) { 1024 VOP_UNLOCK(fvp, 0, p); 1025 error = EPERM; 1026 goto abortit; 1027 } 1028 if ((ip->i_mode & IFMT) == IFDIR) { 1029 /* 1030 * Avoid ".", "..", and aliases of "." for obvious reasons. 1031 */ 1032 if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') || 1033 dp == ip || (fcnp->cn_flags | tcnp->cn_flags) & ISDOTDOT || 1034 (ip->i_flag & IN_RENAME)) { 1035 VOP_UNLOCK(fvp, 0, p); 1036 error = EINVAL; 1037 goto abortit; 1038 } 1039 ip->i_flag |= IN_RENAME; 1040 oldparent = dp->i_number; 1041 doingdirectory = 1; 1042 } 1043 VN_KNOTE(fdvp, NOTE_WRITE); /* XXX right place? */ 1044 vrele(fdvp); 1045 1046 /* 1047 * When the target exists, both the directory 1048 * and target vnodes are returned locked. 1049 */ 1050 dp = VTOI(tdvp); 1051 xp = NULL; 1052 if (tvp) 1053 xp = VTOI(tvp); 1054 1055 /* 1056 * 1) Bump link count while we're moving stuff 1057 * around. If we crash somewhere before 1058 * completing our work, the link count 1059 * may be wrong, but correctable. 1060 */ 1061 ip->i_effnlink++; 1062 ip->i_nlink++; 1063 ip->i_flag |= IN_CHANGE; 1064 if (DOINGSOFTDEP(fvp)) 1065 softdep_change_linkcnt(ip); 1066 if ((error = UFS_UPDATE(fvp, !(DOINGSOFTDEP(fvp) | 1067 DOINGASYNC(fvp)))) != 0) { 1068 VOP_UNLOCK(fvp, 0, p); 1069 goto bad; 1070 } 1071 1072 /* 1073 * If ".." must be changed (ie the directory gets a new 1074 * parent) then the source directory must not be in the 1075 * directory heirarchy above the target, as this would 1076 * orphan everything below the source directory. Also 1077 * the user must have write permission in the source so 1078 * as to be able to change "..". We must repeat the call 1079 * to namei, as the parent directory is unlocked by the 1080 * call to checkpath(). 1081 */ 1082 error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_proc); 1083 VOP_UNLOCK(fvp, 0, p); 1084 if (oldparent != dp->i_number) 1085 newparent = dp->i_number; 1086 if (doingdirectory && newparent) { 1087 if (error) /* write access check above */ 1088 goto bad; 1089 if (xp != NULL) 1090 vput(tvp); 1091 error = ufs_checkpath(ip, dp, tcnp->cn_cred); 1092 if (error) 1093 goto out; 1094 if ((tcnp->cn_flags & SAVESTART) == 0) 1095 panic("ufs_rename: lost to startdir"); 1096 VREF(tdvp); 1097 error = relookup(tdvp, &tvp, tcnp); 1098 if (error) 1099 goto out; 1100 vrele(tdvp); 1101 dp = VTOI(tdvp); 1102 xp = NULL; 1103 if (tvp) 1104 xp = VTOI(tvp); 1105 } 1106 /* 1107 * 2) If target doesn't exist, link the target 1108 * to the source and unlink the source. 1109 * Otherwise, rewrite the target directory 1110 * entry to reference the source inode and 1111 * expunge the original entry's existence. 1112 */ 1113 if (xp == NULL) { 1114 if (dp->i_dev != ip->i_dev) 1115 panic("ufs_rename: EXDEV"); 1116 /* 1117 * Account for ".." in new directory. 1118 * When source and destination have the same 1119 * parent we don't fool with the link count. 1120 */ 1121 if (doingdirectory && newparent) { 1122 if ((nlink_t)dp->i_nlink >= LINK_MAX) { 1123 error = EMLINK; 1124 goto bad; 1125 } 1126 dp->i_effnlink++; 1127 dp->i_nlink++; 1128 dp->i_flag |= IN_CHANGE; 1129 if (DOINGSOFTDEP(tdvp)) 1130 softdep_change_linkcnt(dp); 1131 error = UFS_UPDATE(tdvp, !(DOINGSOFTDEP(tdvp) | 1132 DOINGASYNC(tdvp))); 1133 if (error) 1134 goto bad; 1135 } 1136 ufs_makedirentry(ip, tcnp, &newdir); 1137 error = ufs_direnter(tdvp, NULL, &newdir, tcnp, NULL); 1138 if (error) { 1139 if (doingdirectory && newparent) { 1140 dp->i_effnlink--; 1141 dp->i_nlink--; 1142 dp->i_flag |= IN_CHANGE; 1143 if (DOINGSOFTDEP(tdvp)) 1144 softdep_change_linkcnt(dp); 1145 (void)UFS_UPDATE(tdvp, 1); 1146 } 1147 goto bad; 1148 } 1149 VN_KNOTE(tdvp, NOTE_WRITE); 1150 vput(tdvp); 1151 } else { 1152 if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev) 1153 panic("ufs_rename: EXDEV"); 1154 /* 1155 * Short circuit rename(foo, foo). 1156 */ 1157 if (xp->i_number == ip->i_number) 1158 panic("ufs_rename: same file"); 1159 /* 1160 * If the parent directory is "sticky", then the caller 1161 * must possess VADMIN for the parent directory, or the 1162 * destination of the rename. This implements append-only 1163 * directories. 1164 */ 1165 if ((dp->i_mode & S_ISTXT) && 1166 VOP_ACCESS(tdvp, VADMIN, tcnp->cn_cred, p) && 1167 VOP_ACCESS(tvp, VADMIN, tcnp->cn_cred, p)) { 1168 error = EPERM; 1169 goto bad; 1170 } 1171 /* 1172 * Target must be empty if a directory and have no links 1173 * to it. Also, ensure source and target are compatible 1174 * (both directories, or both not directories). 1175 */ 1176 if ((xp->i_mode&IFMT) == IFDIR) { 1177 if ((xp->i_effnlink > 2) || 1178 !ufs_dirempty(xp, dp->i_number, tcnp->cn_cred)) { 1179 error = ENOTEMPTY; 1180 goto bad; 1181 } 1182 if (!doingdirectory) { 1183 error = ENOTDIR; 1184 goto bad; 1185 } 1186 cache_purge(tdvp); 1187 } else if (doingdirectory) { 1188 error = EISDIR; 1189 goto bad; 1190 } 1191 error = ufs_dirrewrite(dp, xp, ip->i_number, 1192 IFTODT(ip->i_mode), 1193 (doingdirectory && newparent) ? newparent : doingdirectory); 1194 if (error) 1195 goto bad; 1196 if (doingdirectory) { 1197 if (!newparent) { 1198 dp->i_effnlink--; 1199 if (DOINGSOFTDEP(tdvp)) 1200 softdep_change_linkcnt(dp); 1201 } 1202 xp->i_effnlink--; 1203 if (DOINGSOFTDEP(tvp)) 1204 softdep_change_linkcnt(xp); 1205 } 1206 if (doingdirectory && !DOINGSOFTDEP(tvp)) { 1207 /* 1208 * Truncate inode. The only stuff left in the directory 1209 * is "." and "..". The "." reference is inconsequential 1210 * since we are quashing it. We have removed the "." 1211 * reference and the reference in the parent directory, 1212 * but there may be other hard links. The soft 1213 * dependency code will arrange to do these operations 1214 * after the parent directory entry has been deleted on 1215 * disk, so when running with that code we avoid doing 1216 * them now. 1217 */ 1218 if (!newparent) { 1219 dp->i_nlink--; 1220 dp->i_flag |= IN_CHANGE; 1221 } 1222 xp->i_nlink--; 1223 xp->i_flag |= IN_CHANGE; 1224 ioflag = DOINGASYNC(tvp) ? 0 : IO_SYNC; 1225 if ((error = UFS_TRUNCATE(tvp, (off_t)0, ioflag, 1226 tcnp->cn_cred, tcnp->cn_proc)) != 0) 1227 goto bad; 1228 } 1229 VN_KNOTE(tdvp, NOTE_WRITE); 1230 vput(tdvp); 1231 VN_KNOTE(tvp, NOTE_DELETE); 1232 vput(tvp); 1233 xp = NULL; 1234 } 1235 1236 /* 1237 * 3) Unlink the source. 1238 */ 1239 fcnp->cn_flags &= ~MODMASK; 1240 fcnp->cn_flags |= LOCKPARENT | LOCKLEAF; 1241 if ((fcnp->cn_flags & SAVESTART) == 0) 1242 panic("ufs_rename: lost from startdir"); 1243 VREF(fdvp); 1244 error = relookup(fdvp, &fvp, fcnp); 1245 if (error == 0) 1246 vrele(fdvp); 1247 if (fvp != NULL) { 1248 xp = VTOI(fvp); 1249 dp = VTOI(fdvp); 1250 } else { 1251 /* 1252 * From name has disappeared. 1253 */ 1254 if (doingdirectory) 1255 panic("ufs_rename: lost dir entry"); 1256 vrele(ap->a_fvp); 1257 return (0); 1258 } 1259 /* 1260 * Ensure that the directory entry still exists and has not 1261 * changed while the new name has been entered. If the source is 1262 * a file then the entry may have been unlinked or renamed. In 1263 * either case there is no further work to be done. If the source 1264 * is a directory then it cannot have been rmdir'ed; the IN_RENAME 1265 * flag ensures that it cannot be moved by another rename or removed 1266 * by a rmdir. 1267 */ 1268 if (xp != ip) { 1269 if (doingdirectory) 1270 panic("ufs_rename: lost dir entry"); 1271 } else { 1272 /* 1273 * If the source is a directory with a 1274 * new parent, the link count of the old 1275 * parent directory must be decremented 1276 * and ".." set to point to the new parent. 1277 */ 1278 if (doingdirectory && newparent) { 1279 xp->i_offset = mastertemplate.dot_reclen; 1280 ufs_dirrewrite(xp, dp, newparent, DT_DIR, 0); 1281 cache_purge(fdvp); 1282 } 1283 error = ufs_dirremove(fdvp, xp, fcnp->cn_flags, 0); 1284 xp->i_flag &= ~IN_RENAME; 1285 } 1286 VN_KNOTE(fvp, NOTE_RENAME); 1287 if (dp) 1288 vput(fdvp); 1289 if (xp) 1290 vput(fvp); 1291 vrele(ap->a_fvp); 1292 return (error); 1293 1294bad: 1295 if (xp) 1296 vput(ITOV(xp)); 1297 vput(ITOV(dp)); 1298out: 1299 if (doingdirectory) 1300 ip->i_flag &= ~IN_RENAME; 1301 if (vn_lock(fvp, LK_EXCLUSIVE, p) == 0) { 1302 ip->i_effnlink--; 1303 ip->i_nlink--; 1304 ip->i_flag |= IN_CHANGE; 1305 ip->i_flag &= ~IN_RENAME; 1306 if (DOINGSOFTDEP(fvp)) 1307 softdep_change_linkcnt(ip); 1308 vput(fvp); 1309 } else 1310 vrele(fvp); 1311 return (error); 1312} 1313 1314/* 1315 * Mkdir system call 1316 */ 1317int 1318ufs_mkdir(ap) 1319 struct vop_mkdir_args /* { 1320 struct vnode *a_dvp; 1321 struct vnode **a_vpp; 1322 struct componentname *a_cnp; 1323 struct vattr *a_vap; 1324 } */ *ap; 1325{ 1326 register struct vnode *dvp = ap->a_dvp; 1327 register struct vattr *vap = ap->a_vap; 1328 register struct componentname *cnp = ap->a_cnp; 1329 register struct inode *ip, *dp; 1330 struct vnode *tvp; 1331 struct buf *bp; 1332 struct dirtemplate dirtemplate, *dtp; 1333 struct direct newdir; 1334#ifdef UFS_ACL 1335 struct acl *acl, *dacl; 1336#endif 1337 int error, dmode; 1338 long blkoff; 1339 1340#ifdef DIAGNOSTIC 1341 if ((cnp->cn_flags & HASBUF) == 0) 1342 panic("ufs_mkdir: no name"); 1343#endif 1344 dp = VTOI(dvp); 1345 if ((nlink_t)dp->i_nlink >= LINK_MAX) { 1346 error = EMLINK; 1347 goto out; 1348 } 1349 dmode = vap->va_mode & 0777; 1350 dmode |= IFDIR; 1351 /* 1352 * Must simulate part of ufs_makeinode here to acquire the inode, 1353 * but not have it entered in the parent directory. The entry is 1354 * made later after writing "." and ".." entries. 1355 */ 1356 error = UFS_VALLOC(dvp, dmode, cnp->cn_cred, &tvp); 1357 if (error) 1358 goto out; 1359 ip = VTOI(tvp); 1360 ip->i_gid = dp->i_gid; 1361#ifdef SUIDDIR 1362 { 1363#ifdef QUOTA 1364 struct ucred ucred, *ucp; 1365 ucp = cnp->cn_cred; 1366#endif 1367 /* 1368 * If we are hacking owners here, (only do this where told to) 1369 * and we are not giving it TO root, (would subvert quotas) 1370 * then go ahead and give it to the other user. 1371 * The new directory also inherits the SUID bit. 1372 * If user's UID and dir UID are the same, 1373 * 'give it away' so that the SUID is still forced on. 1374 */ 1375 if ((dvp->v_mount->mnt_flag & MNT_SUIDDIR) && 1376 (dp->i_mode & ISUID) && dp->i_uid) { 1377 dmode |= ISUID; 1378 ip->i_uid = dp->i_uid; 1379#ifdef QUOTA 1380 if (dp->i_uid != cnp->cn_cred->cr_uid) { 1381 /* 1382 * Make sure the correct user gets charged 1383 * for the space. 1384 * Make a dummy credential for the victim. 1385 * XXX This seems to never be accessed out of 1386 * our context so a stack variable is ok. 1387 */ 1388 ucred.cr_ref = 1; 1389 ucred.cr_uid = ip->i_uid; 1390 ucred.cr_ngroups = 1; 1391 ucred.cr_groups[0] = dp->i_gid; 1392 ucp = &ucred; 1393 } 1394#endif 1395 } else 1396 ip->i_uid = cnp->cn_cred->cr_uid; 1397#ifdef QUOTA 1398 if ((error = getinoquota(ip)) || 1399 (error = chkiq(ip, 1, ucp, 0))) { 1400 UFS_VFREE(tvp, ip->i_number, dmode); 1401 vput(tvp); 1402 return (error); 1403 } 1404#endif 1405 } 1406#else /* !SUIDDIR */ 1407 ip->i_uid = cnp->cn_cred->cr_uid; 1408#ifdef QUOTA 1409 if ((error = getinoquota(ip)) || 1410 (error = chkiq(ip, 1, cnp->cn_cred, 0))) { 1411 UFS_VFREE(tvp, ip->i_number, dmode); 1412 vput(tvp); 1413 return (error); 1414 } 1415#endif 1416#endif /* !SUIDDIR */ 1417 ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE; 1418#ifdef UFS_ACL 1419 MALLOC(acl, struct acl *, sizeof(*acl), M_ACL, M_WAITOK); 1420 MALLOC(dacl, struct acl *, sizeof(*acl), M_ACL, M_WAITOK); 1421 1422 /* 1423 * Retrieve default ACL from parent, if any. 1424 */ 1425 error = VOP_GETACL(dvp, ACL_TYPE_DEFAULT, acl, cnp->cn_cred, 1426 cnp->cn_proc); 1427 switch (error) { 1428 case 0: 1429 /* 1430 * Retrieved a default ACL, so merge mode and ACL if 1431 * necessary. 1432 */ 1433 if (acl->acl_cnt != 0) { 1434 /* 1435 * Two possible ways for default ACL to not be 1436 * present. First, the EA can be undefined, 1437 * or second, the default ACL can be blank. 1438 * If it's blank, fall through to the it's 1439 * not defined case. 1440 */ 1441 ip->i_mode = dmode; 1442 *dacl = *acl; 1443 ufs_sync_acl_from_inode(ip, acl); 1444 break; 1445 } 1446 /* FALLTHROUGH */ 1447 1448 case EOPNOTSUPP: 1449 /* 1450 * Just use the mode as-is. 1451 */ 1452 ip->i_mode = dmode; 1453 FREE(acl, M_ACL); 1454 FREE(dacl, M_ACL); 1455 dacl = acl = NULL; 1456 break; 1457 1458 default: 1459 UFS_VFREE(tvp, ip->i_number, dmode); 1460 vput(tvp); 1461 return (error); 1462 } 1463#else /* !UFS_ACL */ 1464 ip->i_mode = dmode; 1465#endif /* !UFS_ACL */ 1466 tvp->v_type = VDIR; /* Rest init'd in getnewvnode(). */ 1467 ip->i_effnlink = 2; 1468 ip->i_nlink = 2; 1469 if (DOINGSOFTDEP(tvp)) 1470 softdep_change_linkcnt(ip); 1471 if (cnp->cn_flags & ISWHITEOUT) 1472 ip->i_flags |= UF_OPAQUE; 1473 1474 /* 1475 * Bump link count in parent directory to reflect work done below. 1476 * Should be done before reference is created so cleanup is 1477 * possible if we crash. 1478 */ 1479 dp->i_effnlink++; 1480 dp->i_nlink++; 1481 dp->i_flag |= IN_CHANGE; 1482 if (DOINGSOFTDEP(dvp)) 1483 softdep_change_linkcnt(dp); 1484 error = UFS_UPDATE(tvp, !(DOINGSOFTDEP(dvp) | DOINGASYNC(dvp))); 1485 if (error) 1486 goto bad; 1487#ifdef UFS_ACL 1488 if (acl != NULL) { 1489 /* 1490 * XXX: If we abort now, will Soft Updates notify the extattr 1491 * code that the EAs for the file need to be released? 1492 */ 1493 error = VOP_SETACL(tvp, ACL_TYPE_ACCESS, acl, cnp->cn_cred, 1494 cnp->cn_proc); 1495 if (error == 0) 1496 error = VOP_SETACL(tvp, ACL_TYPE_DEFAULT, dacl, 1497 cnp->cn_cred, cnp->cn_proc); 1498 switch (error) { 1499 case 0: 1500 break; 1501 1502 case EOPNOTSUPP: 1503 /* 1504 * XXX: This should not happen, as EOPNOTSUPP above 1505 * was supposed to free acl. 1506 */ 1507 printf("ufs_mkdir: VOP_GETACL() but no VOP_SETACL()\n"); 1508 /* 1509 panic("ufs_mkdir: VOP_GETACL() but no VOP_SETACL()"); 1510 */ 1511 break; 1512 1513 default: 1514 FREE(acl, M_ACL); 1515 FREE(dacl, M_ACL); 1516 goto bad; 1517 } 1518 FREE(acl, M_ACL); 1519 FREE(dacl, M_ACL); 1520 } 1521#endif /* !UFS_ACL */ 1522 1523 /* 1524 * Initialize directory with "." and ".." from static template. 1525 */ 1526 if (dvp->v_mount->mnt_maxsymlinklen > 0 1527 ) 1528 dtp = &mastertemplate; 1529 else 1530 dtp = (struct dirtemplate *)&omastertemplate; 1531 dirtemplate = *dtp; 1532 dirtemplate.dot_ino = ip->i_number; 1533 dirtemplate.dotdot_ino = dp->i_number; 1534 if ((error = UFS_BALLOC(tvp, (off_t)0, DIRBLKSIZ, cnp->cn_cred, 1535 B_CLRBUF, &bp)) != 0) 1536 goto bad; 1537 ip->i_size = DIRBLKSIZ; 1538 ip->i_flag |= IN_CHANGE | IN_UPDATE; 1539 vnode_pager_setsize(tvp, (u_long)ip->i_size); 1540 bcopy((caddr_t)&dirtemplate, (caddr_t)bp->b_data, sizeof dirtemplate); 1541 if (DOINGSOFTDEP(tvp)) { 1542 /* 1543 * Ensure that the entire newly allocated block is a 1544 * valid directory so that future growth within the 1545 * block does not have to ensure that the block is 1546 * written before the inode. 1547 */ 1548 blkoff = DIRBLKSIZ; 1549 while (blkoff < bp->b_bcount) { 1550 ((struct direct *) 1551 (bp->b_data + blkoff))->d_reclen = DIRBLKSIZ; 1552 blkoff += DIRBLKSIZ; 1553 } 1554 } 1555 if ((error = UFS_UPDATE(tvp, !(DOINGSOFTDEP(tvp) | 1556 DOINGASYNC(tvp)))) != 0) { 1557 (void)BUF_WRITE(bp); 1558 goto bad; 1559 } 1560 /* 1561 * Directory set up, now install its entry in the parent directory. 1562 * 1563 * If we are not doing soft dependencies, then we must write out the 1564 * buffer containing the new directory body before entering the new 1565 * name in the parent. If we are doing soft dependencies, then the 1566 * buffer containing the new directory body will be passed to and 1567 * released in the soft dependency code after the code has attached 1568 * an appropriate ordering dependency to the buffer which ensures that 1569 * the buffer is written before the new name is written in the parent. 1570 */ 1571 if (DOINGASYNC(dvp)) 1572 bdwrite(bp); 1573 else if (!DOINGSOFTDEP(dvp) && ((error = BUF_WRITE(bp)))) 1574 goto bad; 1575 ufs_makedirentry(ip, cnp, &newdir); 1576 error = ufs_direnter(dvp, tvp, &newdir, cnp, bp); 1577 1578bad: 1579 if (error == 0) { 1580 VN_KNOTE(dvp, NOTE_WRITE); 1581 *ap->a_vpp = tvp; 1582 } else { 1583 dp->i_effnlink--; 1584 dp->i_nlink--; 1585 dp->i_flag |= IN_CHANGE; 1586 if (DOINGSOFTDEP(dvp)) 1587 softdep_change_linkcnt(dp); 1588 /* 1589 * No need to do an explicit VOP_TRUNCATE here, vrele will 1590 * do this for us because we set the link count to 0. 1591 */ 1592 ip->i_effnlink = 0; 1593 ip->i_nlink = 0; 1594 ip->i_flag |= IN_CHANGE; 1595 if (DOINGSOFTDEP(tvp)) 1596 softdep_change_linkcnt(ip); 1597 vput(tvp); 1598 } 1599out: 1600 return (error); 1601} 1602 1603/* 1604 * Rmdir system call. 1605 */ 1606int 1607ufs_rmdir(ap) 1608 struct vop_rmdir_args /* { 1609 struct vnode *a_dvp; 1610 struct vnode *a_vp; 1611 struct componentname *a_cnp; 1612 } */ *ap; 1613{ 1614 struct vnode *vp = ap->a_vp; 1615 struct vnode *dvp = ap->a_dvp; 1616 struct componentname *cnp = ap->a_cnp; 1617 struct inode *ip, *dp; 1618 int error, ioflag; 1619 1620 ip = VTOI(vp); 1621 dp = VTOI(dvp); 1622 1623 /* 1624 * Do not remove a directory that is in the process of being renamed. 1625 * Verify the directory is empty (and valid). Rmdir ".." will not be 1626 * valid since ".." will contain a reference to the current directory 1627 * and thus be non-empty. Do not allow the removal of mounted on 1628 * directories (this can happen when an NFS exported filesystem 1629 * tries to remove a locally mounted on directory). 1630 */ 1631 error = 0; 1632 if (ip->i_flag & IN_RENAME) { 1633 error = EINVAL; 1634 goto out; 1635 } 1636 if (ip->i_effnlink != 2 || 1637 !ufs_dirempty(ip, dp->i_number, cnp->cn_cred)) { 1638 error = ENOTEMPTY; 1639 goto out; 1640 } 1641 if ((dp->i_flags & APPEND) 1642 || (ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND))) { 1643 error = EPERM; 1644 goto out; 1645 } 1646 if (vp->v_mountedhere != 0) { 1647 error = EINVAL; 1648 goto out; 1649 } 1650 /* 1651 * Delete reference to directory before purging 1652 * inode. If we crash in between, the directory 1653 * will be reattached to lost+found, 1654 */ 1655 dp->i_effnlink--; 1656 ip->i_effnlink--; 1657 if (DOINGSOFTDEP(vp)) { 1658 softdep_change_linkcnt(dp); 1659 softdep_change_linkcnt(ip); 1660 } 1661 error = ufs_dirremove(dvp, ip, cnp->cn_flags, 1); 1662 if (error) { 1663 dp->i_effnlink++; 1664 ip->i_effnlink++; 1665 if (DOINGSOFTDEP(vp)) { 1666 softdep_change_linkcnt(dp); 1667 softdep_change_linkcnt(ip); 1668 } 1669 goto out; 1670 } 1671 VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK); 1672 cache_purge(dvp); 1673 /* 1674 * Truncate inode. The only stuff left in the directory is "." and 1675 * "..". The "." reference is inconsequential since we are quashing 1676 * it. The soft dependency code will arrange to do these operations 1677 * after the parent directory entry has been deleted on disk, so 1678 * when running with that code we avoid doing them now. 1679 */ 1680 if (!DOINGSOFTDEP(vp)) { 1681 dp->i_nlink--; 1682 dp->i_flag |= IN_CHANGE; 1683 ip->i_nlink--; 1684 ip->i_flag |= IN_CHANGE; 1685 ioflag = DOINGASYNC(vp) ? 0 : IO_SYNC; 1686 error = UFS_TRUNCATE(vp, (off_t)0, ioflag, cnp->cn_cred, 1687 cnp->cn_proc); 1688 } 1689 cache_purge(vp); 1690out: 1691 VN_KNOTE(vp, NOTE_DELETE); 1692 return (error); 1693} 1694 1695/* 1696 * symlink -- make a symbolic link 1697 */ 1698int 1699ufs_symlink(ap) 1700 struct vop_symlink_args /* { 1701 struct vnode *a_dvp; 1702 struct vnode **a_vpp; 1703 struct componentname *a_cnp; 1704 struct vattr *a_vap; 1705 char *a_target; 1706 } */ *ap; 1707{ 1708 register struct vnode *vp, **vpp = ap->a_vpp; 1709 register struct inode *ip; 1710 int len, error; 1711 1712 error = ufs_makeinode(IFLNK | ap->a_vap->va_mode, ap->a_dvp, 1713 vpp, ap->a_cnp); 1714 if (error) 1715 return (error); 1716 VN_KNOTE(ap->a_dvp, NOTE_WRITE); 1717 vp = *vpp; 1718 len = strlen(ap->a_target); 1719 if (len < vp->v_mount->mnt_maxsymlinklen) { 1720 ip = VTOI(vp); 1721 bcopy(ap->a_target, (char *)ip->i_shortlink, len); 1722 ip->i_size = len; 1723 ip->i_flag |= IN_CHANGE | IN_UPDATE; 1724 } else 1725 error = vn_rdwr(UIO_WRITE, vp, ap->a_target, len, (off_t)0, 1726 UIO_SYSSPACE, IO_NODELOCKED, ap->a_cnp->cn_cred, (int *)0, 1727 (struct proc *)0); 1728 if (error) 1729 vput(vp); 1730 return (error); 1731} 1732 1733/* 1734 * Vnode op for reading directories. 1735 * 1736 * The routine below assumes that the on-disk format of a directory 1737 * is the same as that defined by <sys/dirent.h>. If the on-disk 1738 * format changes, then it will be necessary to do a conversion 1739 * from the on-disk format that read returns to the format defined 1740 * by <sys/dirent.h>. 1741 */ 1742int 1743ufs_readdir(ap) 1744 struct vop_readdir_args /* { 1745 struct vnode *a_vp; 1746 struct uio *a_uio; 1747 struct ucred *a_cred; 1748 int *a_eofflag; 1749 int *ncookies; 1750 u_long **a_cookies; 1751 } */ *ap; 1752{ 1753 register struct uio *uio = ap->a_uio; 1754 int error; 1755 size_t count, lost; 1756 off_t off; 1757 1758 if (ap->a_ncookies != NULL) 1759 /* 1760 * Ensure that the block is aligned. The caller can use 1761 * the cookies to determine where in the block to start. 1762 */ 1763 uio->uio_offset &= ~(DIRBLKSIZ - 1); 1764 off = uio->uio_offset; 1765 count = uio->uio_resid; 1766 /* Make sure we don't return partial entries. */ 1767 if (count <= ((uio->uio_offset + count) & (DIRBLKSIZ -1))) 1768 return (EINVAL); 1769 count -= (uio->uio_offset + count) & (DIRBLKSIZ -1); 1770 lost = uio->uio_resid - count; 1771 uio->uio_resid = count; 1772 uio->uio_iov->iov_len = count; 1773# if (BYTE_ORDER == LITTLE_ENDIAN) 1774 if (ap->a_vp->v_mount->mnt_maxsymlinklen > 0) { 1775 error = VOP_READ(ap->a_vp, uio, 0, ap->a_cred); 1776 } else { 1777 struct dirent *dp, *edp; 1778 struct uio auio; 1779 struct iovec aiov; 1780 caddr_t dirbuf; 1781 int readcnt; 1782 u_char tmp; 1783 1784 auio = *uio; 1785 auio.uio_iov = &aiov; 1786 auio.uio_iovcnt = 1; 1787 auio.uio_segflg = UIO_SYSSPACE; 1788 aiov.iov_len = count; 1789 MALLOC(dirbuf, caddr_t, count, M_TEMP, M_WAITOK); 1790 aiov.iov_base = dirbuf; 1791 error = VOP_READ(ap->a_vp, &auio, 0, ap->a_cred); 1792 if (error == 0) { 1793 readcnt = count - auio.uio_resid; 1794 edp = (struct dirent *)&dirbuf[readcnt]; 1795 for (dp = (struct dirent *)dirbuf; dp < edp; ) { 1796 tmp = dp->d_namlen; 1797 dp->d_namlen = dp->d_type; 1798 dp->d_type = tmp; 1799 if (dp->d_reclen > 0) { 1800 dp = (struct dirent *) 1801 ((char *)dp + dp->d_reclen); 1802 } else { 1803 error = EIO; 1804 break; 1805 } 1806 } 1807 if (dp >= edp) 1808 error = uiomove(dirbuf, readcnt, uio); 1809 } 1810 FREE(dirbuf, M_TEMP); 1811 } 1812# else 1813 error = VOP_READ(ap->a_vp, uio, 0, ap->a_cred); 1814# endif 1815 if (!error && ap->a_ncookies != NULL) { 1816 struct dirent* dpStart; 1817 struct dirent* dpEnd; 1818 struct dirent* dp; 1819 int ncookies; 1820 u_long *cookies; 1821 u_long *cookiep; 1822 1823 if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) 1824 panic("ufs_readdir: unexpected uio from NFS server"); 1825 dpStart = (struct dirent *) 1826 (uio->uio_iov->iov_base - (uio->uio_offset - off)); 1827 dpEnd = (struct dirent *) uio->uio_iov->iov_base; 1828 for (dp = dpStart, ncookies = 0; 1829 dp < dpEnd; 1830 dp = (struct dirent *)((caddr_t) dp + dp->d_reclen)) 1831 ncookies++; 1832 MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP, 1833 M_WAITOK); 1834 for (dp = dpStart, cookiep = cookies; 1835 dp < dpEnd; 1836 dp = (struct dirent *)((caddr_t) dp + dp->d_reclen)) { 1837 off += dp->d_reclen; 1838 *cookiep++ = (u_long) off; 1839 } 1840 *ap->a_ncookies = ncookies; 1841 *ap->a_cookies = cookies; 1842 } 1843 uio->uio_resid += lost; 1844 if (ap->a_eofflag) 1845 *ap->a_eofflag = VTOI(ap->a_vp)->i_size <= uio->uio_offset; 1846 return (error); 1847} 1848 1849/* 1850 * Return target name of a symbolic link 1851 */ 1852int 1853ufs_readlink(ap) 1854 struct vop_readlink_args /* { 1855 struct vnode *a_vp; 1856 struct uio *a_uio; 1857 struct ucred *a_cred; 1858 } */ *ap; 1859{ 1860 register struct vnode *vp = ap->a_vp; 1861 register struct inode *ip = VTOI(vp); 1862 int isize; 1863 1864 isize = ip->i_size; 1865 if ((isize < vp->v_mount->mnt_maxsymlinklen) || 1866 (ip->i_din.di_blocks == 0)) { /* XXX - for old fastlink support */ 1867 uiomove((char *)ip->i_shortlink, isize, ap->a_uio); 1868 return (0); 1869 } 1870 return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred)); 1871} 1872 1873/* 1874 * Calculate the logical to physical mapping if not done already, 1875 * then call the device strategy routine. 1876 * 1877 * In order to be able to swap to a file, the VOP_BMAP operation may not 1878 * deadlock on memory. See ufs_bmap() for details. 1879 */ 1880int 1881ufs_strategy(ap) 1882 struct vop_strategy_args /* { 1883 struct vnode *a_vp; 1884 struct buf *a_bp; 1885 } */ *ap; 1886{ 1887 register struct buf *bp = ap->a_bp; 1888 register struct vnode *vp = ap->a_vp; 1889 register struct inode *ip; 1890 int error; 1891 1892 ip = VTOI(vp); 1893 if (vp->v_type == VBLK || vp->v_type == VCHR) 1894 panic("ufs_strategy: spec"); 1895 if (bp->b_blkno == bp->b_lblkno) { 1896 error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL, NULL); 1897 if (error) { 1898 bp->b_error = error; 1899 bp->b_ioflags |= BIO_ERROR; 1900 bufdone(bp); 1901 return (error); 1902 } 1903 if ((long)bp->b_blkno == -1) 1904 vfs_bio_clrbuf(bp); 1905 } 1906 if ((long)bp->b_blkno == -1) { 1907 bufdone(bp); 1908 return (0); 1909 } 1910 vp = ip->i_devvp; 1911 bp->b_dev = vp->v_rdev; 1912 VOP_STRATEGY(vp, bp); 1913 return (0); 1914} 1915 1916/* 1917 * Print out the contents of an inode. 1918 */ 1919int 1920ufs_print(ap) 1921 struct vop_print_args /* { 1922 struct vnode *a_vp; 1923 } */ *ap; 1924{ 1925 register struct vnode *vp = ap->a_vp; 1926 register struct inode *ip = VTOI(vp); 1927 1928 printf("tag VT_UFS, ino %lu, on dev %s (%d, %d)", 1929 (u_long)ip->i_number, devtoname(ip->i_dev), major(ip->i_dev), 1930 minor(ip->i_dev)); 1931 if (vp->v_type == VFIFO) 1932 fifo_printinfo(vp); 1933 lockmgr_printinfo(&vp->v_lock); 1934 printf("\n"); 1935 return (0); 1936} 1937 1938/* 1939 * Read wrapper for special devices. 1940 */ 1941int 1942ufsspec_read(ap) 1943 struct vop_read_args /* { 1944 struct vnode *a_vp; 1945 struct uio *a_uio; 1946 int a_ioflag; 1947 struct ucred *a_cred; 1948 } */ *ap; 1949{ 1950 int error, resid; 1951 struct inode *ip; 1952 struct uio *uio; 1953 1954 uio = ap->a_uio; 1955 resid = uio->uio_resid; 1956 error = VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap); 1957 /* 1958 * The inode may have been revoked during the call, so it must not 1959 * be accessed blindly here or in the other wrapper functions. 1960 */ 1961 ip = VTOI(ap->a_vp); 1962 if (ip != NULL && (uio->uio_resid != resid || (error == 0 && resid != 0))) 1963 ip->i_flag |= IN_ACCESS; 1964 return (error); 1965} 1966 1967/* 1968 * Write wrapper for special devices. 1969 */ 1970int 1971ufsspec_write(ap) 1972 struct vop_write_args /* { 1973 struct vnode *a_vp; 1974 struct uio *a_uio; 1975 int a_ioflag; 1976 struct ucred *a_cred; 1977 } */ *ap; 1978{ 1979 int error, resid; 1980 struct inode *ip; 1981 struct uio *uio; 1982 1983 uio = ap->a_uio; 1984 resid = uio->uio_resid; 1985 error = VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap); 1986 ip = VTOI(ap->a_vp); 1987 if (ip != NULL && (uio->uio_resid != resid || (error == 0 && resid != 0))) 1988 VTOI(ap->a_vp)->i_flag |= IN_CHANGE | IN_UPDATE; 1989 return (error); 1990} 1991 1992/* 1993 * Close wrapper for special devices. 1994 * 1995 * Update the times on the inode then do device close. 1996 */ 1997int 1998ufsspec_close(ap) 1999 struct vop_close_args /* { 2000 struct vnode *a_vp; 2001 int a_fflag; 2002 struct ucred *a_cred; 2003 struct proc *a_p; 2004 } */ *ap; 2005{ 2006 struct vnode *vp = ap->a_vp; 2007 2008 mtx_lock(&vp->v_interlock); 2009 if (vp->v_usecount > 1) 2010 ufs_itimes(vp); 2011 mtx_unlock(&vp->v_interlock); 2012 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap)); 2013} 2014 2015/* 2016 * Read wrapper for fifos. 2017 */ 2018int 2019ufsfifo_read(ap) 2020 struct vop_read_args /* { 2021 struct vnode *a_vp; 2022 struct uio *a_uio; 2023 int a_ioflag; 2024 struct ucred *a_cred; 2025 } */ *ap; 2026{ 2027 int error, resid; 2028 struct inode *ip; 2029 struct uio *uio; 2030 2031 uio = ap->a_uio; 2032 resid = uio->uio_resid; 2033 error = VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap); 2034 ip = VTOI(ap->a_vp); 2035 if ((ap->a_vp->v_mount->mnt_flag & MNT_NOATIME) == 0 && ip != NULL && 2036 (uio->uio_resid != resid || (error == 0 && resid != 0))) 2037 VTOI(ap->a_vp)->i_flag |= IN_ACCESS; 2038 return (error); 2039} 2040 2041/* 2042 * Write wrapper for fifos. 2043 */ 2044int 2045ufsfifo_write(ap) 2046 struct vop_write_args /* { 2047 struct vnode *a_vp; 2048 struct uio *a_uio; 2049 int a_ioflag; 2050 struct ucred *a_cred; 2051 } */ *ap; 2052{ 2053 int error, resid; 2054 struct inode *ip; 2055 struct uio *uio; 2056 2057 uio = ap->a_uio; 2058 resid = uio->uio_resid; 2059 error = VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap); 2060 ip = VTOI(ap->a_vp); 2061 if (ip != NULL && (uio->uio_resid != resid || (error == 0 && resid != 0))) 2062 VTOI(ap->a_vp)->i_flag |= IN_CHANGE | IN_UPDATE; 2063 return (error); 2064} 2065 2066/* 2067 * Close wrapper for fifos. 2068 * 2069 * Update the times on the inode then do device close. 2070 */ 2071int 2072ufsfifo_close(ap) 2073 struct vop_close_args /* { 2074 struct vnode *a_vp; 2075 int a_fflag; 2076 struct ucred *a_cred; 2077 struct proc *a_p; 2078 } */ *ap; 2079{ 2080 struct vnode *vp = ap->a_vp; 2081 2082 mtx_lock(&vp->v_interlock); 2083 if (vp->v_usecount > 1) 2084 ufs_itimes(vp); 2085 mtx_unlock(&vp->v_interlock); 2086 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap)); 2087} 2088 2089/* 2090 * Return POSIX pathconf information applicable to ufs filesystems. 2091 */ 2092int 2093ufs_pathconf(ap) 2094 struct vop_pathconf_args /* { 2095 struct vnode *a_vp; 2096 int a_name; 2097 int *a_retval; 2098 } */ *ap; 2099{ 2100 2101 switch (ap->a_name) { 2102 case _PC_LINK_MAX: 2103 *ap->a_retval = LINK_MAX; 2104 return (0); 2105 case _PC_NAME_MAX: 2106 *ap->a_retval = NAME_MAX; 2107 return (0); 2108 case _PC_PATH_MAX: 2109 *ap->a_retval = PATH_MAX; 2110 return (0); 2111 case _PC_PIPE_BUF: 2112 *ap->a_retval = PIPE_BUF; 2113 return (0); 2114 case _PC_CHOWN_RESTRICTED: 2115 *ap->a_retval = 1; 2116 return (0); 2117 case _PC_NO_TRUNC: 2118 *ap->a_retval = 1; 2119 return (0); 2120 default: 2121 return (EINVAL); 2122 } 2123 /* NOTREACHED */ 2124} 2125 2126/* 2127 * Advisory record locking support 2128 */ 2129int 2130ufs_advlock(ap) 2131 struct vop_advlock_args /* { 2132 struct vnode *a_vp; 2133 caddr_t a_id; 2134 int a_op; 2135 struct flock *a_fl; 2136 int a_flags; 2137 } */ *ap; 2138{ 2139 register struct inode *ip = VTOI(ap->a_vp); 2140 2141 return (lf_advlock(ap, &(ip->i_lockf), ip->i_size)); 2142} 2143 2144/* 2145 * Initialize the vnode associated with a new inode, handle aliased 2146 * vnodes. 2147 */ 2148int 2149ufs_vinit(mntp, specops, fifoops, vpp) 2150 struct mount *mntp; 2151 vop_t **specops; 2152 vop_t **fifoops; 2153 struct vnode **vpp; 2154{ 2155 struct inode *ip; 2156 struct vnode *vp; 2157 struct timeval tv; 2158 2159 vp = *vpp; 2160 ip = VTOI(vp); 2161 switch(vp->v_type = IFTOVT(ip->i_mode)) { 2162 case VCHR: 2163 case VBLK: 2164 vp->v_op = specops; 2165 vp = addaliasu(vp, ip->i_rdev); 2166 ip->i_vnode = vp; 2167 break; 2168 case VFIFO: 2169 vp->v_op = fifoops; 2170 break; 2171 default: 2172 break; 2173 2174 } 2175 if (ip->i_number == ROOTINO) 2176 vp->v_flag |= VROOT; 2177 /* 2178 * Initialize modrev times 2179 */ 2180 getmicrouptime(&tv); 2181 SETHIGH(ip->i_modrev, tv.tv_sec); 2182 SETLOW(ip->i_modrev, tv.tv_usec * 4294); 2183 *vpp = vp; 2184 return (0); 2185} 2186 2187/* 2188 * Allocate a new inode. 2189 * Vnode dvp must be locked. 2190 */ 2191int 2192ufs_makeinode(mode, dvp, vpp, cnp) 2193 int mode; 2194 struct vnode *dvp; 2195 struct vnode **vpp; 2196 struct componentname *cnp; 2197{ 2198 register struct inode *ip, *pdir; 2199 struct direct newdir; 2200 struct vnode *tvp; 2201#ifdef UFS_ACL 2202 struct acl *acl; 2203#endif 2204 int error; 2205 2206 pdir = VTOI(dvp); 2207#ifdef DIAGNOSTIC 2208 if ((cnp->cn_flags & HASBUF) == 0) 2209 panic("ufs_makeinode: no name"); 2210#endif 2211 *vpp = NULL; 2212 if ((mode & IFMT) == 0) 2213 mode |= IFREG; 2214 2215 error = UFS_VALLOC(dvp, mode, cnp->cn_cred, &tvp); 2216 if (error) 2217 return (error); 2218 ip = VTOI(tvp); 2219 ip->i_gid = pdir->i_gid; 2220#ifdef SUIDDIR 2221 { 2222#ifdef QUOTA 2223 struct ucred ucred, *ucp; 2224 ucp = cnp->cn_cred; 2225#endif 2226 /* 2227 * If we are not the owner of the directory, 2228 * and we are hacking owners here, (only do this where told to) 2229 * and we are not giving it TO root, (would subvert quotas) 2230 * then go ahead and give it to the other user. 2231 * Note that this drops off the execute bits for security. 2232 */ 2233 if ((dvp->v_mount->mnt_flag & MNT_SUIDDIR) && 2234 (pdir->i_mode & ISUID) && 2235 (pdir->i_uid != cnp->cn_cred->cr_uid) && pdir->i_uid) { 2236 ip->i_uid = pdir->i_uid; 2237 mode &= ~07111; 2238#ifdef QUOTA 2239 /* 2240 * Make sure the correct user gets charged 2241 * for the space. 2242 * Quickly knock up a dummy credential for the victim. 2243 * XXX This seems to never be accessed out of our 2244 * context so a stack variable is ok. 2245 */ 2246 ucred.cr_ref = 1; 2247 ucred.cr_uid = ip->i_uid; 2248 ucred.cr_ngroups = 1; 2249 ucred.cr_groups[0] = pdir->i_gid; 2250 ucp = &ucred; 2251#endif 2252 } else 2253 ip->i_uid = cnp->cn_cred->cr_uid; 2254 2255#ifdef QUOTA 2256 if ((error = getinoquota(ip)) || 2257 (error = chkiq(ip, 1, ucp, 0))) { 2258 UFS_VFREE(tvp, ip->i_number, mode); 2259 vput(tvp); 2260 return (error); 2261 } 2262#endif 2263 } 2264#else /* !SUIDDIR */ 2265 ip->i_uid = cnp->cn_cred->cr_uid; 2266#ifdef QUOTA 2267 if ((error = getinoquota(ip)) || 2268 (error = chkiq(ip, 1, cnp->cn_cred, 0))) { 2269 UFS_VFREE(tvp, ip->i_number, mode); 2270 vput(tvp); 2271 return (error); 2272 } 2273#endif 2274#endif /* !SUIDDIR */ 2275 ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE; 2276#ifdef UFS_ACL 2277 MALLOC(acl, struct acl *, sizeof(*acl), M_ACL, M_WAITOK); 2278 /* 2279 * Retrieve default ACL for parent, if any. 2280 */ 2281 error = VOP_GETACL(dvp, ACL_TYPE_DEFAULT, acl, cnp->cn_cred, 2282 cnp->cn_proc); 2283 switch (error) { 2284 case 0: 2285 /* 2286 * Retrieved a default ACL, so merge mode and ACL if 2287 * necessary. 2288 */ 2289 if (acl->acl_cnt != 0) { 2290 /* 2291 * Two possible ways for default ACL to not be 2292 * present. First, the EA can be undefined, 2293 * or second, the default ACL can be blank. 2294 * If it's blank, fall through to the it's 2295 * not defined case. 2296 */ 2297 ip->i_mode = mode; 2298 ufs_sync_acl_from_inode(ip, acl); 2299 break; 2300 } 2301 2302 case EOPNOTSUPP: 2303 /* 2304 * Just use the mode as-is. 2305 */ 2306 ip->i_mode = mode; 2307 FREE(acl, M_ACL); 2308 acl = NULL; 2309 break; 2310 2311 default: 2312 UFS_VFREE(tvp, ip->i_number, mode); 2313 vput(tvp); 2314 return (error); 2315 } 2316#else /* !UFS_ACL */ 2317 ip->i_mode = mode; 2318#endif /* !UFS_ACL */ 2319 tvp->v_type = IFTOVT(mode); /* Rest init'd in getnewvnode(). */ 2320 ip->i_effnlink = 1; 2321 ip->i_nlink = 1; 2322 if (DOINGSOFTDEP(tvp)) 2323 softdep_change_linkcnt(ip); 2324 if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, cnp->cn_cred) && 2325 suser_xxx(cnp->cn_cred, NULL, PRISON_ROOT)) 2326 ip->i_mode &= ~ISGID; 2327 2328 if (cnp->cn_flags & ISWHITEOUT) 2329 ip->i_flags |= UF_OPAQUE; 2330 2331 /* 2332 * Make sure inode goes to disk before directory entry. 2333 */ 2334 error = UFS_UPDATE(tvp, !(DOINGSOFTDEP(tvp) | DOINGASYNC(tvp))); 2335 if (error) 2336 goto bad; 2337#ifdef UFS_ACL 2338 if (acl != NULL) { 2339 /* 2340 * XXX: If we abort now, will Soft Updates notify the extattr 2341 * code that the EAs for the file need to be released? 2342 */ 2343 error = VOP_SETACL(tvp, ACL_TYPE_ACCESS, acl, cnp->cn_cred, 2344 cnp->cn_proc); 2345 switch (error) { 2346 case 0: 2347 break; 2348 2349 case EOPNOTSUPP: 2350 /* 2351 * XXX: This should not happen, as EOPNOTSUPP above was 2352 * supposed to free acl. 2353 */ 2354 printf("ufs_makeinode: VOP_GETACL() but no " 2355 "VOP_SETACL()\n"); 2356 /* panic("ufs_makeinode: VOP_GETACL() but no " 2357 "VOP_SETACL()"); */ 2358 break; 2359 2360 default: 2361 FREE(acl, M_ACL); 2362 goto bad; 2363 } 2364 FREE(acl, M_ACL); 2365 } 2366#endif /* !UFS_ACL */ 2367 ufs_makedirentry(ip, cnp, &newdir); 2368 error = ufs_direnter(dvp, tvp, &newdir, cnp, NULL); 2369 if (error) 2370 goto bad; 2371 *vpp = tvp; 2372 return (0); 2373 2374bad: 2375 /* 2376 * Write error occurred trying to update the inode 2377 * or the directory so must deallocate the inode. 2378 */ 2379 ip->i_effnlink = 0; 2380 ip->i_nlink = 0; 2381 ip->i_flag |= IN_CHANGE; 2382 if (DOINGSOFTDEP(tvp)) 2383 softdep_change_linkcnt(ip); 2384 vput(tvp); 2385 return (error); 2386} 2387 2388static int 2389ufs_missingop(ap) 2390 struct vop_generic_args *ap; 2391{ 2392 2393 panic("no vop function for %s in ufs child", ap->a_desc->vdesc_name); 2394 return (EOPNOTSUPP); 2395} 2396 2397static struct filterops ufsread_filtops = 2398 { 1, NULL, filt_ufsdetach, filt_ufsread }; 2399static struct filterops ufsvnode_filtops = 2400 { 1, NULL, filt_ufsdetach, filt_ufsvnode }; 2401 2402static int 2403ufs_kqfilter(ap) 2404 struct vop_kqfilter_args /* { 2405 struct vnode *a_vp; 2406 struct knote *a_kn; 2407 } */ *ap; 2408{ 2409 struct vnode *vp = ap->a_vp; 2410 struct knote *kn = ap->a_kn; 2411 2412 switch (kn->kn_filter) { 2413 case EVFILT_READ: 2414 kn->kn_fop = &ufsread_filtops; 2415 break; 2416 case EVFILT_VNODE: 2417 kn->kn_fop = &ufsvnode_filtops; 2418 break; 2419 default: 2420 return (1); 2421 } 2422 2423 kn->kn_hook = (caddr_t)vp; 2424 2425 mtx_lock(&vp->v_pollinfo.vpi_lock); 2426 SLIST_INSERT_HEAD(&vp->v_pollinfo.vpi_selinfo.si_note, kn, kn_selnext); 2427 mtx_unlock(&vp->v_pollinfo.vpi_lock); 2428 2429 return (0); 2430} 2431 2432static void 2433filt_ufsdetach(struct knote *kn) 2434{ 2435 struct vnode *vp = (struct vnode *)kn->kn_hook; 2436 2437 mtx_lock(&vp->v_pollinfo.vpi_lock); 2438 SLIST_REMOVE(&vp->v_pollinfo.vpi_selinfo.si_note, 2439 kn, knote, kn_selnext); 2440 mtx_unlock(&vp->v_pollinfo.vpi_lock); 2441} 2442 2443/*ARGSUSED*/ 2444static int 2445filt_ufsread(struct knote *kn, long hint) 2446{ 2447 struct vnode *vp = (struct vnode *)kn->kn_hook; 2448 struct inode *ip = VTOI(vp); 2449 2450 /* 2451 * filesystem is gone, so set the EOF flag and schedule 2452 * the knote for deletion. 2453 */ 2454 if (hint == NOTE_REVOKE) { 2455 kn->kn_flags |= (EV_EOF | EV_ONESHOT); 2456 return (1); 2457 } 2458 2459 kn->kn_data = ip->i_size - kn->kn_fp->f_offset; 2460 return (kn->kn_data != 0); 2461} 2462 2463static int 2464filt_ufsvnode(struct knote *kn, long hint) 2465{ 2466 2467 if (kn->kn_sfflags & hint) 2468 kn->kn_fflags |= hint; 2469 if (hint == NOTE_REVOKE) { 2470 kn->kn_flags |= EV_EOF; 2471 return (1); 2472 } 2473 return (kn->kn_fflags != 0); 2474} 2475 2476/* Global vfs data structures for ufs. */ 2477static vop_t **ufs_vnodeop_p; 2478static struct vnodeopv_entry_desc ufs_vnodeop_entries[] = { 2479 { &vop_default_desc, (vop_t *) vop_defaultop }, 2480 { &vop_fsync_desc, (vop_t *) ufs_missingop }, 2481 { &vop_read_desc, (vop_t *) ufs_missingop }, 2482 { &vop_reallocblks_desc, (vop_t *) ufs_missingop }, 2483 { &vop_write_desc, (vop_t *) ufs_missingop }, 2484 { &vop_access_desc, (vop_t *) ufs_access }, 2485 { &vop_advlock_desc, (vop_t *) ufs_advlock }, 2486 { &vop_bmap_desc, (vop_t *) ufs_bmap }, 2487 { &vop_cachedlookup_desc, (vop_t *) ufs_lookup }, 2488 { &vop_close_desc, (vop_t *) ufs_close }, 2489 { &vop_create_desc, (vop_t *) ufs_create }, 2490 { &vop_getattr_desc, (vop_t *) ufs_getattr }, 2491 { &vop_inactive_desc, (vop_t *) ufs_inactive }, 2492 { &vop_islocked_desc, (vop_t *) vop_stdislocked }, 2493 { &vop_link_desc, (vop_t *) ufs_link }, 2494 { &vop_lock_desc, (vop_t *) vop_stdlock }, 2495 { &vop_lookup_desc, (vop_t *) vfs_cache_lookup }, 2496 { &vop_mkdir_desc, (vop_t *) ufs_mkdir }, 2497 { &vop_mknod_desc, (vop_t *) ufs_mknod }, 2498 { &vop_open_desc, (vop_t *) ufs_open }, 2499 { &vop_pathconf_desc, (vop_t *) ufs_pathconf }, 2500 { &vop_poll_desc, (vop_t *) vop_stdpoll }, 2501 { &vop_kqfilter_desc, (vop_t *) ufs_kqfilter }, 2502 { &vop_getwritemount_desc, (vop_t *) vop_stdgetwritemount }, 2503 { &vop_print_desc, (vop_t *) ufs_print }, 2504 { &vop_readdir_desc, (vop_t *) ufs_readdir }, 2505 { &vop_readlink_desc, (vop_t *) ufs_readlink }, 2506 { &vop_reclaim_desc, (vop_t *) ufs_reclaim }, 2507 { &vop_remove_desc, (vop_t *) ufs_remove }, 2508 { &vop_rename_desc, (vop_t *) ufs_rename }, 2509 { &vop_rmdir_desc, (vop_t *) ufs_rmdir }, 2510 { &vop_setattr_desc, (vop_t *) ufs_setattr }, 2511 { &vop_strategy_desc, (vop_t *) ufs_strategy }, 2512 { &vop_symlink_desc, (vop_t *) ufs_symlink }, 2513 { &vop_unlock_desc, (vop_t *) vop_stdunlock }, 2514 { &vop_whiteout_desc, (vop_t *) ufs_whiteout }, 2515#ifdef UFS_ACL 2516 { &vop_getacl_desc, (vop_t *) ufs_getacl }, 2517 { &vop_setacl_desc, (vop_t *) ufs_setacl }, 2518 { &vop_aclcheck_desc, (vop_t *) ufs_aclcheck }, 2519#endif 2520 { NULL, NULL } 2521}; 2522static struct vnodeopv_desc ufs_vnodeop_opv_desc = 2523 { &ufs_vnodeop_p, ufs_vnodeop_entries }; 2524 2525static vop_t **ufs_specop_p; 2526static struct vnodeopv_entry_desc ufs_specop_entries[] = { 2527 { &vop_default_desc, (vop_t *) spec_vnoperate }, 2528 { &vop_fsync_desc, (vop_t *) ufs_missingop }, 2529 { &vop_access_desc, (vop_t *) ufs_access }, 2530 { &vop_close_desc, (vop_t *) ufsspec_close }, 2531 { &vop_getattr_desc, (vop_t *) ufs_getattr }, 2532 { &vop_inactive_desc, (vop_t *) ufs_inactive }, 2533 { &vop_islocked_desc, (vop_t *) vop_stdislocked }, 2534 { &vop_lock_desc, (vop_t *) vop_stdlock }, 2535 { &vop_print_desc, (vop_t *) ufs_print }, 2536 { &vop_read_desc, (vop_t *) ufsspec_read }, 2537 { &vop_reclaim_desc, (vop_t *) ufs_reclaim }, 2538 { &vop_setattr_desc, (vop_t *) ufs_setattr }, 2539 { &vop_unlock_desc, (vop_t *) vop_stdunlock }, 2540 { &vop_write_desc, (vop_t *) ufsspec_write }, 2541#ifdef UFS_ACL 2542 { &vop_getacl_desc, (vop_t *) ufs_getacl }, 2543 { &vop_setacl_desc, (vop_t *) ufs_setacl }, 2544 { &vop_aclcheck_desc, (vop_t *) ufs_aclcheck }, 2545#endif 2546 {NULL, NULL} 2547}; 2548static struct vnodeopv_desc ufs_specop_opv_desc = 2549 { &ufs_specop_p, ufs_specop_entries }; 2550 2551static vop_t **ufs_fifoop_p; 2552static struct vnodeopv_entry_desc ufs_fifoop_entries[] = { 2553 { &vop_default_desc, (vop_t *) fifo_vnoperate }, 2554 { &vop_fsync_desc, (vop_t *) ufs_missingop }, 2555 { &vop_access_desc, (vop_t *) ufs_access }, 2556 { &vop_close_desc, (vop_t *) ufsfifo_close }, 2557 { &vop_getattr_desc, (vop_t *) ufs_getattr }, 2558 { &vop_inactive_desc, (vop_t *) ufs_inactive }, 2559 { &vop_islocked_desc, (vop_t *) vop_stdislocked }, 2560 { &vop_lock_desc, (vop_t *) vop_stdlock }, 2561 { &vop_print_desc, (vop_t *) ufs_print }, 2562 { &vop_read_desc, (vop_t *) ufsfifo_read }, 2563 { &vop_reclaim_desc, (vop_t *) ufs_reclaim }, 2564 { &vop_setattr_desc, (vop_t *) ufs_setattr }, 2565 { &vop_unlock_desc, (vop_t *) vop_stdunlock }, 2566 { &vop_write_desc, (vop_t *) ufsfifo_write }, 2567#ifdef UFS_ACL 2568 { &vop_getacl_desc, (vop_t *) ufs_getacl }, 2569 { &vop_setacl_desc, (vop_t *) ufs_setacl }, 2570 { &vop_aclcheck_desc, (vop_t *) ufs_aclcheck }, 2571#endif 2572 { NULL, NULL } 2573}; 2574static struct vnodeopv_desc ufs_fifoop_opv_desc = 2575 { &ufs_fifoop_p, ufs_fifoop_entries }; 2576 2577VNODEOP_SET(ufs_vnodeop_opv_desc); 2578VNODEOP_SET(ufs_specop_opv_desc); 2579VNODEOP_SET(ufs_fifoop_opv_desc); 2580 2581int 2582ufs_vnoperate(ap) 2583 struct vop_generic_args /* { 2584 struct vnodeop_desc *a_desc; 2585 } */ *ap; 2586{ 2587 return (VOCALL(ufs_vnodeop_p, ap->a_desc->vdesc_offset, ap)); 2588} 2589 2590int 2591ufs_vnoperatefifo(ap) 2592 struct vop_generic_args /* { 2593 struct vnodeop_desc *a_desc; 2594 } */ *ap; 2595{ 2596 return (VOCALL(ufs_fifoop_p, ap->a_desc->vdesc_offset, ap)); 2597} 2598 2599int 2600ufs_vnoperatespec(ap) 2601 struct vop_generic_args /* { 2602 struct vnodeop_desc *a_desc; 2603 } */ *ap; 2604{ 2605 return (VOCALL(ufs_specop_p, ap->a_desc->vdesc_offset, ap)); 2606} 2607