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

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


File: fs/fat/cache.c
Instrumentation mode: function-decision-multicondition
TER: 70 % (117/166)

Start/ End/    
True False - Line Source

  1 /*
  2  *  linux/fs/fat/cache.c
  3  *
  4  *  Written 1992,1993 by Werner Almesberger
  5  *
  6  *  Mar 1999. AV. Changed cache, so that it uses the starting cluster instead
  7  *   of inode number.
  8  *  May 1999. AV. Fixed the bogosity with FAT32 (read "FAT28"). Fscking lusers.
  9  */
  10 
  11 #include <linux/fs.h>
  12 #include <linux/msdos_fs.h>
  13 #include <linux/buffer_head.h>
  14 
  15 /* this must be > 0. */
  16 #define FAT_MAX_CACHE   8
  17 
  18 struct fat_cache {
  19    struct list_head cache_list;
  20    int nr_contig;   /* number of contiguous clusters */
  21    int fcluster;   /* cluster number in the file. */
  22    int dcluster;   /* cluster number on disk. */
  23 };
  24 
  25 struct fat_cache_id {
  26    unsigned int id;
  27    int nr_contig;
  28    int fcluster;
  29    int dcluster;
  30 };
  31 
 
240   32 static inline int fat_max_cache(struct inode *inode)
  33 {
240    34    return FAT_MAX_CACHE;
  35 }
  36 
  37 static kmem_cache_t *fat_cache_cachep;
  38 
 
448 448   39 static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags)
  40 {
  41    struct fat_cache *cache = (struct fat_cache *)foo;
  42 
  43    if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
448 - 44        SLAB_CTOR_CONSTRUCTOR)
  45       INIT_LIST_HEAD(&cache->cache_list);
  46 }
  47 
 
  48 int __init fat_cache_init(void)
  49 {
  50    fat_cache_cachep = kmem_cache_create("fat_cache",
  51             sizeof(struct fat_cache),
  52             0, SLAB_RECLAIM_ACCOUNT,
  53             init_once, NULL);
- 54    if (fat_cache_cachep == NULL)
 - 55       return -ENOMEM;
   56    return 0;
  57 }
  58 
 
- 59 void fat_cache_destroy(void)
  60 {
- 61    if (kmem_cache_destroy(fat_cache_cachep))
  62       printk(KERN_INFO "fat_cache: not all structures were freed\n");
  63 }
  64 
 
187   65 static inline struct fat_cache *fat_cache_alloc(struct inode *inode)
  66 {
187    67    return kmem_cache_alloc(fat_cache_cachep, SLAB_KERNEL);
  68 }
  69 
 
