LCOV - code coverage report
Current view: top level - lkbce/fs/fat - fatent.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 293 425 68.9 %
Date: 2017-01-25 Functions: 25 30 83.3 %

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

Generated by: LCOV version 1.10