CTC++ Coverage Report - Execution Profile    #889/1532

Files Summary | Functions Summary | Execution Profile | Index | No Index
First | Previous | Next | Last


File: fs/ext2/dir.c
Instrumentation mode: function-decision-multicondition
TER: 0 % ( 0/245)

Start/ End/    
True False - Line Source

  1 /*
  2  *  linux/fs/ext2/dir.c
  3  *
  4  * Copyright (C) 1992, 1993, 1994, 1995
  5  * Remy Card (card@masi.ibp.fr)
  6  * Laboratoire MASI - Institut Blaise Pascal
  7  * Universite Pierre et Marie Curie (Paris VI)
  8  *
  9  *  from
  10  *
  11  *  linux/fs/minix/dir.c
  12  *
  13  *  Copyright (C) 1991, 1992  Linus Torvalds
  14  *
  15  *  ext2 directory handling functions
  16  *
  17  *  Big-endian to little-endian byte-swapping/bitmaps by
  18  *        David S. Miller (davem@caip.rutgers.edu), 1995
  19  *
  20  * All code that works with directory layout had been switched to pagecache
  21  * and moved here. AV
  22  */
  23 
  24 #include "ext2.h"
  25 #include <linux/pagemap.h>
  26 #include <linux/smp_lock.h>
  27 
  28 typedef struct ext2_dir_entry_2 ext2_dirent;
  29 
  30 /*
  31  * ext2 uses block-sized chunks. Arguably, sector-sized ones would be
  32  * more robust, but we have what we have
  33  */
 
- 34 static inline unsigned ext2_chunk_size(struct inode *inode)
  35 {
 - 36    return inode->i_sb->s_blocksize;
  37 }
  38 
 
- 39 static inline void ext2_put_page(struct page *page)
  40 {
    41    kunmap(page);
- 41 do-while (0)
  42    page_cache_release(page);
  43 }
  44 
 
- 45 static inline unsigned long dir_pages(struct inode *inode)
  46 {
 - 47    return (inode->i_size+PAGE_CACHE_SIZE-1)>>PAGE_CACHE_SHIFT;
  48 }
  49 
  50 /*
  51  * Return the offset into page `page_nr' of the last valid
  52  * byte in that page, plus one.
  53  */
  54 static unsigned
 
- 55 ext2_last_byte(struct inode *inode, unsigned long page_nr)
  56 {
  57    unsigned last_byte = inode->i_size;
  58 
  59    last_byte -= page_nr << PAGE_CACHE_SHIFT;
- 60    if (last_byte > PAGE_CACHE_SIZE)
  61       last_byte = PAGE_CACHE_SIZE;
 - 62    return last_byte;
  63 }
  64 
 
- 65 static int ext2_commit_chunk(struct page *page, unsigned from, unsigned to)
  66 {
  67    struct inode *dir = page->mapping->host;
  68    int err = 0;
  69    dir->i_version++;
  70    page->mapping->a_ops->commit_write(NULL, page, from, to);
- 71    if (IS_DIRSYNC(dir))
 - 71   ((T) || (_))
 - 71   ((F) || (T))
 - 71   ((F) || (F))
  72       err = write_one_page(page, 1);
    73    else
  74       unlock_page(page);
 - 75    return err;
  76 }
  77 
 
