|
@@ -301,15 +301,59 @@ static int fat_bmap_cluster(struct inode *inode, int cluster)
|
|
|
return dclus;
|
|
|
}
|
|
|
|
|
|
-int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
|
|
|
- unsigned long *mapped_blocks, int create)
|
|
|
+int fat_get_mapped_cluster(struct inode *inode, sector_t sector,
|
|
|
+ sector_t last_block,
|
|
|
+ unsigned long *mapped_blocks, sector_t *bmap)
|
|
|
{
|
|
|
struct super_block *sb = inode->i_sb;
|
|
|
struct msdos_sb_info *sbi = MSDOS_SB(sb);
|
|
|
+ int cluster, offset;
|
|
|
+
|
|
|
+ cluster = sector >> (sbi->cluster_bits - sb->s_blocksize_bits);
|
|
|
+ offset = sector & (sbi->sec_per_clus - 1);
|
|
|
+ cluster = fat_bmap_cluster(inode, cluster);
|
|
|
+ if (cluster < 0)
|
|
|
+ return cluster;
|
|
|
+ else if (cluster) {
|
|
|
+ *bmap = fat_clus_to_blknr(sbi, cluster) + offset;
|
|
|
+ *mapped_blocks = sbi->sec_per_clus - offset;
|
|
|
+ if (*mapped_blocks > last_block - sector)
|
|
|
+ *mapped_blocks = last_block - sector;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int is_exceed_eof(struct inode *inode, sector_t sector,
|
|
|
+ sector_t *last_block, int create)
|
|
|
+{
|
|
|
+ struct super_block *sb = inode->i_sb;
|
|
|
const unsigned long blocksize = sb->s_blocksize;
|
|
|
const unsigned char blocksize_bits = sb->s_blocksize_bits;
|
|
|
+
|
|
|
+ *last_block = (i_size_read(inode) + (blocksize - 1)) >> blocksize_bits;
|
|
|
+ if (sector >= *last_block) {
|
|
|
+ if (!create)
|
|
|
+ return 1;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * ->mmu_private can access on only allocation path.
|
|
|
+ * (caller must hold ->i_mutex)
|
|
|
+ */
|
|
|
+ *last_block = (MSDOS_I(inode)->mmu_private + (blocksize - 1))
|
|
|
+ >> blocksize_bits;
|
|
|
+ if (sector >= *last_block)
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
|
|
|
+ unsigned long *mapped_blocks, int create, bool from_bmap)
|
|
|
+{
|
|
|
+ struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
|
|
|
sector_t last_block;
|
|
|
- int cluster, offset;
|
|
|
|
|
|
*phys = 0;
|
|
|
*mapped_blocks = 0;
|
|
@@ -321,31 +365,16 @@ int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- last_block = (i_size_read(inode) + (blocksize - 1)) >> blocksize_bits;
|
|
|
- if (sector >= last_block) {
|
|
|
- if (!create)
|
|
|
+ if (!from_bmap) {
|
|
|
+ if (is_exceed_eof(inode, sector, &last_block, create))
|
|
|
return 0;
|
|
|
-
|
|
|
- /*
|
|
|
- * ->mmu_private can access on only allocation path.
|
|
|
- * (caller must hold ->i_mutex)
|
|
|
- */
|
|
|
- last_block = (MSDOS_I(inode)->mmu_private + (blocksize - 1))
|
|
|
- >> blocksize_bits;
|
|
|
+ } else {
|
|
|
+ last_block = inode->i_blocks >>
|
|
|
+ (inode->i_sb->s_blocksize_bits - 9);
|
|
|
if (sector >= last_block)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- cluster = sector >> (sbi->cluster_bits - sb->s_blocksize_bits);
|
|
|
- offset = sector & (sbi->sec_per_clus - 1);
|
|
|
- cluster = fat_bmap_cluster(inode, cluster);
|
|
|
- if (cluster < 0)
|
|
|
- return cluster;
|
|
|
- else if (cluster) {
|
|
|
- *phys = fat_clus_to_blknr(sbi, cluster) + offset;
|
|
|
- *mapped_blocks = sbi->sec_per_clus - offset;
|
|
|
- if (*mapped_blocks > last_block - sector)
|
|
|
- *mapped_blocks = last_block - sector;
|
|
|
- }
|
|
|
- return 0;
|
|
|
+ return fat_get_mapped_cluster(inode, sector, last_block, mapped_blocks,
|
|
|
+ phys);
|
|
|
}
|