root/ufs/ufs/ufs_vnops.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ufs_create
  2. ufs_mknod
  3. ufs_open
  4. ufs_close
  5. ufs_access
  6. ufs_getattr
  7. ufs_setattr
  8. ufs_chmod
  9. ufs_chown
  10. ufs_ioctl
  11. ufs_poll
  12. ufs_remove
  13. ufs_link
  14. ufs_rename
  15. ufs_mkdir
  16. ufs_rmdir
  17. ufs_symlink
  18. ufs_readdir
  19. ufs_readlink
  20. ufs_lock
  21. ufs_unlock
  22. ufs_islocked
  23. ufs_strategy
  24. ufs_print
  25. ufsspec_read
  26. ufsspec_write
  27. ufsspec_close
  28. ufsfifo_read
  29. ufsfifo_write
  30. ufsfifo_close
  31. ufs_pathconf
  32. ufs_advlock
  33. ufs_vinit
  34. ufs_makeinode
  35. ufs_kqfilter
  36. filt_ufsdetach
  37. filt_ufsread
  38. filt_ufswrite
  39. filt_ufsvnode

    1 /*      $OpenBSD: ufs_vnops.c,v 1.82 2007/06/20 15:03:40 thib Exp $     */
    2 /*      $NetBSD: ufs_vnops.c,v 1.18 1996/05/11 18:28:04 mycroft Exp $   */
    3 
    4 /*
    5  * Copyright (c) 1982, 1986, 1989, 1993
    6  *      The Regents of the University of California.  All rights reserved.
    7  * (c) UNIX System Laboratories, Inc.
    8  * All or some portions of this file are derived from material licensed
    9  * to the University of California by American Telephone and Telegraph
   10  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
   11  * the permission of UNIX System Laboratories, Inc.
   12  *
   13  * Redistribution and use in source and binary forms, with or without
   14  * modification, are permitted provided that the following conditions
   15  * are met:
   16  * 1. Redistributions of source code must retain the above copyright
   17  *    notice, this list of conditions and the following disclaimer.
   18  * 2. Redistributions in binary form must reproduce the above copyright
   19  *    notice, this list of conditions and the following disclaimer in the
   20  *    documentation and/or other materials provided with the distribution.
   21  * 3. Neither the name of the University nor the names of its contributors
   22  *    may be used to endorse or promote products derived from this software
   23  *    without specific prior written permission.
   24  *
   25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   35  * SUCH DAMAGE.
   36  *
   37  *      @(#)ufs_vnops.c 8.14 (Berkeley) 10/26/94
   38  */
   39 
   40 #include <sys/param.h>
   41 #include <sys/systm.h>
   42 #include <sys/namei.h>
   43 #include <sys/resourcevar.h>
   44 #include <sys/kernel.h>
   45 #include <sys/file.h>
   46 #include <sys/stat.h>
   47 #include <sys/buf.h>
   48 #include <sys/proc.h>
   49 #include <sys/conf.h>
   50 #include <sys/mount.h>
   51 #include <sys/vnode.h>
   52 #include <sys/malloc.h>
   53 #include <sys/pool.h>
   54 #include <sys/dirent.h>
   55 #include <sys/lockf.h>
   56 #include <sys/event.h>
   57 #include <sys/poll.h>
   58 
   59 #include <uvm/uvm_extern.h>
   60 
   61 #include <miscfs/specfs/specdev.h>
   62 #include <miscfs/fifofs/fifo.h>
   63 
   64 #include <ufs/ufs/quota.h>
   65 #include <ufs/ufs/inode.h>
   66 #include <ufs/ufs/dir.h>
   67 #include <ufs/ufs/ufsmount.h>
   68 #include <ufs/ufs/ufs_extern.h>
   69 #ifdef UFS_DIRHASH
   70 #include <ufs/ufs/dirhash.h>
   71 #endif
   72 #include <ufs/ext2fs/ext2fs_extern.h>
   73 
   74 static int ufs_chmod(struct vnode *, int, struct ucred *, struct proc *);
   75 static int ufs_chown(struct vnode *, uid_t, gid_t, struct ucred *, struct proc *);
   76 int filt_ufsread(struct knote *, long);
   77 int filt_ufswrite(struct knote *, long);
   78 int filt_ufsvnode(struct knote *, long);
   79 void filt_ufsdetach(struct knote *);
   80 
   81 union _qcvt {
   82         int64_t qcvt;
   83         int32_t val[2];
   84 };
   85 
   86 #define SETHIGH(q, h) { \
   87         union _qcvt tmp; \
   88         tmp.qcvt = (q); \
   89         tmp.val[_QUAD_HIGHWORD] = (h); \
   90         (q) = tmp.qcvt; \
   91 }
   92 #define SETLOW(q, l) { \
   93         union _qcvt tmp; \
   94         tmp.qcvt = (q); \
   95         tmp.val[_QUAD_LOWWORD] = (l); \
   96         (q) = tmp.qcvt; \
   97 }
   98 
   99 /*
  100  * A virgin directory (no blushing please).
  101  */
  102 static struct dirtemplate mastertemplate = {
  103         0, 12, DT_DIR, 1, ".",
  104         0, DIRBLKSIZ - 12, DT_DIR, 2, ".."
  105 };
  106 static struct odirtemplate omastertemplate = {
  107         0, 12, 1, ".",
  108         0, DIRBLKSIZ - 12, 2, ".."
  109 };
  110 
  111 /*
  112  * Create a regular file
  113  */
  114 int
  115 ufs_create(void *v)
  116 {
  117         struct vop_create_args *ap = v;
  118         int error;
  119 
  120         error =
  121             ufs_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode),
  122                           ap->a_dvp, ap->a_vpp, ap->a_cnp);
  123         if (error)
  124                 return (error);
  125         VN_KNOTE(ap->a_dvp, NOTE_WRITE);
  126         return (0);
  127 }
  128 
  129 /*
  130  * Mknod vnode call
  131  */
  132 /* ARGSUSED */
  133 int
  134 ufs_mknod(void *v)
  135 {
  136         struct vop_mknod_args *ap = v;
  137         struct vattr *vap = ap->a_vap;
  138         struct vnode **vpp = ap->a_vpp;
  139         struct inode *ip;
  140         int error;
  141 
  142         if ((error =
  143              ufs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode),
  144                            ap->a_dvp, vpp, ap->a_cnp)) != 0)
  145                 return (error);
  146         VN_KNOTE(ap->a_dvp, NOTE_WRITE);
  147         ip = VTOI(*vpp);
  148         ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
  149         if (vap->va_rdev != VNOVAL) {
  150                 /*
  151                  * Want to be able to use this to make badblock
  152                  * inodes, so don't truncate the dev number.
  153                  */
  154                 DIP_ASSIGN(ip, rdev, vap->va_rdev);
  155         }
  156         /*
  157          * Remove inode so that it will be reloaded by VFS_VGET and
  158          * checked to see if it is an alias of an existing entry in
  159          * the inode cache.
  160          */
  161         vput(*vpp);
  162         (*vpp)->v_type = VNON;
  163         vgone(*vpp);
  164         *vpp = 0;
  165         return (0);
  166 }
  167 
  168 /*
  169  * Open called.
  170  *
  171  * Nothing to do.
  172  */
  173 /* ARGSUSED */
  174 int
  175 ufs_open(void *v)
  176 {
  177         struct vop_open_args *ap = v;
  178         struct inode *ip = VTOI(ap->a_vp);
  179 
  180         /*
  181          * Files marked append-only must be opened for appending.
  182          */
  183         if ((DIP(ip, flags) & APPEND) &&
  184             (ap->a_mode & (FWRITE | O_APPEND)) == FWRITE)
  185                 return (EPERM);
  186 
  187         if (ap->a_mode & O_TRUNC)
  188                 ip->i_flag |= IN_CHANGE | IN_UPDATE;
  189 
  190         return (0);
  191 }
  192 
  193 /*
  194  * Close called.
  195  *
  196  * Update the times on the inode.
  197  */
  198 /* ARGSUSED */
  199 int
  200 ufs_close(void *v)
  201 {
  202         struct vop_close_args *ap = v;
  203         struct vnode *vp = ap->a_vp;
  204         struct inode *ip = VTOI(vp);
  205 
  206         if (vp->v_usecount > 1) {
  207                 struct timeval tv;
  208 
  209                 getmicrotime(&tv);
  210                 ITIMES(ip, &tv, &tv);
  211         }
  212         return (0);
  213 }
  214 
  215 int
  216 ufs_access(void *v)
  217 {
  218         struct vop_access_args *ap = v;
  219         struct vnode *vp = ap->a_vp;
  220         struct inode *ip = VTOI(vp);
  221         mode_t mode = ap->a_mode;
  222 
  223         /*
  224          * Disallow write attempts on read-only file systems;
  225          * unless the file is a socket, fifo, or a block or
  226          * character device resident on the file system.
  227          */
  228         if (mode & VWRITE) {
  229                 switch (vp->v_type) {
  230                         int error;
  231                 case VDIR:
  232                 case VLNK:
  233                 case VREG:
  234                         if (vp->v_mount->mnt_flag & MNT_RDONLY)
  235                                 return (EROFS);
  236 
  237                         if ((error = getinoquota(ip)) != 0)
  238                                 return (error);
  239                         break;
  240                 case VBAD:
  241                 case VBLK:
  242                 case VCHR:
  243                 case VSOCK:
  244                 case VFIFO:
  245                 case VNON:
  246                         break;
  247 
  248                 }
  249         }
  250 
  251         /* If immutable bit set, nobody gets to write it. */
  252         if ((mode & VWRITE) && (DIP(ip, flags) & IMMUTABLE))
  253                 return (EPERM);
  254 
  255         return (vaccess(DIP(ip, mode), DIP(ip, uid), DIP(ip, gid), mode,
  256             ap->a_cred));
  257 }
  258 
  259 /* ARGSUSED */
  260 int
  261 ufs_getattr(void *v)
  262 {
  263         struct vop_getattr_args *ap = v;
  264         struct vnode *vp = ap->a_vp;
  265         struct inode *ip = VTOI(vp);
  266         struct vattr *vap = ap->a_vap;
  267         struct timeval tv;
  268 
  269         getmicrotime(&tv);
  270         ITIMES(ip, &tv, &tv);
  271         /*
  272          * Copy from inode table
  273          */
  274         vap->va_fsid = ip->i_dev;
  275         vap->va_fileid = ip->i_number;
  276         vap->va_mode = DIP(ip, mode) & ~IFMT;
  277         vap->va_nlink = ip->i_effnlink;
  278         vap->va_uid = DIP(ip, uid);
  279         vap->va_gid = DIP(ip, gid);
  280         vap->va_rdev = (dev_t) DIP(ip, rdev);
  281         vap->va_size = DIP(ip, size);
  282         vap->va_atime.tv_sec = DIP(ip, atime);
  283         vap->va_atime.tv_nsec = DIP(ip, atimensec);
  284         vap->va_mtime.tv_sec = DIP(ip, mtime);
  285         vap->va_mtime.tv_nsec = DIP(ip, mtimensec);
  286         vap->va_ctime.tv_sec = DIP(ip, ctime);
  287         vap->va_ctime.tv_nsec = DIP(ip, ctimensec);
  288         vap->va_flags = DIP(ip, flags);
  289         vap->va_gen = DIP(ip, gen);
  290         /* this doesn't belong here */
  291         if (vp->v_type == VBLK)
  292                 vap->va_blocksize = BLKDEV_IOSIZE;
  293         else if (vp->v_type == VCHR)
  294                 vap->va_blocksize = MAXBSIZE;
  295         else
  296                 vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize;
  297         vap->va_bytes = dbtob((u_quad_t) DIP(ip, blocks));
  298         vap->va_type = vp->v_type;
  299         vap->va_filerev = ip->i_modrev;
  300         return (0);
  301 }
  302 
  303 /*
  304  * Set attribute vnode op. called from several syscalls
  305  */
  306 int
  307 ufs_setattr(void *v)
  308 {
  309         struct vop_setattr_args *ap = v;
  310         struct vattr *vap = ap->a_vap;
  311         struct vnode *vp = ap->a_vp;
  312         struct inode *ip = VTOI(vp);
  313         struct ucred *cred = ap->a_cred;
  314         struct proc *p = ap->a_p;
  315         int error;
  316         long hint = NOTE_ATTRIB;
  317         u_quad_t oldsize;
  318 
  319         /*
  320          * Check for unsettable attributes.
  321          */
  322         if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
  323             (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
  324             (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
  325             ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
  326                 return (EINVAL);
  327         }
  328         if (vap->va_flags != VNOVAL) {
  329                 if (vp->v_mount->mnt_flag & MNT_RDONLY)
  330                         return (EROFS);
  331                 if (cred->cr_uid != DIP(ip, uid) &&
  332                     (error = suser_ucred(cred)))
  333                         return (error);
  334                 if (cred->cr_uid == 0) {
  335                         if ((DIP(ip, flags) & (SF_IMMUTABLE | SF_APPEND)) &&
  336                             securelevel > 0)
  337                                 return (EPERM);
  338                         DIP_ASSIGN(ip, flags, vap->va_flags);
  339                 } else {
  340                         if (DIP(ip, flags) & (SF_IMMUTABLE | SF_APPEND) ||
  341                             (vap->va_flags & UF_SETTABLE) != vap->va_flags)
  342                                 return (EPERM);
  343                         DIP(ip, flags) &= SF_SETTABLE;
  344                         DIP(ip, flags) |= (vap->va_flags & UF_SETTABLE);
  345                 }
  346                 ip->i_flag |= IN_CHANGE;
  347                 if (vap->va_flags & (IMMUTABLE | APPEND))
  348                         return (0);
  349         }
  350         if (DIP(ip, flags) & (IMMUTABLE | APPEND))
  351                 return (EPERM);
  352         /*
  353          * Go through the fields and update if not VNOVAL.
  354          */
  355         if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) {
  356                 if (vp->v_mount->mnt_flag & MNT_RDONLY)
  357                         return (EROFS);
  358                 error = ufs_chown(vp, vap->va_uid, vap->va_gid, cred, p);
  359                 if (error)
  360                         return (error);
  361         }
  362         if (vap->va_size != VNOVAL) {
  363                 oldsize = DIP(ip, size);
  364                 /*
  365                  * Disallow write attempts on read-only file systems;
  366                  * unless the file is a socket, fifo, or a block or
  367                  * character device resident on the file system.
  368                  */
  369                 switch (vp->v_type) {
  370                 case VDIR:
  371                         return (EISDIR);
  372                 case VLNK:
  373                 case VREG:
  374                         if (vp->v_mount->mnt_flag & MNT_RDONLY)
  375                                 return (EROFS);
  376                         break;
  377                 default:
  378                         break;
  379                 }
  380                 if ((error = UFS_TRUNCATE(ip, vap->va_size, 0, cred)) != 0)
  381                         return (error);
  382                 if (vap->va_size < oldsize)
  383                         hint |= NOTE_TRUNCATE;
  384         }
  385         if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
  386                 if (vp->v_mount->mnt_flag & MNT_RDONLY)
  387                         return (EROFS);
  388                 if (cred->cr_uid != DIP(ip, uid) &&
  389                     (error = suser_ucred(cred)) &&
  390                     ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || 
  391                     (error = VOP_ACCESS(vp, VWRITE, cred, p))))
  392                         return (error);
  393                 if (vap->va_atime.tv_sec != VNOVAL)
  394                         ip->i_flag |= IN_ACCESS;
  395                 if (vap->va_mtime.tv_sec != VNOVAL)
  396                         ip->i_flag |= IN_CHANGE | IN_UPDATE;
  397                 error = UFS_UPDATE2(ip, &vap->va_atime, &vap->va_mtime, 0);
  398                 if (error)
  399                         return (error);
  400         }
  401         error = 0;
  402         if (vap->va_mode != (mode_t)VNOVAL) {
  403                 if (vp->v_mount->mnt_flag & MNT_RDONLY)
  404                         return (EROFS);
  405                 error = ufs_chmod(vp, (int)vap->va_mode, cred, p);
  406         }
  407         VN_KNOTE(vp, hint);
  408         return (error);
  409 }
  410 
  411 /*
  412  * Change the mode on a file.
  413  * Inode must be locked before calling.
  414  */
  415 static int
  416 ufs_chmod(struct vnode *vp, int mode, struct ucred *cred, struct proc *p)
  417 {
  418         struct inode *ip = VTOI(vp);
  419         int error;
  420 
  421         if (cred->cr_uid != DIP(ip, uid) &&
  422             (error = suser_ucred(cred)))
  423                 return (error);
  424         if (cred->cr_uid) {
  425                 if (vp->v_type != VDIR && (mode & S_ISTXT))
  426                         return (EFTYPE);
  427                 if (!groupmember(DIP(ip, gid), cred) && (mode & ISGID))
  428                         return (EPERM);
  429         }
  430         DIP(ip, mode) &= ~ALLPERMS;
  431         DIP(ip, mode) |= (mode & ALLPERMS);
  432         ip->i_flag |= IN_CHANGE;
  433         if ((vp->v_flag & VTEXT) && (DIP(ip, mode) & S_ISTXT) == 0)
  434                 (void) uvm_vnp_uncache(vp);
  435         return (0);
  436 }
  437 
  438 /*
  439  * Perform chown operation on inode ip;
  440  * inode must be locked prior to call.
  441  */
  442 static int
  443 ufs_chown(struct vnode *vp, uid_t uid, gid_t gid, struct ucred *cred,
  444     struct proc *p)
  445 {
  446         struct inode *ip = VTOI(vp);
  447         uid_t ouid;
  448         gid_t ogid;
  449         int error = 0;
  450         daddr_t change;
  451         enum ufs_quota_flags quota_flags = 0;
  452 
  453         if (uid == (uid_t)VNOVAL)
  454                 uid = DIP(ip, uid);
  455         if (gid == (gid_t)VNOVAL)
  456                 gid = DIP(ip, gid);
  457         /*
  458          * If we don't own the file, are trying to change the owner
  459          * of the file, or are not a member of the target group,
  460          * the caller must be superuser or the call fails.
  461          */
  462         if ((cred->cr_uid != DIP(ip, uid) || uid != DIP(ip, uid) ||
  463             (gid != DIP(ip, gid) && !groupmember((gid_t)gid, cred))) &&
  464             (error = suser_ucred(cred)))
  465                 return (error);
  466         ogid = DIP(ip, gid);
  467         ouid = DIP(ip, uid);
  468         change = DIP(ip, blocks);
  469 
  470         if (ouid == uid)
  471                 quota_flags |= UFS_QUOTA_NOUID;
  472         
  473         if (ogid == gid)
  474                 quota_flags |= UFS_QUOTA_NOGID;
  475 
  476         if ((error = getinoquota(ip)) != 0)
  477                 return (error);
  478         (void) ufs_quota_free_blocks2(ip, change, cred, quota_flags);
  479         (void) ufs_quota_free_inode2(ip, cred, quota_flags);
  480         (void) ufs_quota_delete(ip);
  481 
  482         DIP_ASSIGN(ip, gid, gid);
  483         DIP_ASSIGN(ip, uid, uid);
  484 
  485         if ((error = getinoquota(ip)) != 0)
  486                 goto error;
  487 
  488         if ((error = ufs_quota_alloc_blocks2(ip, change, cred, 
  489                  quota_flags)) != 0) 
  490                 goto error;
  491 
  492         if ((error = ufs_quota_alloc_inode2(ip, cred ,
  493                  quota_flags)) != 0) {
  494                 (void)ufs_quota_free_blocks2(ip, change, cred, 
  495                     quota_flags);               
  496                 goto error;
  497         }
  498 
  499         if (getinoquota(ip))
  500                 panic("chown: lost quota");
  501 
  502         if (ouid != uid || ogid != gid)
  503                 ip->i_flag |= IN_CHANGE;
  504         if (ouid != uid && cred->cr_uid != 0)
  505                 DIP(ip, mode) &= ~ISUID;
  506         if (ogid != gid && cred->cr_uid != 0)
  507                 DIP(ip, mode) &= ~ISGID;
  508         return (0);
  509 
  510 error:
  511         (void) ufs_quota_delete(ip);
  512 
  513         DIP_ASSIGN(ip, gid, ogid);
  514         DIP_ASSIGN(ip, uid, ouid);
  515 
  516         if (getinoquota(ip) == 0) {
  517                 (void) ufs_quota_alloc_blocks2(ip, change, cred, 
  518                     quota_flags | UFS_QUOTA_FORCE);
  519                 (void) ufs_quota_alloc_inode2(ip, cred,
  520                     quota_flags | UFS_QUOTA_FORCE);
  521                 (void) getinoquota(ip);
  522         }
  523         return (error);
  524 
  525 }
  526 
  527 /* ARGSUSED */
  528 int
  529 ufs_ioctl(void *v)
  530 {
  531 #if 0
  532         struct vop_ioctl_args *ap = v;
  533 #endif
  534         return (ENOTTY);
  535 }
  536 
  537 /* ARGSUSED */
  538 int
  539 ufs_poll(void *v)
  540 {
  541         struct vop_poll_args *ap = v;
  542 
  543         /*
  544          * We should really check to see if I/O is possible.
  545          */
  546         return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
  547 }
  548 
  549 int
  550 ufs_remove(void *v)
  551 {
  552         struct vop_remove_args *ap = v;
  553         struct inode *ip;
  554         struct vnode *vp = ap->a_vp;
  555         struct vnode *dvp = ap->a_dvp;
  556         int error;
  557 
  558         ip = VTOI(vp);
  559         if (vp->v_type == VDIR || (DIP(ip, flags) & (IMMUTABLE | APPEND)) ||
  560             (DIP(VTOI(dvp), flags) & APPEND)) {
  561                 error = EPERM;
  562                 goto out;
  563         }
  564         error = ufs_dirremove(dvp, ip, ap->a_cnp->cn_flags, 0);
  565         VN_KNOTE(vp, NOTE_DELETE);
  566         VN_KNOTE(dvp, NOTE_WRITE);
  567  out:
  568         if (dvp == vp)
  569                 vrele(vp);
  570         else
  571                 vput(vp);
  572         vput(dvp);
  573         return (error);
  574 }
  575 
  576 /*
  577  * link vnode call
  578  */
  579 int
  580 ufs_link(void *v)
  581 {
  582         struct vop_link_args *ap = v;
  583         struct vnode *dvp = ap->a_dvp;
  584         struct vnode *vp = ap->a_vp;
  585         struct componentname *cnp = ap->a_cnp;
  586         struct proc *p = cnp->cn_proc;
  587         struct inode *ip;
  588         struct direct newdir;
  589         int error;
  590 
  591 #ifdef DIAGNOSTIC
  592         if ((cnp->cn_flags & HASBUF) == 0)
  593                 panic("ufs_link: no name");
  594 #endif
  595         if (vp->v_type == VDIR) {
  596                 VOP_ABORTOP(dvp, cnp);
  597                 error = EPERM;
  598                 goto out2;
  599         }
  600         if (dvp->v_mount != vp->v_mount) {
  601                 VOP_ABORTOP(dvp, cnp);
  602                 error = EXDEV;
  603                 goto out2;
  604         }
  605         if (dvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE, p))) {
  606                 VOP_ABORTOP(dvp, cnp);
  607                 goto out2;
  608         }
  609         ip = VTOI(vp);
  610         if ((nlink_t) DIP(ip, nlink) >= LINK_MAX) {
  611                 VOP_ABORTOP(dvp, cnp);
  612                 error = EMLINK;
  613                 goto out1;
  614         }
  615         if (DIP(ip, flags) & (IMMUTABLE | APPEND)) {
  616                 VOP_ABORTOP(dvp, cnp);
  617                 error = EPERM;
  618                 goto out1;
  619         }
  620         ip->i_effnlink++;
  621         DIP_ADD(ip, nlink, 1);
  622         ip->i_flag |= IN_CHANGE;
  623         if (DOINGSOFTDEP(vp))
  624                 softdep_change_linkcnt(ip, 0);
  625         if ((error = UFS_UPDATE(ip, !DOINGSOFTDEP(vp))) == 0) {
  626                 ufs_makedirentry(ip, cnp, &newdir);
  627                 error = ufs_direnter(dvp, vp, &newdir, cnp, NULL);
  628         }
  629         if (error) {
  630                 ip->i_effnlink--;
  631                 DIP_ADD(ip, nlink, -1);
  632                 ip->i_flag |= IN_CHANGE;
  633                 if (DOINGSOFTDEP(vp))
  634                         softdep_change_linkcnt(ip, 0);
  635         }
  636         pool_put(&namei_pool, cnp->cn_pnbuf);
  637         VN_KNOTE(vp, NOTE_LINK);
  638         VN_KNOTE(dvp, NOTE_WRITE);
  639 out1:
  640         if (dvp != vp)
  641                 VOP_UNLOCK(vp, 0, p);
  642 out2:
  643         vput(dvp);
  644         return (error);
  645 }
  646 
  647 /*
  648  * Rename system call.
  649  *      rename("foo", "bar");
  650  * is essentially
  651  *      unlink("bar");
  652  *      link("foo", "bar");
  653  *      unlink("foo");
  654  * but ``atomically''.  Can't do full commit without saving state in the
  655  * inode on disk which isn't feasible at this time.  Best we can do is
  656  * always guarantee the target exists.
  657  *
  658  * Basic algorithm is:
  659  *
  660  * 1) Bump link count on source while we're linking it to the
  661  *    target.  This also ensure the inode won't be deleted out
  662  *    from underneath us while we work (it may be truncated by
  663  *    a concurrent `trunc' or `open' for creation).
  664  * 2) Link source to destination.  If destination already exists,
  665  *    delete it first.
  666  * 3) Unlink source reference to inode if still around. If a
  667  *    directory was moved and the parent of the destination
  668  *    is different from the source, patch the ".." entry in the
  669  *    directory.
  670  */
  671 int
  672 ufs_rename(void *v)
  673 {
  674         struct vop_rename_args *ap = v;
  675         struct vnode *tvp = ap->a_tvp;
  676         struct vnode *tdvp = ap->a_tdvp;
  677         struct vnode *fvp = ap->a_fvp;
  678         struct vnode *fdvp = ap->a_fdvp;
  679         struct componentname *tcnp = ap->a_tcnp;
  680         struct componentname *fcnp = ap->a_fcnp;
  681         struct proc *p = fcnp->cn_proc;
  682         struct inode *ip, *xp, *dp;
  683         struct direct newdir;
  684         int doingdirectory = 0, oldparent = 0, newparent = 0;
  685         int error = 0;
  686 
  687 #ifdef DIAGNOSTIC
  688         if ((tcnp->cn_flags & HASBUF) == 0 ||
  689             (fcnp->cn_flags & HASBUF) == 0)
  690                 panic("ufs_rename: no name");
  691 #endif
  692         /*
  693          * Check for cross-device rename.
  694          */
  695         if ((fvp->v_mount != tdvp->v_mount) ||
  696             (tvp && (fvp->v_mount != tvp->v_mount))) {
  697                 error = EXDEV;
  698 abortit:
  699                 VOP_ABORTOP(tdvp, tcnp);
  700                 if (tdvp == tvp)
  701                         vrele(tdvp);
  702                 else
  703                         vput(tdvp);
  704                 if (tvp)
  705                         vput(tvp);
  706                 VOP_ABORTOP(fdvp, fcnp);
  707                 vrele(fdvp);
  708                 vrele(fvp);
  709                 return (error);
  710         }
  711 
  712         if (tvp && ((DIP(VTOI(tvp), flags) & (IMMUTABLE | APPEND)) ||
  713             (DIP(VTOI(tdvp), flags) & APPEND))) {
  714                 error = EPERM;
  715                 goto abortit;
  716         }
  717 
  718         /*
  719          * Check if just deleting a link name or if we've lost a race.
  720          * If another process completes the same rename after we've looked
  721          * up the source and have blocked looking up the target, then the
  722          * source and target inodes may be identical now although the
  723          * names were never linked.
  724          */
  725         if (fvp == tvp) {
  726                 if (fvp->v_type == VDIR) {
  727                         /*
  728                          * Linked directories are impossible, so we must
  729                          * have lost the race.  Pretend that the rename
  730                          * completed before the lookup.
  731                          */
  732                         error = ENOENT;
  733                         goto abortit;
  734                 }
  735 
  736                 /* Release destination completely. */
  737                 VOP_ABORTOP(tdvp, tcnp);
  738                 vput(tdvp);
  739                 vput(tvp);
  740 
  741                 /*
  742                  * Delete source.  There is another race now that everything
  743                  * is unlocked, but this doesn't cause any new complications.
  744                  * relookup() may find a file that is unrelated to the
  745                  * original one, or it may fail.  Too bad.
  746                  */
  747                 vrele(fvp);
  748                 fcnp->cn_flags &= ~MODMASK;
  749                 fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
  750                 if ((fcnp->cn_flags & SAVESTART) == 0)
  751                         panic("ufs_rename: lost from startdir");
  752                 fcnp->cn_nameiop = DELETE;
  753                 if ((error = relookup(fdvp, &fvp, fcnp)) != 0)
  754                         return (error);         /* relookup did vrele() */
  755                 vrele(fdvp);
  756                 return (VOP_REMOVE(fdvp, fvp, fcnp));
  757         }
  758 
  759         if ((error = vn_lock(fvp, LK_EXCLUSIVE, p)) != 0)
  760                 goto abortit;
  761 
  762         /* fvp, tdvp, tvp now locked */
  763         dp = VTOI(fdvp);
  764         ip = VTOI(fvp);
  765         if ((nlink_t) DIP(ip, nlink) >= LINK_MAX) {
  766                 VOP_UNLOCK(fvp, 0, p);
  767                 error = EMLINK;
  768                 goto abortit;
  769         }
  770         if ((DIP(ip, flags) & (IMMUTABLE | APPEND)) ||
  771             (DIP(dp, flags) & APPEND)) {
  772                 VOP_UNLOCK(fvp, 0, p);
  773                 error = EPERM;
  774                 goto abortit;
  775         }
  776         if ((DIP(ip, mode) & IFMT) == IFDIR) {
  777                 error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_proc);
  778                 if (!error && tvp)
  779                         error = VOP_ACCESS(tvp, VWRITE, tcnp->cn_cred, tcnp->cn_proc);
  780                 if (error) {
  781                         VOP_UNLOCK(fvp, 0, p);
  782                         error = EACCES;
  783                         goto abortit;
  784                 }
  785                 /*
  786                  * Avoid ".", "..", and aliases of "." for obvious reasons.
  787                  */
  788                 if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') ||
  789                     dp == ip ||
  790                     (fcnp->cn_flags & ISDOTDOT) ||
  791                     (tcnp->cn_flags & ISDOTDOT) ||
  792                     (ip->i_flag & IN_RENAME)) {
  793                         VOP_UNLOCK(fvp, 0, p);
  794                         error = EINVAL;
  795                         goto abortit;
  796                 }
  797                 ip->i_flag |= IN_RENAME;
  798                 oldparent = dp->i_number;
  799                 doingdirectory = 1;
  800         }
  801         VN_KNOTE(fdvp, NOTE_WRITE);             /* XXX right place? */
  802 
  803         /*
  804          * When the target exists, both the directory
  805          * and target vnodes are returned locked.
  806          */
  807         dp = VTOI(tdvp);
  808         xp = NULL;
  809         if (tvp)
  810                 xp = VTOI(tvp);
  811 
  812         /*
  813          * 1) Bump link count while we're moving stuff
  814          *    around.  If we crash somewhere before
  815          *    completing our work, the link count
  816          *    may be wrong, but correctable.
  817          */
  818         ip->i_effnlink++;
  819         DIP_ADD(ip, nlink, 1);
  820         ip->i_flag |= IN_CHANGE;
  821         if (DOINGSOFTDEP(fvp))
  822                 softdep_change_linkcnt(ip, 0);
  823         if ((error = UFS_UPDATE(ip, !DOINGSOFTDEP(fvp))) != 0) {
  824                 VOP_UNLOCK(fvp, 0, p);
  825                 goto bad;
  826         }
  827 
  828         /*
  829          * If ".." must be changed (ie the directory gets a new
  830          * parent) then the source directory must not be in the
  831          * directory hierarchy above the target, as this would
  832          * orphan everything below the source directory. Also
  833          * the user must have write permission in the source so
  834          * as to be able to change "..". We must repeat the call 
  835          * to namei, as the parent directory is unlocked by the
  836          * call to checkpath().
  837          */
  838         error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_proc);
  839         VOP_UNLOCK(fvp, 0, p);
  840 
  841         /* tdvp and tvp locked */
  842         if (oldparent != dp->i_number)
  843                 newparent = dp->i_number;
  844         if (doingdirectory && newparent) {
  845                 if (error)      /* write access check above */
  846                         goto bad;
  847                 if (xp != NULL)
  848                         vput(tvp);
  849                 /*
  850                  * Compensate for the reference ufs_checkpath() loses.
  851                  */
  852                 vref(tdvp);
  853                 /* Only tdvp is locked */
  854                 if ((error = ufs_checkpath(ip, dp, tcnp->cn_cred)) != 0) {
  855                         vrele(tdvp);
  856                         goto out;
  857                 }
  858                 if ((tcnp->cn_flags & SAVESTART) == 0)
  859                         panic("ufs_rename: lost to startdir");
  860                 if ((error = relookup(tdvp, &tvp, tcnp)) != 0)
  861                         goto out;
  862                 vrele(tdvp); /* relookup() acquired a reference */
  863                 dp = VTOI(tdvp);
  864                 xp = NULL;
  865                 if (tvp)
  866                         xp = VTOI(tvp);
  867         }
  868         /*
  869          * 2) If target doesn't exist, link the target
  870          *    to the source and unlink the source. 
  871          *    Otherwise, rewrite the target directory
  872          *    entry to reference the source inode and
  873          *    expunge the original entry's existence.
  874          */
  875         if (xp == NULL) {
  876                 if (dp->i_dev != ip->i_dev)
  877                         panic("rename: EXDEV");
  878                 /*
  879                  * Account for ".." in new directory.
  880                  * When source and destination have the same
  881                  * parent we don't fool with the link count.
  882                  */
  883                 if (doingdirectory && newparent) {
  884                         if ((nlink_t) DIP(dp, nlink) >= LINK_MAX) {
  885                                 error = EMLINK;
  886                                 goto bad;
  887                         }
  888                         dp->i_effnlink++;
  889                         DIP_ADD(dp, nlink, 1);
  890                         dp->i_flag |= IN_CHANGE;
  891                         if (DOINGSOFTDEP(tdvp))
  892                                softdep_change_linkcnt(dp, 0);
  893                         if ((error = UFS_UPDATE(dp, !DOINGSOFTDEP(tdvp))) 
  894                             != 0) {
  895                                 dp->i_effnlink--;
  896                                 DIP_ADD(dp, nlink, -1);
  897                                 dp->i_flag |= IN_CHANGE;
  898                                 if (DOINGSOFTDEP(tdvp))
  899                                         softdep_change_linkcnt(dp, 0);
  900                                 goto bad;
  901                         }
  902                 }
  903                 ufs_makedirentry(ip, tcnp, &newdir);
  904                 if ((error = ufs_direnter(tdvp, NULL, &newdir, tcnp, NULL)) != 0) {
  905                         if (doingdirectory && newparent) {
  906                                 dp->i_effnlink--;
  907                                 DIP_ADD(dp, nlink, -1);
  908                                 dp->i_flag |= IN_CHANGE;
  909                                 if (DOINGSOFTDEP(tdvp))
  910                                         softdep_change_linkcnt(dp, 0);
  911                                 (void)UFS_UPDATE(dp, 1);
  912                         }
  913                         goto bad;
  914                 }
  915                 VN_KNOTE(tdvp, NOTE_WRITE);
  916                 vput(tdvp);
  917         } else {
  918                 if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev)
  919                         panic("rename: EXDEV");
  920                 /*
  921                  * Short circuit rename(foo, foo).
  922                  */
  923                 if (xp->i_number == ip->i_number)
  924                         panic("ufs_rename: same file");
  925                 /*
  926                  * If the parent directory is "sticky", then the user must
  927                  * own the parent directory, or the destination of the rename,
  928                  * otherwise the destination may not be changed (except by
  929                  * root). This implements append-only directories.
  930                  */
  931                 if ((DIP(dp, mode) & S_ISTXT) && tcnp->cn_cred->cr_uid != 0 &&
  932                     tcnp->cn_cred->cr_uid != DIP(dp, uid) &&
  933                     DIP(xp, uid )!= tcnp->cn_cred->cr_uid) {
  934                         error = EPERM;
  935                         goto bad;
  936                 }
  937                 /*
  938                  * Target must be empty if a directory and have no links
  939                  * to it. Also, ensure source and target are compatible
  940                  * (both directories, or both not directories).
  941                  */
  942                 if ((DIP(xp, mode) & IFMT) == IFDIR) {
  943                         if (xp->i_effnlink > 2 ||
  944                             !ufs_dirempty(xp, dp->i_number, tcnp->cn_cred)) {
  945                                 error = ENOTEMPTY;
  946                                 goto bad;
  947                         }
  948                         if (!doingdirectory) {
  949                                 error = ENOTDIR;
  950                                 goto bad;
  951                         }
  952                         cache_purge(tdvp);
  953                 } else if (doingdirectory) {
  954                         error = EISDIR;
  955                         goto bad;
  956                 }
  957                 
  958                 if ((error = ufs_dirrewrite(dp, xp, ip->i_number,
  959                    IFTODT(DIP(ip, mode)), (doingdirectory && newparent) ?
  960                    newparent : doingdirectory)) != 0)
  961                         goto bad;
  962                 if (doingdirectory) {
  963                         if (!newparent) {
  964                                 dp->i_effnlink--;
  965                                 if (DOINGSOFTDEP(tdvp))
  966                                         softdep_change_linkcnt(dp, 0);
  967                         }
  968                         xp->i_effnlink--;
  969                         if (DOINGSOFTDEP(tvp))
  970                                 softdep_change_linkcnt(xp, 0);
  971                 }
  972                 if (doingdirectory && !DOINGSOFTDEP(tvp)) {
  973                        /*
  974                         * Truncate inode. The only stuff left in the directory
  975                         * is "." and "..". The "." reference is inconsequential
  976                         * since we are quashing it. We have removed the "."
  977                         * reference and the reference in the parent directory,
  978                         * but there may be other hard links. The soft
  979                         * dependency code will arrange to do these operations
  980                         * after the parent directory entry has been deleted on
  981                         * disk, so when running with that code we avoid doing
  982                         * them now.
  983                         */
  984                         if (!newparent) {
  985                                 DIP_ADD(dp, nlink, -1);
  986                                 dp->i_flag |= IN_CHANGE;
  987                         }
  988 
  989                         DIP_ADD(xp, nlink, -1);
  990                         xp->i_flag |= IN_CHANGE;
  991                         if ((error = UFS_TRUNCATE(VTOI(tvp), (off_t)0, IO_SYNC,
  992                                 tcnp->cn_cred)) != 0)
  993                                 goto bad;
  994                 }
  995                 VN_KNOTE(tdvp, NOTE_WRITE);
  996                 vput(tdvp);
  997                 VN_KNOTE(tvp, NOTE_DELETE);
  998                 vput(tvp);
  999                 xp = NULL;
 1000         }
 1001 
 1002         /*
 1003          * 3) Unlink the source.
 1004          */
 1005         fcnp->cn_flags &= ~MODMASK;
 1006         fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
 1007         if ((fcnp->cn_flags & SAVESTART) == 0)
 1008                 panic("ufs_rename: lost from startdir");
 1009         if ((error = relookup(fdvp, &fvp, fcnp)) != 0) {
 1010                 vrele(ap->a_fvp);
 1011                 return (error);
 1012         }
 1013         vrele(fdvp);
 1014         if (fvp == NULL) {
 1015                 /*
 1016                  * From name has disappeared.
 1017                  */
 1018                 if (doingdirectory)
 1019                         panic("ufs_rename: lost dir entry");
 1020                 vrele(ap->a_fvp);
 1021                 return (0);
 1022         }
 1023 
 1024         xp = VTOI(fvp);
 1025         dp = VTOI(fdvp);
 1026 
 1027         /*
 1028          * Ensure that the directory entry still exists and has not
 1029          * changed while the new name has been entered. If the source is
 1030          * a file then the entry may have been unlinked or renamed. In
 1031          * either case there is no further work to be done. If the source
 1032          * is a directory then it cannot have been rmdir'ed; the IN_RENAME 
 1033          * flag ensures that it cannot be moved by another rename or removed
 1034          * by a rmdir.
 1035          */
 1036         if (xp != ip) {
 1037                 if (doingdirectory)
 1038                         panic("ufs_rename: lost dir entry");
 1039         } else {
 1040                 /*
 1041                  * If the source is a directory with a
 1042                  * new parent, the link count of the old
 1043                  * parent directory must be decremented
 1044                  * and ".." set to point to the new parent.
 1045                  */
 1046                 if (doingdirectory && newparent) {
 1047                         xp->i_offset = mastertemplate.dot_reclen;
 1048                         ufs_dirrewrite(xp, dp, newparent, DT_DIR, 0);
 1049                         cache_purge(fdvp);
 1050                 }
 1051                 error = ufs_dirremove(fdvp, xp, fcnp->cn_flags, 0);
 1052                 xp->i_flag &= ~IN_RENAME;
 1053         }
 1054         VN_KNOTE(fvp, NOTE_RENAME);
 1055         if (dp)
 1056                 vput(fdvp);
 1057         if (xp)
 1058                 vput(fvp);
 1059         vrele(ap->a_fvp);
 1060         return (error);
 1061 
 1062 bad:
 1063         if (xp)
 1064                 vput(ITOV(xp));
 1065         vput(ITOV(dp));
 1066 out:
 1067         vrele(fdvp);
 1068         if (doingdirectory)
 1069                 ip->i_flag &= ~IN_RENAME;
 1070         if (vn_lock(fvp, LK_EXCLUSIVE, p) == 0) {
 1071                 ip->i_effnlink--;
 1072                 DIP_ADD(ip, nlink, -1);
 1073                 ip->i_flag |= IN_CHANGE;
 1074                 ip->i_flag &= ~IN_RENAME;
 1075                 if (DOINGSOFTDEP(fvp))
 1076                         softdep_change_linkcnt(ip, 0);
 1077                 vput(fvp);
 1078         } else
 1079                 vrele(fvp);
 1080         return (error);
 1081 }
 1082 
 1083 /*
 1084  * Mkdir system call
 1085  */
 1086 int
 1087 ufs_mkdir(void *v)
 1088 {
 1089         struct vop_mkdir_args *ap = v;
 1090         struct vnode *dvp = ap->a_dvp;
 1091         struct vattr *vap = ap->a_vap;
 1092         struct componentname *cnp = ap->a_cnp;
 1093         struct inode *ip, *dp;
 1094         struct vnode *tvp;
 1095         struct buf *bp;
 1096         struct direct newdir;
 1097         struct dirtemplate dirtemplate, *dtp;
 1098         int error, dmode, blkoff;
 1099 
 1100 #ifdef DIAGNOSTIC
 1101         if ((cnp->cn_flags & HASBUF) == 0)
 1102                 panic("ufs_mkdir: no name");
 1103 #endif
 1104         dp = VTOI(dvp);
 1105         if ((nlink_t) DIP(dp, nlink) >= LINK_MAX) {
 1106                 error = EMLINK;
 1107                 goto out;
 1108         }
 1109         dmode = vap->va_mode & 0777;
 1110         dmode |= IFDIR;
 1111         /*
 1112          * Must simulate part of ufs_makeinode here to acquire the inode,
 1113          * but not have it entered in the parent directory. The entry is
 1114          * made later after writing "." and ".." entries.
 1115          */
 1116         if ((error = UFS_INODE_ALLOC(dp, dmode, cnp->cn_cred, &tvp)) != 0)
 1117                 goto out;
 1118 
 1119         ip = VTOI(tvp);
 1120 
 1121         DIP_ASSIGN(ip, uid, cnp->cn_cred->cr_uid);
 1122         DIP_ASSIGN(ip, gid, DIP(dp, gid));
 1123 
 1124         if ((error = getinoquota(ip)) ||
 1125             (error = ufs_quota_alloc_inode(ip, cnp->cn_cred))) {
 1126                 pool_put(&namei_pool, cnp->cn_pnbuf);
 1127                 UFS_INODE_FREE(ip, ip->i_number, dmode);
 1128                 vput(tvp);
 1129                 vput(dvp);
 1130                 return (error);
 1131         }
 1132 
 1133         ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
 1134         DIP_ASSIGN(ip, mode, dmode);
 1135         tvp->v_type = VDIR;     /* Rest init'd in getnewvnode(). */
 1136         ip->i_effnlink = 2;
 1137         DIP_ASSIGN(ip, nlink, 2);
 1138         if (DOINGSOFTDEP(tvp))
 1139                 softdep_change_linkcnt(ip, 0);
 1140 
 1141         /*
 1142          * Bump link count in parent directory to reflect work done below.
 1143          * Should be done before reference is create so cleanup is 
 1144          * possible if we crash.
 1145          */
 1146         dp->i_effnlink++;
 1147         DIP_ADD(dp, nlink, 1);
 1148         dp->i_flag |= IN_CHANGE;
 1149         if (DOINGSOFTDEP(dvp))
 1150                 softdep_change_linkcnt(dp, 0);
 1151         if ((error = UFS_UPDATE(dp, !DOINGSOFTDEP(dvp))) != 0)
 1152                 goto bad;
 1153 
 1154         /* 
 1155          * Initialize directory with "." and ".." from static template.
 1156          */
 1157         if (dvp->v_mount->mnt_maxsymlinklen > 0)
 1158                 dtp = &mastertemplate;
 1159         else
 1160                 dtp = (struct dirtemplate *)&omastertemplate;
 1161         dirtemplate = *dtp;
 1162         dirtemplate.dot_ino = ip->i_number;
 1163         dirtemplate.dotdot_ino = dp->i_number;
 1164 
 1165         if ((error = UFS_BUF_ALLOC(ip, (off_t)0, DIRBLKSIZ, cnp->cn_cred,
 1166             B_CLRBUF, &bp)) != 0)
 1167                 goto bad;
 1168         DIP_ASSIGN(ip, size, DIRBLKSIZ);
 1169         ip->i_flag |= IN_CHANGE | IN_UPDATE;
 1170         uvm_vnp_setsize(tvp, DIP(ip, size));
 1171         bcopy((caddr_t)&dirtemplate, (caddr_t)bp->b_data, sizeof dirtemplate);
 1172         if (DOINGSOFTDEP(tvp)) {
 1173                 /*
 1174                  * Ensure that the entire newly allocated block is a
 1175                  * valid directory so that future growth within the
 1176                  * block does not have to ensure that the block is
 1177                  * written before the inode
 1178                  */
 1179                 blkoff = DIRBLKSIZ;
 1180                 while (blkoff < bp->b_bcount) {
 1181                         ((struct direct *)
 1182                          (bp->b_data + blkoff))->d_reclen = DIRBLKSIZ;
 1183                         blkoff += DIRBLKSIZ;
 1184                 }
 1185         }
 1186         if ((error = UFS_UPDATE(ip, !DOINGSOFTDEP(tvp))) != 0) {
 1187                 (void)VOP_BWRITE(bp);
 1188                 goto bad;
 1189         }
 1190 
 1191         /*
 1192          * Directory set up, now install its entry in the parent directory.
 1193          *
 1194          * If we are not doing soft dependencies, then we must write out the
 1195          * buffer containing the new directory body before entering the new
 1196          * name in the parent. If we are doing soft dependencies, then the
 1197          * buffer containing the new directory body will be passed to and
 1198          * released in the soft dependency code after the code has attached
 1199          * an appropriate ordering dependency to the buffer which ensures that
 1200          * the buffer is written before the new name is written in the parent.
 1201          */
 1202         if (!DOINGSOFTDEP(dvp) && ((error = VOP_BWRITE(bp)) != 0))
 1203                 goto bad;
 1204         ufs_makedirentry(ip, cnp, &newdir);
 1205         error = ufs_direnter(dvp, tvp, &newdir, cnp, bp);
 1206   
 1207 bad:
 1208         if (error == 0) {
 1209                 VN_KNOTE(dvp, NOTE_WRITE);
 1210                 *ap->a_vpp = tvp;
 1211         } else {
 1212                 dp->i_effnlink--;
 1213                 DIP_ADD(dp, nlink, -1);
 1214                 dp->i_flag |= IN_CHANGE;
 1215                 if (DOINGSOFTDEP(dvp))
 1216                         softdep_change_linkcnt(dp, 0);
 1217                 /*
 1218                  * No need to do an explicit VOP_TRUNCATE here, vrele will
 1219                  * do this for us because we set the link count to 0.
 1220                  */
 1221                 ip->i_effnlink = 0;
 1222                 DIP_ASSIGN(ip, nlink, 0);
 1223                 ip->i_flag |= IN_CHANGE;
 1224                 if (DOINGSOFTDEP(tvp))
 1225                         softdep_change_linkcnt(ip, 0);
 1226                 vput(tvp);
 1227         }
 1228 out:
 1229         pool_put(&namei_pool, cnp->cn_pnbuf);
 1230         vput(dvp);
 1231 
 1232         return (error);
 1233 }
 1234 
 1235 /*
 1236  * Rmdir system call.
 1237  */
 1238 int
 1239 ufs_rmdir(void *v)
 1240 {
 1241         struct vop_rmdir_args *ap = v;
 1242         struct vnode *vp = ap->a_vp;
 1243         struct vnode *dvp = ap->a_dvp;
 1244         struct componentname *cnp = ap->a_cnp;
 1245         struct inode *ip, *dp;
 1246         int error;
 1247 
 1248         ip = VTOI(vp);
 1249         dp = VTOI(dvp);
 1250         /*
 1251          * No rmdir "." or of mounted on directories.
 1252          */
 1253         if (dp == ip || vp->v_mountedhere != 0) {
 1254                 if (dp == ip)
 1255                         vrele(dvp);
 1256                 else
 1257                         vput(dvp);
 1258                 vput(vp);
 1259                 return (EINVAL);
 1260         }
 1261         /*
 1262          * Do not remove a directory that is in the process of being renamed.
 1263          * Verify the directory is empty (and valid). Rmdir ".." will not be
 1264          * valid since ".." will contain a reference to the current directory
 1265          * and thus be non-empty.
 1266          */
 1267         error = 0;
 1268         if (ip->i_flag & IN_RENAME) {
 1269                 error = EINVAL;
 1270                 goto out;
 1271         }
 1272         if (ip->i_effnlink != 2 ||
 1273             !ufs_dirempty(ip, dp->i_number, cnp->cn_cred)) {
 1274                 error = ENOTEMPTY;
 1275                 goto out;
 1276         }
 1277         if ((DIP(dp, flags) & APPEND) ||
 1278                 (DIP(ip, flags) & (IMMUTABLE | APPEND))) {
 1279                 error = EPERM;
 1280                 goto out;
 1281         }
 1282         /*
 1283          * Delete reference to directory before purging
 1284          * inode.  If we crash in between, the directory
 1285          * will be reattached to lost+found,
 1286          */
 1287         dp->i_effnlink--;
 1288         ip->i_effnlink--;
 1289         if (DOINGSOFTDEP(vp)) {
 1290                 softdep_change_linkcnt(dp, 0);
 1291                 softdep_change_linkcnt(ip, 0);
 1292         }
 1293         if ((error = ufs_dirremove(dvp, ip, cnp->cn_flags, 1)) != 0) {
 1294                 dp->i_effnlink++;
 1295                 ip->i_effnlink++;
 1296                 if (DOINGSOFTDEP(vp)) {
 1297                         softdep_change_linkcnt(dp, 0);
 1298                         softdep_change_linkcnt(ip, 0);
 1299                 }
 1300                 goto out;
 1301         }
 1302 
 1303         VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
 1304         cache_purge(dvp);
 1305         /*
 1306          * Truncate inode. The only stuff left in the directory is "." and
 1307          * "..". The "." reference is inconsequential since we are quashing
 1308          * it. The soft dependency code will arrange to do these operations
 1309          * after the parent directory entry has been deleted on disk, so
 1310          * when running with that code we avoid doing them now.
 1311          */
 1312         if (!DOINGSOFTDEP(vp)) {
 1313                 int ioflag;
 1314 
 1315                 DIP_ADD(dp, nlink, -1);
 1316                 dp->i_flag |= IN_CHANGE;
 1317                 DIP_ADD(ip, nlink, -1);
 1318                 ip->i_flag |= IN_CHANGE;
 1319                 ioflag = DOINGASYNC(vp) ? 0 : IO_SYNC;
 1320                 error = UFS_TRUNCATE(ip, (off_t)0, ioflag, cnp->cn_cred);
 1321         }
 1322         cache_purge(vp);
 1323 #ifdef UFS_DIRHASH
 1324         /* Kill any active hash; i_effnlink == 0, so it will not come back. */
 1325         if (ip->i_dirhash != NULL)
 1326                 ufsdirhash_free(ip);
 1327 #endif
 1328 
 1329 out:
 1330         VN_KNOTE(vp, NOTE_DELETE);
 1331         vput(dvp);
 1332         vput(vp);
 1333         return (error);
 1334 }
 1335 
 1336 /*
 1337  * symlink -- make a symbolic link
 1338  */
 1339 int
 1340 ufs_symlink(void *v)
 1341 {
 1342         struct vop_symlink_args *ap = v;
 1343         struct vnode *vp, **vpp = ap->a_vpp;
 1344         struct inode *ip;
 1345         int len, error;
 1346 
 1347         error = ufs_makeinode(IFLNK | ap->a_vap->va_mode, ap->a_dvp,
 1348                               vpp, ap->a_cnp);
 1349         if (error)
 1350                 return (error);
 1351         VN_KNOTE(ap->a_dvp, NOTE_WRITE);
 1352         vp = *vpp;
 1353         len = strlen(ap->a_target);
 1354         if (len < vp->v_mount->mnt_maxsymlinklen) {
 1355                 ip = VTOI(vp);
 1356                 bcopy(ap->a_target, (char *)SHORTLINK(ip), len);
 1357                 DIP_ASSIGN(ip, size, len);
 1358                 ip->i_flag |= IN_CHANGE | IN_UPDATE;
 1359         } else
 1360                 error = vn_rdwr(UIO_WRITE, vp, ap->a_target, len, (off_t)0,
 1361                     UIO_SYSSPACE, IO_NODELOCKED, ap->a_cnp->cn_cred, NULL,
 1362                     (struct proc *)0);
 1363         vput(vp);
 1364         return (error);
 1365 }
 1366 
 1367 /*
 1368  * Vnode op for reading directories.
 1369  * 
 1370  * The routine below assumes that the on-disk format of a directory
 1371  * is the same as that defined by <sys/dirent.h>. If the on-disk
 1372  * format changes, then it will be necessary to do a conversion
 1373  * from the on-disk format that read returns to the format defined
 1374  * by <sys/dirent.h>.
 1375  */
 1376 int
 1377 ufs_readdir(void *v)
 1378 {
 1379         struct vop_readdir_args *ap = v;
 1380         struct uio *uio = ap->a_uio;
 1381         int error;
 1382         size_t count, lost, entries;
 1383         off_t off = uio->uio_offset;
 1384 
 1385         count = uio->uio_resid;
 1386         entries = (uio->uio_offset + count) & (DIRBLKSIZ - 1);
 1387 
 1388         /* Make sure we don't return partial entries. */
 1389         if (count <= entries)
 1390                 return (EINVAL);
 1391 
 1392         count -= entries;
 1393         lost = uio->uio_resid - count;
 1394         uio->uio_resid = count;
 1395         uio->uio_iov->iov_len = count;
 1396 #       if (BYTE_ORDER == LITTLE_ENDIAN)
 1397                 if (ap->a_vp->v_mount->mnt_maxsymlinklen > 0) {
 1398                         error = VOP_READ(ap->a_vp, uio, 0, ap->a_cred);
 1399                 } else {
 1400                         struct dirent *dp, *edp;
 1401                         struct uio auio;
 1402                         struct iovec aiov;
 1403                         caddr_t dirbuf;
 1404                         int readcnt;
 1405                         u_char tmp;
 1406 
 1407                         auio = *uio;
 1408                         auio.uio_iov = &aiov;
 1409                         auio.uio_iovcnt = 1;
 1410                         auio.uio_segflg = UIO_SYSSPACE;
 1411                         aiov.iov_len = count;
 1412                         MALLOC(dirbuf, caddr_t, count, M_TEMP, M_WAITOK);
 1413                         aiov.iov_base = dirbuf;
 1414                         error = VOP_READ(ap->a_vp, &auio, 0, ap->a_cred);
 1415                         if (error == 0) {
 1416                                 readcnt = count - auio.uio_resid;
 1417                                 edp = (struct dirent *)&dirbuf[readcnt];
 1418                                 for (dp = (struct dirent *)dirbuf; dp < edp; ) {
 1419                                         tmp = dp->d_namlen;
 1420                                         dp->d_namlen = dp->d_type;
 1421                                         dp->d_type = tmp;
 1422                                         if (dp->d_reclen > 0) {
 1423                                                 dp = (struct dirent *)
 1424                                                     ((char *)dp + dp->d_reclen);
 1425                                         } else {
 1426                                                 error = EIO;
 1427                                                 break;
 1428                                         }
 1429                                 }
 1430                                 if (dp >= edp)
 1431                                         error = uiomove(dirbuf, readcnt, uio);
 1432                         }
 1433                         FREE(dirbuf, M_TEMP);
 1434                 }
 1435 #       else
 1436                 error = VOP_READ(ap->a_vp, uio, 0, ap->a_cred);
 1437 #       endif
 1438         if (!error && ap->a_ncookies) {
 1439                 struct dirent *dp, *dpstart;
 1440                 off_t offstart;
 1441                 u_long *cookies;
 1442                 int ncookies;
 1443 
 1444                 /*
 1445                  * Only the NFS server and emulations use cookies, and they
 1446                  * load the directory block into system space, so we can
 1447                  * just look at it directly.
 1448                  */
 1449                 if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
 1450                         panic("ufs_readdir: lost in space");
 1451 
 1452                 dpstart = (struct dirent *)
 1453                         ((char *)uio->uio_iov->iov_base -
 1454                         (uio->uio_offset - off));
 1455                 offstart = off;
 1456                 for (dp = dpstart, ncookies = 0; off < uio->uio_offset; ) {
 1457                         if (dp->d_reclen == 0)
 1458                                 break;
 1459                         off += dp->d_reclen;
 1460                         ncookies++;
 1461                         dp = (struct dirent *)((caddr_t)dp + dp->d_reclen);
 1462                 }
 1463                 lost += uio->uio_offset - off;
 1464                 uio->uio_offset = off;
 1465                 MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP,
 1466                     M_WAITOK);
 1467                 *ap->a_ncookies = ncookies;
 1468                 *ap->a_cookies = cookies;
 1469                 for (off = offstart, dp = dpstart; off < uio->uio_offset; ) {
 1470                         off += dp->d_reclen;
 1471                         *cookies = off;
 1472                         cookies++;
 1473                         dp = (struct dirent *)((caddr_t)dp + dp->d_reclen);
 1474                 }
 1475         }
 1476 
 1477         uio->uio_resid += lost;
 1478         *ap->a_eofflag = DIP(VTOI(ap->a_vp), size) <= uio->uio_offset;
 1479 
 1480         return (error);
 1481 }
 1482 
 1483 /*
 1484  * Return target name of a symbolic link
 1485  */
 1486 int
 1487 ufs_readlink(void *v)
 1488 {
 1489         struct vop_readlink_args *ap = v;
 1490         struct vnode *vp = ap->a_vp;
 1491         struct inode *ip = VTOI(vp);
 1492         int isize;
 1493 
 1494         isize = DIP(ip, size);
 1495         if (isize < vp->v_mount->mnt_maxsymlinklen ||
 1496             (vp->v_mount->mnt_maxsymlinklen == 0 && DIP(ip, blocks) == 0)) {
 1497                 uiomove((char *)SHORTLINK(ip), isize, ap->a_uio);
 1498                 return (0);
 1499         }
 1500         return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred));
 1501 }
 1502 
 1503 /*
 1504  * Lock an inode. If its already locked, set the WANT bit and sleep.
 1505  */
 1506 int
 1507 ufs_lock(void *v)
 1508 {
 1509         struct vop_lock_args *ap = v;
 1510         struct vnode *vp = ap->a_vp;
 1511 
 1512         return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags, NULL));
 1513 }
 1514 
 1515 /*
 1516  * Unlock an inode.  If WANT bit is on, wakeup.
 1517  */
 1518 int
 1519 ufs_unlock(void *v)
 1520 {
 1521         struct vop_unlock_args *ap = v;
 1522         struct vnode *vp = ap->a_vp;
 1523 
 1524         return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags | LK_RELEASE, NULL));
 1525 }
 1526 
 1527 /*
 1528  * Check for a locked inode.
 1529  */
 1530 int
 1531 ufs_islocked(void *v)
 1532 {
 1533         struct vop_islocked_args *ap = v;
 1534 
 1535         return (lockstatus(&VTOI(ap->a_vp)->i_lock));
 1536 }
 1537 
 1538 /*
 1539  * Calculate the logical to physical mapping if not done already,
 1540  * then call the device strategy routine.
 1541  */
 1542 int
 1543 ufs_strategy(void *v)
 1544 {
 1545         struct vop_strategy_args *ap = v;
 1546         struct buf *bp = ap->a_bp;
 1547         struct vnode *vp = bp->b_vp;
 1548         struct inode *ip;
 1549         int error;
 1550         int s;
 1551 
 1552         ip = VTOI(vp);
 1553         if (vp->v_type == VBLK || vp->v_type == VCHR)
 1554                 panic("ufs_strategy: spec");
 1555         if (bp->b_blkno == bp->b_lblkno) {
 1556                 error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno,
 1557                                  NULL);
 1558                 if (error) {
 1559                         bp->b_error = error;
 1560                         bp->b_flags |= B_ERROR;
 1561                         s = splbio();
 1562                         biodone(bp);
 1563                         splx(s);
 1564                         return (error);
 1565                 }
 1566                 if ((long)bp->b_blkno == -1)
 1567                         clrbuf(bp);
 1568         }
 1569         if ((long)bp->b_blkno == -1) {
 1570                 s = splbio();
 1571                 biodone(bp);
 1572                 splx(s);
 1573                 return (0);
 1574         }
 1575         vp = ip->i_devvp;
 1576         bp->b_dev = vp->v_rdev;
 1577         VOCALL (vp->v_op, VOFFSET(vop_strategy), ap);
 1578         return (0);
 1579 }
 1580 
 1581 /*
 1582  * Print out the contents of an inode.
 1583  */
 1584 int
 1585 ufs_print(void *v)
 1586 {
 1587 #ifdef DIAGNOSTIC
 1588         struct vop_print_args *ap = v;
 1589 
 1590         struct vnode *vp = ap->a_vp;
 1591         struct inode *ip = VTOI(vp);
 1592 
 1593         printf("tag VT_UFS, ino %d, on dev %d, %d", ip->i_number,
 1594                 major(ip->i_dev), minor(ip->i_dev));
 1595         printf(" flags 0x%x, effnlink %d, nlink %d\n",
 1596                ip->i_flag, ip->i_effnlink, DIP(ip, nlink));
 1597         printf("\tmode 0%o, owner %d, group %d, size %lld",
 1598                DIP(ip, mode), DIP(ip, uid), DIP(ip, gid), DIP(ip, size));
 1599 
 1600 #ifdef FIFO
 1601         if (vp->v_type == VFIFO)
 1602                 fifo_printinfo(vp);
 1603 #endif /* FIFO */
 1604         lockmgr_printinfo(&ip->i_lock);
 1605         printf("\n");
 1606 
 1607 #endif /* DIAGNOSTIC */
 1608 
 1609         return (0);
 1610 }
 1611 
 1612 /*
 1613  * Read wrapper for special devices.
 1614  */
 1615 int
 1616 ufsspec_read(void *v)
 1617 {
 1618         struct vop_read_args *ap = v;
 1619 
 1620         /*
 1621          * Set access flag.
 1622          */
 1623         VTOI(ap->a_vp)->i_flag |= IN_ACCESS;
 1624         return (VOCALL (spec_vnodeop_p, VOFFSET(vop_read), ap));
 1625 }
 1626 
 1627 /*
 1628  * Write wrapper for special devices.
 1629  */
 1630 int
 1631 ufsspec_write(void *v)
 1632 {
 1633         struct vop_write_args *ap = v;
 1634 
 1635         /*
 1636          * Set update and change flags.
 1637          */
 1638         VTOI(ap->a_vp)->i_flag |= IN_CHANGE | IN_UPDATE;
 1639         return (VOCALL (spec_vnodeop_p, VOFFSET(vop_write), ap));
 1640 }
 1641 
 1642 /*
 1643  * Close wrapper for special devices.
 1644  *
 1645  * Update the times on the inode then do device close.
 1646  */
 1647 int
 1648 ufsspec_close(void *v)
 1649 {
 1650         struct vop_close_args *ap = v;
 1651         struct vnode *vp = ap->a_vp;
 1652         struct inode *ip = VTOI(vp);
 1653 
 1654         if (ap->a_vp->v_usecount > 1) {
 1655                 struct timeval tv;
 1656 
 1657                 getmicrotime(&tv);
 1658                 ITIMES(ip, &tv, &tv);
 1659         }
 1660         return (VOCALL (spec_vnodeop_p, VOFFSET(vop_close), ap));
 1661 }
 1662 
 1663 #ifdef FIFO
 1664 /*
 1665  * Read wrapper for fifo's
 1666  */
 1667 int
 1668 ufsfifo_read(void *v)
 1669 {
 1670         struct vop_read_args *ap = v;
 1671         extern int (**fifo_vnodeop_p)(void *);
 1672 
 1673         /*
 1674          * Set access flag.
 1675          */
 1676         VTOI(ap->a_vp)->i_flag |= IN_ACCESS;
 1677         return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_read), ap));
 1678 }
 1679 
 1680 /*
 1681  * Write wrapper for fifo's.
 1682  */
 1683 int
 1684 ufsfifo_write(void *v)
 1685 {
 1686         struct vop_write_args *ap = v;
 1687         extern int (**fifo_vnodeop_p)(void *);
 1688 
 1689         /*
 1690          * Set update and change flags.
 1691          */
 1692         VTOI(ap->a_vp)->i_flag |= IN_CHANGE | IN_UPDATE;
 1693         return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_write), ap));
 1694 }
 1695 
 1696 /*
 1697  * Close wrapper for fifo's.
 1698  *
 1699  * Update the times on the inode then do device close.
 1700  */
 1701 int
 1702 ufsfifo_close(void *v)
 1703 {
 1704         struct vop_close_args *ap = v;
 1705         extern int (**fifo_vnodeop_p)(void *);
 1706         struct vnode *vp = ap->a_vp;
 1707         struct inode *ip = VTOI(vp);
 1708 
 1709         if (ap->a_vp->v_usecount > 1) {
 1710                 struct timeval tv;
 1711 
 1712                 getmicrotime(&tv);
 1713                 ITIMES(ip, &tv, &tv);
 1714         }
 1715         return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_close), ap));
 1716 }
 1717 #endif /* FIFO */
 1718 
 1719 /*
 1720  * Return POSIX pathconf information applicable to ufs filesystems.
 1721  */
 1722 int
 1723 ufs_pathconf(void *v)
 1724 {
 1725         struct vop_pathconf_args *ap = v;
 1726 
 1727         switch (ap->a_name) {
 1728         case _PC_LINK_MAX:
 1729                 *ap->a_retval = LINK_MAX;
 1730                 return (0);
 1731         case _PC_NAME_MAX:
 1732                 *ap->a_retval = NAME_MAX;
 1733                 return (0);
 1734         case _PC_PATH_MAX:
 1735                 *ap->a_retval = PATH_MAX;
 1736                 return (0);
 1737         case _PC_PIPE_BUF:
 1738                 *ap->a_retval = PIPE_BUF;
 1739                 return (0);
 1740         case _PC_CHOWN_RESTRICTED:
 1741                 *ap->a_retval = 1;
 1742                 return (0);
 1743         case _PC_NO_TRUNC:
 1744                 *ap->a_retval = 1;
 1745                 return (0);
 1746         default:
 1747                 return (EINVAL);
 1748         }
 1749         /* NOTREACHED */
 1750 }
 1751 
 1752 /*
 1753  * Advisory record locking support
 1754  */
 1755 int
 1756 ufs_advlock(void *v)
 1757 {
 1758         struct vop_advlock_args *ap = v;
 1759         struct inode *ip = VTOI(ap->a_vp);
 1760 
 1761         return (lf_advlock(&ip->i_lockf, DIP(ip, size), ap->a_id, ap->a_op,
 1762             ap->a_fl, ap->a_flags));
 1763 }
 1764 
 1765 /*
 1766  * Initialize the vnode associated with a new inode, handle aliased
 1767  * vnodes.
 1768  */
 1769 int
 1770 ufs_vinit(struct mount *mntp, int (**specops)(void *),
 1771     int (**fifoops)(void *), struct vnode **vpp)
 1772 {
 1773         struct inode *ip;
 1774         struct vnode *vp, *nvp;
 1775         struct timeval mtv;
 1776 
 1777         vp = *vpp;
 1778         ip = VTOI(vp);
 1779         switch(vp->v_type = IFTOVT(DIP(ip, mode))) {
 1780         case VCHR:
 1781         case VBLK:
 1782                 vp->v_op = specops;
 1783                 if ((nvp = checkalias(vp, DIP(ip, rdev), mntp)) != NULL) {
 1784                         /*
 1785                          * Discard unneeded vnode, but save its inode.
 1786                          * Note that the lock is carried over in the inode
 1787                          * to the replacement vnode.
 1788                          */
 1789                         nvp->v_data = vp->v_data;
 1790                         vp->v_data = NULL;
 1791                         vp->v_op = spec_vnodeop_p;
 1792 #ifdef VFSDEBUG
 1793                         vp->v_flag &= ~VLOCKSWORK;
 1794 #endif
 1795                         vrele(vp);
 1796                         vgone(vp);
 1797                         /*
 1798                          * Reinitialize aliased inode.
 1799                          */
 1800                         vp = nvp;
 1801                         ip->i_vnode = vp;
 1802                 }
 1803                 break;
 1804         case VFIFO:
 1805 #ifdef FIFO
 1806                 vp->v_op = fifoops;
 1807                 break;
 1808 #else
 1809                 return (EOPNOTSUPP);
 1810 #endif
 1811         case VNON:
 1812         case VBAD:
 1813         case VSOCK:
 1814         case VLNK:
 1815         case VDIR:
 1816         case VREG:
 1817                 break;
 1818         }
 1819         if (ip->i_number == ROOTINO)
 1820                 vp->v_flag |= VROOT;
 1821         /*
 1822          * Initialize modrev times
 1823          */
 1824         getmicrouptime(&mtv);
 1825         SETHIGH(ip->i_modrev, mtv.tv_sec);
 1826         SETLOW(ip->i_modrev, mtv.tv_usec * 4294);
 1827         *vpp = vp;
 1828         return (0);
 1829 }
 1830 
 1831 /*
 1832  * Allocate a new inode.
 1833  */
 1834 int
 1835 ufs_makeinode(int mode, struct vnode *dvp, struct vnode **vpp,
 1836     struct componentname *cnp)
 1837 {
 1838         struct inode *ip, *pdir;
 1839         struct direct newdir;
 1840         struct vnode *tvp;
 1841         int error;
 1842 
 1843         pdir = VTOI(dvp);
 1844 #ifdef DIAGNOSTIC
 1845         if ((cnp->cn_flags & HASBUF) == 0)
 1846                 panic("ufs_makeinode: no name");
 1847 #endif
 1848         *vpp = NULL;
 1849         if ((mode & IFMT) == 0)
 1850                 mode |= IFREG;
 1851 
 1852         if ((error = UFS_INODE_ALLOC(pdir, mode, cnp->cn_cred, &tvp)) != 0) {
 1853                 pool_put(&namei_pool, cnp->cn_pnbuf);
 1854                 vput(dvp);
 1855                 return (error);
 1856         }
 1857 
 1858         ip = VTOI(tvp);
 1859 
 1860         DIP_ASSIGN(ip, gid, DIP(pdir, gid));
 1861         DIP_ASSIGN(ip, uid, cnp->cn_cred->cr_uid);
 1862 
 1863         if ((error = getinoquota(ip)) ||
 1864             (error = ufs_quota_alloc_inode(ip, cnp->cn_cred))) {
 1865                 pool_put(&namei_pool, cnp->cn_pnbuf);
 1866                 UFS_INODE_FREE(ip, ip->i_number, mode);
 1867                 vput(tvp);
 1868                 vput(dvp);
 1869                 return (error);
 1870         }
 1871 
 1872         ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
 1873         DIP_ASSIGN(ip, mode, mode);
 1874         tvp->v_type = IFTOVT(mode);     /* Rest init'd in getnewvnode(). */
 1875         ip->i_effnlink = 1;
 1876         DIP_ASSIGN(ip, nlink, 1);
 1877         if (DOINGSOFTDEP(tvp))
 1878                 softdep_change_linkcnt(ip, 0);
 1879         if ((DIP(ip, mode) & ISGID) &&
 1880                 !groupmember(DIP(ip, gid), cnp->cn_cred) &&
 1881             suser_ucred(cnp->cn_cred))
 1882                 DIP(ip, mode) &= ~ISGID;
 1883 
 1884         /*
 1885          * Make sure inode goes to disk before directory entry.
 1886          */
 1887         if ((error = UFS_UPDATE(ip, !DOINGSOFTDEP(tvp))) != 0)
 1888                 goto bad;
 1889 
 1890         ufs_makedirentry(ip, cnp, &newdir);
 1891         if ((error = ufs_direnter(dvp, tvp, &newdir, cnp, NULL)) != 0)
 1892                 goto bad;
 1893 
 1894         if ((cnp->cn_flags & SAVESTART) == 0)
 1895                 pool_put(&namei_pool, cnp->cn_pnbuf);
 1896         vput(dvp);
 1897         *vpp = tvp;
 1898         return (0);
 1899 
 1900 bad:
 1901         /*
 1902          * Write error occurred trying to update the inode
 1903          * or the directory so must deallocate the inode.
 1904          */
 1905         pool_put(&namei_pool, cnp->cn_pnbuf);
 1906         vput(dvp);
 1907         ip->i_effnlink = 0;
 1908         DIP_ASSIGN(ip, nlink, 0);
 1909         ip->i_flag |= IN_CHANGE;
 1910         if (DOINGSOFTDEP(tvp))
 1911                 softdep_change_linkcnt(ip, 0);
 1912         tvp->v_type = VNON;
 1913         vput(tvp);
 1914 
 1915         return (error);
 1916 }
 1917 
 1918 struct filterops ufsread_filtops = 
 1919         { 1, NULL, filt_ufsdetach, filt_ufsread };
 1920 struct filterops ufswrite_filtops = 
 1921         { 1, NULL, filt_ufsdetach, filt_ufswrite };
 1922 struct filterops ufsvnode_filtops = 
 1923         { 1, NULL, filt_ufsdetach, filt_ufsvnode };
 1924 
 1925 int
 1926 ufs_kqfilter(void *v)
 1927 {
 1928         struct vop_kqfilter_args *ap = v;
 1929         struct vnode *vp = ap->a_vp;
 1930         struct knote *kn = ap->a_kn;
 1931 
 1932         switch (kn->kn_filter) {
 1933         case EVFILT_READ:
 1934                 kn->kn_fop = &ufsread_filtops;
 1935                 break;
 1936         case EVFILT_WRITE:
 1937                 kn->kn_fop = &ufswrite_filtops;
 1938                 break;
 1939         case EVFILT_VNODE:
 1940                 kn->kn_fop = &ufsvnode_filtops;
 1941                 break;
 1942         default:
 1943                 return (1);
 1944         }
 1945 
 1946         kn->kn_hook = (caddr_t)vp;
 1947 
 1948         SLIST_INSERT_HEAD(&vp->v_selectinfo.si_note, kn, kn_selnext);
 1949 
 1950         return (0);
 1951 }
 1952 
 1953 void
 1954 filt_ufsdetach(struct knote *kn)
 1955 {
 1956         struct vnode *vp = (struct vnode *)kn->kn_hook;
 1957 
 1958         SLIST_REMOVE(&vp->v_selectinfo.si_note, kn, knote, kn_selnext);
 1959 }
 1960 
 1961 /*ARGSUSED*/
 1962 int
 1963 filt_ufsread(struct knote *kn, long hint)
 1964 {
 1965         struct vnode *vp = (struct vnode *)kn->kn_hook;
 1966         struct inode *ip = VTOI(vp);
 1967 
 1968         /*
 1969          * filesystem is gone, so set the EOF flag and schedule 
 1970          * the knote for deletion.
 1971          */
 1972         if (hint == NOTE_REVOKE) {
 1973                 kn->kn_flags |= (EV_EOF | EV_ONESHOT);
 1974                 return (1);
 1975         }
 1976 
 1977         kn->kn_data = DIP(ip, size) - kn->kn_fp->f_offset;
 1978         if (kn->kn_data == 0 && kn->kn_sfflags & NOTE_EOF) {
 1979                 kn->kn_fflags |= NOTE_EOF;
 1980                 return (1);
 1981         }
 1982 
 1983         return (kn->kn_data != 0);
 1984 }
 1985 
 1986 int
 1987 filt_ufswrite(struct knote *kn, long hint)
 1988 {
 1989         /*
 1990          * filesystem is gone, so set the EOF flag and schedule 
 1991          * the knote for deletion.
 1992          */
 1993         if (hint == NOTE_REVOKE) {
 1994                 kn->kn_flags |= (EV_EOF | EV_ONESHOT);
 1995                 return (1);
 1996         }
 1997 
 1998         kn->kn_data = 0;
 1999         return (1);
 2000 }
 2001 
 2002 int
 2003 filt_ufsvnode(struct knote *kn, long hint)
 2004 {
 2005         if (kn->kn_sfflags & hint)
 2006                 kn->kn_fflags |= hint;
 2007         if (hint == NOTE_REVOKE) {
 2008                 kn->kn_flags |= EV_EOF;
 2009                 return (1);
 2010         }
 2011         return (kn->kn_fflags != 0);
 2012 }

/* [<][>][^][v][top][bottom][index][help] */