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/xfs/xfs_node-bsd.c

Version: -  FREEBSD  -  FREEBSD11  -  FREEBSD10  -  FREEBSD9  -  FREEBSD92  -  FREEBSD91  -  FREEBSD90  -  FREEBSD8  -  FREEBSD82  -  FREEBSD81  -  FREEBSD80  -  FREEBSD7  -  FREEBSD74  -  FREEBSD73  -  FREEBSD72  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 1995 - 2002 Kungliga Tekniska Högskolan
    3  * (Royal Institute of Technology, Stockholm, Sweden).
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  *
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  *
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * 3. Neither the name of the Institute nor the names of its contributors
   18  *    may be used to endorse or promote products derived from this software
   19  *    without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
   22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
   25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31  * SUCH DAMAGE.
   32  */
   33 
   34 #include <sys/queue.h>
   35 #include <xfs/xfs_locl.h>
   36 #include <xfs/xfs_common.h>
   37 #include <xfs/xfs_fs.h>
   38 #include <xfs/xfs_deb.h>
   39 #include <xfs/xfs_vnodeops.h>
   40 
   41 RCSID("$arla: xfs_node-bsd.c,v 1.70 2003/02/28 02:01:06 lha Exp $");
   42 
   43 extern vop_t **xfs_vnodeop_p;
   44 
   45 #ifndef LK_NOPAUSE
   46 #define LK_NOPAUSE 0
   47 #endif
   48 
   49 /*
   50  * Allocate a new vnode with handle `handle' in `mp' and return it in
   51  * `vpp'.  Return 0 or error.
   52  */
   53 
   54 int
   55 xfs_getnewvnode(struct xfs *xfsp, struct vnode **vpp, 
   56                 struct xfs_handle *handle)
   57 {
   58     struct xfs_node *result, *check;
   59     int error;
   60 
   61     error = getnewvnode(VT_XFS, NNPFS_TO_VFS(xfsp), xfs_vnodeop_p, vpp);
   62     if (error)
   63         return error;
   64     
   65     result = xfs_alloc(sizeof(*result), M_NNPFS_NODE);
   66     bzero(result, sizeof(*result));
   67     
   68     (*vpp)->v_data = result;
   69     result->vn = *vpp;
   70     
   71     result->handle = *handle;
   72     result->flags = 0;
   73     result->tokens = 0;
   74     result->offset = 0;
   75 #if defined(HAVE_KERNEL_LOCKMGR) || defined(HAVE_KERNEL_DEBUGLOCKMGR)
   76     lockinit (&result->lock, PVFS, "xfs_lock", 0, LK_NOPAUSE);
   77 #else
   78     result->vnlocks = 0;
   79 #endif
   80     result->anonrights = 0;
   81     result->rd_cred = NULL;
   82     result->wr_cred = NULL;
   83 
   84 #if defined(__NetBSD_Version__) && __NetBSD_Version__ >= 105280000
   85     genfs_node_init(*vpp, &xfs_genfsops);
   86 #endif
   87 
   88     check = xfs_node_find(&xfsp->nodehead, handle);
   89     if (check) {
   90         vput(*vpp);
   91         *vpp = result->vn;
   92         return 0;
   93     }
   94 
   95     xfs_insert(&xfs->nodehead, result);
   96 
   97     return 0;
   98 }
   99 
  100 /*
  101  * Create a new xfs_node and make a vget
  102  *
  103  * Also prevents creation of duplicates. This happens
  104  * whenever there are more than one name to a file,
  105  * "." and ".." are common cases.  */
  106 
  107 int
  108 new_xfs_node(struct xfs *xfsp,
  109              struct xfs_msg_node *node,
  110              struct xfs_node **xpp,
  111              d_thread_t *p)
  112 {
  113     struct xfs_node *result;
  114 
  115     NNPFSDEB(XDEBNODE, ("new_xfs_node (%d,%d,%d,%d)\n",
  116                       node->handle.a,
  117                       node->handle.b,
  118                       node->handle.c,
  119                       node->handle.d));
  120 
  121 retry:
  122     /* Does not allow duplicates */
  123     result = xfs_node_find(&xfsp->nodehead, &node->handle);
  124     if (result == 0) {
  125         int error;
  126         struct vnode *v;
  127 
  128         error = xfs_getnewvnode(xfsp, &v, &node->handle);
  129         if (error)
  130             return error;
  131 
  132         result = VNODE_TO_XNODE(v);
  133         result->anonrights = node->anonrights;
  134 
  135         xfsp->nnodes++;
  136     } else {
  137         /* Node is already cached */
  138         if(xfs_do_vget(XNODE_TO_VNODE(result), 0, p))
  139             goto retry;
  140     }
  141 
  142     /* Init other fields */
  143     xfs_attr2vattr(&node->attr, &result->attr, 1);
  144     result->vn->v_type = result->attr.va_type;
  145     result->tokens = node->tokens;
  146     bcopy(node->id, result->id, sizeof(result->id));
  147     bcopy(node->rights, result->rights, sizeof(result->rights));
  148 
  149 #ifdef __APPLE__
  150     if (result->vn->v_type == VREG && (!UBCINFOEXISTS(result->vn)))
  151         ubc_info_init(result->vn);
  152 #endif
  153 
  154     *xpp = result;
  155     NNPFSDEB(XDEBNODE, ("return: new_xfs_node\n"));
  156     return 0;
  157 }
  158 
  159 void
  160 free_xfs_node(struct xfs_node *node)
  161 {
  162     struct xfs *xfsp = NNPFS_FROM_XNODE(node);
  163 
  164     NNPFSDEB(XDEBNODE, ("free_xfs_node(%lx) (%d,%d,%d,%d)\n",
  165                       (unsigned long)node,
  166                       node->handle.a,
  167                       node->handle.b,
  168                       node->handle.c,
  169                       node->handle.d));
  170 
  171     /* XXX Really need to put back dirty data first. */
  172 
  173     if (DATA_FROM_XNODE(node)) {
  174         vrele(DATA_FROM_XNODE(node));
  175         DATA_FROM_XNODE(node) = NULL;
  176     }
  177     xfsp->nnodes--;
  178     XNODE_TO_VNODE(node)->v_data = NULL;
  179     if (node->rd_cred) {
  180         crfree (node->rd_cred);
  181         node->rd_cred = NULL;
  182     }
  183     if (node->wr_cred) {
  184         crfree (node->wr_cred);
  185         node->wr_cred = NULL;
  186     }
  187 
  188     xfs_free(node, sizeof(*node), M_NNPFS_NODE);
  189 
  190     NNPFSDEB(XDEBNODE, ("free_xfs_node done\n"));
  191 }
  192 
  193 /*
  194  * FreeBSD 4.4 and newer changed to API to vflush around June 2001
  195  */
  196 
  197 static int
  198 xfs_vflush(struct mount *mp, int flags)
  199 {
  200 #if __FreeBSD__ && __FreeBSD_version > 430000
  201     return vflush(mp, 0, flags);
  202 #else
  203     return vflush(mp, NULL, flags);
  204 #endif
  205 }
  206 
  207 int
  208 free_all_xfs_nodes(struct xfs *xfsp, int flags, int unmountp)
  209 {
  210     int error = 0;
  211     struct mount *mp = NNPFS_TO_VFS(xfsp);
  212 
  213     if (mp == NULL) {
  214         NNPFSDEB(XDEBNODE, ("free_all_xfs_nodes already freed\n"));
  215         return 0;
  216     }
  217 
  218     NNPFSDEB(XDEBNODE, ("free_all_xfs_nodes starting\n"));
  219 
  220     xfs_dnlc_purge_mp(mp);
  221 
  222     if (xfsp->root) {
  223         NNPFSDEB(XDEBNODE, ("free_all_xfs_nodes now removing root\n"));
  224 
  225         vgone(XNODE_TO_VNODE(xfsp->root));
  226         xfsp->root = NULL;
  227     }
  228 
  229     NNPFSDEB(XDEBNODE, ("free_all_xfs_nodes root removed\n"));
  230     NNPFSDEB(XDEBNODE, ("free_all_xfs_nodes now killing all remaining nodes\n"));
  231 
  232     /*
  233      * If we have a syncer vnode, release it (to emulate dounmount)
  234      * and the create it again when if we are going to need it.
  235      */
  236 
  237 #ifdef HAVE_STRUCT_MOUNT_MNT_SYNCER
  238     if (!unmountp) {
  239         if (mp->mnt_syncer != NULL) {
  240 #ifdef HAVE_KERNEL_VFS_DEALLOCATE_SYNCVNODE
  241             vfs_deallocate_syncvnode(mp);
  242 #else
  243             /* 
  244              * FreeBSD and OpenBSD uses different semantics,
  245              * FreeBSD does vrele, and OpenBSD does vgone.
  246              */
  247 #if defined(__OpenBSD__)
  248             vgone(mp->mnt_syncer);
  249 #elif defined(__FreeBSD__)
  250             vrele(mp->mnt_syncer);
  251 #else
  252 #error what os do you use ?
  253 #endif
  254             mp->mnt_syncer = NULL;
  255 #endif
  256         }
  257     }
  258 #endif
  259     error = xfs_vflush(mp, flags);
  260 #ifdef HAVE_STRUCT_MOUNT_MNT_SYNCER
  261     if (!unmountp) {
  262         NNPFSDEB(XDEBNODE, ("free_all_xfs_nodes not flushing syncer vnode\n"));
  263         if (mp->mnt_syncer == NULL)
  264             if (vfs_allocate_syncvnode(mp))
  265                 panic("failed to allocate syncer node when xfs daemon died");
  266     }
  267 #endif
  268 
  269     if (error) {
  270         NNPFSDEB(XDEBNODE, ("xfree_all_xfs_nodes: vflush() error == %d\n",
  271                           error));
  272         return error;
  273     }
  274 
  275     NNPFSDEB(XDEBNODE, ("free_all_xfs_nodes done\n"));
  276     return error;
  277 }
  278 
  279 void
  280 vattr2xfs_attr(const struct vattr *va, struct xfs_attr *xa)
  281 {
  282     bzero(xa, sizeof(*xa));
  283     if (va->va_mode != (mode_t)VNOVAL)
  284         XA_SET_MODE(xa, va->va_mode);
  285     if (va->va_nlink != VNOVAL)
  286         XA_SET_NLINK(xa, va->va_nlink);
  287     if (va->va_size != VNOVAL)
  288         XA_SET_SIZE(xa, va->va_size);
  289     if (va->va_uid != VNOVAL)
  290         XA_SET_UID(xa, va->va_uid);
  291     if (va->va_gid != VNOVAL)
  292         XA_SET_GID(xa, va->va_gid);
  293     if (va->va_atime.tv_sec != VNOVAL)
  294         XA_SET_ATIME(xa, va->va_atime.tv_sec);
  295     if (va->va_mtime.tv_sec != VNOVAL)
  296         XA_SET_MTIME(xa, va->va_mtime.tv_sec);
  297     if (va->va_ctime.tv_sec != VNOVAL)
  298         XA_SET_CTIME(xa, va->va_ctime.tv_sec);
  299     if (va->va_fileid != VNOVAL)
  300         XA_SET_FILEID(xa, va->va_fileid);
  301     switch (va->va_type) {
  302     case VNON:
  303         xa->xa_type = NNPFS_FILE_NON;
  304         break;
  305     case VREG:
  306         xa->xa_type = NNPFS_FILE_REG;
  307         break;
  308     case VDIR:
  309         xa->xa_type = NNPFS_FILE_DIR;
  310         break;
  311     case VBLK:
  312         xa->xa_type = NNPFS_FILE_BLK;
  313         break;
  314     case VCHR:
  315         xa->xa_type = NNPFS_FILE_CHR;
  316         break;
  317     case VLNK:
  318         xa->xa_type = NNPFS_FILE_LNK;
  319         break;
  320     case VSOCK:
  321         xa->xa_type = NNPFS_FILE_SOCK;
  322         break;
  323     case VFIFO:
  324         xa->xa_type = NNPFS_FILE_FIFO;
  325         break;
  326     case VBAD:
  327         xa->xa_type = NNPFS_FILE_BAD;
  328         break;
  329     default:
  330         panic("xfs_attr2attr: bad value");
  331     }
  332 }
  333 
  334 #define SET_TIMEVAL(X, S, N) do { (X)->tv_sec = (S); (X)->tv_nsec = (N); } while(0)
  335 
  336 void
  337 xfs_attr2vattr(const struct xfs_attr *xa, struct vattr *va, int clear_node)
  338 {
  339     if (clear_node)
  340         VATTR_NULL(va);
  341     if (XA_VALID_MODE(xa))
  342         va->va_mode = xa->xa_mode;
  343     if (XA_VALID_NLINK(xa))
  344         va->va_nlink = xa->xa_nlink;
  345     if (XA_VALID_SIZE(xa)) {
  346         va->va_size = xa->xa_size;
  347         va->va_bytes = va->va_size;
  348     }
  349     if (XA_VALID_UID(xa))
  350         va->va_uid = xa->xa_uid;
  351     if (XA_VALID_GID(xa))
  352         va->va_gid = xa->xa_gid;
  353     if (XA_VALID_ATIME(xa)) {
  354         SET_TIMEVAL(&va->va_atime, xa->xa_atime, 0);
  355     }
  356     if (XA_VALID_MTIME(xa)) {
  357         SET_TIMEVAL(&va->va_mtime, xa->xa_mtime, 0);
  358     }
  359     if (XA_VALID_CTIME(xa)) {
  360         SET_TIMEVAL(&va->va_ctime, xa->xa_ctime, 0);
  361     }
  362     if (XA_VALID_FILEID(xa)) {
  363         va->va_fileid = xa->xa_fileid;
  364     }
  365     if (XA_VALID_TYPE(xa)) {
  366         switch (xa->xa_type) {
  367         case NNPFS_FILE_NON:
  368             va->va_type = VNON;
  369             break;
  370         case NNPFS_FILE_REG:
  371             va->va_type = VREG;
  372             break;
  373         case NNPFS_FILE_DIR:
  374             va->va_type = VDIR;
  375             break;
  376         case NNPFS_FILE_BLK:
  377             va->va_type = VBLK;
  378             break;
  379         case NNPFS_FILE_CHR:
  380             va->va_type = VCHR;
  381             break;
  382         case NNPFS_FILE_LNK:
  383             va->va_type = VLNK;
  384             break;
  385         case NNPFS_FILE_SOCK:
  386             va->va_type = VSOCK;
  387             break;
  388         case NNPFS_FILE_FIFO:
  389             va->va_type = VFIFO;
  390             break;
  391         case NNPFS_FILE_BAD:
  392             va->va_type = VBAD;
  393             break;
  394         default:
  395             panic("xfs_attr2vattr: bad value");
  396         }
  397     }
  398     va->va_flags = 0;
  399     va->va_blocksize = 8192;
  400 }
  401 
  402 /*
  403  * A single entry DNLC for systems for handling long names that don't
  404  * get put into the system DNLC.
  405  */
  406 
  407 struct long_entry {
  408     struct vnode *dvp, *vp;
  409     char name[MAXNAMLEN + 1];
  410     size_t len;
  411     u_long dvpid, vpid;
  412 };
  413 
  414 static struct long_entry tbl;
  415 
  416 /*
  417  * Nuke the `tbl'
  418  */
  419 
  420 static void
  421 tbl_clear (void)
  422 {
  423     tbl.dvp = tbl.vp = NULL;
  424     tbl.name[0] = '\0';
  425     tbl.len = 0;
  426     tbl.dvpid = tbl.vpid = 0;
  427 }
  428 
  429 /*
  430  * Set the entry in the `tbl'
  431  */
  432 
  433 static void
  434 tbl_enter (size_t len, const char *name, struct vnode *dvp, struct vnode *vp)
  435 {
  436     tbl.len = len;
  437     bcopy(name, tbl.name, len);
  438     tbl.dvp = dvp;
  439     tbl.vp = vp;
  440     tbl.dvpid = dvp->v_id;
  441     tbl.vpid = vp->v_id;
  442 }
  443 
  444 /*
  445  * Lookup in tbl (`dvp', `name', `len') and return result in `res'.
  446  * Return -1 if successful, otherwise 0.
  447  */
  448 
  449 static int
  450 tbl_lookup (struct componentname *cnp,
  451             struct vnode *dvp,
  452             struct vnode **res)
  453 {
  454     if (tbl.dvp == dvp
  455         && tbl.len == cnp->cn_namelen
  456         && strncmp(tbl.name, cnp->cn_nameptr, tbl.len) == 0
  457         && tbl.dvpid == tbl.dvp->v_id
  458         && tbl.vpid == tbl.vp->v_id) {
  459 
  460         *res = tbl.vp;
  461         return -1;
  462     } else
  463         return 0;
  464 }
  465 
  466 /*
  467  * Store a componentname in the DNLC
  468  */
  469 
  470 int
  471 xfs_dnlc_enter(struct vnode *dvp,
  472                xfs_componentname *cnp,
  473                struct vnode *vp)
  474 {
  475     NNPFSDEB(XDEBDNLC, ("xfs_dnlc_enter_cnp(%lx, %lx, %lx)\n",
  476                       (unsigned long)dvp,
  477                       (unsigned long)cnp,
  478                       (unsigned long)vp));
  479     NNPFSDEB(XDEBDNLC, ("xfs_dnlc_enter: v_id = %lu\n", (u_long)dvp->v_id));
  480 
  481     NNPFSDEB(XDEBDNLC, ("xfs_dnlc_enter: calling cache_enter:"
  482                       "dvp = %lx, vp = %lx, cnp = (%s, %ld), "
  483                       "nameiop = %lu, flags = %lx\n",
  484                       (unsigned long)dvp,
  485                       (unsigned long)vp,
  486                       cnp->cn_nameptr, cnp->cn_namelen,
  487                       cnp->cn_nameiop, cnp->cn_flags));
  488 
  489 #ifdef NCHNAMLEN
  490     if (cnp->cn_namelen <= NCHNAMLEN)
  491 #endif
  492     {
  493         /*
  494          * This is to make sure there's no negative entry already in the dnlc
  495          */
  496         u_long save_nameiop;
  497         u_long save_flags;
  498         struct vnode *dummy;
  499 
  500         save_nameiop    = cnp->cn_nameiop;
  501         save_flags      = cnp->cn_flags;
  502         cnp->cn_nameiop = CREATE;
  503         cnp->cn_flags  &= ~MAKEENTRY;
  504 
  505 /*
  506  * The version number here is not entirely correct, but it's conservative.
  507  * The real change is sys/kern/vfs_cache:1.20
  508  */
  509 
  510 #if __NetBSD_Version__ >= 104120000 || OpenBSD > 200211
  511         if (cache_lookup(dvp, &dummy, cnp) != -1) {
  512             xfs_vfs_unlock(dummy, xfs_cnp_to_proc(cnp));
  513             printf ("NNPFS PANIC WARNING! xfs_dnlc_enter: %s already in cache\n",
  514                     cnp->cn_nameptr);
  515         }
  516 #else
  517         if (cache_lookup(dvp, &dummy, cnp) != 0) {
  518             printf ("NNPFS PANIC WARNING! xfs_dnlc_enter: %s already in cache\n",
  519                     cnp->cn_nameptr);
  520         }
  521 #endif
  522 
  523 
  524         cnp->cn_nameiop = save_nameiop;
  525         cnp->cn_flags   = save_flags;
  526         cache_enter(dvp, vp, cnp);
  527     }
  528 
  529     if (vp != NULL)
  530         tbl_enter (cnp->cn_namelen, cnp->cn_nameptr, dvp, vp);
  531 
  532     return 0;
  533 }
  534                    
  535 
  536 static void
  537 xfs_cnp_init (struct componentname *cn,
  538               const char *name,
  539               d_thread_t *proc, struct ucred *cred,
  540               int nameiop)
  541 {
  542     bzero(cn, sizeof(*cn));
  543     cn->cn_nameptr = (char *)name;
  544     cn->cn_namelen = strlen(name);
  545     cn->cn_flags   = 0;
  546 #if __APPLE__
  547     {
  548         const unsigned char *p;
  549         int i;
  550 
  551         cn->cn_hash = 0;
  552         for (p = cn->cn_nameptr, i = 1; *p; ++p, ++i)
  553             cn->cn_hash += *p * i;
  554     }
  555 #elif defined(HAVE_KERNEL_NAMEI_HASH)
  556     {
  557         const char *cp = name + cn->cn_namelen;
  558         cn->cn_hash = namei_hash(name, &cp);
  559     }
  560 #elif defined(HAVE_STRUCT_COMPONENTNAME_CN_HASH)
  561     {
  562         const unsigned char *p;
  563 
  564         cn->cn_hash = 0;
  565         for (p = cn->cn_nameptr; *p; ++p)
  566             cn->cn_hash += *p;
  567     }
  568 #endif
  569     cn->cn_nameiop = nameiop;
  570 #ifdef HAVE_FREEBSD_THREAD
  571     cn->cn_thread = proc;
  572 #else
  573     cn->cn_proc = proc;
  574 #endif
  575     cn->cn_cred = cred;
  576 }
  577 
  578 
  579 /*
  580  * Store (dvp, name, vp) in the DNLC
  581  */
  582 
  583 int
  584 xfs_dnlc_enter_name(struct vnode *dvp,
  585                     const char *name,
  586                     struct vnode *vp)
  587 {
  588     struct componentname cn;
  589 
  590     NNPFSDEB(XDEBDNLC, ("xfs_dnlc_enter_name(%lx, \"%s\", %lx)\n",
  591                       (unsigned long)dvp,
  592                       name,
  593                       (unsigned long)vp));
  594 
  595     xfs_cnp_init (&cn, name, NULL, NULL, LOOKUP);
  596     return xfs_dnlc_enter (dvp, &cn, vp);
  597 }
  598 
  599 /*
  600  * Lookup (dvp, cnp) in the DNLC and return the result in `res'.
  601  * Return the result from cache_lookup.
  602  */
  603 
  604 static int
  605 xfs_dnlc_lookup_int(struct vnode *dvp,
  606                     xfs_componentname *cnp,
  607                     struct vnode **res)
  608 {
  609     int error;
  610     u_long saved_flags;
  611 
  612     NNPFSDEB(XDEBDNLC, ("xfs_dnlc_lookup(%lx, \"%s\")\n",
  613                       (unsigned long)dvp, cnp->cn_nameptr));
  614     
  615     NNPFSDEB(XDEBDNLC, ("xfs_dnlc_lookup: v_id = %lu\n", (u_long)dvp->v_id));
  616     
  617     NNPFSDEB(XDEBDNLC, ("xfs_dnlc_lookup: calling cache_lookup:"
  618                       "dvp = %lx, cnp = (%s, %ld), flags = %lx\n",
  619                       (unsigned long)dvp,
  620                       cnp->cn_nameptr, cnp->cn_namelen,
  621                       cnp->cn_flags));
  622 
  623     saved_flags = cnp->cn_flags;
  624     cnp->cn_flags |= MAKEENTRY | LOCKPARENT | ISLASTCN;
  625 
  626     error = cache_lookup(dvp, res, cnp);
  627 
  628     cnp->cn_flags = saved_flags;
  629 
  630     NNPFSDEB(XDEBDNLC, ("xfs_dnlc_lookup: cache_lookup returned. "
  631                       "error = %d, *res = %lx\n", error,
  632                       (unsigned long)*res));
  633     return error;
  634 }
  635 
  636 /*
  637  * do the last (and locking protocol) portion of xnlc_lookup
  638  *
  639  * return:
  640  * -1 for successful
  641  * 0  for failed
  642  */
  643 
  644 static int
  645 xfs_dnlc_lock(struct vnode *dvp,
  646               xfs_componentname *cnp,
  647               struct vnode **res)
  648 {
  649     int error = 0;
  650 
  651     /*
  652      * Try to handle the (complex) BSD locking protocol.
  653      */
  654 
  655     if (*res == dvp) {          /* "." */
  656         VREF(dvp);
  657     } else if (cnp->cn_flags & ISDOTDOT) { /* ".." */
  658         u_long vpid = dvp->v_id;
  659 
  660 #ifdef HAVE_FREEBSD_THREAD
  661         xfs_vfs_unlock(dvp, xfs_cnp_to_thread(cnp));
  662         error = xfs_do_vget(*res, LK_EXCLUSIVE, xfs_cnp_to_thread(cnp));
  663         xfs_vfs_writelock(dvp, xfs_cnp_to_thread(cnp));
  664 #else
  665         xfs_vfs_unlock(dvp, xfs_cnp_to_proc(cnp));
  666         error = xfs_do_vget(*res, LK_EXCLUSIVE, xfs_cnp_to_proc(cnp));
  667         xfs_vfs_writelock(dvp, xfs_cnp_to_proc(cnp));
  668 #endif
  669 
  670         if (error == 0 && dvp->v_id != vpid) {
  671             vput(*res);
  672             return 0;
  673         }
  674     } else {
  675 #ifdef HAVE_FREEBSD_THREAD
  676         error = xfs_do_vget(*res, LK_EXCLUSIVE, xfs_cnp_to_thread(cnp));
  677 #else
  678         error = xfs_do_vget(*res, LK_EXCLUSIVE, xfs_cnp_to_proc(cnp));
  679 #endif
  680     }
  681 
  682     if (error == 0)
  683         return -1;
  684     else
  685         return 0;
  686 }
  687 
  688 /*
  689  * Lookup (`dvp', `cnp') in the DNLC (and the local cache).
  690  *
  691  * Return -1 if successful, 0 if not and ENOENT if the entry is known
  692  * not to exist.
  693  *
  694  * On modern NetBSD, cache_lookup has been changed to return 0 for
  695  * successful and -1 for not.
  696  * (see the comment above for version information).
  697  */
  698 
  699 #if __NetBSD_Version__ >= 104120000 || defined(__OpenBSD__)
  700 
  701 int
  702 xfs_dnlc_lookup(struct vnode *dvp,
  703                 xfs_componentname *cnp,
  704                 struct vnode **res)
  705 {
  706     int error = xfs_dnlc_lookup_int (dvp, cnp, res);
  707 
  708     if (error == 0)
  709         return -1;
  710     else if (error == ENOENT)
  711         return error;
  712 
  713     error = tbl_lookup (cnp, dvp, res);
  714 
  715     if (error != -1)
  716         return error;
  717 
  718     return xfs_dnlc_lock (dvp, cnp, res);
  719 }
  720 
  721 #else /* !  __NetBSD_Version__ >= 104120000 && ! OpenBSD > 200211 */
  722 
  723 int
  724 xfs_dnlc_lookup(struct vnode *dvp,
  725                 xfs_componentname *cnp,
  726                 struct vnode **res)
  727 {
  728     int error = xfs_dnlc_lookup_int (dvp, cnp, res);
  729 
  730     if (error == 0)
  731         error = tbl_lookup (cnp, dvp, res);
  732 
  733     if (error != -1)
  734         return error;
  735 
  736     return xfs_dnlc_lock (dvp, cnp, res);
  737 }
  738 
  739 #endif /*  __NetBSD_Version__ >= 104120000 || OpenBSD > 200211 */
  740 
  741 /*
  742  * Remove one entry from the DNLC
  743  */
  744 
  745 void
  746 xfs_dnlc_purge (struct vnode *vp)
  747 {
  748     NNPFSDEB(XDEBDNLC, ("xfs_dnlc_purge\n"));
  749 
  750     if (tbl.dvp == vp || tbl.vp == vp)
  751         tbl_clear ();
  752 
  753     cache_purge(vp);
  754 }
  755 
  756 /*
  757  * Remove all entries belong to `mp' from the DNLC
  758  */
  759 
  760 void
  761 xfs_dnlc_purge_mp(struct mount *mp)
  762 {
  763     NNPFSDEB(XDEBDNLC, ("xfs_dnlc_purge_mp()\n"));
  764 
  765     tbl_clear ();
  766     cache_purgevfs(mp);
  767 }
  768 
  769 /*
  770  * Returns 1 if pag has any rights set in the node
  771  */
  772 
  773 int
  774 xfs_has_pag(const struct xfs_node *xn, xfs_pag_t pag)
  775 {
  776     int i;
  777 
  778     for (i = 0; i < MAXRIGHTS; i++)
  779         if (xn->id[i] == pag)
  780             return 1;
  781 
  782     return 0;
  783 }
  784 
  785 void
  786 xfs_update_write_cred(struct xfs_node *xn, struct ucred *cred)
  787 {
  788     if (xn->wr_cred)
  789         crfree (xn->wr_cred);
  790     crhold (cred);
  791     xn->wr_cred = cred;
  792 }
  793 
  794 void
  795 xfs_update_read_cred(struct xfs_node *xn, struct ucred *cred)
  796 {
  797     if (xn->rd_cred)
  798         crfree (xn->rd_cred);
  799     crhold (cred);
  800     xn->rd_cred = cred;
  801 }

Cache object: 09b9f8942b49215c02a6c177f03bd43f


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