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

Cache object: d6afd3704b75e0311b6b45470f72df0a


[ 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.