169 169   70 static inline void fat_cache_free(struct fat_cache *cache)
  71 {
    72    BUG_ON(!list_empty(&cache->cache_list));
169 - 72   if (__builtin_expect ( ! ! ( ( ! list_empty ..
169 - 72 do-while (0)
  73    kmem_cache_free(fat_cache_cachep, cache);
  74 }
  75 
 
5207E3 5207E3   76 static inline void fat_cache_update_lru(struct inode *inode,
  77                struct fat_cache *cache)
  78 {
31932 5175E3   79    if (MSDOS_I(inode)->cache_lru.next != &cache->cache_list)
  80       list_move(&cache->cache_list, &MSDOS_I(inode)->cache_lru);
  81 }
  82 
 
2624E3   83 static int fat_cache_lookup(struct inode *inode, int fclus,
  84              struct fat_cache_id *cid,
  85              int *cached_fclus, int *cached_dclus)
  86 {
  87    static struct fat_cache nohit = { .fcluster = 0, };
  88 
  89    struct fat_cache *hit = &nohit, *p;
  90    int offset = -1;
  91 
    92    spin_lock(&MSDOS_I(inode)->cache_lru_lock);
    92   do
2624E3 - 92   do-while (0)
2624E3 - 92 do-while (0)
2675E3 28861   93    list_for_each_entry(p, &MSDOS_I(inode)->cache_lru, cache_list) {
  94       /* Find the cache of "fclus" or nearest cache. */
2624E3 51358   95       if (p->fcluster <= fclus && hit->fcluster < p->fcluster) {
2624E3    95     T && T
 18217   95     T && F
 33141   95     F && _
  96          hit = p;
28673 2595E3   97          if ((hit->fcluster + hit->nr_contig) < fclus) {
  98             offset = hit->nr_contig;
    99          } else {
  100             offset = fclus - hit->fcluster;
2595E3    101             break;
  102          }
  103       }
  104    }
2603E3 20717   105    if (hit != &nohit) {
  106       fat_cache_update_lru(inode, hit);
  107 
  108       cid->id = MSDOS_I(inode)->cache_valid_id;
  109       cid->nr_contig = hit->nr_contig;
  110       cid->fcluster = hit->fcluster;
  111       cid->dcluster = hit->dcluster;
  112       *cached_fclus = cid->fcluster + offset;
  113       *cached_dclus = cid->dcluster + offset;
  114    }
    115    spin_unlock(&MSDOS_I(inode)->cache_lru_lock);
    115   do
2624E3 - 115   do-while (0)
2624E3 - 115 do-while (0)
  116 
2624E3    117    return offset;
  118 }
  119 
 
2603E3   120 static struct fat_cache *fat_cache_merge(struct inode *inode,
  121                 struct fat_cache_id *new)
  122 {
  123    struct fat_cache *p;
  124 
2604E3 427   125    list_for_each_entry(p, &MSDOS_I(inode)->cache_lru, cache_list) {
  126       /* Find the same part as "new" in cluster-chain. */
2603E3 586   127       if (p->fcluster == new->fcluster) {
    128          BUG_ON(p->dcluster != new->dcluster);
2603E3 - 128       if (__builtin_expect ( ! ! ( ( p -> dclu..
2603E3 - 128     do-while (0)
7677 2595E3   129          if (new->nr_contig > p->nr_contig)
  130             p->nr_contig = new->nr_contig;
2603E3    131          return p;
  132       }
  133    }
427    134    return NULL;
  135 }
  136 
 
2624E3 2603E3   137 static void fat_cache_add(struct inode *inode, struct fat_cache_id *new)
  138 {
  139    struct fat_cache *cache, *tmp;
  140 
20554 2603E3   141    if (new->fcluster == -1) /* dummy cache */
20554    142       return;
  143 
    144    spin_lock(&MSDOS_I(inode)->cache_lru_lock);
    144   do
2603E3 - 144   do-while (0)
2603E3 - 144 do-while (0)
  145    if (new->id != FAT_CACHE_VALID &&
2603E3 - 146        new->id != MSDOS_I(inode)->cache_valid_id)
 - 146   T && T
 2603E3   146   T && F
 240   146   F && _
 - 147       goto out;   /* this cache was invalidated */
  148 
  149    cache = fat_cache_merge(inode, new);
240 2603E3   150    if (cache == NULL) {
187 53   151       if (MSDOS_I(inode)->nr_caches < fat_max_cache(inode)) {
  152          MSDOS_I(inode)->nr_caches++;
    153          spin_unlock(&MSDOS_I(inode)->cache_lru_lock);
    153       do
187 - 153       do-while (0)
187 - 153     do-while (0)
  154 
  155          tmp = fat_cache_alloc(inode);
    156          spin_lock(&MSDOS_I(inode)->cache_lru_lock);
    156       do
187 - 156       do-while (0)
187 - 156     do-while (0)
  157          cache = fat_cache_merge(inode, new);
187 - 158          if (cache != NULL) {
  159             MSDOS_I(inode)->nr_caches--;
  160             fat_cache_free(tmp);
 - 161             goto out_update_lru;
  162          }
  163          cache = tmp;
    164       } else {
  165          struct list_head *p = MSDOS_I(inode)->cache_lru.prev;
  166          cache = list_entry(p, struct fat_cache, cache_list);
  167       }
  168       cache->fcluster = new->fcluster;
  169       cache->dcluster = new->dcluster;
  170       cache->nr_contig = new->nr_contig;
  171    }
  172 out_update_lru:
  173    fat_cache_update_lru(inode, cache);
  174 out:
    175    spin_unlock(&MSDOS_I(inode)->cache_lru_lock);
    175   do
2603E3 - 175   do-while (0)
2603E3 - 175 do-while (0)
  176 }
  177 
  178 /*
  179  * Cache invalidation occurs rarely, thus the LRU chain is not updated. It
  180  * fixes itself after a while.
  181  */
 
211509 211509   182 static void __fat_cache_inval_inode(struct inode *inode)
  183 {
  184    struct msdos_inode_info *i = MSDOS_I(inode);
  185    struct fat_cache *cache;
  186 
169 211509   187    while (!list_empty(&i->cache_lru)) {
  188       cache = list_entry(i->cache_lru.next, struct fat_cache, cache_list);
  189       list_del_init(&cache->cache_list);
  190       i->nr_caches--;
  191       fat_cache_free(cache);
  192    }
  193    /* Update. The copy of caches before this id is discarded. */
  194    i->cache_valid_id++;
211509 - 195    if (i->cache_valid_id == FAT_CACHE_VALID)
  196       i->cache_valid_id++;
  197 }
  198 
 
211509 211509   199 void fat_cache_inval_inode(struct inode *inode)
  200 {
    201    spin_lock(&MSDOS_I(inode)->cache_lru_lock);
    201   do
211509 - 201   do-while (0)
211509 - 201 do-while (0)
  202    __fat_cache_inval_inode(inode);
    203    spin_unlock(&MSDOS_I(inode)->cache_lru_lock);
    203   do
211509 - 203   do-while (0)
211509 - 203 do-while (0)
  204 }
  205 
 
7950   206 static inline int cache_contiguous(struct fat_cache_id *cid, int dclus)
  207 {
  208    cid->nr_contig++;
7950    209    return ((cid->dcluster + cid->nr_contig) == dclus);
  210 }
  211 
 
20984 20984   212 static inline void cache_init(struct fat_cache_id *cid, int fclus, int dclus)
  213 {
  214    cid->id = FAT_CACHE_VALID;
  215    cid->fcluster = fclus;
  216    cid->dcluster = dclus;
  217    cid->nr_contig = 0;
  218 }
  219 
 
9060E3   220 int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus)
  221 {
  222    struct super_block *sb = inode->i_sb;
  223    const int limit = sb->s_maxbytes >> MSDOS_SB(sb)->cluster_bits;
  224    struct fat_entry fatent;
  225    struct fat_cache_id cid;
  226    int nr;
  227 
    228    BUG_ON(MSDOS_I(inode)->i_start == 0);
9060E3 - 228   if (__builtin_expect ( ! ! ( ( MSDOS_I ( ino..
9060E3 - 228 do-while (0)
  229 
  230    *fclus = 0;
  231    *dclus = MSDOS_I(inode)->i_start;
6436E3 2624E3   232    if (cluster == 0)
6436E3    233       return 0;
  234 
20717 2603E3   235    if (fat_cache_lookup(inode, cluster, &cid, fclus, dclus) < 0) {
  236       /*
  237        * dummy, always not contiguous
  238        * This is reinitialized by cache_init(), later.
  239        */
  240       cache_init(&cid, -1, -1);
  241    }
  242 
  243    fatent_init(&fatent);
28942 2603E3   244    while (*fclus < cluster) {
  245       /* prevent the infinite loop of cluster chain */
28942 - 246       if (*fclus > limit) {
  247          fat_fs_panic(sb, "%s: detected the cluster chain loop"
  248                  " (i_pos %lld)", __FUNCTION__,
  249                  MSDOS_I(inode)->i_pos);
  250          nr = -EIO;
 - 251          goto out;
  252       }
  253 
  254       nr = fat_ent_read(inode, &fatent, *dclus);
28942 - 255       if (nr < 0)
 - 256          goto out;
28942 - 257       else if (nr == FAT_ENT_FREE) {
  258          fat_fs_panic(sb, "%s: invalid cluster chain"
  259                  " (i_pos %lld)", __FUNCTION__,
  260                  MSDOS_I(inode)->i_pos);
  261          nr = -EIO;
 - 262          goto out;
20992 7950   263       } else if (nr == FAT_ENT_EOF) {
  264          fat_cache_add(inode, &cid);
20992    265          goto out;
  266       }
  267       (*fclus)++;
  268       *dclus = nr;
267 7683   269       if (!cache_contiguous(&cid, *dclus))
  270          cache_init(&cid, *fclus, *dclus);
  271    }
  272    nr = 0;
  273    fat_cache_add(inode, &cid);
  274 out:
  275    fatent_brelse(&fatent);
2624E3    276    return nr;
  277 }
  278 
 
9039E3   279 static int fat_bmap_cluster(struct inode *inode, int cluster)
  280 {
  281    struct super_block *sb = inode->i_sb;
  282    int ret, fclus, dclus;
  283 
9039E3 - 284    if (MSDOS_I(inode)->i_start == 0)
 - 285       return 0;
  286 
  287    ret = fat_get_cluster(inode, cluster, &fclus, &dclus);
9039E3 - 288    if (ret < 0)
 - 289       return ret;
9039E3 - 290    else if (ret == FAT_ENT_EOF) {
  291       fat_fs_panic(sb, "%s: request beyond EOF (i_pos %lld)",
  292               __FUNCTION__, MSDOS_I(inode)->i_pos);
 - 293       return -EIO;
  294    }
9039E3    295    return dclus;
  296 }
  297 
 
9126E3   298 int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
  299         unsigned long *mapped_blocks)
  300 {
  301    struct super_block *sb = inode->i_sb;
  302    struct msdos_sb_info *sbi = MSDOS_SB(sb);
  303    sector_t last_block;
  304    int cluster, offset;
  305 
  306    *phys = 0;
  307    *mapped_blocks = 0;
273 9126E3   308    if ((sbi->fat_bits != 32) && (inode->i_ino == MSDOS_ROOT_INO)) {
273    308   (T) && (T)
 240800   308   (T) && (F)
 8885E3   308   (F) && (_)
258 15   309       if (sector < (sbi->dir_entries >> sbi->dir_per_block_bits)) {
  310          *phys = sector + sbi->dir_start;
  311          *mapped_blocks = 1;
  312       }
273    313       return 0;
  314    }
  315    last_block = (MSDOS_I(inode)->mmu_private + (sb->s_blocksize - 1))
  316       >> sb->s_blocksize_bits;
86751 9039E3   317    if (sector >= last_block)
86751    318       return 0;
  319 
  320    cluster = sector >> (sbi->cluster_bits - sb->s_blocksize_bits);
  321    offset  = sector & (sbi->sec_per_clus - 1);
  322    cluster = fat_bmap_cluster(inode, cluster);
9039E3 - 323    if (cluster < 0)
 - 324       return cluster;
9039E3 - 325    else if (cluster) {
  326       *phys = fat_clus_to_blknr(sbi, cluster) + offset;
  327       *mapped_blocks = sbi->sec_per_clus - offset;
26132 9013E3   328       if (*mapped_blocks > last_block - sector)
  329          *mapped_blocks = last_block - sector;
  330    }
9039E3    331    return 0;
  332 }
***TER 70% (117/166) of SOURCE FILE cache.c

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