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/freevxfs/vxfs_lookup.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) 2000-2001 Christoph Hellwig.
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions, and the following disclaimer,
   10  *    without modification.
   11  * 2. The name of the author may not be used to endorse or promote products
   12  *    derived from this software without specific prior written permission.
   13  *
   14  * Alternatively, this software may be distributed under the terms of the
   15  * GNU General Public License ("GPL").
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   21  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  */
   29 
   30 #ident "$Id: vxfs_lookup.c,v 1.21 2002/01/02 22:00:13 hch Exp hch $"
   31 
   32 /*
   33  * Veritas filesystem driver - lookup and other directory related code.
   34  */
   35 #include <linux/fs.h>
   36 #include <linux/sched.h>
   37 #include <linux/mm.h>
   38 #include <linux/highmem.h>
   39 #include <linux/kernel.h>
   40 #include <linux/pagemap.h>
   41 
   42 #include "vxfs.h"
   43 #include "vxfs_dir.h"
   44 #include "vxfs_inode.h"
   45 #include "vxfs_extern.h"
   46 
   47 /*
   48  * Number of VxFS blocks per page.
   49  */
   50 #define VXFS_BLOCK_PER_PAGE(sbp)  ((PAGE_CACHE_SIZE / (sbp)->s_blocksize))
   51 
   52 
   53 static struct dentry *  vxfs_lookup(struct inode *, struct dentry *);
   54 static int              vxfs_readdir(struct file *, void *, filldir_t);
   55 
   56 struct inode_operations vxfs_dir_inode_ops = {
   57         .lookup =               vxfs_lookup,
   58 };
   59 
   60 struct file_operations vxfs_dir_operations = {
   61         .readdir =              vxfs_readdir,
   62 };
   63 
   64  
   65 static __inline__ u_long
   66 dir_pages(struct inode *inode)
   67 {
   68         return (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
   69 }
   70  
   71 static __inline__ u_long
   72 dir_blocks(struct inode *ip)
   73 {
   74         u_long                  bsize = ip->i_sb->s_blocksize;
   75         return (ip->i_size + bsize - 1) & ~(bsize - 1);
   76 }
   77 
   78 /*
   79  * NOTE! unlike strncmp, vxfs_match returns 1 for success, 0 for failure.
   80  *
   81  * len <= VXFS_NAMELEN and de != NULL are guaranteed by caller.
   82  */
   83 static __inline__ int
   84 vxfs_match(int len, const char * const name, struct vxfs_direct *de)
   85 {
   86         if (len != de->d_namelen)
   87                 return 0;
   88         if (!de->d_ino)
   89                 return 0;
   90         return !memcmp(name, de->d_name, len);
   91 }
   92 
   93 static __inline__ struct vxfs_direct *
   94 vxfs_next_entry(struct vxfs_direct *de)
   95 {
   96         return ((struct vxfs_direct *)((char*)de + de->d_reclen));
   97 }
   98 
   99 /**
  100  * vxfs_find_entry - find a mathing directory entry for a dentry
  101  * @ip:         directory inode
  102  * @dp:         dentry for which we want to find a direct
  103  * @ppp:        gets filled with the page the return value sits in
  104  *
  105  * Description:
  106  *   vxfs_find_entry finds a &struct vxfs_direct for the VFS directory
  107  *   cache entry @dp.  @ppp will be filled with the page the return
  108  *   value resides in.
  109  *
  110  * Returns:
  111  *   The wanted direct on success, else a NULL pointer.
  112  */
  113 static struct vxfs_direct *
  114 vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp)
  115 {
  116         u_long                          npages, page, nblocks, pblocks, block;
  117         u_long                          bsize = ip->i_sb->s_blocksize;
  118         const char                      *name = dp->d_name.name;
  119         int                             namelen = dp->d_name.len;
  120 
  121         npages = dir_pages(ip);
  122         nblocks = dir_blocks(ip);
  123         pblocks = VXFS_BLOCK_PER_PAGE(ip->i_sb);
  124         
  125         for (page = 0; page < npages; page++) {
  126                 caddr_t                 kaddr;
  127                 struct page             *pp;
  128 
  129                 pp = vxfs_get_page(ip->i_mapping, page);
  130                 if (IS_ERR(pp))
  131                         continue;
  132                 kaddr = (caddr_t)page_address(pp);
  133 
  134                 for (block = 0; block <= nblocks && block <= pblocks; block++) {
  135                         caddr_t                 baddr, limit;
  136                         struct vxfs_dirblk      *dbp;
  137                         struct vxfs_direct      *de;
  138 
  139                         baddr = kaddr + (block * bsize);
  140                         limit = baddr + bsize - VXFS_DIRLEN(1);
  141                         
  142                         dbp = (struct vxfs_dirblk *)baddr;
  143                         de = (struct vxfs_direct *)(baddr + VXFS_DIRBLKOV(dbp));
  144 
  145                         for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) {
  146                                 if (!de->d_reclen)
  147                                         break;
  148                                 if (!de->d_ino)
  149                                         continue;
  150                                 if (vxfs_match(namelen, name, de)) {
  151                                         *ppp = pp;
  152                                         return (de);
  153                                 }
  154                         }
  155                 }
  156                 vxfs_put_page(pp);
  157         }
  158 
  159         return NULL;
  160 }
  161 
  162 /**
  163  * vxfs_inode_by_name - find inode number for dentry
  164  * @dip:        directory to search in
  165  * @dp:         dentry we seach for
  166  *
  167  * Description:
  168  *   vxfs_inode_by_name finds out the inode number of
  169  *   the path component described by @dp in @dip.
  170  *
  171  * Returns:
  172  *   The wanted inode number on success, else Zero.
  173  */
  174 static ino_t
  175 vxfs_inode_by_name(struct inode *dip, struct dentry *dp)
  176 {
  177         struct vxfs_direct              *de;
  178         struct page                     *pp;
  179         ino_t                           ino = 0;
  180 
  181         de = vxfs_find_entry(dip, dp, &pp);
  182         if (de) {
  183                 ino = de->d_ino;
  184                 kunmap(pp);
  185                 page_cache_release(pp);
  186         }
  187         
  188         return (ino);
  189 }
  190 
  191 /**
  192  * vxfs_lookup - lookup pathname component
  193  * @dip:        dir in which we lookup
  194  * @dp:         dentry we lookup
  195  *
  196  * Description:
  197  *   vxfs_lookup tries to lookup the pathname component described
  198  *   by @dp in @dip.
  199  *
  200  * Returns:
  201  *   A NULL-pointer on success, else an negative error code encoded
  202  *   in the return pointer.
  203  */
  204 static struct dentry *
  205 vxfs_lookup(struct inode *dip, struct dentry *dp)
  206 {
  207         struct inode            *ip = NULL;
  208         ino_t                   ino;
  209                          
  210         if (dp->d_name.len > VXFS_NAMELEN)
  211                 return ERR_PTR(-ENAMETOOLONG);
  212                                  
  213         ino = vxfs_inode_by_name(dip, dp);
  214         if (ino == 0)
  215                 return NULL;
  216 
  217         ip = iget(dip->i_sb, ino);
  218         if (!ip)
  219                 return ERR_PTR(-EACCES);
  220         d_add(dp, ip);
  221         return NULL;
  222 }
  223 
  224 /**
  225  * vxfs_readdir - read a directory
  226  * @fp:         the directory to read
  227  * @retp:       return buffer
  228  * @filler:     filldir callback
  229  *
  230  * Description:
  231  *   vxfs_readdir fills @retp with directory entries from @fp
  232  *   using the VFS supplied callback @filler.
  233  *
  234  * Returns:
  235  *   Zero.
  236  */
  237 static int
  238 vxfs_readdir(struct file *fp, void *retp, filldir_t filler)
  239 {
  240         struct inode            *ip = fp->f_dentry->d_inode;
  241         struct super_block      *sbp = ip->i_sb;
  242         u_long                  bsize = sbp->s_blocksize;
  243         u_long                  page, npages, block, pblocks, nblocks, offset;
  244         loff_t                  pos;
  245 
  246         switch ((long)fp->f_pos) {
  247         case 0:
  248                 if (filler(retp, ".", 1, fp->f_pos, ip->i_ino, DT_DIR) < 0)
  249                         goto out;
  250                 fp->f_pos++;
  251                 /* fallthrough */
  252         case 1:
  253                 if (filler(retp, "..", 2, fp->f_pos, VXFS_INO(ip)->vii_dotdot, DT_DIR) < 0)
  254                         goto out;
  255                 fp->f_pos++;
  256                 /* fallthrough */
  257         }
  258 
  259         pos = fp->f_pos - 2;
  260         
  261         if (pos > VXFS_DIRROUND(ip->i_size))
  262                 return 0;
  263 
  264         npages = dir_pages(ip);
  265         nblocks = dir_blocks(ip);
  266         pblocks = VXFS_BLOCK_PER_PAGE(sbp);
  267 
  268         page = pos >> PAGE_CACHE_SHIFT;
  269         offset = pos & ~PAGE_CACHE_MASK;
  270         block = (u_long)(pos >> sbp->s_blocksize_bits) % pblocks;
  271 
  272         for (; page < npages; page++, block = 0) {
  273                 caddr_t                 kaddr;
  274                 struct page             *pp;
  275 
  276                 pp = vxfs_get_page(ip->i_mapping, page);
  277                 if (IS_ERR(pp))
  278                         continue;
  279                 kaddr = (caddr_t)page_address(pp);
  280 
  281                 for (; block <= nblocks && block <= pblocks; block++) {
  282                         caddr_t                 baddr, limit;
  283                         struct vxfs_dirblk      *dbp;
  284                         struct vxfs_direct      *de;
  285 
  286                         baddr = kaddr + (block * bsize);
  287                         limit = baddr + bsize - VXFS_DIRLEN(1);
  288         
  289                         dbp = (struct vxfs_dirblk *)baddr;
  290                         de = (struct vxfs_direct *)
  291                                 (offset ?
  292                                  (kaddr + offset) :
  293                                  (baddr + VXFS_DIRBLKOV(dbp)));
  294 
  295                         for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) {
  296                                 int     over;
  297 
  298                                 if (!de->d_reclen)
  299                                         break;
  300                                 if (!de->d_ino)
  301                                         continue;
  302 
  303                                 offset = (caddr_t)de - kaddr;
  304                                 over = filler(retp, de->d_name, de->d_namelen,
  305                                         ((page << PAGE_CACHE_SHIFT) | offset) + 2,
  306                                         de->d_ino, DT_UNKNOWN);
  307                                 if (over) {
  308                                         vxfs_put_page(pp);
  309                                         goto done;
  310                                 }
  311                         }
  312                         offset = 0;
  313                 }
  314                 vxfs_put_page(pp);
  315                 offset = 0;
  316         }
  317 
  318 done:
  319         fp->f_pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2;
  320 out:
  321         return 0;
  322 }

Cache object: 2e52c3a8164f7b61911cee256d4e940d


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