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/fs/unionfs/union_subr.c

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

    1 /*-
    2  * Copyright (c) 1994 Jan-Simon Pendry
    3  * Copyright (c) 1994
    4  *      The Regents of the University of California.  All rights reserved.
    5  * Copyright (c) 2005, 2006 Masanori Ozawa <ozawa@ongs.co.jp>, ONGS Inc.
    6  * Copyright (c) 2006 Daichi Goto <daichi@freebsd.org>
    7  *
    8  * This code is derived from software contributed to Berkeley by
    9  * Jan-Simon Pendry.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 4. Neither the name of the University nor the names of its contributors
   20  *    may be used to endorse or promote products derived from this software
   21  *    without specific prior written permission.
   22  *
   23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   33  * SUCH DAMAGE.
   34  *
   35  *      @(#)union_subr.c        8.20 (Berkeley) 5/20/95
   36  * $FreeBSD: releng/9.0/sys/fs/unionfs/union_subr.c 211826 2010-08-25 21:32:08Z trasz $
   37  */
   38 
   39 #include <sys/param.h>
   40 #include <sys/systm.h>
   41 #include <sys/kernel.h>
   42 #include <sys/lock.h>
   43 #include <sys/mutex.h>
   44 #include <sys/malloc.h>
   45 #include <sys/mount.h>
   46 #include <sys/namei.h>
   47 #include <sys/proc.h>
   48 #include <sys/vnode.h>
   49 #include <sys/dirent.h>
   50 #include <sys/fcntl.h>
   51 #include <sys/filedesc.h>
   52 #include <sys/stat.h>
   53 #include <sys/resourcevar.h>
   54 
   55 #include <security/mac/mac_framework.h>
   56 
   57 #include <vm/uma.h>
   58 
   59 #include <fs/unionfs/union.h>
   60 
   61 #define NUNIONFSNODECACHE 16
   62 
   63 static MALLOC_DEFINE(M_UNIONFSHASH, "UNIONFS hash", "UNIONFS hash table");
   64 MALLOC_DEFINE(M_UNIONFSNODE, "UNIONFS node", "UNIONFS vnode private part");
   65 MALLOC_DEFINE(M_UNIONFSPATH, "UNIONFS path", "UNIONFS path private part");
   66 
   67 /*
   68  * Initialize
   69  */
   70 int 
   71 unionfs_init(struct vfsconf *vfsp)
   72 {
   73         UNIONFSDEBUG("unionfs_init\n"); /* printed during system boot */
   74         return (0);
   75 }
   76 
   77 /*
   78  * Uninitialize
   79  */
   80 int 
   81 unionfs_uninit(struct vfsconf *vfsp)
   82 {
   83         return (0);
   84 }
   85 
   86 static struct unionfs_node_hashhead *
   87 unionfs_get_hashhead(struct vnode *dvp, char *path)
   88 {
   89         int             count;
   90         char            hash;
   91         struct unionfs_node *unp;
   92 
   93         hash = 0;
   94         unp = VTOUNIONFS(dvp);
   95         if (path != NULL) {
   96                 for (count = 0; path[count]; count++)
   97                         hash += path[count];
   98         }
   99 
  100         return (&(unp->un_hashtbl[hash & (unp->un_hashmask)]));
  101 }
  102 
  103 /*
  104  * Get the cached vnode.
  105  */
  106 static struct vnode *
  107 unionfs_get_cached_vnode(struct vnode *uvp, struct vnode *lvp,
  108                         struct vnode *dvp, char *path)
  109 {
  110         struct unionfs_node_hashhead *hd;
  111         struct unionfs_node *unp;
  112         struct vnode   *vp;
  113 
  114         KASSERT((uvp == NULLVP || uvp->v_type == VDIR),
  115             ("unionfs_get_cached_vnode: v_type != VDIR"));
  116         KASSERT((lvp == NULLVP || lvp->v_type == VDIR),
  117             ("unionfs_get_cached_vnode: v_type != VDIR"));
  118 
  119         VI_LOCK(dvp);
  120         hd = unionfs_get_hashhead(dvp, path);
  121         LIST_FOREACH(unp, hd, un_hash) {
  122                 if (!strcmp(unp->un_path, path)) {
  123                         vp = UNIONFSTOV(unp);
  124                         VI_LOCK_FLAGS(vp, MTX_DUPOK);
  125                         VI_UNLOCK(dvp);
  126                         vp->v_iflag &= ~VI_OWEINACT;
  127                         if ((vp->v_iflag & (VI_DOOMED | VI_DOINGINACT)) != 0) {
  128                                 VI_UNLOCK(vp);
  129                                 vp = NULLVP;
  130                         } else
  131                                 VI_UNLOCK(vp);
  132                         return (vp);
  133                 }
  134         }
  135         VI_UNLOCK(dvp);
  136 
  137         return (NULLVP);
  138 }
  139 
  140 /*
  141  * Add the new vnode into cache.
  142  */
  143 static struct vnode *
  144 unionfs_ins_cached_vnode(struct unionfs_node *uncp,
  145                         struct vnode *dvp, char *path)
  146 {
  147         struct unionfs_node_hashhead *hd;
  148         struct unionfs_node *unp;
  149         struct vnode   *vp;
  150 
  151         KASSERT((uncp->un_uppervp==NULLVP || uncp->un_uppervp->v_type==VDIR),
  152             ("unionfs_ins_cached_vnode: v_type != VDIR"));
  153         KASSERT((uncp->un_lowervp==NULLVP || uncp->un_lowervp->v_type==VDIR),
  154             ("unionfs_ins_cached_vnode: v_type != VDIR"));
  155 
  156         VI_LOCK(dvp);
  157         hd = unionfs_get_hashhead(dvp, path);
  158         LIST_FOREACH(unp, hd, un_hash) {
  159                 if (!strcmp(unp->un_path, path)) {
  160                         vp = UNIONFSTOV(unp);
  161                         VI_LOCK_FLAGS(vp, MTX_DUPOK);
  162                         vp->v_iflag &= ~VI_OWEINACT;
  163                         if ((vp->v_iflag & (VI_DOOMED | VI_DOINGINACT)) != 0) {
  164                                 LIST_INSERT_HEAD(hd, uncp, un_hash);
  165                                 VI_UNLOCK(vp);
  166                                 vp = NULLVP;
  167                         } else
  168                                 VI_UNLOCK(vp);
  169                         VI_UNLOCK(dvp);
  170                         return (vp);
  171                 }
  172         }
  173 
  174         LIST_INSERT_HEAD(hd, uncp, un_hash);
  175         VI_UNLOCK(dvp);
  176 
  177         return (NULLVP);
  178 }
  179 
  180 /*
  181  * Remove the vnode.
  182  */
  183 static void
  184 unionfs_rem_cached_vnode(struct unionfs_node *unp, struct vnode *dvp)
  185 {
  186         KASSERT((unp != NULL), ("unionfs_rem_cached_vnode: null node"));
  187         KASSERT((dvp != NULLVP),
  188             ("unionfs_rem_cached_vnode: null parent vnode"));
  189         KASSERT((unp->un_hash.le_prev != NULL),
  190             ("unionfs_rem_cached_vnode: null hash"));
  191 
  192         VI_LOCK(dvp);
  193         LIST_REMOVE(unp, un_hash);
  194         unp->un_hash.le_next = NULL;
  195         unp->un_hash.le_prev = NULL;
  196         VI_UNLOCK(dvp);
  197 }
  198 
  199 /*
  200  * Make a new or get existing unionfs node.
  201  * 
  202  * uppervp and lowervp should be unlocked. Because if new unionfs vnode is
  203  * locked, uppervp or lowervp is locked too. In order to prevent dead lock,
  204  * you should not lock plurality simultaneously.
  205  */
  206 int
  207 unionfs_nodeget(struct mount *mp, struct vnode *uppervp,
  208                 struct vnode *lowervp, struct vnode *dvp,
  209                 struct vnode **vpp, struct componentname *cnp,
  210                 struct thread *td)
  211 {
  212         struct unionfs_mount *ump;
  213         struct unionfs_node *unp;
  214         struct vnode   *vp;
  215         int             error;
  216         int             lkflags;
  217         enum vtype      vt;
  218         char           *path;
  219 
  220         ump = MOUNTTOUNIONFSMOUNT(mp);
  221         lkflags = (cnp ? cnp->cn_lkflags : 0);
  222         path = (cnp ? cnp->cn_nameptr : NULL);
  223         *vpp = NULLVP;
  224 
  225         if (uppervp == NULLVP && lowervp == NULLVP)
  226                 panic("unionfs_nodeget: upper and lower is null");
  227 
  228         vt = (uppervp != NULLVP ? uppervp->v_type : lowervp->v_type);
  229 
  230         /* If it has no ISLASTCN flag, path check is skipped. */
  231         if (cnp && !(cnp->cn_flags & ISLASTCN))
  232                 path = NULL;
  233 
  234         /* check the cache */
  235         if (path != NULL && dvp != NULLVP && vt == VDIR) {
  236                 vp = unionfs_get_cached_vnode(uppervp, lowervp, dvp, path);
  237                 if (vp != NULLVP) {
  238                         vref(vp);
  239                         *vpp = vp;
  240                         goto unionfs_nodeget_out;
  241                 }
  242         }
  243 
  244         if ((uppervp == NULLVP || ump->um_uppervp != uppervp) ||
  245             (lowervp == NULLVP || ump->um_lowervp != lowervp)) {
  246                 /* dvp will be NULLVP only in case of root vnode. */
  247                 if (dvp == NULLVP)
  248                         return (EINVAL);
  249         }
  250 
  251         /*
  252          * Do the MALLOC before the getnewvnode since doing so afterward
  253          * might cause a bogus v_data pointer to get dereferenced elsewhere
  254          * if MALLOC should block.
  255          */
  256         unp = malloc(sizeof(struct unionfs_node),
  257             M_UNIONFSNODE, M_WAITOK | M_ZERO);
  258 
  259         error = getnewvnode("unionfs", mp, &unionfs_vnodeops, &vp);
  260         if (error != 0) {
  261                 free(unp, M_UNIONFSNODE);
  262                 return (error);
  263         }
  264         error = insmntque(vp, mp);      /* XXX: Too early for mpsafe fs */
  265         if (error != 0) {
  266                 free(unp, M_UNIONFSNODE);
  267                 return (error);
  268         }
  269         if (dvp != NULLVP)
  270                 vref(dvp);
  271         if (uppervp != NULLVP)
  272                 vref(uppervp);
  273         if (lowervp != NULLVP)
  274                 vref(lowervp);
  275 
  276         if (vt == VDIR)
  277                 unp->un_hashtbl = hashinit(NUNIONFSNODECACHE, M_UNIONFSHASH,
  278                     &(unp->un_hashmask));
  279 
  280         unp->un_vnode = vp;
  281         unp->un_uppervp = uppervp;
  282         unp->un_lowervp = lowervp;
  283         unp->un_dvp = dvp;
  284         if (uppervp != NULLVP)
  285                 vp->v_vnlock = uppervp->v_vnlock;
  286         else
  287                 vp->v_vnlock = lowervp->v_vnlock;
  288 
  289         if (path != NULL) {
  290                 unp->un_path = (char *)
  291                     malloc(cnp->cn_namelen +1, M_UNIONFSPATH, M_WAITOK|M_ZERO);
  292                 bcopy(cnp->cn_nameptr, unp->un_path, cnp->cn_namelen);
  293                 unp->un_path[cnp->cn_namelen] = '\0';
  294         }
  295         vp->v_type = vt;
  296         vp->v_data = unp;
  297 
  298         if ((uppervp != NULLVP && ump->um_uppervp == uppervp) &&
  299             (lowervp != NULLVP && ump->um_lowervp == lowervp))
  300                 vp->v_vflag |= VV_ROOT;
  301 
  302         if (path != NULL && dvp != NULLVP && vt == VDIR)
  303                 *vpp = unionfs_ins_cached_vnode(unp, dvp, path);
  304         if ((*vpp) != NULLVP) {
  305                 if (dvp != NULLVP)
  306                         vrele(dvp);
  307                 if (uppervp != NULLVP)
  308                         vrele(uppervp);
  309                 if (lowervp != NULLVP)
  310                         vrele(lowervp);
  311 
  312                 unp->un_uppervp = NULLVP;
  313                 unp->un_lowervp = NULLVP;
  314                 unp->un_dvp = NULLVP;
  315                 vrele(vp);
  316                 vp = *vpp;
  317                 vref(vp);
  318         } else
  319                 *vpp = vp;
  320 
  321 unionfs_nodeget_out:
  322         if (lkflags & LK_TYPE_MASK)
  323                 vn_lock(vp, lkflags | LK_RETRY);
  324 
  325         return (0);
  326 }
  327 
  328 /*
  329  * Clean up the unionfs node.
  330  */
  331 void
  332 unionfs_noderem(struct vnode *vp, struct thread *td)
  333 {
  334         int             vfslocked;
  335         int             count;
  336         struct unionfs_node *unp, *unp_t1, *unp_t2;
  337         struct unionfs_node_hashhead *hd;
  338         struct unionfs_node_status *unsp, *unsp_tmp;
  339         struct vnode   *lvp;
  340         struct vnode   *uvp;
  341         struct vnode   *dvp;
  342 
  343         /*
  344          * Use the interlock to protect the clearing of v_data to
  345          * prevent faults in unionfs_lock().
  346          */
  347         VI_LOCK(vp);
  348         unp = VTOUNIONFS(vp);
  349         lvp = unp->un_lowervp;
  350         uvp = unp->un_uppervp;
  351         dvp = unp->un_dvp;
  352         unp->un_lowervp = unp->un_uppervp = NULLVP;
  353 
  354         vp->v_vnlock = &(vp->v_lock);
  355         vp->v_data = NULL;
  356         lockmgr(vp->v_vnlock, LK_EXCLUSIVE | LK_INTERLOCK, VI_MTX(vp));
  357         if (lvp != NULLVP)
  358                 VOP_UNLOCK(lvp, 0);
  359         if (uvp != NULLVP)
  360                 VOP_UNLOCK(uvp, 0);
  361         vp->v_object = NULL;
  362 
  363         if (dvp != NULLVP && unp->un_hash.le_prev != NULL)
  364                 unionfs_rem_cached_vnode(unp, dvp);
  365 
  366         if (lvp != NULLVP) {
  367                 vfslocked = VFS_LOCK_GIANT(lvp->v_mount);
  368                 vrele(lvp);
  369                 VFS_UNLOCK_GIANT(vfslocked);
  370         }
  371         if (uvp != NULLVP) {
  372                 vfslocked = VFS_LOCK_GIANT(uvp->v_mount);
  373                 vrele(uvp);
  374                 VFS_UNLOCK_GIANT(vfslocked);
  375         }
  376         if (dvp != NULLVP) {
  377                 vfslocked = VFS_LOCK_GIANT(dvp->v_mount);
  378                 vrele(dvp);
  379                 VFS_UNLOCK_GIANT(vfslocked);
  380                 unp->un_dvp = NULLVP;
  381         }
  382         if (unp->un_path != NULL) {
  383                 free(unp->un_path, M_UNIONFSPATH);
  384                 unp->un_path = NULL;
  385         }
  386 
  387         if (unp->un_hashtbl != NULL) {
  388                 for (count = 0; count <= unp->un_hashmask; count++) {
  389                         hd = unp->un_hashtbl + count;
  390                         LIST_FOREACH_SAFE(unp_t1, hd, un_hash, unp_t2) {
  391                                 LIST_REMOVE(unp_t1, un_hash);
  392                                 unp_t1->un_hash.le_next = NULL;
  393                                 unp_t1->un_hash.le_prev = NULL;
  394                         }
  395                 }
  396                 hashdestroy(unp->un_hashtbl, M_UNIONFSHASH, unp->un_hashmask);
  397         }
  398 
  399         LIST_FOREACH_SAFE(unsp, &(unp->un_unshead), uns_list, unsp_tmp) {
  400                 LIST_REMOVE(unsp, uns_list);
  401                 free(unsp, M_TEMP);
  402         }
  403         free(unp, M_UNIONFSNODE);
  404 }
  405 
  406 /*
  407  * Get the unionfs node status.
  408  * You need exclusive lock this vnode.
  409  */
  410 void
  411 unionfs_get_node_status(struct unionfs_node *unp, struct thread *td,
  412                         struct unionfs_node_status **unspp)
  413 {
  414         struct unionfs_node_status *unsp;
  415         pid_t pid = td->td_proc->p_pid;
  416 
  417         KASSERT(NULL != unspp, ("null pointer"));
  418         ASSERT_VOP_ELOCKED(UNIONFSTOV(unp), "unionfs_get_node_status");
  419 
  420         LIST_FOREACH(unsp, &(unp->un_unshead), uns_list) {
  421                 if (unsp->uns_pid == pid) {
  422                         *unspp = unsp;
  423                         return;
  424                 }
  425         }
  426 
  427         /* create a new unionfs node status */
  428         unsp = malloc(sizeof(struct unionfs_node_status),
  429             M_TEMP, M_WAITOK | M_ZERO);
  430 
  431         unsp->uns_pid = pid;
  432         LIST_INSERT_HEAD(&(unp->un_unshead), unsp, uns_list);
  433 
  434         *unspp = unsp;
  435 }
  436 
  437 /*
  438  * Remove the unionfs node status, if you can.
  439  * You need exclusive lock this vnode.
  440  */
  441 void
  442 unionfs_tryrem_node_status(struct unionfs_node *unp,
  443                            struct unionfs_node_status *unsp)
  444 {
  445         KASSERT(NULL != unsp, ("null pointer"));
  446         ASSERT_VOP_ELOCKED(UNIONFSTOV(unp), "unionfs_get_node_status");
  447 
  448         if (0 < unsp->uns_lower_opencnt || 0 < unsp->uns_upper_opencnt)
  449                 return;
  450 
  451         LIST_REMOVE(unsp, uns_list);
  452         free(unsp, M_TEMP);
  453 }
  454 
  455 /*
  456  * Create upper node attr.
  457  */
  458 void
  459 unionfs_create_uppervattr_core(struct unionfs_mount *ump,
  460                                struct vattr *lva,
  461                                struct vattr *uva,
  462                                struct thread *td)
  463 {
  464         VATTR_NULL(uva);
  465         uva->va_type = lva->va_type;
  466         uva->va_atime = lva->va_atime;
  467         uva->va_mtime = lva->va_mtime;
  468         uva->va_ctime = lva->va_ctime;
  469 
  470         switch (ump->um_copymode) {
  471         case UNIONFS_TRANSPARENT:
  472                 uva->va_mode = lva->va_mode;
  473                 uva->va_uid = lva->va_uid;
  474                 uva->va_gid = lva->va_gid;
  475                 break;
  476         case UNIONFS_MASQUERADE:
  477                 if (ump->um_uid == lva->va_uid) {
  478                         uva->va_mode = lva->va_mode & 077077;
  479                         uva->va_mode |= (lva->va_type == VDIR ? ump->um_udir : ump->um_ufile) & 0700;
  480                         uva->va_uid = lva->va_uid;
  481                         uva->va_gid = lva->va_gid;
  482                 } else {
  483                         uva->va_mode = (lva->va_type == VDIR ? ump->um_udir : ump->um_ufile);
  484                         uva->va_uid = ump->um_uid;
  485                         uva->va_gid = ump->um_gid;
  486                 }
  487                 break;
  488         default:                /* UNIONFS_TRADITIONAL */
  489                 uva->va_mode = 0777 & ~td->td_proc->p_fd->fd_cmask;
  490                 uva->va_uid = ump->um_uid;
  491                 uva->va_gid = ump->um_gid;
  492                 break;
  493         }
  494 }
  495 
  496 /*
  497  * Create upper node attr.
  498  */
  499 int
  500 unionfs_create_uppervattr(struct unionfs_mount *ump,
  501                           struct vnode *lvp,
  502                           struct vattr *uva,
  503                           struct ucred *cred,
  504                           struct thread *td)
  505 {
  506         int             error;
  507         struct vattr    lva;
  508 
  509         if ((error = VOP_GETATTR(lvp, &lva, cred)))
  510                 return (error);
  511 
  512         unionfs_create_uppervattr_core(ump, &lva, uva, td);
  513 
  514         return (error);
  515 }
  516 
  517 /*
  518  * relookup
  519  * 
  520  * dvp should be locked on entry and will be locked on return.
  521  * 
  522  * If an error is returned, *vpp will be invalid, otherwise it will hold a
  523  * locked, referenced vnode. If *vpp == dvp then remember that only one
  524  * LK_EXCLUSIVE lock is held.
  525  */
  526 int
  527 unionfs_relookup(struct vnode *dvp, struct vnode **vpp,
  528                  struct componentname *cnp, struct componentname *cn,
  529                  struct thread *td, char *path, int pathlen, u_long nameiop)
  530 {
  531         int     error;
  532 
  533         cn->cn_namelen = pathlen;
  534         cn->cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK);
  535         bcopy(path, cn->cn_pnbuf, pathlen);
  536         cn->cn_pnbuf[pathlen] = '\0';
  537 
  538         cn->cn_nameiop = nameiop;
  539         cn->cn_flags = (LOCKPARENT | LOCKLEAF | HASBUF | SAVENAME | ISLASTCN);
  540         cn->cn_lkflags = LK_EXCLUSIVE;
  541         cn->cn_thread = td;
  542         cn->cn_cred = cnp->cn_cred;
  543 
  544         cn->cn_nameptr = cn->cn_pnbuf;
  545         cn->cn_consume = cnp->cn_consume;
  546 
  547         if (nameiop == DELETE)
  548                 cn->cn_flags |= (cnp->cn_flags & (DOWHITEOUT | SAVESTART));
  549         else if (RENAME == nameiop)
  550                 cn->cn_flags |= (cnp->cn_flags & SAVESTART);
  551 
  552         vref(dvp);
  553         VOP_UNLOCK(dvp, 0);
  554 
  555         if ((error = relookup(dvp, vpp, cn))) {
  556                 uma_zfree(namei_zone, cn->cn_pnbuf);
  557                 cn->cn_flags &= ~HASBUF;
  558                 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
  559         } else
  560                 vrele(dvp);
  561 
  562         return (error);
  563 }
  564 
  565 /*
  566  * relookup for CREATE namei operation.
  567  *
  568  * dvp is unionfs vnode. dvp should be locked.
  569  *
  570  * If it called 'unionfs_copyfile' function by unionfs_link etc,
  571  * VOP_LOOKUP information is broken.
  572  * So it need relookup in order to create link etc.
  573  */
  574 int
  575 unionfs_relookup_for_create(struct vnode *dvp, struct componentname *cnp,
  576                             struct thread *td)
  577 {
  578         int     error;
  579         struct vnode *udvp;
  580         struct vnode *vp;
  581         struct componentname cn;
  582 
  583         udvp = UNIONFSVPTOUPPERVP(dvp);
  584         vp = NULLVP;
  585 
  586         error = unionfs_relookup(udvp, &vp, cnp, &cn, td, cnp->cn_nameptr,
  587             strlen(cnp->cn_nameptr), CREATE);
  588         if (error)
  589                 return (error);
  590 
  591         if (vp != NULLVP) {
  592                 if (udvp == vp)
  593                         vrele(vp);
  594                 else
  595                         vput(vp);
  596 
  597                 error = EEXIST;
  598         }
  599 
  600         if (cn.cn_flags & HASBUF) {
  601                 uma_zfree(namei_zone, cn.cn_pnbuf);
  602                 cn.cn_flags &= ~HASBUF;
  603         }
  604 
  605         if (!error) {
  606                 cn.cn_flags |= (cnp->cn_flags & HASBUF);
  607                 cnp->cn_flags = cn.cn_flags;
  608         }
  609 
  610         return (error);
  611 }
  612 
  613 /*
  614  * relookup for DELETE namei operation.
  615  *
  616  * dvp is unionfs vnode. dvp should be locked.
  617  */
  618 int
  619 unionfs_relookup_for_delete(struct vnode *dvp, struct componentname *cnp,
  620                             struct thread *td)
  621 {
  622         int     error;
  623         struct vnode *udvp;
  624         struct vnode *vp;
  625         struct componentname cn;
  626 
  627         udvp = UNIONFSVPTOUPPERVP(dvp);
  628         vp = NULLVP;
  629 
  630         error = unionfs_relookup(udvp, &vp, cnp, &cn, td, cnp->cn_nameptr,
  631             strlen(cnp->cn_nameptr), DELETE);
  632         if (error)
  633                 return (error);
  634 
  635         if (vp == NULLVP)
  636                 error = ENOENT;
  637         else {
  638                 if (udvp == vp)
  639                         vrele(vp);
  640                 else
  641                         vput(vp);
  642         }
  643 
  644         if (cn.cn_flags & HASBUF) {
  645                 uma_zfree(namei_zone, cn.cn_pnbuf);
  646                 cn.cn_flags &= ~HASBUF;
  647         }
  648 
  649         if (!error) {
  650                 cn.cn_flags |= (cnp->cn_flags & HASBUF);
  651                 cnp->cn_flags = cn.cn_flags;
  652         }
  653 
  654         return (error);
  655 }
  656 
  657 /*
  658  * relookup for RENAME namei operation.
  659  *
  660  * dvp is unionfs vnode. dvp should be locked.
  661  */
  662 int
  663 unionfs_relookup_for_rename(struct vnode *dvp, struct componentname *cnp,
  664                             struct thread *td)
  665 {
  666         int error;
  667         struct vnode *udvp;
  668         struct vnode *vp;
  669         struct componentname cn;
  670 
  671         udvp = UNIONFSVPTOUPPERVP(dvp);
  672         vp = NULLVP;
  673 
  674         error = unionfs_relookup(udvp, &vp, cnp, &cn, td, cnp->cn_nameptr,
  675             strlen(cnp->cn_nameptr), RENAME);
  676         if (error)
  677                 return (error);
  678 
  679         if (vp != NULLVP) {
  680                 if (udvp == vp)
  681                         vrele(vp);
  682                 else
  683                         vput(vp);
  684         }
  685 
  686         if (cn.cn_flags & HASBUF) {
  687                 uma_zfree(namei_zone, cn.cn_pnbuf);
  688                 cn.cn_flags &= ~HASBUF;
  689         }
  690 
  691         if (!error) {
  692                 cn.cn_flags |= (cnp->cn_flags & HASBUF);
  693                 cnp->cn_flags = cn.cn_flags;
  694         }
  695 
  696         return (error);
  697 
  698 }
  699 
  700 /*
  701  * Update the unionfs_node.
  702  * 
  703  * uvp is new locked upper vnode. unionfs vnode's lock will be exchanged to the
  704  * uvp's lock and lower's lock will be unlocked.
  705  */
  706 static void
  707 unionfs_node_update(struct unionfs_node *unp, struct vnode *uvp,
  708                     struct thread *td)
  709 {
  710         unsigned        count, lockrec;
  711         struct vnode   *vp;
  712         struct vnode   *lvp;
  713         struct vnode   *dvp;
  714 
  715         vp = UNIONFSTOV(unp);
  716         lvp = unp->un_lowervp;
  717         ASSERT_VOP_ELOCKED(lvp, "unionfs_node_update");
  718         dvp = unp->un_dvp;
  719 
  720         /*
  721          * lock update
  722          */
  723         VI_LOCK(vp);
  724         unp->un_uppervp = uvp;
  725         vp->v_vnlock = uvp->v_vnlock;
  726         VI_UNLOCK(vp);
  727         lockrec = lvp->v_vnlock->lk_recurse;
  728         for (count = 0; count < lockrec; count++)
  729                 vn_lock(uvp, LK_EXCLUSIVE | LK_CANRECURSE | LK_RETRY);
  730 
  731         /*
  732          * cache update
  733          */
  734         if (unp->un_path != NULL && dvp != NULLVP && vp->v_type == VDIR) {
  735                 static struct unionfs_node_hashhead *hd;
  736 
  737                 VI_LOCK(dvp);
  738                 hd = unionfs_get_hashhead(dvp, unp->un_path);
  739                 LIST_REMOVE(unp, un_hash);
  740                 LIST_INSERT_HEAD(hd, unp, un_hash);
  741                 VI_UNLOCK(dvp);
  742         }
  743 }
  744 
  745 /*
  746  * Create a new shadow dir.
  747  * 
  748  * udvp should be locked on entry and will be locked on return.
  749  * 
  750  * If no error returned, unp will be updated.
  751  */
  752 int
  753 unionfs_mkshadowdir(struct unionfs_mount *ump, struct vnode *udvp,
  754                     struct unionfs_node *unp, struct componentname *cnp,
  755                     struct thread *td)
  756 {
  757         int             error;
  758         struct vnode   *lvp;
  759         struct vnode   *uvp;
  760         struct vattr    va;
  761         struct vattr    lva;
  762         struct componentname cn;
  763         struct mount   *mp;
  764         struct ucred   *cred;
  765         struct ucred   *credbk;
  766         struct uidinfo *rootinfo;
  767 
  768         if (unp->un_uppervp != NULLVP)
  769                 return (EEXIST);
  770 
  771         lvp = unp->un_lowervp;
  772         uvp = NULLVP;
  773         credbk = cnp->cn_cred;
  774 
  775         /* Authority change to root */
  776         rootinfo = uifind((uid_t)0);
  777         cred = crdup(cnp->cn_cred);
  778         /*
  779          * The calls to chgproccnt() are needed to compensate for change_ruid()
  780          * calling chgproccnt().
  781          */
  782         chgproccnt(cred->cr_ruidinfo, 1, 0);
  783         change_euid(cred, rootinfo);
  784         change_ruid(cred, rootinfo);
  785         change_svuid(cred, (uid_t)0);
  786         uifree(rootinfo);
  787         cnp->cn_cred = cred;
  788 
  789         memset(&cn, 0, sizeof(cn));
  790 
  791         if ((error = VOP_GETATTR(lvp, &lva, cnp->cn_cred)))
  792                 goto unionfs_mkshadowdir_abort;
  793 
  794         if ((error = unionfs_relookup(udvp, &uvp, cnp, &cn, td, cnp->cn_nameptr, cnp->cn_namelen, CREATE)))
  795                 goto unionfs_mkshadowdir_abort;
  796         if (uvp != NULLVP) {
  797                 if (udvp == uvp)
  798                         vrele(uvp);
  799                 else
  800                         vput(uvp);
  801 
  802                 error = EEXIST;
  803                 goto unionfs_mkshadowdir_free_out;
  804         }
  805 
  806         if ((error = vn_start_write(udvp, &mp, V_WAIT | PCATCH)))
  807                 goto unionfs_mkshadowdir_free_out;
  808         unionfs_create_uppervattr_core(ump, &lva, &va, td);
  809 
  810         error = VOP_MKDIR(udvp, &uvp, &cn, &va);
  811 
  812         if (!error) {
  813                 unionfs_node_update(unp, uvp, td);
  814 
  815                 /*
  816                  * XXX The bug which cannot set uid/gid was corrected.
  817                  * Ignore errors.
  818                  */
  819                 va.va_type = VNON;
  820                 VOP_SETATTR(uvp, &va, cn.cn_cred);
  821         }
  822         vn_finished_write(mp);
  823 
  824 unionfs_mkshadowdir_free_out:
  825         if (cn.cn_flags & HASBUF) {
  826                 uma_zfree(namei_zone, cn.cn_pnbuf);
  827                 cn.cn_flags &= ~HASBUF;
  828         }
  829 
  830 unionfs_mkshadowdir_abort:
  831         cnp->cn_cred = credbk;
  832         chgproccnt(cred->cr_ruidinfo, -1, 0);
  833         crfree(cred);
  834 
  835         return (error);
  836 }
  837 
  838 /*
  839  * Create a new whiteout.
  840  * 
  841  * dvp should be locked on entry and will be locked on return.
  842  */
  843 int
  844 unionfs_mkwhiteout(struct vnode *dvp, struct componentname *cnp,
  845                    struct thread *td, char *path)
  846 {
  847         int             error;
  848         struct vnode   *wvp;
  849         struct componentname cn;
  850         struct mount   *mp;
  851 
  852         if (path == NULL)
  853                 path = cnp->cn_nameptr;
  854 
  855         wvp = NULLVP;
  856         if ((error = unionfs_relookup(dvp, &wvp, cnp, &cn, td, path, strlen(path), CREATE)))
  857                 return (error);
  858         if (wvp != NULLVP) {
  859                 if (cn.cn_flags & HASBUF) {
  860                         uma_zfree(namei_zone, cn.cn_pnbuf);
  861                         cn.cn_flags &= ~HASBUF;
  862                 }
  863                 if (dvp == wvp)
  864                         vrele(wvp);
  865                 else
  866                         vput(wvp);
  867 
  868                 return (EEXIST);
  869         }
  870 
  871         if ((error = vn_start_write(dvp, &mp, V_WAIT | PCATCH)))
  872                 goto unionfs_mkwhiteout_free_out;
  873         error = VOP_WHITEOUT(dvp, &cn, CREATE);
  874 
  875         vn_finished_write(mp);
  876 
  877 unionfs_mkwhiteout_free_out:
  878         if (cn.cn_flags & HASBUF) {
  879                 uma_zfree(namei_zone, cn.cn_pnbuf);
  880                 cn.cn_flags &= ~HASBUF;
  881         }
  882 
  883         return (error);
  884 }
  885 
  886 /*
  887  * Create a new vnode for create a new shadow file.
  888  * 
  889  * If an error is returned, *vpp will be invalid, otherwise it will hold a
  890  * locked, referenced and opened vnode.
  891  * 
  892  * unp is never updated.
  893  */
  894 static int
  895 unionfs_vn_create_on_upper(struct vnode **vpp, struct vnode *udvp,
  896                            struct unionfs_node *unp, struct vattr *uvap,
  897                            struct thread *td)
  898 {
  899         struct unionfs_mount *ump;
  900         struct vnode   *vp;
  901         struct vnode   *lvp;
  902         struct ucred   *cred;
  903         struct vattr    lva;
  904         int             fmode;
  905         int             error;
  906         struct componentname cn;
  907 
  908         ump = MOUNTTOUNIONFSMOUNT(UNIONFSTOV(unp)->v_mount);
  909         vp = NULLVP;
  910         lvp = unp->un_lowervp;
  911         cred = td->td_ucred;
  912         fmode = FFLAGS(O_WRONLY | O_CREAT | O_TRUNC | O_EXCL);
  913         error = 0;
  914 
  915         if ((error = VOP_GETATTR(lvp, &lva, cred)) != 0)
  916                 return (error);
  917         unionfs_create_uppervattr_core(ump, &lva, uvap, td);
  918 
  919         if (unp->un_path == NULL)
  920                 panic("unionfs: un_path is null");
  921 
  922         cn.cn_namelen = strlen(unp->un_path);
  923         cn.cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK);
  924         bcopy(unp->un_path, cn.cn_pnbuf, cn.cn_namelen + 1);
  925         cn.cn_nameiop = CREATE;
  926         cn.cn_flags = (LOCKPARENT | LOCKLEAF | HASBUF | SAVENAME | ISLASTCN);
  927         cn.cn_lkflags = LK_EXCLUSIVE;
  928         cn.cn_thread = td;
  929         cn.cn_cred = cred;
  930         cn.cn_nameptr = cn.cn_pnbuf;
  931         cn.cn_consume = 0;
  932 
  933         vref(udvp);
  934         if ((error = relookup(udvp, &vp, &cn)) != 0)
  935                 goto unionfs_vn_create_on_upper_free_out2;
  936         vrele(udvp);
  937 
  938         if (vp != NULLVP) {
  939                 if (vp == udvp)
  940                         vrele(vp);
  941                 else
  942                         vput(vp);
  943                 error = EEXIST;
  944                 goto unionfs_vn_create_on_upper_free_out1;
  945         }
  946 
  947         if ((error = VOP_CREATE(udvp, &vp, &cn, uvap)) != 0)
  948                 goto unionfs_vn_create_on_upper_free_out1;
  949 
  950         if ((error = VOP_OPEN(vp, fmode, cred, td, NULL)) != 0) {
  951                 vput(vp);
  952                 goto unionfs_vn_create_on_upper_free_out1;
  953         }
  954         vp->v_writecount++;
  955         *vpp = vp;
  956 
  957 unionfs_vn_create_on_upper_free_out1:
  958         VOP_UNLOCK(udvp, 0);
  959 
  960 unionfs_vn_create_on_upper_free_out2:
  961         if (cn.cn_flags & HASBUF) {
  962                 uma_zfree(namei_zone, cn.cn_pnbuf);
  963                 cn.cn_flags &= ~HASBUF;
  964         }
  965 
  966         return (error);
  967 }
  968 
  969 /*
  970  * Copy from lvp to uvp.
  971  * 
  972  * lvp and uvp should be locked and opened on entry and will be locked and
  973  * opened on return.
  974  */
  975 static int
  976 unionfs_copyfile_core(struct vnode *lvp, struct vnode *uvp,
  977                       struct ucred *cred, struct thread *td)
  978 {
  979         int             error;
  980         off_t           offset;
  981         int             count;
  982         int             bufoffset;
  983         char           *buf;
  984         struct uio      uio;
  985         struct iovec    iov;
  986 
  987         error = 0;
  988         memset(&uio, 0, sizeof(uio));
  989 
  990         uio.uio_td = td;
  991         uio.uio_segflg = UIO_SYSSPACE;
  992         uio.uio_offset = 0;
  993 
  994         buf = malloc(MAXBSIZE, M_TEMP, M_WAITOK);
  995 
  996         while (error == 0) {
  997                 offset = uio.uio_offset;
  998 
  999                 uio.uio_iov = &iov;
 1000                 uio.uio_iovcnt = 1;
 1001                 iov.iov_base = buf;
 1002                 iov.iov_len = MAXBSIZE;
 1003                 uio.uio_resid = iov.iov_len;
 1004                 uio.uio_rw = UIO_READ;
 1005 
 1006                 if ((error = VOP_READ(lvp, &uio, 0, cred)) != 0)
 1007                         break;
 1008                 if ((count = MAXBSIZE - uio.uio_resid) == 0)
 1009                         break;
 1010 
 1011                 bufoffset = 0;
 1012                 while (bufoffset < count) {
 1013                         uio.uio_iov = &iov;
 1014                         uio.uio_iovcnt = 1;
 1015                         iov.iov_base = buf + bufoffset;
 1016                         iov.iov_len = count - bufoffset;
 1017                         uio.uio_offset = offset + bufoffset;
 1018                         uio.uio_resid = iov.iov_len;
 1019                         uio.uio_rw = UIO_WRITE;
 1020 
 1021                         if ((error = VOP_WRITE(uvp, &uio, 0, cred)) != 0)
 1022                                 break;
 1023 
 1024                         bufoffset += (count - bufoffset) - uio.uio_resid;
 1025                 }
 1026 
 1027                 uio.uio_offset = offset + bufoffset;
 1028         }
 1029 
 1030         free(buf, M_TEMP);
 1031 
 1032         return (error);
 1033 }
 1034 
 1035 /*
 1036  * Copy file from lower to upper.
 1037  * 
 1038  * If you need copy of the contents, set 1 to docopy. Otherwise, set 0 to
 1039  * docopy.
 1040  * 
 1041  * If no error returned, unp will be updated.
 1042  */
 1043 int
 1044 unionfs_copyfile(struct unionfs_node *unp, int docopy, struct ucred *cred,
 1045                  struct thread *td)
 1046 {
 1047         int             error;
 1048         struct mount   *mp;
 1049         struct vnode   *udvp;
 1050         struct vnode   *lvp;
 1051         struct vnode   *uvp;
 1052         struct vattr    uva;
 1053 
 1054         lvp = unp->un_lowervp;
 1055         uvp = NULLVP;
 1056 
 1057         if ((UNIONFSTOV(unp)->v_mount->mnt_flag & MNT_RDONLY))
 1058                 return (EROFS);
 1059         if (unp->un_dvp == NULLVP)
 1060                 return (EINVAL);
 1061         if (unp->un_uppervp != NULLVP)
 1062                 return (EEXIST);
 1063         udvp = VTOUNIONFS(unp->un_dvp)->un_uppervp;
 1064         if (udvp == NULLVP)
 1065                 return (EROFS);
 1066         if ((udvp->v_mount->mnt_flag & MNT_RDONLY))
 1067                 return (EROFS);
 1068 
 1069         error = VOP_ACCESS(lvp, VREAD, cred, td);
 1070         if (error != 0)
 1071                 return (error);
 1072 
 1073         if ((error = vn_start_write(udvp, &mp, V_WAIT | PCATCH)) != 0)
 1074                 return (error);
 1075         error = unionfs_vn_create_on_upper(&uvp, udvp, unp, &uva, td);
 1076         if (error != 0) {
 1077                 vn_finished_write(mp);
 1078                 return (error);
 1079         }
 1080 
 1081         if (docopy != 0) {
 1082                 error = VOP_OPEN(lvp, FREAD, cred, td, NULL);
 1083                 if (error == 0) {
 1084                         error = unionfs_copyfile_core(lvp, uvp, cred, td);
 1085                         VOP_CLOSE(lvp, FREAD, cred, td);
 1086                 }
 1087         }
 1088         VOP_CLOSE(uvp, FWRITE, cred, td);
 1089         uvp->v_writecount--;
 1090 
 1091         vn_finished_write(mp);
 1092 
 1093         if (error == 0) {
 1094                 /* Reset the attributes. Ignore errors. */
 1095                 uva.va_type = VNON;
 1096                 VOP_SETATTR(uvp, &uva, cred);
 1097         }
 1098 
 1099         unionfs_node_update(unp, uvp, td);
 1100 
 1101         return (error);
 1102 }
 1103 
 1104 /*
 1105  * It checks whether vp can rmdir. (check empty)
 1106  *
 1107  * vp is unionfs vnode.
 1108  * vp should be locked.
 1109  */
 1110 int
 1111 unionfs_check_rmdir(struct vnode *vp, struct ucred *cred, struct thread *td)
 1112 {
 1113         int             error;
 1114         int             eofflag;
 1115         int             lookuperr;
 1116         struct vnode   *uvp;
 1117         struct vnode   *lvp;
 1118         struct vnode   *tvp;
 1119         struct vattr    va;
 1120         struct componentname cn;
 1121         /*
 1122          * The size of buf needs to be larger than DIRBLKSIZ.
 1123          */
 1124         char            buf[256 * 6];
 1125         struct dirent  *dp;
 1126         struct dirent  *edp;
 1127         struct uio      uio;
 1128         struct iovec    iov;
 1129 
 1130         ASSERT_VOP_ELOCKED(vp, "unionfs_check_rmdir");
 1131 
 1132         eofflag = 0;
 1133         uvp = UNIONFSVPTOUPPERVP(vp);
 1134         lvp = UNIONFSVPTOLOWERVP(vp);
 1135 
 1136         /* check opaque */
 1137         if ((error = VOP_GETATTR(uvp, &va, cred)) != 0)
 1138                 return (error);
 1139         if (va.va_flags & OPAQUE)
 1140                 return (0);
 1141 
 1142         /* open vnode */
 1143 #ifdef MAC
 1144         if ((error = mac_vnode_check_open(cred, vp, VEXEC|VREAD)) != 0)
 1145                 return (error);
 1146 #endif
 1147         if ((error = VOP_ACCESS(vp, VEXEC|VREAD, cred, td)) != 0)
 1148                 return (error);
 1149         if ((error = VOP_OPEN(vp, FREAD, cred, td, NULL)) != 0)
 1150                 return (error);
 1151 
 1152         uio.uio_rw = UIO_READ;
 1153         uio.uio_segflg = UIO_SYSSPACE;
 1154         uio.uio_td = td;
 1155         uio.uio_offset = 0;
 1156 
 1157 #ifdef MAC
 1158         error = mac_vnode_check_readdir(td->td_ucred, lvp);
 1159 #endif
 1160         while (!error && !eofflag) {
 1161                 iov.iov_base = buf;
 1162                 iov.iov_len = sizeof(buf);
 1163                 uio.uio_iov = &iov;
 1164                 uio.uio_iovcnt = 1;
 1165                 uio.uio_resid = iov.iov_len;
 1166 
 1167                 error = VOP_READDIR(lvp, &uio, cred, &eofflag, NULL, NULL);
 1168                 if (error != 0)
 1169                         break;
 1170                 if (eofflag == 0 && uio.uio_resid == sizeof(buf)) {
 1171 #ifdef DIAGNOSTIC
 1172                         panic("bad readdir response from lower FS.");
 1173 #endif
 1174                         break;
 1175                 }
 1176 
 1177                 edp = (struct dirent*)&buf[sizeof(buf) - uio.uio_resid];
 1178                 for (dp = (struct dirent*)buf; !error && dp < edp;
 1179                      dp = (struct dirent*)((caddr_t)dp + dp->d_reclen)) {
 1180                         if (dp->d_type == DT_WHT ||
 1181                             (dp->d_namlen == 1 && dp->d_name[0] == '.') ||
 1182                             (dp->d_namlen == 2 && !bcmp(dp->d_name, "..", 2)))
 1183                                 continue;
 1184 
 1185                         cn.cn_namelen = dp->d_namlen;
 1186                         cn.cn_pnbuf = NULL;
 1187                         cn.cn_nameptr = dp->d_name;
 1188                         cn.cn_nameiop = LOOKUP;
 1189                         cn.cn_flags = (LOCKPARENT | LOCKLEAF | SAVENAME | RDONLY | ISLASTCN);
 1190                         cn.cn_lkflags = LK_EXCLUSIVE;
 1191                         cn.cn_thread = td;
 1192                         cn.cn_cred = cred;
 1193                         cn.cn_consume = 0;
 1194 
 1195                         /*
 1196                          * check entry in lower.
 1197                          * Sometimes, readdir function returns
 1198                          * wrong entry.
 1199                          */
 1200                         lookuperr = VOP_LOOKUP(lvp, &tvp, &cn);
 1201 
 1202                         if (!lookuperr)
 1203                                 vput(tvp);
 1204                         else
 1205                                 continue; /* skip entry */
 1206 
 1207                         /*
 1208                          * check entry
 1209                          * If it has no exist/whiteout entry in upper,
 1210                          * directory is not empty.
 1211                          */
 1212                         cn.cn_flags = (LOCKPARENT | LOCKLEAF | SAVENAME | RDONLY | ISLASTCN);
 1213                         lookuperr = VOP_LOOKUP(uvp, &tvp, &cn);
 1214 
 1215                         if (!lookuperr)
 1216                                 vput(tvp);
 1217 
 1218                         /* ignore exist or whiteout entry */
 1219                         if (!lookuperr ||
 1220                             (lookuperr == ENOENT && (cn.cn_flags & ISWHITEOUT)))
 1221                                 continue;
 1222 
 1223                         error = ENOTEMPTY;
 1224                 }
 1225         }
 1226 
 1227         /* close vnode */
 1228         VOP_CLOSE(vp, FREAD, cred, td);
 1229 
 1230         return (error);
 1231 }
 1232 
 1233 #ifdef DIAGNOSTIC
 1234 
 1235 struct vnode   *
 1236 unionfs_checkuppervp(struct vnode *vp, char *fil, int lno)
 1237 {
 1238         struct unionfs_node *unp;
 1239 
 1240         unp = VTOUNIONFS(vp);
 1241 
 1242 #ifdef notyet
 1243         if (vp->v_op != unionfs_vnodeop_p) {
 1244                 printf("unionfs_checkuppervp: on non-unionfs-node.\n");
 1245 #ifdef KDB
 1246                 kdb_enter(KDB_WHY_UNIONFS,
 1247                     "unionfs_checkuppervp: on non-unionfs-node.\n");
 1248 #endif
 1249                 panic("unionfs_checkuppervp");
 1250         };
 1251 #endif
 1252         return (unp->un_uppervp);
 1253 }
 1254 
 1255 struct vnode   *
 1256 unionfs_checklowervp(struct vnode *vp, char *fil, int lno)
 1257 {
 1258         struct unionfs_node *unp;
 1259 
 1260         unp = VTOUNIONFS(vp);
 1261 
 1262 #ifdef notyet
 1263         if (vp->v_op != unionfs_vnodeop_p) {
 1264                 printf("unionfs_checklowervp: on non-unionfs-node.\n");
 1265 #ifdef KDB
 1266                 kdb_enter(KDB_WHY_UNIONFS,
 1267                     "unionfs_checklowervp: on non-unionfs-node.\n");
 1268 #endif
 1269                 panic("unionfs_checklowervp");
 1270         };
 1271 #endif
 1272         return (unp->un_lowervp);
 1273 }
 1274 #endif

Cache object: 485d53635a17d19f6c4dba83a8a10eac


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