LCOV - code coverage report
Current view: top level - fs/fat - fatent.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 314 0.0 %
Date: 2014-02-18 Functions: 0 26 0.0 %
Branches: 0 214 0.0 %

           Branch data     Line data    Source code
       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                 :            : #include <linux/blkdev.h>
      10                 :            : #include "fat.h"
      11                 :            : 
      12                 :            : struct fatent_operations {
      13                 :            :         void (*ent_blocknr)(struct super_block *, int, int *, sector_t *);
      14                 :            :         void (*ent_set_ptr)(struct fat_entry *, int);
      15                 :            :         int (*ent_bread)(struct super_block *, struct fat_entry *,
      16                 :            :                          int, sector_t);
      17                 :            :         int (*ent_get)(struct fat_entry *);
      18                 :            :         void (*ent_put)(struct fat_entry *, int);
      19                 :            :         int (*ent_next)(struct fat_entry *);
      20                 :            : };
      21                 :            : 
      22                 :            : static DEFINE_SPINLOCK(fat12_entry_lock);
      23                 :            : 
      24                 :          0 : static void fat12_ent_blocknr(struct super_block *sb, int entry,
      25                 :            :                               int *offset, sector_t *blocknr)
      26                 :            : {
      27                 :            :         struct msdos_sb_info *sbi = MSDOS_SB(sb);
      28                 :          0 :         int bytes = entry + (entry >> 1);
      29 [ #  # ][ #  # ]:          0 :         WARN_ON(entry < FAT_START_ENT || sbi->max_cluster <= entry);
                 [ #  # ]
      30                 :          0 :         *offset = bytes & (sb->s_blocksize - 1);
      31                 :          0 :         *blocknr = sbi->fat_start + (bytes >> sb->s_blocksize_bits);
      32                 :          0 : }
      33                 :            : 
      34                 :          0 : static void fat_ent_blocknr(struct super_block *sb, int entry,
      35                 :            :                             int *offset, sector_t *blocknr)
      36                 :            : {
      37                 :            :         struct msdos_sb_info *sbi = MSDOS_SB(sb);
      38                 :          0 :         int bytes = (entry << sbi->fatent_shift);
      39 [ #  # ][ #  # ]:          0 :         WARN_ON(entry < FAT_START_ENT || sbi->max_cluster <= entry);
                 [ #  # ]
      40                 :          0 :         *offset = bytes & (sb->s_blocksize - 1);
      41                 :          0 :         *blocknr = sbi->fat_start + (bytes >> sb->s_blocksize_bits);
      42                 :          0 : }
      43                 :            : 
      44                 :          0 : static void fat12_ent_set_ptr(struct fat_entry *fatent, int offset)
      45                 :            : {
      46                 :            :         struct buffer_head **bhs = fatent->bhs;
      47         [ #  # ]:          0 :         if (fatent->nr_bhs == 1) {
      48         [ #  # ]:          0 :                 WARN_ON(offset >= (bhs[0]->b_size - 1));
      49                 :          0 :                 fatent->u.ent12_p[0] = bhs[0]->b_data + offset;
      50                 :          0 :                 fatent->u.ent12_p[1] = bhs[0]->b_data + (offset + 1);
      51                 :            :         } else {
      52         [ #  # ]:          0 :                 WARN_ON(offset != (bhs[0]->b_size - 1));
      53                 :          0 :                 fatent->u.ent12_p[0] = bhs[0]->b_data + offset;
      54                 :          0 :                 fatent->u.ent12_p[1] = bhs[1]->b_data;
      55                 :            :         }
      56                 :          0 : }
      57                 :            : 
      58                 :          0 : static void fat16_ent_set_ptr(struct fat_entry *fatent, int offset)
      59                 :            : {
      60         [ #  # ]:          0 :         WARN_ON(offset & (2 - 1));
      61                 :          0 :         fatent->u.ent16_p = (__le16 *)(fatent->bhs[0]->b_data + offset);
      62                 :          0 : }
      63                 :            : 
      64                 :          0 : static void fat32_ent_set_ptr(struct fat_entry *fatent, int offset)
      65                 :            : {
      66         [ #  # ]:          0 :         WARN_ON(offset & (4 - 1));
      67                 :          0 :         fatent->u.ent32_p = (__le32 *)(fatent->bhs[0]->b_data + offset);
      68                 :          0 : }
      69                 :            : 
      70                 :          0 : static int fat12_ent_bread(struct super_block *sb, struct fat_entry *fatent,
      71                 :            :                            int offset, sector_t blocknr)
      72                 :            : {
      73                 :            :         struct buffer_head **bhs = fatent->bhs;
      74                 :            : 
      75         [ #  # ]:          0 :         WARN_ON(blocknr < MSDOS_SB(sb)->fat_start);
      76                 :          0 :         fatent->fat_inode = MSDOS_SB(sb)->fat_inode;
      77                 :            : 
      78                 :          0 :         bhs[0] = sb_bread(sb, blocknr);
      79         [ #  # ]:          0 :         if (!bhs[0])
      80                 :            :                 goto err;
      81                 :            : 
      82         [ #  # ]:          0 :         if ((offset + 1) < sb->s_blocksize)
      83                 :          0 :                 fatent->nr_bhs = 1;
      84                 :            :         else {
      85                 :            :                 /* This entry is block boundary, it needs the next block */
      86                 :          0 :                 blocknr++;
      87                 :          0 :                 bhs[1] = sb_bread(sb, blocknr);
      88         [ #  # ]:          0 :                 if (!bhs[1])
      89                 :            :                         goto err_brelse;
      90                 :          0 :                 fatent->nr_bhs = 2;
      91                 :            :         }
      92                 :          0 :         fat12_ent_set_ptr(fatent, offset);
      93                 :          0 :         return 0;
      94                 :            : 
      95                 :            : err_brelse:
      96                 :          0 :         brelse(bhs[0]);
      97                 :            : err:
      98                 :          0 :         fat_msg(sb, KERN_ERR, "FAT read failed (blocknr %llu)", (llu)blocknr);
      99                 :          0 :         return -EIO;
     100                 :            : }
     101                 :            : 
     102                 :          0 : static int fat_ent_bread(struct super_block *sb, struct fat_entry *fatent,
     103                 :            :                          int offset, sector_t blocknr)
     104                 :            : {
     105                 :          0 :         struct fatent_operations *ops = MSDOS_SB(sb)->fatent_ops;
     106                 :            : 
     107         [ #  # ]:          0 :         WARN_ON(blocknr < MSDOS_SB(sb)->fat_start);
     108                 :          0 :         fatent->fat_inode = MSDOS_SB(sb)->fat_inode;
     109                 :          0 :         fatent->bhs[0] = sb_bread(sb, blocknr);
     110         [ #  # ]:          0 :         if (!fatent->bhs[0]) {
     111                 :          0 :                 fat_msg(sb, KERN_ERR, "FAT read failed (blocknr %llu)",
     112                 :            :                        (llu)blocknr);
     113                 :          0 :                 return -EIO;
     114                 :            :         }
     115                 :          0 :         fatent->nr_bhs = 1;
     116                 :          0 :         ops->ent_set_ptr(fatent, offset);
     117                 :          0 :         return 0;
     118                 :            : }
     119                 :            : 
     120                 :          0 : static int fat12_ent_get(struct fat_entry *fatent)
     121                 :            : {
     122                 :            :         u8 **ent12_p = fatent->u.ent12_p;
     123                 :            :         int next;
     124                 :            : 
     125                 :            :         spin_lock(&fat12_entry_lock);
     126         [ #  # ]:          0 :         if (fatent->entry & 1)
     127                 :          0 :                 next = (*ent12_p[0] >> 4) | (*ent12_p[1] << 4);
     128                 :            :         else
     129                 :          0 :                 next = (*ent12_p[1] << 8) | *ent12_p[0];
     130                 :            :         spin_unlock(&fat12_entry_lock);
     131                 :            : 
     132                 :          0 :         next &= 0x0fff;
     133         [ #  # ]:          0 :         if (next >= BAD_FAT12)
     134                 :            :                 next = FAT_ENT_EOF;
     135                 :          0 :         return next;
     136                 :            : }
     137                 :            : 
     138                 :          0 : static int fat16_ent_get(struct fat_entry *fatent)
     139                 :            : {
     140                 :          0 :         int next = le16_to_cpu(*fatent->u.ent16_p);
     141         [ #  # ]:          0 :         WARN_ON((unsigned long)fatent->u.ent16_p & (2 - 1));
     142         [ #  # ]:          0 :         if (next >= BAD_FAT16)
     143                 :            :                 next = FAT_ENT_EOF;
     144                 :          0 :         return next;
     145                 :            : }
     146                 :            : 
     147                 :          0 : static int fat32_ent_get(struct fat_entry *fatent)
     148                 :            : {
     149                 :          0 :         int next = le32_to_cpu(*fatent->u.ent32_p) & 0x0fffffff;
     150         [ #  # ]:          0 :         WARN_ON((unsigned long)fatent->u.ent32_p & (4 - 1));
     151         [ #  # ]:          0 :         if (next >= BAD_FAT32)
     152                 :            :                 next = FAT_ENT_EOF;
     153                 :          0 :         return next;
     154                 :            : }
     155                 :            : 
     156                 :          0 : static void fat12_ent_put(struct fat_entry *fatent, int new)
     157                 :            : {
     158                 :            :         u8 **ent12_p = fatent->u.ent12_p;
     159                 :            : 
     160         [ #  # ]:          0 :         if (new == FAT_ENT_EOF)
     161                 :            :                 new = EOF_FAT12;
     162                 :            : 
     163                 :            :         spin_lock(&fat12_entry_lock);
     164         [ #  # ]:          0 :         if (fatent->entry & 1) {
     165                 :          0 :                 *ent12_p[0] = (new << 4) | (*ent12_p[0] & 0x0f);
     166                 :          0 :                 *ent12_p[1] = new >> 4;
     167                 :            :         } else {
     168                 :          0 :                 *ent12_p[0] = new & 0xff;
     169                 :          0 :                 *ent12_p[1] = (*ent12_p[1] & 0xf0) | (new >> 8);
     170                 :            :         }
     171                 :            :         spin_unlock(&fat12_entry_lock);
     172                 :            : 
     173                 :          0 :         mark_buffer_dirty_inode(fatent->bhs[0], fatent->fat_inode);
     174         [ #  # ]:          0 :         if (fatent->nr_bhs == 2)
     175                 :          0 :                 mark_buffer_dirty_inode(fatent->bhs[1], fatent->fat_inode);
     176                 :          0 : }
     177                 :            : 
     178                 :          0 : static void fat16_ent_put(struct fat_entry *fatent, int new)
     179                 :            : {
     180         [ #  # ]:          0 :         if (new == FAT_ENT_EOF)
     181                 :            :                 new = EOF_FAT16;
     182                 :            : 
     183                 :          0 :         *fatent->u.ent16_p = cpu_to_le16(new);
     184                 :          0 :         mark_buffer_dirty_inode(fatent->bhs[0], fatent->fat_inode);
     185                 :          0 : }
     186                 :            : 
     187                 :          0 : static void fat32_ent_put(struct fat_entry *fatent, int new)
     188                 :            : {
     189         [ #  # ]:          0 :         WARN_ON(new & 0xf0000000);
     190                 :          0 :         new |= le32_to_cpu(*fatent->u.ent32_p) & ~0x0fffffff;
     191                 :          0 :         *fatent->u.ent32_p = cpu_to_le32(new);
     192                 :          0 :         mark_buffer_dirty_inode(fatent->bhs[0], fatent->fat_inode);
     193                 :          0 : }
     194                 :            : 
     195                 :          0 : static int fat12_ent_next(struct fat_entry *fatent)
     196                 :            : {
     197                 :            :         u8 **ent12_p = fatent->u.ent12_p;
     198                 :            :         struct buffer_head **bhs = fatent->bhs;
     199                 :          0 :         u8 *nextp = ent12_p[1] + 1 + (fatent->entry & 1);
     200                 :            : 
     201                 :          0 :         fatent->entry++;
     202         [ #  # ]:          0 :         if (fatent->nr_bhs == 1) {
     203         [ #  # ]:          0 :                 WARN_ON(ent12_p[0] > (u8 *)(bhs[0]->b_data +
     204                 :            :                                                         (bhs[0]->b_size - 2)));
     205         [ #  # ]:          0 :                 WARN_ON(ent12_p[1] > (u8 *)(bhs[0]->b_data +
     206                 :            :                                                         (bhs[0]->b_size - 1)));
     207         [ #  # ]:          0 :                 if (nextp < (u8 *)(bhs[0]->b_data + (bhs[0]->b_size - 1))) {
     208                 :          0 :                         ent12_p[0] = nextp - 1;
     209                 :          0 :                         ent12_p[1] = nextp;
     210                 :          0 :                         return 1;
     211                 :            :                 }
     212                 :            :         } else {
     213         [ #  # ]:          0 :                 WARN_ON(ent12_p[0] != (u8 *)(bhs[0]->b_data +
     214                 :            :                                                         (bhs[0]->b_size - 1)));
     215         [ #  # ]:          0 :                 WARN_ON(ent12_p[1] != (u8 *)bhs[1]->b_data);
     216                 :          0 :                 ent12_p[0] = nextp - 1;
     217                 :          0 :                 ent12_p[1] = nextp;
     218                 :          0 :                 brelse(bhs[0]);
     219                 :          0 :                 bhs[0] = bhs[1];
     220                 :          0 :                 fatent->nr_bhs = 1;
     221                 :          0 :                 return 1;
     222                 :            :         }
     223                 :          0 :         ent12_p[0] = NULL;
     224                 :          0 :         ent12_p[1] = NULL;
     225                 :          0 :         return 0;
     226                 :            : }
     227                 :            : 
     228                 :          0 : static int fat16_ent_next(struct fat_entry *fatent)
     229                 :            : {
     230                 :          0 :         const struct buffer_head *bh = fatent->bhs[0];
     231                 :          0 :         fatent->entry++;
     232         [ #  # ]:          0 :         if (fatent->u.ent16_p < (__le16 *)(bh->b_data + (bh->b_size - 2))) {
     233                 :          0 :                 fatent->u.ent16_p++;
     234                 :          0 :                 return 1;
     235                 :            :         }
     236                 :          0 :         fatent->u.ent16_p = NULL;
     237                 :          0 :         return 0;
     238                 :            : }
     239                 :            : 
     240                 :          0 : static int fat32_ent_next(struct fat_entry *fatent)
     241                 :            : {
     242                 :          0 :         const struct buffer_head *bh = fatent->bhs[0];
     243                 :          0 :         fatent->entry++;
     244         [ #  # ]:          0 :         if (fatent->u.ent32_p < (__le32 *)(bh->b_data + (bh->b_size - 4))) {
     245                 :          0 :                 fatent->u.ent32_p++;
     246                 :          0 :                 return 1;
     247                 :            :         }
     248                 :          0 :         fatent->u.ent32_p = NULL;
     249                 :          0 :         return 0;
     250                 :            : }
     251                 :            : 
     252                 :            : static struct fatent_operations fat12_ops = {
     253                 :            :         .ent_blocknr    = fat12_ent_blocknr,
     254                 :            :         .ent_set_ptr    = fat12_ent_set_ptr,
     255                 :            :         .ent_bread      = fat12_ent_bread,
     256                 :            :         .ent_get        = fat12_ent_get,
     257                 :            :         .ent_put        = fat12_ent_put,
     258                 :            :         .ent_next       = fat12_ent_next,
     259                 :            : };
     260                 :            : 
     261                 :            : static struct fatent_operations fat16_ops = {
     262                 :            :         .ent_blocknr    = fat_ent_blocknr,
     263                 :            :         .ent_set_ptr    = fat16_ent_set_ptr,
     264                 :            :         .ent_bread      = fat_ent_bread,
     265                 :            :         .ent_get        = fat16_ent_get,
     266                 :            :         .ent_put        = fat16_ent_put,
     267                 :            :         .ent_next       = fat16_ent_next,
     268                 :            : };
     269                 :            : 
     270                 :            : static struct fatent_operations fat32_ops = {
     271                 :            :         .ent_blocknr    = fat_ent_blocknr,
     272                 :            :         .ent_set_ptr    = fat32_ent_set_ptr,
     273                 :            :         .ent_bread      = fat_ent_bread,
     274                 :            :         .ent_get        = fat32_ent_get,
     275                 :            :         .ent_put        = fat32_ent_put,
     276                 :            :         .ent_next       = fat32_ent_next,
     277                 :            : };
     278                 :            : 
     279                 :            : static inline void lock_fat(struct msdos_sb_info *sbi)
     280                 :            : {
     281                 :          0 :         mutex_lock(&sbi->fat_lock);
     282                 :            : }
     283                 :            : 
     284                 :            : static inline void unlock_fat(struct msdos_sb_info *sbi)
     285                 :            : {
     286                 :          0 :         mutex_unlock(&sbi->fat_lock);
     287                 :            : }
     288                 :            : 
     289                 :          0 : void fat_ent_access_init(struct super_block *sb)
     290                 :            : {
     291                 :            :         struct msdos_sb_info *sbi = MSDOS_SB(sb);
     292                 :            : 
     293                 :          0 :         mutex_init(&sbi->fat_lock);
     294                 :            : 
     295   [ #  #  #  # ]:          0 :         switch (sbi->fat_bits) {
     296                 :            :         case 32:
     297                 :          0 :                 sbi->fatent_shift = 2;
     298                 :          0 :                 sbi->fatent_ops = &fat32_ops;
     299                 :          0 :                 break;
     300                 :            :         case 16:
     301                 :          0 :                 sbi->fatent_shift = 1;
     302                 :          0 :                 sbi->fatent_ops = &fat16_ops;
     303                 :          0 :                 break;
     304                 :            :         case 12:
     305                 :          0 :                 sbi->fatent_shift = -1;
     306                 :          0 :                 sbi->fatent_ops = &fat12_ops;
     307                 :          0 :                 break;
     308                 :            :         }
     309                 :          0 : }
     310                 :            : 
     311                 :          0 : static void mark_fsinfo_dirty(struct super_block *sb)
     312                 :            : {
     313                 :            :         struct msdos_sb_info *sbi = MSDOS_SB(sb);
     314                 :            : 
     315 [ #  # ][ #  # ]:          0 :         if (sb->s_flags & MS_RDONLY || sbi->fat_bits != 32)
     316                 :          0 :                 return;
     317                 :            : 
     318                 :          0 :         __mark_inode_dirty(sbi->fsinfo_inode, I_DIRTY_SYNC);
     319                 :            : }
     320                 :            : 
     321                 :          0 : static inline int fat_ent_update_ptr(struct super_block *sb,
     322                 :            :                                      struct fat_entry *fatent,
     323                 :            :                                      int offset, sector_t blocknr)
     324                 :            : {
     325                 :            :         struct msdos_sb_info *sbi = MSDOS_SB(sb);
     326                 :          0 :         struct fatent_operations *ops = sbi->fatent_ops;
     327                 :            :         struct buffer_head **bhs = fatent->bhs;
     328                 :            : 
     329                 :            :         /* Is this fatent's blocks including this entry? */
     330 [ #  # ][ #  # ]:          0 :         if (!fatent->nr_bhs || bhs[0]->b_blocknr != blocknr)
     331                 :            :                 return 0;
     332         [ #  # ]:          0 :         if (sbi->fat_bits == 12) {
     333         [ #  # ]:          0 :                 if ((offset + 1) < sb->s_blocksize) {
     334                 :            :                         /* This entry is on bhs[0]. */
     335         [ #  # ]:          0 :                         if (fatent->nr_bhs == 2) {
     336                 :          0 :                                 brelse(bhs[1]);
     337                 :          0 :                                 fatent->nr_bhs = 1;
     338                 :            :                         }
     339                 :            :                 } else {
     340                 :            :                         /* This entry needs the next block. */
     341         [ #  # ]:          0 :                         if (fatent->nr_bhs != 2)
     342                 :            :                                 return 0;
     343         [ #  # ]:          0 :                         if (bhs[1]->b_blocknr != (blocknr + 1))
     344                 :            :                                 return 0;
     345                 :            :                 }
     346                 :            :         }
     347                 :          0 :         ops->ent_set_ptr(fatent, offset);
     348                 :            :         return 1;
     349                 :            : }
     350                 :            : 
     351                 :          0 : int fat_ent_read(struct inode *inode, struct fat_entry *fatent, int entry)
     352                 :            : {
     353                 :          0 :         struct super_block *sb = inode->i_sb;
     354                 :          0 :         struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
     355                 :          0 :         struct fatent_operations *ops = sbi->fatent_ops;
     356                 :            :         int err, offset;
     357                 :            :         sector_t blocknr;
     358                 :            : 
     359 [ #  # ][ #  # ]:          0 :         if (entry < FAT_START_ENT || sbi->max_cluster <= entry) {
     360                 :            :                 fatent_brelse(fatent);
     361                 :          0 :                 fat_fs_error(sb, "invalid access to FAT (entry 0x%08x)", entry);
     362                 :          0 :                 return -EIO;
     363                 :            :         }
     364                 :            : 
     365                 :            :         fatent_set_entry(fatent, entry);
     366                 :          0 :         ops->ent_blocknr(sb, entry, &offset, &blocknr);
     367                 :            : 
     368         [ #  # ]:          0 :         if (!fat_ent_update_ptr(sb, fatent, offset, blocknr)) {
     369                 :            :                 fatent_brelse(fatent);
     370                 :          0 :                 err = ops->ent_bread(sb, fatent, offset, blocknr);
     371         [ #  # ]:          0 :                 if (err)
     372                 :            :                         return err;
     373                 :            :         }
     374                 :          0 :         return ops->ent_get(fatent);
     375                 :            : }
     376                 :            : 
     377                 :            : /* FIXME: We can write the blocks as more big chunk. */
     378                 :          0 : static int fat_mirror_bhs(struct super_block *sb, struct buffer_head **bhs,
     379                 :            :                           int nr_bhs)
     380                 :            : {
     381                 :            :         struct msdos_sb_info *sbi = MSDOS_SB(sb);
     382                 :            :         struct buffer_head *c_bh;
     383                 :            :         int err, n, copy;
     384                 :            : 
     385                 :            :         err = 0;
     386         [ #  # ]:          0 :         for (copy = 1; copy < sbi->fats; copy++) {
     387                 :          0 :                 sector_t backup_fat = sbi->fat_length * copy;
     388                 :            : 
     389         [ #  # ]:          0 :                 for (n = 0; n < nr_bhs; n++) {
     390                 :          0 :                         c_bh = sb_getblk(sb, backup_fat + bhs[n]->b_blocknr);
     391         [ #  # ]:          0 :                         if (!c_bh) {
     392                 :            :                                 err = -ENOMEM;
     393                 :            :                                 goto error;
     394                 :            :                         }
     395                 :          0 :                         memcpy(c_bh->b_data, bhs[n]->b_data, sb->s_blocksize);
     396                 :            :                         set_buffer_uptodate(c_bh);
     397                 :          0 :                         mark_buffer_dirty_inode(c_bh, sbi->fat_inode);
     398         [ #  # ]:          0 :                         if (sb->s_flags & MS_SYNCHRONOUS)
     399                 :          0 :                                 err = sync_dirty_buffer(c_bh);
     400                 :            :                         brelse(c_bh);
     401         [ #  # ]:          0 :                         if (err)
     402                 :            :                                 goto error;
     403                 :            :                 }
     404                 :            :         }
     405                 :            : error:
     406                 :          0 :         return err;
     407                 :            : }
     408                 :            : 
     409                 :          0 : int fat_ent_write(struct inode *inode, struct fat_entry *fatent,
     410                 :            :                   int new, int wait)
     411                 :            : {
     412                 :          0 :         struct super_block *sb = inode->i_sb;
     413                 :          0 :         struct fatent_operations *ops = MSDOS_SB(sb)->fatent_ops;
     414                 :            :         int err;
     415                 :            : 
     416                 :          0 :         ops->ent_put(fatent, new);
     417         [ #  # ]:          0 :         if (wait) {
     418                 :          0 :                 err = fat_sync_bhs(fatent->bhs, fatent->nr_bhs);
     419         [ #  # ]:          0 :                 if (err)
     420                 :            :                         return err;
     421                 :            :         }
     422                 :          0 :         return fat_mirror_bhs(sb, fatent->bhs, fatent->nr_bhs);
     423                 :            : }
     424                 :            : 
     425                 :            : static inline int fat_ent_next(struct msdos_sb_info *sbi,
     426                 :            :                                struct fat_entry *fatent)
     427                 :            : {
     428 [ #  # ][ #  # ]:          0 :         if (sbi->fatent_ops->ent_next(fatent)) {
     429 [ #  # ][ #  # ]:          0 :                 if (fatent->entry < sbi->max_cluster)
     430                 :            :                         return 1;
     431                 :            :         }
     432                 :            :         return 0;
     433                 :            : }
     434                 :            : 
     435                 :          0 : static inline int fat_ent_read_block(struct super_block *sb,
     436                 :            :                                      struct fat_entry *fatent)
     437                 :            : {
     438                 :          0 :         struct fatent_operations *ops = MSDOS_SB(sb)->fatent_ops;
     439                 :            :         sector_t blocknr;
     440                 :            :         int offset;
     441                 :            : 
     442                 :            :         fatent_brelse(fatent);
     443                 :          0 :         ops->ent_blocknr(sb, fatent->entry, &offset, &blocknr);
     444                 :          0 :         return ops->ent_bread(sb, fatent, offset, blocknr);
     445                 :            : }
     446                 :            : 
     447                 :          0 : static void fat_collect_bhs(struct buffer_head **bhs, int *nr_bhs,
     448                 :            :                             struct fat_entry *fatent)
     449                 :            : {
     450                 :            :         int n, i;
     451                 :            : 
     452         [ #  # ]:          0 :         for (n = 0; n < fatent->nr_bhs; n++) {
     453         [ #  # ]:          0 :                 for (i = 0; i < *nr_bhs; i++) {
     454         [ #  # ]:          0 :                         if (fatent->bhs[n] == bhs[i])
     455                 :            :                                 break;
     456                 :            :                 }
     457         [ #  # ]:          0 :                 if (i == *nr_bhs) {
     458                 :          0 :                         get_bh(fatent->bhs[n]);
     459                 :          0 :                         bhs[i] = fatent->bhs[n];
     460                 :          0 :                         (*nr_bhs)++;
     461                 :            :                 }
     462                 :            :         }
     463                 :          0 : }
     464                 :            : 
     465                 :          0 : int fat_alloc_clusters(struct inode *inode, int *cluster, int nr_cluster)
     466                 :            : {
     467                 :          0 :         struct super_block *sb = inode->i_sb;
     468                 :          0 :         struct msdos_sb_info *sbi = MSDOS_SB(sb);
     469                 :          0 :         struct fatent_operations *ops = sbi->fatent_ops;
     470                 :            :         struct fat_entry fatent, prev_ent;
     471                 :            :         struct buffer_head *bhs[MAX_BUF_PER_PAGE];
     472                 :            :         int i, count, err, nr_bhs, idx_clus;
     473                 :            : 
     474         [ #  # ]:          0 :         BUG_ON(nr_cluster > (MAX_BUF_PER_PAGE / 2)); /* fixed limit */
     475                 :            : 
     476                 :            :         lock_fat(sbi);
     477 [ #  # ][ #  # ]:          0 :         if (sbi->free_clusters != -1 && sbi->free_clus_valid &&
                 [ #  # ]
     478                 :            :             sbi->free_clusters < nr_cluster) {
     479                 :            :                 unlock_fat(sbi);
     480                 :          0 :                 return -ENOSPC;
     481                 :            :         }
     482                 :            : 
     483                 :          0 :         err = nr_bhs = idx_clus = 0;
     484                 :            :         count = FAT_START_ENT;
     485                 :            :         fatent_init(&prev_ent);
     486                 :            :         fatent_init(&fatent);
     487                 :          0 :         fatent_set_entry(&fatent, sbi->prev_free + 1);
     488         [ #  # ]:          0 :         while (count < sbi->max_cluster) {
     489         [ #  # ]:          0 :                 if (fatent.entry >= sbi->max_cluster)
     490                 :          0 :                         fatent.entry = FAT_START_ENT;
     491                 :            :                 fatent_set_entry(&fatent, fatent.entry);
     492                 :            :                 err = fat_ent_read_block(sb, &fatent);
     493         [ #  # ]:          0 :                 if (err)
     494                 :            :                         goto out;
     495                 :            : 
     496                 :            :                 /* Find the free entries in a block */
     497                 :            :                 do {
     498         [ #  # ]:          0 :                         if (ops->ent_get(&fatent) == FAT_ENT_FREE) {
     499                 :          0 :                                 int entry = fatent.entry;
     500                 :            : 
     501                 :            :                                 /* make the cluster chain */
     502                 :          0 :                                 ops->ent_put(&fatent, FAT_ENT_EOF);
     503         [ #  # ]:          0 :                                 if (prev_ent.nr_bhs)
     504                 :          0 :                                         ops->ent_put(&prev_ent, entry);
     505                 :            : 
     506                 :          0 :                                 fat_collect_bhs(bhs, &nr_bhs, &fatent);
     507                 :            : 
     508                 :          0 :                                 sbi->prev_free = entry;
     509         [ #  # ]:          0 :                                 if (sbi->free_clusters != -1)
     510                 :          0 :                                         sbi->free_clusters--;
     511                 :            : 
     512                 :          0 :                                 cluster[idx_clus] = entry;
     513                 :          0 :                                 idx_clus++;
     514         [ #  # ]:          0 :                                 if (idx_clus == nr_cluster)
     515                 :            :                                         goto out;
     516                 :            : 
     517                 :            :                                 /*
     518                 :            :                                  * fat_collect_bhs() gets ref-count of bhs,
     519                 :            :                                  * so we can still use the prev_ent.
     520                 :            :                                  */
     521                 :          0 :                                 prev_ent = fatent;
     522                 :            :                         }
     523                 :          0 :                         count++;
     524         [ #  # ]:          0 :                         if (count == sbi->max_cluster)
     525                 :            :                                 break;
     526         [ #  # ]:          0 :                 } while (fat_ent_next(sbi, &fatent));
     527                 :            :         }
     528                 :            : 
     529                 :            :         /* Couldn't allocate the free entries */
     530                 :          0 :         sbi->free_clusters = 0;
     531                 :          0 :         sbi->free_clus_valid = 1;
     532                 :            :         err = -ENOSPC;
     533                 :            : 
     534                 :            : out:
     535                 :            :         unlock_fat(sbi);
     536                 :          0 :         mark_fsinfo_dirty(sb);
     537                 :            :         fatent_brelse(&fatent);
     538         [ #  # ]:          0 :         if (!err) {
     539         [ #  # ]:          0 :                 if (inode_needs_sync(inode))
     540                 :          0 :                         err = fat_sync_bhs(bhs, nr_bhs);
     541         [ #  # ]:          0 :                 if (!err)
     542                 :          0 :                         err = fat_mirror_bhs(sb, bhs, nr_bhs);
     543                 :            :         }
     544         [ #  # ]:          0 :         for (i = 0; i < nr_bhs; i++)
     545                 :          0 :                 brelse(bhs[i]);
     546                 :            : 
     547         [ #  # ]:          0 :         if (err && idx_clus)
     548                 :          0 :                 fat_free_clusters(inode, cluster[0]);
     549                 :            : 
     550                 :          0 :         return err;
     551                 :            : }
     552                 :            : 
     553                 :          0 : int fat_free_clusters(struct inode *inode, int cluster)
     554                 :            : {
     555                 :          0 :         struct super_block *sb = inode->i_sb;
     556                 :          0 :         struct msdos_sb_info *sbi = MSDOS_SB(sb);
     557                 :          0 :         struct fatent_operations *ops = sbi->fatent_ops;
     558                 :            :         struct fat_entry fatent;
     559                 :            :         struct buffer_head *bhs[MAX_BUF_PER_PAGE];
     560                 :            :         int i, err, nr_bhs;
     561                 :            :         int first_cl = cluster, dirty_fsinfo = 0;
     562                 :            : 
     563                 :          0 :         nr_bhs = 0;
     564                 :            :         fatent_init(&fatent);
     565                 :            :         lock_fat(sbi);
     566                 :            :         do {
     567                 :          0 :                 cluster = fat_ent_read(inode, &fatent, cluster);
     568         [ #  # ]:          0 :                 if (cluster < 0) {
     569                 :            :                         err = cluster;
     570                 :            :                         goto error;
     571         [ #  # ]:          0 :                 } else if (cluster == FAT_ENT_FREE) {
     572                 :          0 :                         fat_fs_error(sb, "%s: deleting FAT entry beyond EOF",
     573                 :            :                                      __func__);
     574                 :            :                         err = -EIO;
     575                 :          0 :                         goto error;
     576                 :            :                 }
     577                 :            : 
     578         [ #  # ]:          0 :                 if (sbi->options.discard) {
     579                 :            :                         /*
     580                 :            :                          * Issue discard for the sectors we no longer
     581                 :            :                          * care about, batching contiguous clusters
     582                 :            :                          * into one request
     583                 :            :                          */
     584         [ #  # ]:          0 :                         if (cluster != fatent.entry + 1) {
     585                 :          0 :                                 int nr_clus = fatent.entry - first_cl + 1;
     586                 :            : 
     587                 :          0 :                                 sb_issue_discard(sb,
     588                 :            :                                         fat_clus_to_blknr(sbi, first_cl),
     589                 :          0 :                                         nr_clus * sbi->sec_per_clus,
     590                 :            :                                         GFP_NOFS, 0);
     591                 :            : 
     592                 :            :                                 first_cl = cluster;
     593                 :            :                         }
     594                 :            :                 }
     595                 :            : 
     596                 :          0 :                 ops->ent_put(&fatent, FAT_ENT_FREE);
     597         [ #  # ]:          0 :                 if (sbi->free_clusters != -1) {
     598                 :          0 :                         sbi->free_clusters++;
     599                 :            :                         dirty_fsinfo = 1;
     600                 :            :                 }
     601                 :            : 
     602         [ #  # ]:          0 :                 if (nr_bhs + fatent.nr_bhs > MAX_BUF_PER_PAGE) {
     603         [ #  # ]:          0 :                         if (sb->s_flags & MS_SYNCHRONOUS) {
     604                 :          0 :                                 err = fat_sync_bhs(bhs, nr_bhs);
     605         [ #  # ]:          0 :                                 if (err)
     606                 :            :                                         goto error;
     607                 :            :                         }
     608                 :          0 :                         err = fat_mirror_bhs(sb, bhs, nr_bhs);
     609         [ #  # ]:          0 :                         if (err)
     610                 :            :                                 goto error;
     611         [ #  # ]:          0 :                         for (i = 0; i < nr_bhs; i++)
     612                 :          0 :                                 brelse(bhs[i]);
     613                 :          0 :                         nr_bhs = 0;
     614                 :            :                 }
     615                 :          0 :                 fat_collect_bhs(bhs, &nr_bhs, &fatent);
     616         [ #  # ]:          0 :         } while (cluster != FAT_ENT_EOF);
     617                 :            : 
     618         [ #  # ]:          0 :         if (sb->s_flags & MS_SYNCHRONOUS) {
     619                 :          0 :                 err = fat_sync_bhs(bhs, nr_bhs);
     620         [ #  # ]:          0 :                 if (err)
     621                 :            :                         goto error;
     622                 :            :         }
     623                 :          0 :         err = fat_mirror_bhs(sb, bhs, nr_bhs);
     624                 :            : error:
     625                 :            :         fatent_brelse(&fatent);
     626         [ #  # ]:          0 :         for (i = 0; i < nr_bhs; i++)
     627                 :          0 :                 brelse(bhs[i]);
     628                 :            :         unlock_fat(sbi);
     629         [ #  # ]:          0 :         if (dirty_fsinfo)
     630                 :          0 :                 mark_fsinfo_dirty(sb);
     631                 :            : 
     632                 :          0 :         return err;
     633                 :            : }
     634                 :            : EXPORT_SYMBOL_GPL(fat_free_clusters);
     635                 :            : 
     636                 :            : /* 128kb is the whole sectors for FAT12 and FAT16 */
     637                 :            : #define FAT_READA_SIZE          (128 * 1024)
     638                 :            : 
     639                 :          0 : static void fat_ent_reada(struct super_block *sb, struct fat_entry *fatent,
     640                 :            :                           unsigned long reada_blocks)
     641                 :            : {
     642                 :          0 :         struct fatent_operations *ops = MSDOS_SB(sb)->fatent_ops;
     643                 :            :         sector_t blocknr;
     644                 :            :         int i, offset;
     645                 :            : 
     646                 :          0 :         ops->ent_blocknr(sb, fatent->entry, &offset, &blocknr);
     647                 :            : 
     648         [ #  # ]:          0 :         for (i = 0; i < reada_blocks; i++)
     649                 :          0 :                 sb_breadahead(sb, blocknr + i);
     650                 :          0 : }
     651                 :            : 
     652                 :          0 : int fat_count_free_clusters(struct super_block *sb)
     653                 :            : {
     654                 :          0 :         struct msdos_sb_info *sbi = MSDOS_SB(sb);
     655                 :          0 :         struct fatent_operations *ops = sbi->fatent_ops;
     656                 :            :         struct fat_entry fatent;
     657                 :            :         unsigned long reada_blocks, reada_mask, cur_block;
     658                 :            :         int err = 0, free;
     659                 :            : 
     660                 :            :         lock_fat(sbi);
     661 [ #  # ][ #  # ]:          0 :         if (sbi->free_clusters != -1 && sbi->free_clus_valid)
     662                 :            :                 goto out;
     663                 :            : 
     664                 :          0 :         reada_blocks = FAT_READA_SIZE >> sb->s_blocksize_bits;
     665                 :          0 :         reada_mask = reada_blocks - 1;
     666                 :            :         cur_block = 0;
     667                 :            : 
     668                 :            :         free = 0;
     669                 :            :         fatent_init(&fatent);
     670                 :            :         fatent_set_entry(&fatent, FAT_START_ENT);
     671         [ #  # ]:          0 :         while (fatent.entry < sbi->max_cluster) {
     672                 :            :                 /* readahead of fat blocks */
     673         [ #  # ]:          0 :                 if ((cur_block & reada_mask) == 0) {
     674                 :          0 :                         unsigned long rest = sbi->fat_length - cur_block;
     675                 :          0 :                         fat_ent_reada(sb, &fatent, min(reada_blocks, rest));
     676                 :            :                 }
     677                 :          0 :                 cur_block++;
     678                 :            : 
     679                 :            :                 err = fat_ent_read_block(sb, &fatent);
     680         [ #  # ]:          0 :                 if (err)
     681                 :            :                         goto out;
     682                 :            : 
     683                 :            :                 do {
     684         [ #  # ]:          0 :                         if (ops->ent_get(&fatent) == FAT_ENT_FREE)
     685                 :          0 :                                 free++;
     686         [ #  # ]:          0 :                 } while (fat_ent_next(sbi, &fatent));
     687                 :            :         }
     688                 :          0 :         sbi->free_clusters = free;
     689                 :          0 :         sbi->free_clus_valid = 1;
     690                 :          0 :         mark_fsinfo_dirty(sb);
     691                 :            :         fatent_brelse(&fatent);
     692                 :            : out:
     693                 :            :         unlock_fat(sbi);
     694                 :          0 :         return err;
     695                 :            : }

Generated by: LCOV version 1.9