- 78 static void ext2_check_page(struct page *page)
  79 {
  80    struct inode *dir = page->mapping->host;
  81    struct super_block *sb = dir->i_sb;
  82    unsigned chunk_size = ext2_chunk_size(dir);
  83    char *kaddr = page_address(page);
  84    u32 max_inumber = le32_to_cpu(EXT2_SB(sb)->s_es->s_inodes_count);
  85    unsigned offs, rec_len;
  86    unsigned limit = PAGE_CACHE_SIZE;
  87    ext2_dirent *p;
  88    char *error;
  89 
- 90    if ((dir->i_size >> PAGE_CACHE_SHIFT) == page->index) {
  91       limit = dir->i_size & ~PAGE_CACHE_MASK;
- 92       if (limit & (chunk_size - 1))
 - 93          goto Ebadsize;
- 94       if (!limit)
 - 95          goto out;
  96    }
- 97    for (offs = 0; offs <= limit - EXT2_DIR_REC_LEN(1); offs += rec_len) {
  98       p = (ext2_dirent *)(kaddr + offs);
  99       rec_len = le16_to_cpu(p->rec_len);
  100 
- 101       if (rec_len < EXT2_DIR_REC_LEN(1))
 - 102          goto Eshort;
- 103       if (rec_len & 3)
 - 104          goto Ealign;
- 105       if (rec_len < EXT2_DIR_REC_LEN(p->name_len))
 - 106          goto Enamelen;
- 107       if (((offs + rec_len - 1) ^ offs) & ~(chunk_size-1))
 - 108          goto Espan;
- 109       if (le32_to_cpu(p->inode) > max_inumber)
 - 110          goto Einumber;
  111    }
- 112    if (offs != limit)
 - 113       goto Eend;
  114 out:
  115    SetPageChecked(page);
 - 116    return;
  117 
  118    /* Too bad, we had an error */
  119 
  120 Ebadsize:
  121    ext2_error(sb, "ext2_check_page",
  122       "size of directory #%lu is not a multiple of chunk size",
  123       dir->i_ino
  124    );
 - 125    goto fail;
  126 Eshort:
  127    error = "rec_len is smaller than minimal";
 - 128    goto bad_entry;
  129 Ealign:
  130    error = "unaligned directory entry";
 - 131    goto bad_entry;
  132 Enamelen:
  133    error = "rec_len is too small for name_len";
 - 134    goto bad_entry;
  135 Espan:
  136    error = "directory entry across blocks";
 - 137    goto bad_entry;
  138 Einumber:
  139    error = "inode out of bounds";
  140 bad_entry:
  141    ext2_error (sb, "ext2_check_page", "bad entry in directory #%lu: %s - "
  142       "offset=%lu, inode=%lu, rec_len=%d, name_len=%d",
  143       dir->i_ino, error, (page->index<<PAGE_CACHE_SHIFT)+offs,
  144       (unsigned long) le32_to_cpu(p->inode),
  145       rec_len, p->name_len);
 - 146    goto fail;
  147 Eend:
  148    p = (ext2_dirent *)(kaddr + offs);
  149    ext2_error (sb, "ext2_check_page",
  150       "entry in directory #%lu spans the page boundary"
  151       "offset=%lu, inode=%lu",
  152       dir->i_ino, (page->index<<PAGE_CACHE_SHIFT)+offs,
  153       (unsigned long) le32_to_cpu(p->inode));
  154 fail:
  155    SetPageChecked(page);
  156    SetPageError(page);
  157 }
  158 
 
- 159 static struct page * ext2_get_page(struct inode *dir, unsigned long n)
  160 {
  161    struct address_space *mapping = dir->i_mapping;
  162    struct page *page = read_cache_page(mapping, n,
  163             (filler_t*)mapping->a_ops->readpage, NULL);
- 164    if (!IS_ERR(page)) {
  165       wait_on_page_locked(page);
  166       kmap(page);
- 167       if (!PageUptodate(page))
- 167   ternary-?: __builtin_constant_p ( 3 )
 - 168          goto fail;
- 169       if (!PageChecked(page))
- 169   ternary-?: __builtin_constant_p ( 8 )
  170          ext2_check_page(page);
- 171       if (PageError(page))
- 171   ternary-?: __builtin_constant_p ( 1 )
 - 172          goto fail;
  173    }
 - 174    return page;
  175 
  176 fail:
  177    ext2_put_page(page);
 - 178    return ERR_PTR(-EIO);
  179 }
  180 
  181 /*
  182  * NOTE! unlike strncmp, ext2_match returns 1 for success, 0 for failure.
  183  *
  184  * len <= EXT2_NAME_LEN and de != NULL are guaranteed by caller.
  185  */
 
- 186 static inline int ext2_match (int len, const char * const name,
  187                struct ext2_dir_entry_2 * de)
  188 {
- 189    if (len != de->name_len)
 - 190       return 0;
- 191    if (!de->inode)
 - 192       return 0;
 - 193    return !memcmp(name, de->name, len);
  194 }
  195 
  196 /*
  197  * p is at least 6 bytes before the end of page
  198  */
 
- 199 static inline ext2_dirent *ext2_next_entry(ext2_dirent *p)
  200 {
 - 201    return (ext2_dirent *)((char*)p + le16_to_cpu(p->rec_len));
  202 }
  203 
  204 static inline unsigned 
 
