The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/ufs/ufs/ufs_vnops.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: b524f78875932f803b51bd3a8491cde8


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.