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

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


File: fs/fat/fatent.c
Instrumentation mode: function-decision-multicondition
TER: 42 % (126/300)

Start/ End/    
True False - Line Source

  1 /*
  2  * Copyright (C) 2004, OGAWA Hirofumi
  3  * Released under GPL v2.
  4  */
  5 
  6 #include <linux/module.h>
  7 #include <linux/fs.h>
  8 #include <linux/msdos_fs.h>
  9 
  10 struct fatent_operations {
  11    void (*ent_blocknr)(struct super_block *, int, int *, sector_t *);
  12    void (*ent_set_ptr)(struct fat_entry *, int);
  13    int (*ent_bread)(struct super_block *, struct fat_entry *,
  14           int, sector_t);
  15    int (*ent_get)(struct fat_entry *);
  16    void (*ent_put)(struct fat_entry *, int);
  17    int (*ent_next)(struct fat_entry *);
  18 };
  19 
 
- 20 static void fat12_ent_blocknr(struct super_block *sb, int entry,
  21                int *offset, sector_t *blocknr)
  22 {
  23    struct msdos_sb_info *sbi = MSDOS_SB(sb);
  24    int bytes = entry + (entry >> 1);
    25    WARN_ON(entry < FAT_START_ENT || sbi->max_cluster <= entry);
- 25   if (__builtin_expect ( ! ! ( ( entry < 2 || ..
- 25 do-while (0)
  26    *offset = bytes & (sb->s_blocksize - 1);
  27    *blocknr = sbi->fat_start + (bytes >> sb->s_blocksize_bits);
  28 }
  29 
 
30623 30623   30 static void fat_ent_blocknr(struct super_block *sb, int entry,
  31              int *offset, sector_t *blocknr)
  32 {
  33    struct msdos_sb_info *sbi = MSDOS_SB(sb);
  34    int bytes = (entry << sbi->fatent_shift);
    35    WARN_ON(entry < FAT_START_ENT || sbi->max_cluster <= entry);
30623 - 35   if (__builtin_expect ( ! ! ( ( entry < 2 || ..
30623 - 35 do-while (0)
  36    *offset = bytes & (sb->s_blocksize - 1);
  37    *blocknr = sbi->fat_start + (bytes >> sb->s_blocksize_bits);
  38 }
  39 
 
- 40 static void fat12_ent_set_ptr(struct fat_entry *fatent, int offset)
  41 {
  42    struct buffer_head **bhs = fatent->bhs;
- 43    if (fatent->nr_bhs == 1) {
    44       WARN_ON(offset >= (bhs[0]->b_size - 1));
- 44     if (__builtin_expect ( ! ! ( ( offset >= (..
- 44   do-while (0)
  45       fatent->u.ent12_p[0] = bhs[0]->b_data + offset;
  46       fatent->u.ent12_p[1] = bhs[0]->b_data + (offset + 1);
    47    } else {
    48       WARN_ON(offset != (bhs[0]->b_size - 1));
- 48     if (__builtin_expect ( ! ! ( ( offset != (..
- 48   do-while (0)
  49       fatent->u.ent12_p[0] = bhs[0]->b_data + offset;
  50       fatent->u.ent12_p[1] = bhs[1]->b_data;
  51    }
  52 }
  53 
 
7484 7484   54 static void fat16_ent_set_ptr(struct fat_entry *fatent, int offset)
  55 {
    56    WARN_ON(offset & (2 - 1));
7484 - 56   if (__builtin_expect ( ! ! ( ( offset & ( 2 ..
7484 - 56 do-while (0)
  57    fatent->u.ent16_p = (__le16 *)(fatent->bhs[0]->b_data + offset);
  58 }
  59 
 
23139 23139   60 static void fat32_ent_set_ptr(struct fat_entry *fatent, int offset)
  61 {
    62    WARN_ON(offset & (4 - 1));
23139 - 62   if (__builtin_expect ( ! ! ( ( offset & ( 4 ..
23139 - 62 do-while (0)
  63    fatent->u.ent32_p = (__le32 *)(fatent->bhs[0]->b_data + offset);
  64 }
  65 
 
- 66 static int fat12_ent_bread(struct super_block *sb, struct fat_entry *fatent,
  67             int offset, sector_t blocknr)
  68 {
  69    struct buffer_head **bhs = fatent->bhs;
  70 
    71    WARN_ON(blocknr < MSDOS_SB(sb)->fat_start);
- 71   if (__builtin_expect ( ! ! ( ( blocknr < MSD..
- 71 do-while (0)
  72    bhs[0] = sb_bread(sb, blocknr);
- 73    if (!bhs[0])
 - 74       goto err;
  75 
- 76    if ((offset + 1) < sb->s_blocksize)
  77       fatent->nr_bhs = 1;
    78    else {
  79       /* This entry is block boundary, it needs the next block */
  80       blocknr++;
  81       bhs[1] = sb_bread(sb, blocknr);
- 82       if (!bhs[1])
 - 83          goto err_brelse;
  84       fatent->nr_bhs = 2;
  85    }
  86    fat12_ent_set_ptr(fatent, offset);
 - 87    return 0;
  88 
  89 err_brelse:
  90    brelse(bhs[0]);
  91 err:
  92    printk(KERN_ERR "FAT: FAT read failed (blocknr %llu)\n",
  93           (unsigned long long)blocknr);
 - 94    return -EIO;
  95 }
  96 
 
30596   97 static int fat_ent_bread(struct super_block *sb, struct fat_entry *fatent,
  98           int offset, sector_t blocknr)
  99 {
  100    struct fatent_operations *ops = MSDOS_SB(sb)->fatent_ops;
  101 
    102    WARN_ON(blocknr < MSDOS_SB(sb)->fat_start);
30596 - 102   if (__builtin_expect ( ! ! ( ( blocknr < MSD..
30596 - 102 do-while (0)
  103    fatent->bhs[0] = sb_bread(sb, blocknr);
30596 - 104    if (!fatent->bhs[0]) {
  105       printk(KERN_ERR "FAT: FAT read failed (blocknr %llu)\n",
  106              (unsigned long long)blocknr);
 - 107       return -EIO;
  108    }
  109    fatent->nr_bhs = 1;
  110    ops->ent_set_ptr(fatent, offset);
30596    111    return 0;
  112 }
  113 
 
- 114 static int fat12_ent_get(struct fat_entry *fatent)
  115 {
  116    u8 **ent12_p = fatent->u.ent12_p;
  117    int next;
  118 
- 119    if (fatent->entry & 1)
  120       next = (*ent12_p[0] >> 4) | (*ent12_p[1] << 4);
    121    else
  122       next = (*ent12_p[1] << 8) | *ent12_p[0];
  123    next &= 0x0fff;
- 124    if (next >= BAD_FAT12)
  125       next = FAT_ENT_EOF;
 - 126    return next;
  127 }
  128 
 
15120   129 static int fat16_ent_get(struct fat_entry *fatent)
  130 {
  131    int next = le16_to_cpu(*fatent->u.ent16_p);
    132    WARN_ON((unsigned long)fatent->u.ent16_p & (2 - 1));
15120 - 132   if (__builtin_expect ( ! ! ( ( ( unsigned lo..
15120 - 132 do-while (0)
103 15017   133    if (next >= BAD_FAT16)
  134       next = FAT_ENT_EOF;
15120    135    return next;
  136 }
  137 
 
133397   138 static int fat32_ent_get(struct fat_entry *fatent)
  139 {
  140    int next = le32_to_cpu(*fatent->u.ent32_p) & 0x0fffffff;
    141    WARN_ON((unsigned long)fatent->u.ent32_p & (4 - 1));
133397 - 141   if (__builtin_expect ( ! ! ( ( ( unsigned lo..
133397 - 141 do-while (0)
47657 85740   142    if (next >= BAD_FAT32)
  143       next = FAT_ENT_EOF;
133397    144    return next;
  145 }
  146 
 
- 147 static void fat12_ent_put(struct fat_entry *fatent, int new)
  148 {
  149    u8 **ent12_p = fatent->u.ent12_p;
  150 
- 151    if (new == FAT_ENT_EOF)
  152       new = EOF_FAT12;
  153 
- 154    if (fatent->entry & 1) {
  155       *ent12_p[0] = (new << 4) | (*ent12_p[0] & 0x0f);
  156       *ent12_p[1] = new >> 4;
    157    } else {
  158       *ent12_p[0] = new & 0xff;
  159       *ent12_p[1] = (*ent12_p[1] & 0xf0) | (new >> 8);
  160    }
  161 
  162    mark_buffer_dirty(fatent->bhs[0]);
- 163    if (fatent->nr_bhs == 2)
  164       mark_buffer_dirty(fatent->bhs[1]);
  165 }
  166 
 
- 167 static void fat16_ent_put(struct fat_entry *fatent, int new)
  168 {
- 169    if (new == FAT_ENT_EOF)
  170       new = EOF_FAT16;
  171 
  172    *fatent->u.ent16_p = cpu_to_le16(new);
  173    mark_buffer_dirty(fatent->bhs[0]);
  174 }
  175 
 
783 783   176 static void fat32_ent_put(struct fat_entry *fatent, int new)
  177 {
392 391   178    if (new == FAT_ENT_EOF)
  179       new = EOF_FAT32;
  180 
    181    WARN_ON(new & 0xf0000000);
783 - 181   if (__builtin_expect ( ! ! ( ( new & 0xf0000..
783 - 181 do-while (0)
  182    new |= le32_to_cpu(*fatent->u.ent32_p) & ~0x0fffffff;
  183    *fatent->u.ent32_p = cpu_to_le32(new);
  184    mark_buffer_dirty(fatent->bhs[0]);
  185 }
  186 
 
- 187 static int fat12_ent_next(struct fat_entry *fatent)
  188 {
  189    u8 **ent12_p = fatent->u.ent12_p;
  190    struct buffer_head **bhs = fatent->bhs;
  191    u8 *nextp = ent12_p[1] + 1 + (fatent->entry & 1);
  192 
  193    fatent->entry++;
- 194    if (fatent->nr_bhs == 1) {
    195       WARN_ON(ent12_p[0] > (u8 *)(bhs[0]->b_data + (bhs[0]->b_size - 2)));
- 195     if (__builtin_expect ( ! ! ( ( ent12_p [ 0..
- 195   do-while (0)
    196       WARN_ON(ent12_p[1] > (u8 *)(bhs[0]->b_data + (bhs[0]->b_size - 1)));
- 196     if (__builtin_expect ( ! ! ( ( ent12_p [ 1..
- 196   do-while (0)
- 197       if (nextp < (u8 *)(bhs[0]->b_data + (bhs[0]->b_size - 1))) {
  198          ent12_p[0] = nextp - 1;
  199          ent12_p[1] = nextp;
 - 200          return 1;
  201       }
    202    } else {
    203       WARN_ON(ent12_p[0] != (u8 *)(bhs[0]->b_data + (bhs[0]->b_size - 1)));
- 203     if (__builtin_expect ( ! ! ( ( ent12_p [ 0..
- 203   do-while (0)
    204       WARN_ON(ent12_p[1] != (u8 *)bhs[1]->b_data);
- 204     if (__builtin_expect ( ! ! ( ( ent12_p [ 1..
- 204   do-while (0)
  205       ent12_p[0] = nextp - 1;
  206       ent12_p[1] = nextp;
  207       brelse(bhs[0]);
  208       bhs[0] = bhs[1];
  209       fatent->nr_bhs = 1;
 - 210       return 1;
  211    }
  212    ent12_p[0] = NULL;
  213    ent12_p[1] = NULL;
 - 214    return 0;
  215 }
  216 
 
7666   217 static int fat16_ent_next(struct fat_entry *fatent)
  218 {
  219    const struct buffer_head *bh = fatent->bhs[0];
  220    fatent->entry++;
7637 29   221    if (fatent->u.ent16_p < (__le16 *)(bh->b_data + (bh->b_size - 2))) {
  222       fatent->u.ent16_p++;
7637    223       return 1;
  224    }
  225    fatent->u.ent16_p = NULL;
29    226    return 0;
  227 }
  228 
 
111126   229 static int fat32_ent_next(struct fat_entry *fatent)
  230 {
  231    const struct buffer_head *bh = fatent->bhs[0];
  232    fatent->entry++;
110258 868   233    if (fatent->u.ent32_p < (__le32 *)(bh->b_data + (bh->b_size - 4))) {
  234       fatent->u.ent32_p++;
110258    235       return 1;
  236    }
  237    fatent->u.ent32_p = NULL;
868    238    return 0;
  239 }
  240 
  241 static struct fatent_operations fat12_ops = {
  242    .ent_blocknr   = fat12_ent_blocknr,
  243    .ent_set_ptr   = fat12_ent_set_ptr,
  244    .ent_bread   = fat12_ent_bread,
  245    .ent_get   = fat12_ent_get,
  246    .ent_put   = fat12_ent_put,
  247    .ent_next   = fat12_ent_next,
  248 };
  249 
  250 static struct fatent_operations fat16_ops = {
  251    .ent_blocknr   = fat_ent_blocknr,
  252    .ent_set_ptr   = fat16_ent_set_ptr,
  253    .ent_bread   = fat_ent_bread,
  254    .ent_get   = fat16_ent_get,
  255    .ent_put   = fat16_ent_put,
  256    .ent_next   = fat16_ent_next,
  257 };
  258 
  259 static struct fatent_operations fat32_ops = {
  260    .ent_blocknr   = fat_ent_blocknr,
  261    .ent_set_ptr   = fat32_ent_set_ptr,
  262    .ent_bread   = fat_ent_bread,
  263    .ent_get   = fat32_ent_get,
  264    .ent_put   = fat32_ent_put,
  265    .ent_next   = fat32_ent_next,
  266 };
  267 
 
393 393   268 static inline void lock_fat(struct msdos_sb_info *sbi)
  269 {
  270    down(&sbi->fat_lock);
  271 }
  272 
 
393 393   273 static inline void unlock_fat(struct msdos_sb_info *sbi)
  274 {
  275    up(&sbi->fat_lock);
  276 }
  277 
 
13 13   278 void fat_ent_access_init(struct super_block *sb)
  279 {
  280    struct msdos_sb_info *sbi = MSDOS_SB(sb);
  281 
  282    init_MUTEX(&sbi->fat_lock);
  283 
    284    switch (sbi->fat_bits) {
12    285    case 32:
  286       sbi->fatent_shift = 2;
  287       sbi->fatent_ops = &fat32_ops;
12    288       break;
   289    case 16:
  290       sbi->fatent_shift = 1;
  291       sbi->fatent_ops = &fat16_ops;
   292       break;
 - 293    case 12:
  294       sbi->fatent_shift = -1;
  295       sbi->fatent_ops = &fat12_ops;
 - 296       break;
  297    }
  298 }
  299 
 
29333   300 static inline int fat_ent_update_ptr(struct super_block *sb,
  301                  struct fat_entry *fatent,
  302                  int offset, sector_t blocknr)
  303 {
  304    struct msdos_sb_info *sbi = MSDOS_SB(sb);
  305    struct fatent_operations *ops = sbi->fatent_ops;
  306    struct buffer_head **bhs = fatent->bhs;
  307 
  308    /* Is this fatent's blocks including this entry? */
29306 27   309    if (!fatent->nr_bhs || bhs[0]->b_blocknr != blocknr)
29252    309   T || _
54    309   F || T
 27   309   F || F
29306    310       return 0;
  311    /* Does this entry need the next block? */
27 - 312    if (sbi->fat_bits == 12 && (offset + 1) >= sb->s_blocksize) {
 - 312   T && T
 - 312   T && F
 27   312   F && _
- 313       if (fatent->nr_bhs != 2 || bhs[1]->b_blocknr != (blocknr + 1))
 - 313     T || _
 - 313     F || T
 - 313     F || F
 - 314          return 0;
  315    }
  316    ops->ent_set_ptr(fatent, offset);
27    317    return 1;
  318 }
  319 
 
29333   320 int fat_ent_read(struct inode *inode, struct fat_entry *fatent, int entry)
  321 {
  322    struct super_block *sb = inode->i_sb;
  323    struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
  324    struct fatent_operations *ops = sbi->fatent_ops;
  325    int err, offset;
  326    sector_t blocknr;
  327 
29333 - 328    if (entry < FAT_START_ENT || sbi->max_cluster <= entry) {
 - 328   T || _
 - 328   F || T
 29333   328   F || F
  329       fatent_brelse(fatent);
  330       fat_fs_panic(sb, "invalid access to FAT (entry 0x%08x)", entry);
 - 331       return -EIO;
  332    }
  333 
  334    fatent_set_entry(fatent, entry);
  335    ops->ent_blocknr(sb, entry, &offset, &blocknr);
  336 
29306 27   337    if (!fat_ent_update_ptr(sb, fatent, offset, blocknr)) {
  338       fatent_brelse(fatent);
  339       err = ops->ent_bread(sb, fatent, offset, blocknr);
29306 - 340       if (err)
 - 341          return err;
  342    }
29333    343    return ops->ent_get(fatent);
  344 }
  345 
  346 /* FIXME: We can write the blocks as more big chunk. */
 
783   347 static int fat_mirror_bhs(struct super_block *sb, struct buffer_head **bhs,
  348            int nr_bhs)
  349 {
  350    struct msdos_sb_info *sbi = MSDOS_SB(sb);
  351    struct buffer_head *c_bh;
  352    int err, n, copy;
  353 
  354    err = 0;
783 783   355    for (copy = 1; copy < sbi->fats; copy++) {
  356       sector_t backup_fat = sbi->fat_length * copy;
  357 
783 783   358       for (n = 0; n < nr_bhs; n++) {
  359          c_bh = sb_getblk(sb, backup_fat + bhs[n]->b_blocknr);
783 - 360          if (!c_bh) {
  361             err = -ENOMEM;
 - 362             goto error;
  363          }
  364          memcpy(c_bh->b_data, bhs[n]->b_data, sb->s_blocksize);
  365          set_buffer_uptodate(c_bh);
  366          mark_buffer_dirty(c_bh);
783 - 367          if (sb->s_flags & MS_SYNCHRONOUS)
  368             err = sync_dirty_buffer(c_bh);
  369          brelse(c_bh);
783 - 370          if (err)
 - 371             goto error;
  372       }
  373    }
  374 error:
783    375    return err;
  376 }
  377 
 
391   378 int fat_ent_write(struct inode *inode, struct fat_entry *fatent,
  379         int new, int wait)
  380 {
  381    struct super_block *sb = inode->i_sb;
  382    struct fatent_operations *ops = MSDOS_SB(sb)->fatent_ops;
  383    int err;
  384 
  385    ops->ent_put(fatent, new);
391 - 386    if (wait) {
  387       err = fat_sync_bhs(fatent->bhs, fatent->nr_bhs);
- 388       if (err)
 - 389          return err;
  390    }
391    391    return fat_mirror_bhs(sb, fatent->bhs, fatent->nr_bhs);
  392 }
  393 
 
118792   394 static inline int fat_ent_next(struct msdos_sb_info *sbi,
  395                 struct fat_entry *fatent)
  396 {
117895 897   397    if (sbi->fatent_ops->ent_next(fatent)) {
117894   398       if (fatent->entry < sbi->max_cluster)
117894    399          return 1;
  400    }
898    401    return 0;
  402 }
  403 
 
1290   404 static inline int fat_ent_read_block(struct super_block *sb,
  405                  struct fat_entry *fatent)
  406 {
  407    struct fatent_operations *ops = MSDOS_SB(sb)->fatent_ops;
  408    sector_t blocknr;
  409    int offset;
  410 
  411    fatent_brelse(fatent);
  412    ops->ent_blocknr(sb, fatent->entry, &offset, &blocknr);
1290    413    return ops->ent_bread(sb, fatent, offset, blocknr);
  414 }
  415 
 
392 392   416 static void fat_collect_bhs(struct buffer_head **bhs, int *nr_bhs,
  417              struct fat_entry *fatent)
  418 {
  419    int n, i;
  420 
392 392   421    for (n = 0; n < fatent->nr_bhs; n++) {
392 - 422       for (i = 0; i < *nr_bhs; i++) {
- 423          if (fatent->bhs[n] == bhs[i])
 - 424             break;
  425       }
392 - 426       if (i == *nr_bhs) {
  427          get_bh(fatent->bhs[n]);
  428          bhs[i] = fatent->bhs[n];
  429          (*nr_bhs)++;
  430       }
  431    }
  432 }
  433 
 
392   434 int fat_alloc_clusters(struct inode *inode, int *cluster, int nr_cluster)
  435 {
  436    struct super_block *sb = inode->i_sb;
  437    struct msdos_sb_info *sbi = MSDOS_SB(sb);
  438    struct fatent_operations *ops = sbi->fatent_ops;
  439    struct fat_entry fatent, prev_ent;
  440    struct buffer_head *bhs[MAX_BUF_PER_PAGE];
  441    int i, count, err, nr_bhs, idx_clus;
  442 
    443    BUG_ON(nr_cluster > (MAX_BUF_PER_PAGE / 2));   /* fixed limit */
392 - 443   if (__builtin_expect ( ! ! ( ( nr_cluster > ..
392 - 443 do-while (0)
  444 
  445    lock_fat(sbi);
392 - 446    if (sbi->free_clusters != -1 && sbi->free_clusters < nr_cluster) {
 - 446   T && T
 392   446   T && F
 - 446   F && _
  447       unlock_fat(sbi);
 - 448       return -ENOSPC;
  449    }
  450 
  451    err = nr_bhs = idx_clus = 0;
  452    count = FAT_START_ENT;
  453    fatent_init(&prev_ent);
  454    fatent_init(&fatent);
  455    fatent_set_entry(&fatent, sbi->prev_free + 1);
1260 - 456    while (count < sbi->max_cluster) {
1260 - 457       if (fatent.entry >= sbi->max_cluster)
  458          fatent.entry = FAT_START_ENT;
  459       fatent_set_entry(&fatent, fatent.entry);
  460       err = fat_ent_read_block(sb, &fatent);
1260 - 461       if (err)
 - 462          goto out;
  463 
  464       /* Find the free entries in a block */
    465       do {
392 111126   466          if (ops->ent_get(&fatent) == FAT_ENT_FREE) {
  467             int entry = fatent.entry;