- 205 ext2_validate_entry(char *base, unsigned offset, unsigned mask)
  206 {
  207    ext2_dirent *de = (ext2_dirent*)(base + offset);
  208    ext2_dirent *p = (ext2_dirent*)(base + (offset&mask));
- 209    while ((char*)p < (char*)de) {
- 210       if (p->rec_len == 0)
 - 211          break;
  212       p = ext2_next_entry(p);
  213    }
 - 214    return (char *)p - base;
  215 }
  216 
  217 static unsigned char ext2_filetype_table[EXT2_FT_MAX] = {
  218    [EXT2_FT_UNKNOWN]   = DT_UNKNOWN,
  219    [EXT2_FT_REG_FILE]   = DT_REG,
  220    [EXT2_FT_DIR]      = DT_DIR,
  221    [EXT2_FT_CHRDEV]   = DT_CHR,
  222    [EXT2_FT_BLKDEV]   = DT_BLK,
  223    [EXT2_FT_FIFO]      = DT_FIFO,
  224    [EXT2_FT_SOCK]      = DT_SOCK,
  225    [EXT2_FT_SYMLINK]   = DT_LNK,
  226 };
  227 
  228 #define S_SHIFT 12
  229 static unsigned char ext2_type_by_mode[S_IFMT >> S_SHIFT] = {
  230    [S_IFREG >> S_SHIFT]   = EXT2_FT_REG_FILE,
  231    [S_IFDIR >> S_SHIFT]   = EXT2_FT_DIR,
  232    [S_IFCHR >> S_SHIFT]   = EXT2_FT_CHRDEV,
  233    [S_IFBLK >> S_SHIFT]   = EXT2_FT_BLKDEV,
  234    [S_IFIFO >> S_SHIFT]   = EXT2_FT_FIFO,
  235    [S_IFSOCK >> S_SHIFT]   = EXT2_FT_SOCK,
  236    [S_IFLNK >> S_SHIFT]   = EXT2_FT_SYMLINK,
  237 };
  238 
 
- 239 static inline void ext2_set_de_type(ext2_dirent *de, struct inode *inode)
  240 {
  241    mode_t mode = inode->i_mode;
- 242    if (EXT2_HAS_INCOMPAT_FEATURE(inode->i_sb, EXT2_FEATURE_INCOMPAT_FILETYPE))
  243       de->file_type = ext2_type_by_mode[(mode & S_IFMT)>>S_SHIFT];
    244    else
  245       de->file_type = 0;
  246 }
  247 
  248 static int
 
