LCOV - code coverage report
Current view: top level - fs/fat - fatent.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 474 0.0 %
Date: 2022-03-28 15:32:58 Functions: 0 29 0.0 %
Branches: 0 274 0.0 %

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

Generated by: LCOV version 1.14