diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/fat/cache.c | 13 | ||||
-rw-r--r-- | fs/fat/fat.h | 3 | ||||
-rw-r--r-- | fs/fat/inode.c | 3 |
3 files changed, 16 insertions, 3 deletions
diff --git a/fs/fat/cache.c b/fs/fat/cache.c index a132666920e6..d22c1a209808 100644 --- a/fs/fat/cache.c +++ b/fs/fat/cache.c @@ -325,19 +325,26 @@ int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys, last_block = (i_size_read(inode) + (blocksize - 1)) >> blocksize_bits; if (sector >= last_block) { - if (!create) - return 0; - /* * Both ->mmu_private and ->i_disksize can access * on only allocation path. (caller must hold ->i_mutex) */ last_block = (MSDOS_I(inode)->i_disksize + (blocksize - 1)) >> blocksize_bits; + if (!create) { + /* Map a block in fallocated region */ + if (atomic_read(&MSDOS_I(inode)->beyond_isize)) + if (sector < last_block) + goto out_map_cluster; + + return 0; + } + if (sector >= last_block) return 0; } +out_map_cluster: cluster = sector >> (sbi->cluster_bits - sb->s_blocksize_bits); offset = sector & (sbi->sec_per_clus - 1); cluster = fat_bmap_cluster(inode, cluster); diff --git a/fs/fat/fat.h b/fs/fat/fat.h index 7b5851f7a733..b8842769b0c5 100644 --- a/fs/fat/fat.h +++ b/fs/fat/fat.h @@ -129,6 +129,9 @@ struct msdos_inode_info { struct hlist_node i_dir_hash; /* hash by i_logstart */ struct rw_semaphore truncate_lock; /* protect bmap against truncate */ struct inode vfs_inode; + + /* for getting block number beyond file size in case of fallocate */ + atomic_t beyond_isize; }; struct fat_slot_info { diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 6b3e203ff126..ba9831d9f648 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -256,7 +256,10 @@ static sector_t _fat_bmap(struct address_space *mapping, sector_t block) /* fat_get_cluster() assumes the requested blocknr isn't truncated. */ down_read(&MSDOS_I(mapping->host)->truncate_lock); + /* To get block number beyond file size in fallocated region */ + atomic_set(&MSDOS_I(mapping->host)->beyond_isize, 1); blocknr = generic_block_bmap(mapping, block, fat_get_block); + atomic_set(&MSDOS_I(mapping->host)->beyond_isize, 0); up_read(&MSDOS_I(mapping->host)->truncate_lock); return blocknr; |