- 249 ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
  250 {
  251    loff_t pos = filp->f_pos;
  252    struct inode *inode = filp->f_dentry->d_inode;
  253    struct super_block *sb = inode->i_sb;
  254    unsigned int offset = pos & ~PAGE_CACHE_MASK;
  255    unsigned long n = pos >> PAGE_CACHE_SHIFT;
  256    unsigned long npages = dir_pages(inode);
  257    unsigned chunk_mask = ~(ext2_chunk_size(inode)-1);
  258    unsigned char *types = NULL;
  259    int need_revalidate = filp->f_version != inode->i_version;
  260 
- 261    if (pos > inode->i_size - EXT2_DIR_REC_LEN(1))
 - 262       return 0;
  263 
- 264    if (EXT2_HAS_INCOMPAT_FEATURE(sb, EXT2_FEATURE_INCOMPAT_FILETYPE))
  265       types = ext2_filetype_table;
  266 
- 267    for ( ; n < npages; n++, offset = 0) {
  268       char *kaddr, *limit;
  269       ext2_dirent *de;
  270       struct page *page = ext2_get_page(inode, n);
  271 
- 272       if (IS_ERR(page)) {
  273          ext2_error(sb, __FUNCTION__,
  274                "bad page in #%lu",
  275                inode->i_ino);
  276          filp->f_pos += PAGE_CACHE_SIZE - offset;
 - 277          return -EIO;
  278       }
  279       kaddr = page_address(page);
- 280       if (unlikely(need_revalidate)) {
- 281          if (offset) {
  282             offset = ext2_validate_entry(kaddr, offset, chunk_mask);
  283             filp->f_pos = (n<<PAGE_CACHE_SHIFT) + offset;
  284          }
  285          filp->f_version = inode->i_version;
  286          need_revalidate = 0;
  287       }
  288       de = (ext2_dirent *)(kaddr+offset);
  289       limit = kaddr + ext2_last_byte(inode, n) - EXT2_DIR_REC_LEN(1);
- 290       for ( ;(char*)de <= limit; de = ext2_next_entry(de)) {
- 291          if (de->rec_len == 0) {
  292             ext2_error(sb, __FUNCTION__,
  293                "zero-length directory entry");
  294             ext2_put_page(page);
 - 295             return -EIO;
  296          }
- 297          if (de->inode) {
  298             int over;
  299             unsigned char d_type = DT_UNKNOWN;
  300 
- 301             if (types && de->file_type < EXT2_FT_MAX)
 - 301         T && T
 - 301         T && F
 - 301         F && _
  302                d_type = types[de->file_type];
  303 
  304             offset = (char *)de - kaddr;
  305             over = filldir(dirent, de->name, de->name_len,
  306                   (n<<PAGE_CACHE_SHIFT) | offset,
  307                   le32_to_cpu(de->inode), d_type);
- 308             if (over) {
  309                ext2_put_page(page);
 - 310                return 0;
  311             }
  312          }
  313          filp->f_pos += le16_to_cpu(de->rec_len);
  314       }
  315       ext2_put_page(page);
  316    }
 - 317    return 0;
  318 }
  319 
  320 /*
  321  *   ext2_find_entry()
  322  *
  323  * finds an entry in the specified directory with the wanted name. It
  324  * returns the page in which the entry was found, and the entry itself
  325  * (as a parameter - res_dir). Page is returned mapped and unlocked.
  326  * Entry is guaranteed to be valid.
  327  */
 
- 328 struct ext2_dir_entry_2 * ext2_find_entry (struct inode * dir,
  329          struct dentry *dentry, struct page ** res_page)
  330 {
  331    const char *name = dentry->d_name.name;
  332    int namelen = dentry->d_name.len;
  333    unsigned reclen = EXT2_DIR_REC_LEN(namelen);
  334    unsigned long start, n;
  335    unsigned long npages = dir_pages(dir);
  336    struct page *page = NULL;
  337    struct ext2_inode_info *ei = EXT2_I(dir);
  338    ext2_dirent * de;
  339 
- 340    if (npages == 0)
 - 341       goto out;
  342 
  343    /* OFFSET_CACHE */
  344    *res_page = NULL;
  345 
  346    start = ei->i_dir_start_lookup;
- 347    if (start >= npages)
  348       start = 0;
  349    n = start;
    350    do {
  351       char *kaddr;
  352       page = ext2_get_page(dir, n);
- 353       if (!IS_ERR(page)) {
  354          kaddr = page_address(page);
  355          de = (ext2_dirent *) kaddr;
  356          kaddr += ext2_last_byte(dir, n) - reclen;
- 357          while ((char *) de <= kaddr) {
- 358             if (de->rec_len == 0) {
  359                ext2_error(dir->i_sb, __FUNCTION__,
  360                   "zero-length directory entry");
  361                ext2_put_page(page);
 - 362                goto out;
  363             }
- 364             if (ext2_match (namelen, name, de))
 - 365                goto found;
  366             de = ext2_next_entry(de);
  367          }
  368          ext2_put_page(page);
  369       }
- 370       if (++n >= npages)
  371          n = 0;
- 372    } while (n != start);
  373 out:
 - 374    return NULL;
  375 
  376 found:
  377    *res_page = page;
  378    ei->i_dir_start_lookup = n;
 - 379    return de;
  380 }
  381 
 
- 382 struct ext2_dir_entry_2 * ext2_dotdot (struct inode *dir, struct page **p)
  383 {
  384    struct page *page = ext2_get_page(dir, 0);
  385    ext2_dirent *de = NULL;
  386 
- 387    if (!IS_ERR(page)) {
  388       de = ext2_next_entry((ext2_dirent *) page_address(page));
  389       *p = page;
  390    }
 - 391    return de;
  392 }
  393 
 
