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/ext2fs/ext2fs_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 /*      $NetBSD: ext2fs_vnops.c,v 1.52.2.1 2004/05/23 11:56:04 grant Exp $      */
    2 
    3 /*
    4  * Copyright (c) 1982, 1986, 1989, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  * (c) UNIX System Laboratories, Inc.
    7  * All or some portions of this file are derived from material licensed
    8  * to the University of California by American Telephone and Telegraph
    9  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
   10  * the permission of UNIX System Laboratories, Inc.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. Neither the name of the University nor the names of its contributors
   21  *    may be used to endorse or promote products derived from this software
   22  *    without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  *
   36  *      @(#)ufs_vnops.c 8.14 (Berkeley) 10/26/94
   37  * Modified for ext2fs by Manuel Bouyer.
   38  */
   39 
   40 /*
   41  * Copyright (c) 1997 Manuel Bouyer.
   42  *
   43  * Redistribution and use in source and binary forms, with or without
   44  * modification, are permitted provided that the following conditions
   45  * are met:
   46  * 1. Redistributions of source code must retain the above copyright
   47  *    notice, this list of conditions and the following disclaimer.
   48  * 2. Redistributions in binary form must reproduce the above copyright
   49  *    notice, this list of conditions and the following disclaimer in the
   50  *    documentation and/or other materials provided with the distribution.
   51  * 3. All advertising materials mentioning features or use of this software
   52  *    must display the following acknowledgement:
   53  *      This product includes software developed by Manuel Bouyer.
   54  * 4. The name of the author may not be used to endorse or promote products
   55  *    derived from this software without specific prior written permission.
   56  *
   57  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   58  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   59  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   60  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   61  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   62  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   63  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   64  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   65  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   66  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   67  *
   68  *      @(#)ufs_vnops.c 8.14 (Berkeley) 10/26/94
   69  * Modified for ext2fs by Manuel Bouyer.
   70  */
   71 
   72 #include <sys/cdefs.h>
   73 __KERNEL_RCSID(0, "$NetBSD: ext2fs_vnops.c,v 1.52.2.1 2004/05/23 11:56:04 grant Exp $");
   74 
   75 #include <sys/param.h>
   76 #include <sys/systm.h>
   77 #include <sys/resourcevar.h>
   78 #include <sys/kernel.h>
   79 #include <sys/file.h>
   80 #include <sys/stat.h>
   81 #include <sys/buf.h>
   82 #include <sys/proc.h>
   83 #include <sys/mount.h>
   84 #include <sys/namei.h>
   85 #include <sys/vnode.h>
   86 #include <sys/lockf.h>
   87 #include <sys/malloc.h>
   88 #include <sys/pool.h>
   89 #include <sys/signalvar.h>
   90 
   91 #include <miscfs/fifofs/fifo.h>
   92 #include <miscfs/genfs/genfs.h>
   93 #include <miscfs/specfs/specdev.h>
   94 
   95 #include <ufs/ufs/inode.h>
   96 #include <ufs/ufs/ufs_extern.h>
   97 #include <ufs/ufs/ufsmount.h>
   98 
   99 #include <ufs/ext2fs/ext2fs.h>
  100 #include <ufs/ext2fs/ext2fs_extern.h>
  101 #include <ufs/ext2fs/ext2fs_dir.h>
  102 
  103 extern int prtactive;
  104 
  105 static int ext2fs_chmod
  106         __P((struct vnode *, int, struct ucred *, struct proc *));
  107 static int ext2fs_chown
  108         __P((struct vnode *, uid_t, gid_t, struct ucred *, struct proc *));
  109 
  110 union _qcvt {
  111         int64_t qcvt;
  112         int32_t val[2];
  113 };
  114 #define SETHIGH(q, h) { \
  115         union _qcvt tmp; \
  116         tmp.qcvt = (q); \
  117         tmp.val[_QUAD_HIGHWORD] = (h); \
  118         (q) = tmp.qcvt; \
  119 }
  120 #define SETLOW(q, l) { \
  121         union _qcvt tmp; \
  122         tmp.qcvt = (q); \
  123         tmp.val[_QUAD_LOWWORD] = (l); \
  124         (q) = tmp.qcvt; \
  125 }
  126 
  127 /*
  128  * Create a regular file
  129  */
  130 int
  131 ext2fs_create(v)
  132         void *v;
  133 {
  134         struct vop_create_args /* {
  135                 struct vnode *a_dvp;
  136                 struct vnode **a_vpp;
  137                 struct componentname *a_cnp;
  138                 struct vattr *a_vap;
  139         } */ *ap = v;
  140         int     error;
  141 
  142         error =
  143             ext2fs_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode),
  144                              ap->a_dvp, ap->a_vpp, ap->a_cnp);
  145 
  146         if (error)
  147                 return (error);
  148         VN_KNOTE(ap->a_dvp, NOTE_WRITE);
  149         return (0);
  150 }
  151 
  152 /*
  153  * Mknod vnode call
  154  */
  155 /* ARGSUSED */
  156 int
  157 ext2fs_mknod(v)
  158         void *v;
  159 {
  160         struct vop_mknod_args /* {
  161                 struct vnode *a_dvp;
  162                 struct vnode **a_vpp;
  163                 struct componentname *a_cnp;
  164                 struct vattr *a_vap;
  165         } */ *ap = v;
  166         struct vattr *vap = ap->a_vap;
  167         struct vnode **vpp = ap->a_vpp;
  168         struct inode *ip;
  169         int error;
  170         struct mount    *mp;    
  171         ino_t           ino;
  172 
  173         if ((error = ext2fs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode),
  174                     ap->a_dvp, vpp, ap->a_cnp)) != 0)
  175                 return (error);
  176         VN_KNOTE(ap->a_dvp, NOTE_WRITE);
  177         ip = VTOI(*vpp);
  178         mp  = (*vpp)->v_mount;
  179         ino = ip->i_number;
  180         ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
  181         if (vap->va_rdev != VNOVAL) {
  182                 /*
  183                  * Want to be able to use this to make badblock
  184                  * inodes, so don't truncate the dev number.
  185                  */
  186                 ip->i_din.e2fs_din->e2di_rdev = h2fs32(vap->va_rdev);
  187         }
  188         /*
  189          * Remove inode so that it will be reloaded by VFS_VGET and
  190          * checked to see if it is an alias of an existing entry in
  191          * the inode cache.
  192          */
  193         vput(*vpp);
  194         (*vpp)->v_type = VNON;
  195         vgone(*vpp);
  196         error = VFS_VGET(mp, ino, vpp);
  197         if (error != 0) {
  198                 *vpp = NULL;
  199                 return (error);
  200         }
  201         return (0);
  202 }
  203 
  204 /*
  205  * Open called.
  206  *
  207  * Just check the APPEND flag.
  208  */
  209 /* ARGSUSED */
  210 int
  211 ext2fs_open(v)
  212         void *v;
  213 {
  214         struct vop_open_args /* {
  215                 struct vnode *a_vp;
  216                 int  a_mode;
  217                 struct ucred *a_cred;
  218                 struct proc *a_p;
  219         } */ *ap = v;
  220 
  221         /*
  222          * Files marked append-only must be opened for appending.
  223          */
  224         if ((VTOI(ap->a_vp)->i_e2fs_flags & EXT2_APPEND) &&
  225                 (ap->a_mode & (FWRITE | O_APPEND)) == FWRITE)
  226                 return (EPERM);
  227         return (0);
  228 }
  229 
  230 int
  231 ext2fs_access(v)
  232         void *v;
  233 {
  234         struct vop_access_args /* {
  235                 struct vnode *a_vp;
  236                 int  a_mode;
  237                 struct ucred *a_cred;
  238                 struct proc *a_p;
  239         } */ *ap = v;
  240         struct vnode *vp = ap->a_vp;
  241         struct inode *ip = VTOI(vp);
  242         mode_t mode = ap->a_mode;
  243 
  244         /*
  245          * Disallow write attempts on read-only file systems;
  246          * unless the file is a socket, fifo, or a block or
  247          * character device resident on the file system.
  248          */
  249         if (mode & VWRITE) {
  250                 switch (vp->v_type) {
  251                 case VDIR:
  252                 case VLNK:
  253                 case VREG:
  254                         if (vp->v_mount->mnt_flag & MNT_RDONLY)
  255                                 return (EROFS);
  256                         break;
  257                 default:
  258                         break;
  259                 }
  260         }
  261 
  262         /* If immutable bit set, nobody gets to write it. */
  263         if ((mode & VWRITE) && (ip->i_e2fs_flags & EXT2_IMMUTABLE))
  264                 return (EPERM);
  265 
  266         return (vaccess(vp->v_type, ip->i_e2fs_mode & ALLPERMS,
  267                         ip->i_e2fs_uid, ip->i_e2fs_gid, mode, ap->a_cred));
  268 }
  269 
  270 /* ARGSUSED */
  271 int
  272 ext2fs_getattr(v)
  273         void *v;
  274 {
  275         struct vop_getattr_args /* {
  276                 struct vnode *a_vp;
  277                 struct vattr *a_vap;
  278                 struct ucred *a_cred;
  279                 struct proc *a_p;
  280         } */ *ap = v;
  281         struct vnode *vp = ap->a_vp;
  282         struct inode *ip = VTOI(vp);
  283         struct vattr *vap = ap->a_vap;
  284         struct timespec ts;
  285 
  286         TIMEVAL_TO_TIMESPEC(&time, &ts);
  287         EXT2FS_ITIMES(ip, &ts, &ts, &ts);
  288         /*
  289          * Copy from inode table
  290          */
  291         vap->va_fsid = ip->i_dev;
  292         vap->va_fileid = ip->i_number;
  293         vap->va_mode = ip->i_e2fs_mode & ALLPERMS;
  294         vap->va_nlink = ip->i_e2fs_nlink;
  295         vap->va_uid = ip->i_e2fs_uid;
  296         vap->va_gid = ip->i_e2fs_gid;
  297         vap->va_rdev = (dev_t)fs2h32(ip->i_din.e2fs_din->e2di_rdev);
  298         vap->va_size = vp->v_size;
  299         vap->va_atime.tv_sec = ip->i_e2fs_atime;
  300         vap->va_atime.tv_nsec = 0;
  301         vap->va_mtime.tv_sec = ip->i_e2fs_mtime;
  302         vap->va_mtime.tv_nsec = 0;
  303         vap->va_ctime.tv_sec = ip->i_e2fs_ctime;
  304         vap->va_ctime.tv_nsec = 0;
  305 #ifdef EXT2FS_SYSTEM_FLAGS
  306         vap->va_flags = (ip->i_e2fs_flags & EXT2_APPEND) ? SF_APPEND : 0;
  307         vap->va_flags |= (ip->i_e2fs_flags & EXT2_IMMUTABLE) ? SF_IMMUTABLE : 0;
  308 #else
  309         vap->va_flags = (ip->i_e2fs_flags & EXT2_APPEND) ? UF_APPEND : 0;
  310         vap->va_flags |= (ip->i_e2fs_flags & EXT2_IMMUTABLE) ? UF_IMMUTABLE : 0;
  311 #endif
  312         vap->va_gen = ip->i_e2fs_gen;
  313         /* this doesn't belong here */
  314         if (vp->v_type == VBLK)
  315                 vap->va_blocksize = BLKDEV_IOSIZE;
  316         else if (vp->v_type == VCHR)
  317                 vap->va_blocksize = MAXBSIZE;
  318         else
  319                 vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize;
  320         vap->va_bytes = dbtob((u_quad_t)ip->i_e2fs_nblock);
  321         vap->va_type = vp->v_type;
  322         vap->va_filerev = ip->i_modrev;
  323         return (0);
  324 }
  325 
  326 /*
  327  * Set attribute vnode op. called from several syscalls
  328  */
  329 int
  330 ext2fs_setattr(v)
  331         void *v;
  332 {
  333         struct vop_setattr_args /* {
  334                 struct vnode *a_vp;
  335                 struct vattr *a_vap;
  336                 struct ucred *a_cred;
  337                 struct proc *a_p;
  338         } */ *ap = v;
  339         struct vattr *vap = ap->a_vap;
  340         struct vnode *vp = ap->a_vp;
  341         struct inode *ip = VTOI(vp);
  342         struct ucred *cred = ap->a_cred;
  343         struct proc *p = ap->a_p;
  344         int error;
  345 
  346         /*
  347          * Check for unsettable attributes.
  348          */
  349         if ((vap->va_type != VNON) || (vap->va_nlink != (nlink_t)VNOVAL) ||
  350             (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
  351             (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
  352             ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
  353                 return (EINVAL);
  354         }
  355         if (vap->va_flags != VNOVAL) {
  356                 if (vp->v_mount->mnt_flag & MNT_RDONLY)
  357                         return (EROFS);
  358                 if (cred->cr_uid != ip->i_e2fs_uid &&
  359                         (error = suser(cred, &p->p_acflag)))
  360                         return (error);
  361 #ifdef EXT2FS_SYSTEM_FLAGS
  362                 if (cred->cr_uid == 0) {
  363                         if ((ip->i_e2fs_flags &
  364                             (EXT2_APPEND | EXT2_IMMUTABLE)) && securelevel > 0)
  365                                 return (EPERM);
  366                         ip->i_e2fs_flags &= ~(EXT2_APPEND | EXT2_IMMUTABLE);
  367                         ip->i_e2fs_flags |=
  368                             (vap->va_flags & SF_APPEND) ?  EXT2_APPEND : 0 |
  369                             (vap->va_flags & SF_IMMUTABLE) ? EXT2_IMMUTABLE : 0;
  370                 } else
  371                         return (EPERM);
  372 #else
  373                 ip->i_e2fs_flags &= ~(EXT2_APPEND | EXT2_IMMUTABLE);
  374                 ip->i_e2fs_flags |=
  375                     (vap->va_flags & UF_APPEND) ? EXT2_APPEND : 0 |
  376                     (vap->va_flags & UF_IMMUTABLE) ? EXT2_IMMUTABLE : 0;
  377 #endif
  378                 ip->i_flag |= IN_CHANGE;
  379                 if (vap->va_flags & (IMMUTABLE | APPEND))
  380                         return (0);
  381         }
  382         if (ip->i_e2fs_flags & (EXT2_APPEND | EXT2_IMMUTABLE))
  383                 return (EPERM);
  384         /*
  385          * Go through the fields and update iff not VNOVAL.
  386          */
  387         if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) {
  388                 if (vp->v_mount->mnt_flag & MNT_RDONLY)
  389                         return (EROFS);
  390                 error = ext2fs_chown(vp, vap->va_uid, vap->va_gid, cred, p);
  391                 if (error)
  392                         return (error);
  393         }
  394         if (vap->va_size != VNOVAL) {
  395                 /*
  396                  * Disallow write attempts on read-only file systems;
  397                  * unless the file is a socket, fifo, or a block or
  398                  * character device resident on the file system.
  399                  */
  400                 switch (vp->v_type) {
  401                 case VDIR:
  402                         return (EISDIR);
  403                 case VLNK:
  404                 case VREG:
  405                         if (vp->v_mount->mnt_flag & MNT_RDONLY)
  406                                 return (EROFS);
  407                 default:
  408                         break;
  409                 }
  410                 error = VOP_TRUNCATE(vp, vap->va_size, 0, cred, p);
  411                 if (error)
  412                         return (error);
  413         }
  414         ip = VTOI(vp);
  415         if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
  416                 if (vp->v_mount->mnt_flag & MNT_RDONLY)
  417                         return (EROFS);
  418                 if (cred->cr_uid != ip->i_e2fs_uid &&
  419                         (error = suser(cred, &p->p_acflag)) &&
  420                         ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || 
  421                         (error = VOP_ACCESS(vp, VWRITE, cred, p))))
  422                         return (error);
  423                 if (vap->va_atime.tv_sec != VNOVAL)
  424                         if (!(vp->v_mount->mnt_flag & MNT_NOATIME))
  425                                 ip->i_flag |= IN_ACCESS;
  426                 if (vap->va_mtime.tv_sec != VNOVAL)
  427                         ip->i_flag |= IN_CHANGE | IN_UPDATE;
  428                 error = VOP_UPDATE(vp, &vap->va_atime, &vap->va_mtime,
  429                         UPDATE_WAIT);
  430                 if (error)
  431                         return (error);
  432         }
  433         error = 0;
  434         if (vap->va_mode != (mode_t)VNOVAL) {
  435                 if (vp->v_mount->mnt_flag & MNT_RDONLY)
  436                         return (EROFS);
  437                 error = ext2fs_chmod(vp, (int)vap->va_mode, cred, p);
  438         }
  439         VN_KNOTE(vp, NOTE_ATTRIB);
  440         return (error);
  441 }
  442 
  443 /*
  444  * Change the mode on a file.
  445  * Inode must be locked before calling.
  446  */
  447 static int
  448 ext2fs_chmod(vp, mode, cred, p)
  449         struct vnode *vp;
  450         int mode;
  451         struct ucred *cred;
  452         struct proc *p;
  453 {
  454         struct inode *ip = VTOI(vp);
  455         int error;
  456 
  457         if (cred->cr_uid != ip->i_e2fs_uid &&
  458                 (error = suser(cred, &p->p_acflag)))
  459                 return (error);
  460         if (cred->cr_uid) {
  461                 if (vp->v_type != VDIR && (mode & S_ISTXT))
  462                         return (EFTYPE);
  463                 if (!groupmember(ip->i_e2fs_gid, cred) && (mode & ISGID))
  464                         return (EPERM);
  465         }
  466         ip->i_e2fs_mode &= ~ALLPERMS;
  467         ip->i_e2fs_mode |= (mode & ALLPERMS);
  468         ip->i_flag |= IN_CHANGE;
  469         return (0);
  470 }
  471 
  472 /*
  473  * Perform chown operation on inode ip;
  474  * inode must be locked prior to call.
  475  */
  476 static int
  477 ext2fs_chown(vp, uid, gid, cred, p)
  478         struct vnode *vp;
  479         uid_t uid;
  480         gid_t gid;
  481         struct ucred *cred;
  482         struct proc *p;
  483 {
  484         struct inode *ip = VTOI(vp);
  485         uid_t ouid;
  486         gid_t ogid;
  487         int error = 0;
  488 
  489         if (uid == (uid_t)VNOVAL)
  490                 uid = ip->i_e2fs_uid;
  491         if (gid == (gid_t)VNOVAL)
  492                 gid = ip->i_e2fs_gid;
  493         /*
  494          * If we don't own the file, are trying to change the owner
  495          * of the file, or are not a member of the target group,
  496          * the caller must be superuser or the call fails.
  497          */
  498         if ((cred->cr_uid != ip->i_e2fs_uid || uid != ip->i_e2fs_uid ||
  499                 (gid != ip->i_e2fs_gid &&
  500                  !(cred->cr_gid == gid || groupmember((gid_t)gid, cred)))) &&
  501                 (error = suser(cred, &p->p_acflag)))
  502                 return (error);
  503         ogid = ip->i_e2fs_gid;
  504         ouid = ip->i_e2fs_uid;
  505 
  506         ip->i_e2fs_gid = gid;
  507         ip->i_e2fs_uid = uid;
  508         if (ouid != uid || ogid != gid)
  509                 ip->i_flag |= IN_CHANGE;
  510         if (ouid != uid && cred->cr_uid != 0)
  511                 ip->i_e2fs_mode &= ~ISUID;
  512         if (ogid != gid && cred->cr_uid != 0)
  513                 ip->i_e2fs_mode &= ~ISGID;
  514         return (0);
  515 }
  516 
  517 int
  518 ext2fs_remove(v)
  519         void *v;
  520 {
  521         struct vop_remove_args /* {
  522                 struct vnode *a_dvp;
  523                 struct vnode *a_vp;
  524                 struct componentname *a_cnp;
  525         } */ *ap = v;
  526         struct inode *ip;
  527         struct vnode *vp = ap->a_vp;
  528         struct vnode *dvp = ap->a_dvp;
  529         int error;
  530 
  531         ip = VTOI(vp);
  532         if (vp->v_type == VDIR ||
  533                 (ip->i_e2fs_flags & (EXT2_IMMUTABLE | EXT2_APPEND)) ||
  534                 (VTOI(dvp)->i_e2fs_flags & EXT2_APPEND)) {
  535                 error = EPERM;
  536         } else {
  537                 error = ext2fs_dirremove(dvp, ap->a_cnp);
  538                 if (error == 0) {
  539                         ip->i_e2fs_nlink--;
  540                         ip->i_flag |= IN_CHANGE;
  541                 }
  542         }
  543 
  544         VN_KNOTE(vp, NOTE_DELETE);
  545         VN_KNOTE(dvp, NOTE_WRITE);
  546         if (dvp == vp)
  547                 vrele(vp);
  548         else
  549                 vput(vp);
  550         vput(dvp);
  551         return (error);
  552 }
  553 
  554 /*
  555  * link vnode call
  556  */
  557 int
  558 ext2fs_link(v)
  559         void *v;
  560 {
  561         struct vop_link_args /* {
  562                 struct vnode *a_dvp;
  563                 struct vnode *a_vp;
  564                 struct componentname *a_cnp;
  565         } */ *ap = v;
  566         struct vnode *dvp = ap->a_dvp;
  567         struct vnode *vp = ap->a_vp;
  568         struct componentname *cnp = ap->a_cnp;
  569         struct inode *ip;
  570         int error;
  571 
  572 #ifdef DIAGNOSTIC
  573         if ((cnp->cn_flags & HASBUF) == 0)
  574                 panic("ext2fs_link: no name");
  575 #endif
  576         if (vp->v_type == VDIR) {
  577                 VOP_ABORTOP(dvp, cnp);
  578                 error = EISDIR;
  579                 goto out2;
  580         }
  581         if (dvp->v_mount != vp->v_mount) {
  582                 VOP_ABORTOP(dvp, cnp);
  583                 error = EXDEV;
  584                 goto out2;
  585         }
  586         if (dvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE))) {
  587                 VOP_ABORTOP(dvp, cnp);
  588                 goto out2;
  589         }
  590         ip = VTOI(vp);
  591         if ((nlink_t)ip->i_e2fs_nlink >= LINK_MAX) {
  592                 VOP_ABORTOP(dvp, cnp);
  593                 error = EMLINK;
  594                 goto out1;
  595         }
  596         if (ip->i_e2fs_flags & (EXT2_IMMUTABLE | EXT2_APPEND)) {
  597                 VOP_ABORTOP(dvp, cnp);
  598                 error = EPERM;
  599                 goto out1;
  600         }
  601         ip->i_e2fs_nlink++;
  602         ip->i_flag |= IN_CHANGE;
  603         error = VOP_UPDATE(vp, NULL, NULL, UPDATE_WAIT);
  604         if (!error)
  605                 error = ext2fs_direnter(ip, dvp, cnp);
  606         if (error) {
  607                 ip->i_e2fs_nlink--;
  608                 ip->i_flag |= IN_CHANGE;
  609         }
  610         PNBUF_PUT(cnp->cn_pnbuf);
  611 out1:
  612         if (dvp != vp)
  613                 VOP_UNLOCK(vp, 0);
  614 out2:
  615         VN_KNOTE(vp, NOTE_LINK);
  616         VN_KNOTE(dvp, NOTE_WRITE);
  617         vput(dvp);
  618         return (error);
  619 }
  620 
  621 /*
  622  * Rename system call.
  623  *      rename("foo", "bar");
  624  * is essentially
  625  *      unlink("bar");
  626  *      link("foo", "bar");
  627  *      unlink("foo");
  628  * but ``atomically''.  Can't do full commit without saving state in the
  629  * inode on disk which isn't feasible at this time.  Best we can do is
  630  * always guarantee the target exists.
  631  *
  632  * Basic algorithm is:
  633  *
  634  * 1) Bump link count on source while we're linking it to the
  635  *    target.  This also ensure the inode won't be deleted out
  636  *    from underneath us while we work (it may be truncated by
  637  *    a concurrent `trunc' or `open' for creation).
  638  * 2) Link source to destination.  If destination already exists,
  639  *    delete it first.
  640  * 3) Unlink source reference to inode if still around. If a
  641  *    directory was moved and the parent of the destination
  642  *    is different from the source, patch the ".." entry in the
  643  *    directory.
  644  */
  645 int
  646 ext2fs_rename(v)
  647         void *v;
  648 {
  649         struct vop_rename_args  /* {
  650                 struct vnode *a_fdvp;
  651                 struct vnode *a_fvp;
  652                 struct componentname *a_fcnp;
  653                 struct vnode *a_tdvp;
  654                 struct vnode *a_tvp;
  655                 struct componentname *a_tcnp;
  656         } */ *ap = v;
  657         struct vnode *tvp = ap->a_tvp;
  658         struct vnode *tdvp = ap->a_tdvp;
  659         struct vnode *fvp = ap->a_fvp;
  660         struct vnode *fdvp = ap->a_fdvp;
  661         struct componentname *tcnp = ap->a_tcnp;
  662         struct componentname *fcnp = ap->a_fcnp;
  663         struct inode *ip, *xp, *dp;
  664         struct ext2fs_dirtemplate dirbuf;
  665         int doingdirectory = 0, oldparent = 0, newparent = 0;
  666         int error = 0;
  667         u_char namlen;
  668 
  669 #ifdef DIAGNOSTIC
  670         if ((tcnp->cn_flags & HASBUF) == 0 ||
  671             (fcnp->cn_flags & HASBUF) == 0)
  672                 panic("ext2fs_rename: no name");
  673 #endif
  674         /*
  675          * Check for cross-device rename.
  676          */
  677         if ((fvp->v_mount != tdvp->v_mount) ||
  678             (tvp && (fvp->v_mount != tvp->v_mount))) {
  679                 error = EXDEV;
  680 abortit:
  681                 VOP_ABORTOP(tdvp, tcnp); /* XXX, why not in NFS? */
  682                 if (tdvp == tvp)
  683                         vrele(tdvp);
  684                 else
  685                         vput(tdvp);
  686                 if (tvp)
  687                         vput(tvp);
  688                 VOP_ABORTOP(fdvp, fcnp); /* XXX, why not in NFS? */
  689                 vrele(fdvp);
  690                 vrele(fvp);
  691                 return (error);
  692         }
  693 
  694         /*
  695          * Check if just deleting a link name.
  696          */
  697         if (tvp && ((VTOI(tvp)->i_e2fs_flags & (EXT2_IMMUTABLE | EXT2_APPEND)) ||
  698             (VTOI(tdvp)->i_e2fs_flags & EXT2_APPEND))) {
  699                 error = EPERM;
  700                 goto abortit;
  701         }
  702         if (fvp == tvp) {
  703                 if (fvp->v_type == VDIR) {
  704                         error = EINVAL;
  705                         goto abortit;
  706                 }
  707 
  708                 /* Release destination completely. */
  709                 VOP_ABORTOP(tdvp, tcnp);
  710                 vput(tdvp);
  711                 vput(tvp);
  712 
  713                 /* Delete source. */
  714                 vrele(fdvp);
  715                 vrele(fvp);
  716                 fcnp->cn_flags &= ~MODMASK;
  717                 fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
  718                 if ((fcnp->cn_flags & SAVESTART) == 0)
  719                         panic("ext2fs_rename: lost from startdir");
  720                 fcnp->cn_nameiop = DELETE;
  721                 (void) relookup(fdvp, &fvp, fcnp);
  722                 return (VOP_REMOVE(fdvp, fvp, fcnp));
  723         }
  724         if ((error = vn_lock(fvp, LK_EXCLUSIVE)) != 0)
  725                 goto abortit;
  726         dp = VTOI(fdvp);
  727         ip = VTOI(fvp);
  728         if ((nlink_t) ip->i_e2fs_nlink >= LINK_MAX) {
  729                 VOP_UNLOCK(fvp, 0);
  730                 error = EMLINK;
  731                 goto abortit;
  732         }
  733         if ((ip->i_e2fs_flags & (EXT2_IMMUTABLE | EXT2_APPEND)) ||
  734                 (dp->i_e2fs_flags & EXT2_APPEND)) {
  735                 VOP_UNLOCK(fvp, 0);
  736                 error = EPERM;
  737                 goto abortit;
  738         }
  739         if ((ip->i_e2fs_mode & IFMT) == IFDIR) {
  740                 error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_proc);
  741                 if (!error && tvp)
  742                         error = VOP_ACCESS(tvp, VWRITE, tcnp->cn_cred,
  743                             tcnp->cn_proc);
  744                 if (error) {
  745                         VOP_UNLOCK(fvp, 0);
  746                         error = EACCES;
  747                         goto abortit;
  748                 }
  749                 /*
  750                  * Avoid ".", "..", and aliases of "." for obvious reasons.
  751                  */
  752                 if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') ||
  753                     dp == ip ||
  754                     (fcnp->cn_flags&ISDOTDOT) ||
  755                     (tcnp->cn_flags & ISDOTDOT) ||
  756                     (ip->i_flag & IN_RENAME)) {
  757                         VOP_UNLOCK(fvp, 0);
  758                         error = EINVAL;
  759                         goto abortit;
  760                 }
  761                 ip->i_flag |= IN_RENAME;
  762                 oldparent = dp->i_number;
  763                 doingdirectory++;
  764         }
  765         VN_KNOTE(fdvp, NOTE_WRITE);             /* XXXLUKEM/XXX: right place? */
  766         vrele(fdvp);
  767 
  768         /*
  769          * When the target exists, both the directory
  770          * and target vnodes are returned locked.
  771          */
  772         dp = VTOI(tdvp);
  773         xp = NULL;
  774         if (tvp)
  775                 xp = VTOI(tvp);
  776 
  777         /*
  778          * 1) Bump link count while we're moving stuff
  779          *    around.  If we crash somewhere before
  780          *    completing our work, the link count
  781          *    may be wrong, but correctable.
  782          */
  783         ip->i_e2fs_nlink++;
  784         ip->i_flag |= IN_CHANGE;
  785         if ((error = VOP_UPDATE(fvp, NULL, NULL, UPDATE_WAIT)) != 0) {
  786                 VOP_UNLOCK(fvp, 0);
  787                 goto bad;
  788         }
  789 
  790         /*
  791          * If ".." must be changed (ie the directory gets a new
  792          * parent) then the source directory must not be in the
  793          * directory hierarchy above the target, as this would
  794          * orphan everything below the source directory. Also
  795          * the user must have write permission in the source so
  796          * as to be able to change "..". We must repeat the call 
  797          * to namei, as the parent directory is unlocked by the
  798          * call to checkpath().
  799          */
  800         error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_proc);
  801         VOP_UNLOCK(fvp, 0);
  802         if (oldparent != dp->i_number)
  803                 newparent = dp->i_number;
  804         if (doingdirectory && newparent) {
  805                 if (error)      /* write access check above */
  806                         goto bad;
  807                 if (xp != NULL)
  808                         vput(tvp);
  809                 error = ext2fs_checkpath(ip, dp, tcnp->cn_cred);
  810                 if (error != 0)
  811                         goto out;
  812                 if ((tcnp->cn_flags & SAVESTART) == 0)
  813                         panic("ext2fs_rename: lost to startdir");
  814                 if ((error = relookup(tdvp, &tvp, tcnp)) != 0)
  815                         goto out;
  816                 dp = VTOI(tdvp);
  817                 xp = NULL;
  818                 if (tvp)
  819                         xp = VTOI(tvp);
  820         }
  821         /*
  822          * 2) If target doesn't exist, link the target
  823          *    to the source and unlink the source. 
  824          *    Otherwise, rewrite the target directory
  825          *    entry to reference the source inode and
  826          *    expunge the original entry's existence.
  827          */
  828         if (xp == NULL) {
  829                 if (dp->i_dev != ip->i_dev)
  830                         panic("rename: EXDEV");
  831                 /*
  832                  * Account for ".." in new directory.
  833                  * When source and destination have the same
  834                  * parent we don't fool with the link count.
  835                  */
  836                 if (doingdirectory && newparent) {
  837                         if ((nlink_t)dp->i_e2fs_nlink >= LINK_MAX) {
  838                                 error = EMLINK;
  839                                 goto bad;
  840                         }
  841                         dp->i_e2fs_nlink++;
  842                         dp->i_flag |= IN_CHANGE;
  843                         if ((error = VOP_UPDATE(tdvp, NULL, NULL, UPDATE_WAIT))
  844                             != 0)
  845                                 goto bad;
  846                 }
  847                 error = ext2fs_direnter(ip, tdvp, tcnp);
  848                 if (error != 0) {
  849                         if (doingdirectory && newparent) {
  850                                 dp->i_e2fs_nlink--;
  851                                 dp->i_flag |= IN_CHANGE;
  852                                 (void)VOP_UPDATE(tdvp, NULL, NULL, UPDATE_WAIT);
  853                         }
  854                         goto bad;
  855                 }
  856                 VN_KNOTE(tdvp, NOTE_WRITE);
  857                 vput(tdvp);
  858         } else {
  859                 if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev)
  860                         panic("rename: EXDEV");
  861                 /*
  862                  * Short circuit rename(foo, foo).
  863                  */
  864                 if (xp->i_number == ip->i_number)
  865                         panic("rename: same file");
  866                 /*
  867                  * If the parent directory is "sticky", then the user must
  868                  * own the parent directory, or the destination of the rename,
  869                  * otherwise the destination may not be changed (except by
  870                  * root). This implements append-only directories.
  871                  */
  872                 if ((dp->i_e2fs_mode & S_ISTXT) && tcnp->cn_cred->cr_uid != 0 &&
  873                     tcnp->cn_cred->cr_uid != dp->i_e2fs_uid &&
  874                     xp->i_e2fs_uid != tcnp->cn_cred->cr_uid) {
  875                         error = EPERM;
  876                         goto bad;
  877                 }
  878                 /*
  879                  * Target must be empty if a directory and have no links
  880                  * to it. Also, ensure source and target are compatible
  881                  * (both directories, or both not directories).
  882                  */
  883                 if ((xp->i_e2fs_mode & IFMT) == IFDIR) {
  884                         if (!ext2fs_dirempty(xp, dp->i_number, tcnp->cn_cred) ||
  885                                 xp->i_e2fs_nlink > 2) {
  886                                 error = ENOTEMPTY;
  887                                 goto bad;
  888                         }
  889                         if (!doingdirectory) {
  890                                 error = ENOTDIR;
  891                                 goto bad;
  892                         }
  893                         cache_purge(tdvp);
  894                 } else if (doingdirectory) {
  895                         error = EISDIR;
  896                         goto bad;
  897                 }
  898                 error = ext2fs_dirrewrite(dp, ip, tcnp);
  899                 if (error != 0)
  900                         goto bad;
  901                 /*
  902                  * If the target directory is in the same
  903                  * directory as the source directory,
  904                  * decrement the link count on the parent
  905                  * of the target directory.
  906                  */
  907                  if (doingdirectory && !newparent) {
  908                         dp->i_e2fs_nlink--;
  909                         dp->i_flag |= IN_CHANGE;
  910                 }
  911                 VN_KNOTE(tdvp, NOTE_WRITE);
  912                 vput(tdvp);
  913                 /*
  914                  * Adjust the link count of the target to
  915                  * reflect the dirrewrite above.  If this is
  916                  * a directory it is empty and there are
  917                  * no links to it, so we can squash the inode and
  918                  * any space associated with it.  We disallowed
  919                  * renaming over top of a directory with links to
  920                  * it above, as the remaining link would point to
  921                  * a directory without "." or ".." entries.
  922                  */
  923                 xp->i_e2fs_nlink--;
  924                 if (doingdirectory) {
  925                         if (--xp->i_e2fs_nlink != 0)
  926                                 panic("rename: linked directory");
  927                         error = VOP_TRUNCATE(tvp, (off_t)0, IO_SYNC,
  928                             tcnp->cn_cred, tcnp->cn_proc);
  929                 }
  930                 xp->i_flag |= IN_CHANGE;
  931                 VN_KNOTE(tvp, NOTE_DELETE);
  932                 vput(tvp);
  933                 xp = NULL;
  934         }
  935 
  936         /*
  937          * 3) Unlink the source.
  938          */
  939         fcnp->cn_flags &= ~MODMASK;
  940         fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
  941         if ((fcnp->cn_flags & SAVESTART) == 0)
  942                 panic("ext2fs_rename: lost from startdir");
  943         (void) relookup(fdvp, &fvp, fcnp);
  944         if (fvp != NULL) {
  945                 xp = VTOI(fvp);
  946                 dp = VTOI(fdvp);
  947         } else {
  948                 /*
  949                  * From name has disappeared.
  950                  */
  951                 if (doingdirectory)
  952                         panic("ext2fs_rename: lost dir entry");
  953                 vrele(ap->a_fvp);
  954                 return (0);
  955         }
  956         /*
  957          * Ensure that the directory entry still exists and has not
  958          * changed while the new name has been entered. If the source is
  959          * a file then the entry may have been unlinked or renamed. In
  960          * either case there is no further work to be done. If the source
  961          * is a directory then it cannot have been rmdir'ed; its link
  962          * count of three would cause a rmdir to fail with ENOTEMPTY.
  963          * The IRENAME flag ensures that it cannot be moved by another
  964          * rename.
  965          */
  966         if (xp != ip) {
  967                 if (doingdirectory)
  968                         panic("ext2fs_rename: lost dir entry");
  969         } else {
  970                 /*
  971                  * If the source is a directory with a
  972                  * new parent, the link count of the old
  973                  * parent directory must be decremented
  974                  * and ".." set to point to the new parent.
  975                  */
  976                 if (doingdirectory && newparent) {
  977                         dp->i_e2fs_nlink--;
  978                         dp->i_flag |= IN_CHANGE;
  979                         error = vn_rdwr(UIO_READ, fvp, (caddr_t)&dirbuf,
  980                                 sizeof (struct ext2fs_dirtemplate), (off_t)0,
  981                                 UIO_SYSSPACE, IO_NODELOCKED, 
  982                                 tcnp->cn_cred, (size_t *)0, (struct proc *)0);
  983                         if (error == 0) {
  984                                         namlen = dirbuf.dotdot_namlen;
  985                                 if (namlen != 2 ||
  986                                     dirbuf.dotdot_name[0] != '.' ||
  987                                     dirbuf.dotdot_name[1] != '.') {
  988                                         ufs_dirbad(xp, (doff_t)12,
  989                                             "ext2fs_rename: mangled dir");
  990                                 } else {
  991                                         dirbuf.dotdot_ino = h2fs32(newparent);
  992                                         (void) vn_rdwr(UIO_WRITE, fvp,
  993                                             (caddr_t)&dirbuf,
  994                                             sizeof (struct dirtemplate),
  995                                             (off_t)0, UIO_SYSSPACE,
  996                                             IO_NODELOCKED|IO_SYNC,
  997                                             tcnp->cn_cred, (size_t *)0,
  998                                             (struct proc *)0);
  999                                         cache_purge(fdvp);
 1000                                 }
 1001                         }
 1002                 }
 1003                 error = ext2fs_dirremove(fdvp, fcnp);
 1004                 if (!error) {
 1005                         xp->i_e2fs_nlink--;
 1006                         xp->i_flag |= IN_CHANGE;
 1007                 }
 1008                 xp->i_flag &= ~IN_RENAME;
 1009         }
 1010         VN_KNOTE(fvp, NOTE_RENAME);
 1011         if (dp)
 1012                 vput(fdvp);
 1013         if (xp)
 1014                 vput(fvp);
 1015         vrele(ap->a_fvp);
 1016         return (error);
 1017 
 1018 bad:
 1019         if (xp)
 1020                 vput(ITOV(xp));
 1021         vput(ITOV(dp));
 1022 out:
 1023         if (doingdirectory)
 1024                 ip->i_flag &= ~IN_RENAME;
 1025         if (vn_lock(fvp, LK_EXCLUSIVE) == 0) {
 1026                 ip->i_e2fs_nlink--;
 1027                 ip->i_flag |= IN_CHANGE;
 1028                 vput(fvp);
 1029         } else
 1030                 vrele(fvp);
 1031         return (error);
 1032 }
 1033 
 1034 /*
 1035  * Mkdir system call
 1036  */
 1037 int
 1038 ext2fs_mkdir(v)
 1039         void *v;
 1040 {
 1041         struct vop_mkdir_args /* {
 1042                 struct vnode *a_dvp;
 1043                 struct vnode **a_vpp;
 1044                 struct componentname *a_cnp;
 1045                 struct vattr *a_vap;
 1046         } */ *ap = v;
 1047         struct vnode *dvp = ap->a_dvp;
 1048         struct vattr *vap = ap->a_vap;
 1049         struct componentname *cnp = ap->a_cnp;
 1050         struct inode *ip, *dp;
 1051         struct vnode *tvp;
 1052         struct ext2fs_dirtemplate dirtemplate;
 1053         int error, dmode;
 1054 
 1055 #ifdef DIAGNOSTIC
 1056         if ((cnp->cn_flags & HASBUF) == 0)
 1057                 panic("ext2fs_mkdir: no name");
 1058 #endif
 1059         dp = VTOI(dvp);
 1060         if ((nlink_t)dp->i_e2fs_nlink >= LINK_MAX) {
 1061                 error = EMLINK;
 1062                 goto out;
 1063         }
 1064         dmode = vap->va_mode & ACCESSPERMS;
 1065         dmode |= IFDIR;
 1066         /*
 1067          * Must simulate part of ext2fs_makeinode here to acquire the inode,
 1068          * but not have it entered in the parent directory. The entry is
 1069          * made later after writing "." and ".." entries.
 1070          */
 1071         if ((error = VOP_VALLOC(dvp, dmode, cnp->cn_cred, &tvp)) != 0)
 1072                 goto out;
 1073         ip = VTOI(tvp);
 1074         ip->i_e2fs_uid = cnp->cn_cred->cr_uid;
 1075         ip->i_e2fs_gid = dp->i_e2fs_gid;
 1076         ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
 1077         ip->i_e2fs_mode = dmode;
 1078         tvp->v_type = VDIR;     /* Rest init'd in getnewvnode(). */
 1079         ip->i_e2fs_nlink = 2;
 1080         error = VOP_UPDATE(tvp, NULL, NULL, UPDATE_WAIT);
 1081 
 1082         /*
 1083          * Bump link count in parent directory
 1084          * to reflect work done below.  Should
 1085          * be done before reference is created
 1086          * so reparation is possible if we crash.
 1087          */
 1088         dp->i_e2fs_nlink++;
 1089         dp->i_flag |= IN_CHANGE;
 1090         if ((error = VOP_UPDATE(dvp, NULL, NULL, UPDATE_WAIT)) != 0)
 1091                 goto bad;
 1092 
 1093         /* Initialize directory with "." and ".." from static template. */
 1094         memset(&dirtemplate, 0, sizeof(dirtemplate));
 1095         dirtemplate.dot_ino = h2fs32(ip->i_number);
 1096         dirtemplate.dot_reclen = h2fs16(12);
 1097         dirtemplate.dot_namlen = 1;
 1098         if (ip->i_e2fs->e2fs.e2fs_rev > E2FS_REV0 &&
 1099             (ip->i_e2fs->e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE)) {
 1100                 dirtemplate.dot_type = EXT2_FT_DIR;
 1101         }
 1102         dirtemplate.dot_name[0] = '.';
 1103         dirtemplate.dotdot_ino = h2fs32(dp->i_number);
 1104     dirtemplate.dotdot_reclen = h2fs16(VTOI(dvp)->i_e2fs->e2fs_bsize - 12);
 1105         dirtemplate.dotdot_namlen = 2;
 1106         if (ip->i_e2fs->e2fs.e2fs_rev > E2FS_REV0 &&
 1107             (ip->i_e2fs->e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE)) {
 1108                 dirtemplate.dotdot_type = EXT2_FT_DIR;
 1109         }
 1110         dirtemplate.dotdot_name[0] = dirtemplate.dotdot_name[1] = '.';
 1111         error = vn_rdwr(UIO_WRITE, tvp, (caddr_t)&dirtemplate,
 1112             sizeof (dirtemplate), (off_t)0, UIO_SYSSPACE,
 1113             IO_NODELOCKED|IO_SYNC, cnp->cn_cred, (size_t *)0, (struct proc *)0);
 1114         if (error) {
 1115                 dp->i_e2fs_nlink--;
 1116                 dp->i_flag |= IN_CHANGE;
 1117                 goto bad;
 1118         }
 1119         if (VTOI(dvp)->i_e2fs->e2fs_bsize >
 1120                                                         VFSTOUFS(dvp->v_mount)->um_mountp->mnt_stat.f_bsize)
 1121                 panic("ext2fs_mkdir: blksize"); /* XXX should grow with balloc() */
 1122         else {
 1123                 ip->i_e2fs_size = VTOI(dvp)->i_e2fs->e2fs_bsize;
 1124                 ip->i_flag |= IN_CHANGE;
 1125         }
 1126 
 1127         /* Directory set up, now install it's entry in the parent directory. */
 1128         error = ext2fs_direnter(ip, dvp, cnp);
 1129         if (error != 0) {
 1130                 dp->i_e2fs_nlink--;
 1131                 dp->i_flag |= IN_CHANGE;
 1132         }
 1133 bad:
 1134         /*
 1135          * No need to do an explicit VOP_TRUNCATE here, vrele will do this
 1136          * for us because we set the link count to 0.
 1137          */
 1138         if (error) {
 1139                 ip->i_e2fs_nlink = 0;
 1140                 ip->i_flag |= IN_CHANGE;
 1141                 vput(tvp);
 1142         } else {
 1143                 VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
 1144                 *ap->a_vpp = tvp;
 1145         }
 1146 out:
 1147         PNBUF_PUT(cnp->cn_pnbuf);
 1148         vput(dvp);
 1149         return (error);
 1150 }
 1151 
 1152 /*
 1153  * Rmdir system call.
 1154  */
 1155 int
 1156 ext2fs_rmdir(v)
 1157         void *v;
 1158 {
 1159         struct vop_rmdir_args /* {
 1160                 struct vnode *a_dvp;
 1161                 struct vnode *a_vp;
 1162                 struct componentname *a_cnp;
 1163         } */ *ap = v;
 1164         struct vnode *vp = ap->a_vp;
 1165         struct vnode *dvp = ap->a_dvp;
 1166         struct componentname *cnp = ap->a_cnp;
 1167         struct inode *ip, *dp;
 1168         int error;
 1169 
 1170         ip = VTOI(vp);
 1171         dp = VTOI(dvp);
 1172         /*
 1173          * No rmdir "." please.
 1174          */
 1175         if (dp == ip) {
 1176                 vrele(dvp);
 1177                 vput(vp);
 1178                 return (EINVAL);
 1179         }
 1180         /*
 1181          * Verify the directory is empty (and valid).
 1182          * (Rmdir ".." won't be valid since
 1183          *  ".." will contain a reference to
 1184          *  the current directory and thus be
 1185          *  non-empty.)
 1186          */
 1187         error = 0;
 1188         if (ip->i_e2fs_nlink != 2 ||
 1189             !ext2fs_dirempty(ip, dp->i_number, cnp->cn_cred)) {
 1190                 error = ENOTEMPTY;
 1191                 goto out;
 1192         }
 1193         if ((dp->i_e2fs_flags & EXT2_APPEND) ||
 1194                                  (ip->i_e2fs_flags & (EXT2_IMMUTABLE | EXT2_APPEND))) {
 1195                 error = EPERM;
 1196                 goto out;
 1197         }
 1198         /*
 1199          * Delete reference to directory before purging
 1200          * inode.  If we crash in between, the directory
 1201          * will be reattached to lost+found,
 1202          */
 1203         error = ext2fs_dirremove(dvp, cnp);
 1204         if (error != 0)
 1205                 goto out;
 1206         dp->i_e2fs_nlink--;
 1207         dp->i_flag |= IN_CHANGE;
 1208         VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
 1209         cache_purge(dvp);
 1210         vput(dvp);
 1211         dvp = NULL;
 1212         /*
 1213          * Truncate inode.  The only stuff left
 1214          * in the directory is "." and "..".  The
 1215          * "." reference is inconsequential since
 1216          * we're quashing it.  The ".." reference
 1217          * has already been adjusted above.  We've
 1218          * removed the "." reference and the reference
 1219          * in the parent directory, but there may be
 1220          * other hard links so decrement by 2 and
 1221          * worry about them later.
 1222          */
 1223         ip->i_e2fs_nlink -= 2;
 1224         error = VOP_TRUNCATE(vp, (off_t)0, IO_SYNC, cnp->cn_cred,
 1225             cnp->cn_proc);
 1226         cache_purge(ITOV(ip));
 1227 out:
 1228         VN_KNOTE(vp, NOTE_DELETE);
 1229         if (dvp)
 1230                 vput(dvp);
 1231         vput(vp);
 1232         return (error);
 1233 }
 1234 
 1235 /*
 1236  * symlink -- make a symbolic link
 1237  */
 1238 int
 1239 ext2fs_symlink(v)
 1240         void *v;
 1241 {
 1242         struct vop_symlink_args /* {
 1243                 struct vnode *a_dvp;
 1244                 struct vnode **a_vpp;
 1245                 struct componentname *a_cnp;
 1246                 struct vattr *a_vap;
 1247                 char *a_target;
 1248         } */ *ap = v;
 1249         struct vnode *vp, **vpp = ap->a_vpp;
 1250         struct inode *ip;
 1251         int len, error;
 1252 
 1253         error = ext2fs_makeinode(IFLNK | ap->a_vap->va_mode, ap->a_dvp,
 1254                               vpp, ap->a_cnp);
 1255         if (error)
 1256                 return (error);
 1257         VN_KNOTE(ap->a_dvp, NOTE_WRITE);
 1258         vp = *vpp;
 1259         len = strlen(ap->a_target);
 1260         if (len < vp->v_mount->mnt_maxsymlinklen) {
 1261                 ip = VTOI(vp);
 1262                 memcpy((char *)ip->i_din.e2fs_din->e2di_shortlink, ap->a_target, len);
 1263                 ip->i_e2fs_size = len;
 1264                 ip->i_flag |= IN_CHANGE | IN_UPDATE;
 1265         } else
 1266                 error = vn_rdwr(UIO_WRITE, vp, ap->a_target, len, (off_t)0,
 1267                     UIO_SYSSPACE, IO_NODELOCKED, ap->a_cnp->cn_cred,
 1268                     (size_t *)0, (struct proc *)0);
 1269         if (error)
 1270                 vput(vp);
 1271         return (error);
 1272 }
 1273 
 1274 /*
 1275  * Return target name of a symbolic link
 1276  */
 1277 int
 1278 ext2fs_readlink(v)
 1279         void *v;
 1280 {
 1281         struct vop_readlink_args /* {
 1282                 struct vnode *a_vp;
 1283                 struct uio *a_uio;
 1284                 struct ucred *a_cred;
 1285         } */ *ap = v;
 1286         struct vnode *vp = ap->a_vp;
 1287         struct inode *ip = VTOI(vp);
 1288         int isize;
 1289 
 1290         isize = ip->i_e2fs_size;
 1291         if (isize < vp->v_mount->mnt_maxsymlinklen ||
 1292             (vp->v_mount->mnt_maxsymlinklen == 0 && ip->i_e2fs_nblock == 0)) {
 1293                 uiomove((char *)ip->i_din.e2fs_din->e2di_shortlink, isize, ap->a_uio);
 1294                 return (0);
 1295         }
 1296         return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred));
 1297 }
 1298 
 1299 /*
 1300  * Advisory record locking support
 1301  */
 1302 int
 1303 ext2fs_advlock(v)
 1304         void *v;
 1305 {
 1306         struct vop_advlock_args /* {
 1307                 struct vnode *a_vp;
 1308                 caddr_t  a_id;
 1309                 int  a_op;
 1310                 struct flock *a_fl;
 1311                 int  a_flags;
 1312         } */ *ap = v;
 1313         struct inode *ip = VTOI(ap->a_vp);
 1314 
 1315         return lf_advlock(ap, &ip->i_lockf, ip->i_e2fs_size);
 1316 }
 1317 
 1318 /*
 1319  * Initialize the vnode associated with a new inode, handle aliased
 1320  * vnodes.
 1321  */
 1322 int
 1323 ext2fs_vinit(mntp, specops, fifoops, vpp)
 1324         struct mount *mntp;
 1325         int (**specops) __P((void *));
 1326         int (**fifoops) __P((void *));
 1327         struct vnode **vpp;
 1328 {
 1329         struct inode *ip;
 1330         struct vnode *vp, *nvp;
 1331 
 1332         vp = *vpp;
 1333         ip = VTOI(vp);
 1334         switch(vp->v_type = IFTOVT(ip->i_e2fs_mode)) {
 1335         case VCHR:
 1336         case VBLK:
 1337                 vp->v_op = specops;
 1338                 if ((nvp = checkalias(vp,
 1339                     fs2h32(ip->i_din.e2fs_din->e2di_rdev), mntp)) != NULL) {
 1340                         /*
 1341                          * Discard unneeded vnode, but save its inode.
 1342                          */
 1343                         nvp->v_data = vp->v_data;
 1344                         vp->v_data = NULL;
 1345                         VOP_UNLOCK(vp, 0);
 1346                         vp->v_op = spec_vnodeop_p;
 1347                         vrele(vp);
 1348                         vgone(vp);
 1349                         lockmgr(&nvp->v_lock, LK_EXCLUSIVE, &nvp->v_interlock);
 1350                         /*
 1351                          * Reinitialize aliased inode.
 1352                          */
 1353                         vp = nvp;
 1354                         ip->i_vnode = vp;
 1355                 }
 1356                 break;
 1357         case VFIFO:
 1358                 vp->v_op = fifoops;
 1359                 break;
 1360         case VNON:
 1361         case VBAD:
 1362         case VSOCK:
 1363         case VLNK:
 1364         case VDIR:
 1365         case VREG:
 1366                 break;
 1367         }
 1368         if (ip->i_number == ROOTINO)
 1369                 vp->v_flag |= VROOT;
 1370         /*
 1371          * Initialize modrev times
 1372          */
 1373         SETHIGH(ip->i_modrev, mono_time.tv_sec);
 1374         SETLOW(ip->i_modrev, mono_time.tv_usec * 4294);
 1375         *vpp = vp;
 1376         return (0);
 1377 }
 1378 
 1379 /*
 1380  * Allocate a new inode.
 1381  */
 1382 int
 1383 ext2fs_makeinode(mode, dvp, vpp, cnp)
 1384         int mode;
 1385         struct vnode *dvp;
 1386         struct vnode **vpp;
 1387         struct componentname *cnp;
 1388 {
 1389         struct inode *ip, *pdir;
 1390         struct vnode *tvp;
 1391         int error;
 1392 
 1393         pdir = VTOI(dvp);
 1394 #ifdef DIAGNOSTIC
 1395         if ((cnp->cn_flags & HASBUF) == 0)
 1396                 panic("ext2fs_makeinode: no name");
 1397 #endif
 1398         *vpp = NULL;
 1399         if ((mode & IFMT) == 0)
 1400                 mode |= IFREG;
 1401 
 1402         if ((error = VOP_VALLOC(dvp, mode, cnp->cn_cred, &tvp)) != 0) {
 1403                 PNBUF_PUT(cnp->cn_pnbuf);
 1404                 vput(dvp);
 1405                 return (error);
 1406         }
 1407         ip = VTOI(tvp);
 1408         ip->i_e2fs_gid = pdir->i_e2fs_gid;
 1409         ip->i_e2fs_uid = cnp->cn_cred->cr_uid;
 1410         ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
 1411         ip->i_e2fs_mode = mode;
 1412         tvp->v_type = IFTOVT(mode);     /* Rest init'd in getnewvnode(). */
 1413         ip->i_e2fs_nlink = 1;
 1414         if ((ip->i_e2fs_mode & ISGID) &&
 1415                 !groupmember(ip->i_e2fs_gid, cnp->cn_cred) &&
 1416             suser(cnp->cn_cred, NULL))
 1417                 ip->i_e2fs_mode &= ~ISGID;
 1418 
 1419         /*
 1420          * Make sure inode goes to disk before directory entry.
 1421          */
 1422         if ((error = VOP_UPDATE(tvp, NULL, NULL, UPDATE_WAIT)) != 0)
 1423                 goto bad;
 1424         error = ext2fs_direnter(ip, dvp, cnp);
 1425         if (error != 0)
 1426                 goto bad;
 1427         if ((cnp->cn_flags & SAVESTART) == 0)
 1428                 PNBUF_PUT(cnp->cn_pnbuf);
 1429         vput(dvp);
 1430         *vpp = tvp;
 1431         return (0);
 1432 
 1433 bad:
 1434         /*
 1435          * Write error occurred trying to update the inode
 1436          * or the directory so must deallocate the inode.
 1437          */
 1438         tvp->v_type = VNON;     /* Stop explosion if VBLK */
 1439         ip->i_e2fs_nlink = 0;
 1440         ip->i_flag |= IN_CHANGE;
 1441         vput(tvp);
 1442         PNBUF_PUT(cnp->cn_pnbuf);
 1443         vput(dvp);
 1444         return (error);
 1445 }
 1446 
 1447 /*
 1448  * Reclaim an inode so that it can be used for other purposes.
 1449  */
 1450 int
 1451 ext2fs_reclaim(v)
 1452         void *v;
 1453 {
 1454         struct vop_reclaim_args /* {
 1455                 struct vnode *a_vp;
 1456         } */ *ap = v;
 1457         struct vnode *vp = ap->a_vp;
 1458         struct inode *ip;
 1459 
 1460         if (prtactive && vp->v_usecount != 0) 
 1461                 vprint("ext2fs_reclaim: pushing active", vp);
 1462         /*
 1463          * Remove the inode from its hash chain.
 1464          */
 1465         ip = VTOI(vp);
 1466         ufs_ihashrem(ip);
 1467         /*
 1468          * Purge old data structures associated with the inode.
 1469          */
 1470         cache_purge(vp);
 1471         if (ip->i_devvp) {
 1472                 vrele(ip->i_devvp);
 1473                 ip->i_devvp = 0;
 1474         }
 1475 
 1476         if (ip->i_din.e2fs_din != NULL)
 1477                 pool_put(&ext2fs_dinode_pool, ip->i_din.e2fs_din);
 1478 
 1479         pool_put(&ext2fs_inode_pool, vp->v_data);
 1480         vp->v_data = NULL;
 1481         return (0);
 1482 }
 1483 
 1484 /* Global vfs data structures for ext2fs. */
 1485 int (**ext2fs_vnodeop_p) __P((void *));
 1486 const struct vnodeopv_entry_desc ext2fs_vnodeop_entries[] = {
 1487         { &vop_default_desc, vn_default_error },
 1488         { &vop_lookup_desc, ext2fs_lookup },            /* lookup */
 1489         { &vop_create_desc, ext2fs_create },            /* create */
 1490         { &vop_mknod_desc, ext2fs_mknod },              /* mknod */
 1491         { &vop_open_desc, ext2fs_open },                /* open */
 1492         { &vop_close_desc, ufs_close },                 /* close */
 1493         { &vop_access_desc, ext2fs_access },            /* access */
 1494         { &vop_getattr_desc, ext2fs_getattr },          /* getattr */
 1495         { &vop_setattr_desc, ext2fs_setattr },          /* setattr */
 1496         { &vop_read_desc, ext2fs_read },                /* read */
 1497         { &vop_write_desc, ext2fs_write },              /* write */
 1498         { &vop_lease_desc, ufs_lease_check },           /* lease */
 1499         { &vop_ioctl_desc, ufs_ioctl },                 /* ioctl */
 1500         { &vop_fcntl_desc, ufs_fcntl },                 /* fcntl */
 1501         { &vop_poll_desc, ufs_poll },                   /* poll */
 1502         { &vop_kqfilter_desc, genfs_kqfilter },         /* kqfilter */
 1503         { &vop_revoke_desc, ufs_revoke },               /* revoke */
 1504         { &vop_mmap_desc, ufs_mmap },                   /* mmap */
 1505         { &vop_fsync_desc, ext2fs_fsync },              /* fsync */
 1506         { &vop_seek_desc, ufs_seek },                   /* seek */
 1507         { &vop_remove_desc, ext2fs_remove },            /* remove */
 1508         { &vop_link_desc, ext2fs_link },                /* link */
 1509         { &vop_rename_desc, ext2fs_rename },            /* rename */
 1510         { &vop_mkdir_desc, ext2fs_mkdir },              /* mkdir */
 1511         { &vop_rmdir_desc, ext2fs_rmdir },              /* rmdir */
 1512         { &vop_symlink_desc, ext2fs_symlink },          /* symlink */
 1513         { &vop_readdir_desc, ext2fs_readdir },          /* readdir */
 1514         { &vop_readlink_desc, ext2fs_readlink },        /* readlink */
 1515         { &vop_abortop_desc, ufs_abortop },             /* abortop */
 1516         { &vop_inactive_desc, ext2fs_inactive },        /* inactive */
 1517         { &vop_reclaim_desc, ext2fs_reclaim },          /* reclaim */
 1518         { &vop_lock_desc, ufs_lock },                   /* lock */
 1519         { &vop_unlock_desc, ufs_unlock },               /* unlock */
 1520         { &vop_bmap_desc, ext2fs_bmap },                /* bmap */
 1521         { &vop_strategy_desc, ufs_strategy },           /* strategy */
 1522         { &vop_print_desc, ufs_print },                 /* print */
 1523         { &vop_islocked_desc, ufs_islocked },           /* islocked */
 1524         { &vop_pathconf_desc, ufs_pathconf },           /* pathconf */
 1525         { &vop_advlock_desc, ext2fs_advlock },          /* advlock */
 1526         { &vop_blkatoff_desc, ext2fs_blkatoff },        /* blkatoff */
 1527         { &vop_valloc_desc, ext2fs_valloc },            /* valloc */
 1528         { &vop_vfree_desc, ext2fs_vfree },              /* vfree */
 1529         { &vop_truncate_desc, ext2fs_truncate },        /* truncate */
 1530         { &vop_update_desc, ext2fs_update },            /* update */
 1531         { &vop_bwrite_desc, vn_bwrite },                /* bwrite */
 1532         { &vop_getpages_desc, genfs_getpages },         /* getpages */
 1533         { &vop_putpages_desc, genfs_putpages },         /* putpages */
 1534         { NULL, NULL }
 1535 };
 1536 const struct vnodeopv_desc ext2fs_vnodeop_opv_desc =
 1537         { &ext2fs_vnodeop_p, ext2fs_vnodeop_entries };
 1538 
 1539 int (**ext2fs_specop_p) __P((void *));
 1540 const struct vnodeopv_entry_desc ext2fs_specop_entries[] = {
 1541         { &vop_default_desc, vn_default_error },
 1542         { &vop_lookup_desc, spec_lookup },              /* lookup */
 1543         { &vop_create_desc, spec_create },              /* create */
 1544         { &vop_mknod_desc, spec_mknod },                /* mknod */
 1545         { &vop_open_desc, spec_open },                  /* open */
 1546         { &vop_close_desc, ufsspec_close },             /* close */
 1547         { &vop_access_desc, ext2fs_access },            /* access */
 1548         { &vop_getattr_desc, ext2fs_getattr },          /* getattr */
 1549         { &vop_setattr_desc, ext2fs_setattr },          /* setattr */
 1550         { &vop_read_desc, ufsspec_read },               /* read */
 1551         { &vop_write_desc, ufsspec_write },             /* write */
 1552         { &vop_lease_desc, spec_lease_check },          /* lease */
 1553         { &vop_ioctl_desc, spec_ioctl },                /* ioctl */
 1554         { &vop_fcntl_desc, ufs_fcntl },                 /* fcntl */
 1555         { &vop_poll_desc, spec_poll },                  /* poll */
 1556         { &vop_kqfilter_desc, spec_kqfilter },          /* kqfilter */
 1557         { &vop_revoke_desc, spec_revoke },              /* revoke */
 1558         { &vop_mmap_desc, spec_mmap },                  /* mmap */
 1559         { &vop_fsync_desc, ext2fs_fsync },              /* fsync */
 1560         { &vop_seek_desc, spec_seek },                  /* seek */
 1561         { &vop_remove_desc, spec_remove },              /* remove */
 1562         { &vop_link_desc, spec_link },                  /* link */
 1563         { &vop_rename_desc, spec_rename },              /* rename */
 1564         { &vop_mkdir_desc, spec_mkdir },                /* mkdir */
 1565         { &vop_rmdir_desc, spec_rmdir },                /* rmdir */
 1566         { &vop_symlink_desc, spec_symlink },            /* symlink */
 1567         { &vop_readdir_desc, spec_readdir },            /* readdir */
 1568         { &vop_readlink_desc, spec_readlink },          /* readlink */
 1569         { &vop_abortop_desc, spec_abortop },            /* abortop */
 1570         { &vop_inactive_desc, ext2fs_inactive },        /* inactive */
 1571         { &vop_reclaim_desc, ext2fs_reclaim },          /* reclaim */
 1572         { &vop_lock_desc, ufs_lock },                   /* lock */
 1573         { &vop_unlock_desc, ufs_unlock },               /* unlock */
 1574         { &vop_bmap_desc, spec_bmap },                  /* bmap */
 1575         { &vop_strategy_desc, spec_strategy },          /* strategy */
 1576         { &vop_print_desc, ufs_print },                 /* print */
 1577         { &vop_islocked_desc, ufs_islocked },           /* islocked */
 1578         { &vop_pathconf_desc, spec_pathconf },          /* pathconf */
 1579         { &vop_advlock_desc, spec_advlock },            /* advlock */
 1580         { &vop_blkatoff_desc, spec_blkatoff },          /* blkatoff */
 1581         { &vop_valloc_desc, spec_valloc },              /* valloc */
 1582         { &vop_vfree_desc, ext2fs_vfree },              /* vfree */
 1583         { &vop_truncate_desc, spec_truncate },          /* truncate */
 1584         { &vop_update_desc, ext2fs_update },            /* update */
 1585         { &vop_bwrite_desc, vn_bwrite },                /* bwrite */
 1586         { &vop_getpages_desc, spec_getpages },          /* getpages */
 1587         { &vop_putpages_desc, spec_putpages },          /* putpages */
 1588         { NULL, NULL }
 1589 };
 1590 const struct vnodeopv_desc ext2fs_specop_opv_desc =
 1591         { &ext2fs_specop_p, ext2fs_specop_entries };
 1592 
 1593 int (**ext2fs_fifoop_p) __P((void *));
 1594 const struct vnodeopv_entry_desc ext2fs_fifoop_entries[] = {
 1595         { &vop_default_desc, vn_default_error },
 1596         { &vop_lookup_desc, fifo_lookup },              /* lookup */
 1597         { &vop_create_desc, fifo_create },              /* create */
 1598         { &vop_mknod_desc, fifo_mknod },                /* mknod */
 1599         { &vop_open_desc, fifo_open },                  /* open */
 1600         { &vop_close_desc, ufsfifo_close },             /* close */
 1601         { &vop_access_desc, ext2fs_access },            /* access */
 1602         { &vop_getattr_desc, ext2fs_getattr },          /* getattr */
 1603         { &vop_setattr_desc, ext2fs_setattr },          /* setattr */
 1604         { &vop_read_desc, ufsfifo_read },               /* read */
 1605         { &vop_write_desc, ufsfifo_write },             /* write */
 1606         { &vop_lease_desc, fifo_lease_check },          /* lease */
 1607         { &vop_ioctl_desc, fifo_ioctl },                /* ioctl */
 1608         { &vop_fcntl_desc, ufs_fcntl },                 /* fcntl */
 1609         { &vop_poll_desc, fifo_poll },                  /* poll */
 1610         { &vop_kqfilter_desc, fifo_kqfilter },          /* kqfilter */
 1611         { &vop_revoke_desc, fifo_revoke },              /* revoke */
 1612         { &vop_mmap_desc, fifo_mmap },                  /* mmap */
 1613         { &vop_fsync_desc, ext2fs_fsync },              /* fsync */
 1614         { &vop_seek_desc, fifo_seek },                  /* seek */
 1615         { &vop_remove_desc, fifo_remove },              /* remove */
 1616         { &vop_link_desc, fifo_link },                  /* link */
 1617         { &vop_rename_desc, fifo_rename },              /* rename */
 1618         { &vop_mkdir_desc, fifo_mkdir },                /* mkdir */
 1619         { &vop_rmdir_desc, fifo_rmdir },                /* rmdir */
 1620         { &vop_symlink_desc, fifo_symlink },            /* symlink */
 1621         { &vop_readdir_desc, fifo_readdir },            /* readdir */
 1622         { &vop_readlink_desc, fifo_readlink },          /* readlink */
 1623         { &vop_abortop_desc, fifo_abortop },            /* abortop */
 1624         { &vop_inactive_desc, ext2fs_inactive },        /* inactive */
 1625         { &vop_reclaim_desc, ext2fs_reclaim },          /* reclaim */
 1626         { &vop_lock_desc, ufs_lock },                   /* lock */
 1627         { &vop_unlock_desc, ufs_unlock },               /* unlock */
 1628         { &vop_bmap_desc, fifo_bmap },                  /* bmap */
 1629         { &vop_strategy_desc, fifo_strategy },          /* strategy */
 1630         { &vop_print_desc, ufs_print },                 /* print */
 1631         { &vop_islocked_desc, ufs_islocked },           /* islocked */
 1632         { &vop_pathconf_desc, fifo_pathconf },          /* pathconf */
 1633         { &vop_advlock_desc, fifo_advlock },            /* advlock */
 1634         { &vop_blkatoff_desc, fifo_blkatoff },          /* blkatoff */
 1635         { &vop_valloc_desc, fifo_valloc },              /* valloc */
 1636         { &vop_vfree_desc, ext2fs_vfree },              /* vfree */
 1637         { &vop_truncate_desc, fifo_truncate },          /* truncate */
 1638         { &vop_update_desc, ext2fs_update },            /* update */
 1639         { &vop_bwrite_desc, vn_bwrite },                /* bwrite */
 1640         { &vop_putpages_desc, fifo_putpages },          /* putpages */
 1641         { NULL, NULL }
 1642 };
 1643 const struct vnodeopv_desc ext2fs_fifoop_opv_desc =
 1644         { &ext2fs_fifoop_p, ext2fs_fifoop_entries };

Cache object: 834c9cc64cf4242cde088572dad33de3


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