- 394 ino_t ext2_inode_by_name(struct inode * dir, struct dentry *dentry)
  395 {
  396    ino_t res = 0;
  397    struct ext2_dir_entry_2 * de;
  398    struct page *page;
  399    
  400    de = ext2_find_entry (dir, dentry, &page);
- 401    if (de) {
  402       res = le32_to_cpu(de->inode);
    403       kunmap(page);
- 403   do-while (0)
  404       page_cache_release(page);
  405    }
 - 406    return res;
  407 }
  408 
  409 /* Releases the page */
 
- 410 void ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de,
  411          struct page *page, struct inode *inode)
  412 {
  413    unsigned from = (char *) de - (char *) page_address(page);
  414    unsigned to = from + le16_to_cpu(de->rec_len);
  415    int err;
  416 
  417    lock_page(page);
  418    err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
- 419    if (err)
  420       BUG();
  421    de->inode = cpu_to_le32(inode->i_ino);
  422    ext2_set_de_type (de, inode);
  423    err = ext2_commit_chunk(page, from, to);
  424    ext2_put_page(page);
  425    dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
  426    EXT2_I(dir)->i_flags &= ~EXT2_BTREE_FL;
  427    mark_inode_dirty(dir);
  428 }
  429 
  430 /*
  431  *   Parent is locked.
  432  */
 
- 433 int ext2_add_link (struct dentry *dentry, struct inode *inode)
  434 {
  435    struct inode *dir = dentry->d_parent->d_inode;
  436    const char *name = dentry->d_name.name;
  437    int namelen = dentry->d_name.len;
  438    unsigned chunk_size = ext2_chunk_size(dir);
  439    unsigned reclen = EXT2_DIR_REC_LEN(namelen);
  440    unsigned short rec_len, name_len;
  441    struct page *page = NULL;
  442    ext2_dirent * de;
  443    unsigned long npages = dir_pages(dir);
  444    unsigned long n;
  445    char *kaddr;
  446    unsigned from, to;
  447    int err;
  448 
  449    /*
  450     * We take care of directory expansion in the same loop.
  451     * This code plays outside i_size, so it locks the page
  452     * to protect that region.
  453     */
- 454    for (n = 0; n <= npages; n++) {
  455       char *dir_end;
  456 
  457       page = ext2_get_page(dir, n);
  458       err = PTR_ERR(page);
- 459       if (IS_ERR(page))
 - 460          goto out;
  461       lock_page(page);
  462       kaddr = page_address(page);
  463       dir_end = kaddr + ext2_last_byte(dir, n);
  464       de = (ext2_dirent *)kaddr;
  465       kaddr += PAGE_CACHE_SIZE - reclen;
- 466       while ((char *)de <= kaddr) {
- 467          if ((char *)de == dir_end) {
  468             /* We hit i_size */
  469             name_len = 0;
  470             rec_len = chunk_size;
  471             de->rec_len = cpu_to_le16(chunk_size);
  472             de->inode = 0;
 - 473             goto got_it;
  474          }
- 475          if (de->rec_len == 0) {
  476             ext2_error(dir->i_sb, __FUNCTION__,
  477                "zero-length directory entry");
  478             err = -EIO;
 - 479             goto out_unlock;
  480          }
  481          err = -EEXIST;
- 482          if (ext2_match (namelen, name, de))
 - 483             goto out_unlock;
  484          name_len = EXT2_DIR_REC_LEN(de->name_len);
  485          rec_len = le16_to_cpu(de->rec_len);
- 486          if (!de->inode && rec_len >= reclen)
 - 486       T && T
 - 486       T && F
 - 486       F && _
 - 487             goto got_it;
- 488          if (rec_len >= name_len + reclen)
 - 489             goto got_it;
  490          de = (ext2_dirent *) ((char *) de + rec_len);
  491       }
  492       unlock_page(page);
  493       ext2_put_page(page);
  494    }
  495    BUG();
 - 496    return -EINVAL;
  497 
  498 got_it:
  499    from = (char*)de - (char*)page_address(page);
  500    to = from + rec_len;
  501    err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
- 502    if (err)
 - 503       goto out_unlock;
- 504    if (de->inode) {
  505       ext2_dirent *de1 = (ext2_dirent *) ((char *) de + name_len);
  506       de1->rec_len = cpu_to_le16(rec_len - name_len);
  507       de->rec_len = cpu_to_le16(name_len);
  508       de = de1;
  509