aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r--fs/ext4/inode.c32
1 files changed, 25 insertions, 7 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index bb89fe727bb1..9cf85721d83c 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -2671,14 +2671,20 @@ static blkcnt_t ext4_inode_blocks(struct ext4_inode *raw_inode,
2671 struct ext4_inode_info *ei) 2671 struct ext4_inode_info *ei)
2672{ 2672{
2673 blkcnt_t i_blocks ; 2673 blkcnt_t i_blocks ;
2674 struct super_block *sb = ei->vfs_inode.i_sb; 2674 struct inode *inode = &(ei->vfs_inode);
2675 struct super_block *sb = inode->i_sb;
2675 2676
2676 if (EXT4_HAS_RO_COMPAT_FEATURE(sb, 2677 if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
2677 EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) { 2678 EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) {
2678 /* we are using combined 48 bit field */ 2679 /* we are using combined 48 bit field */
2679 i_blocks = ((u64)le16_to_cpu(raw_inode->i_blocks_high)) << 32 | 2680 i_blocks = ((u64)le16_to_cpu(raw_inode->i_blocks_high)) << 32 |
2680 le32_to_cpu(raw_inode->i_blocks_lo); 2681 le32_to_cpu(raw_inode->i_blocks_lo);
2681 return i_blocks; 2682 if (ei->i_flags & EXT4_HUGE_FILE_FL) {
2683 /* i_blocks represent file system block size */
2684 return i_blocks << (inode->i_blkbits - 9);
2685 } else {
2686 return i_blocks;
2687 }
2682 } else { 2688 } else {
2683 return le32_to_cpu(raw_inode->i_blocks_lo); 2689 return le32_to_cpu(raw_inode->i_blocks_lo);
2684 } 2690 }
@@ -2829,8 +2835,9 @@ static int ext4_inode_blocks_set(handle_t *handle,
2829 * i_blocks can be represnted in a 32 bit variable 2835 * i_blocks can be represnted in a 32 bit variable
2830 * as multiple of 512 bytes 2836 * as multiple of 512 bytes
2831 */ 2837 */
2832 raw_inode->i_blocks_lo = cpu_to_le32((u32)i_blocks); 2838 raw_inode->i_blocks_lo = cpu_to_le32(i_blocks);
2833 raw_inode->i_blocks_high = 0; 2839 raw_inode->i_blocks_high = 0;
2840 ei->i_flags &= ~EXT4_HUGE_FILE_FL;
2834 } else if (i_blocks <= 0xffffffffffffULL) { 2841 } else if (i_blocks <= 0xffffffffffffULL) {
2835 /* 2842 /*
2836 * i_blocks can be represented in a 48 bit variable 2843 * i_blocks can be represented in a 48 bit variable
@@ -2841,12 +2848,23 @@ static int ext4_inode_blocks_set(handle_t *handle,
2841 if (err) 2848 if (err)
2842 goto err_out; 2849 goto err_out;
2843 /* i_block is stored in the split 48 bit fields */ 2850 /* i_block is stored in the split 48 bit fields */
2844 raw_inode->i_blocks_lo = cpu_to_le32((u32)i_blocks); 2851 raw_inode->i_blocks_lo = cpu_to_le32(i_blocks);
2845 raw_inode->i_blocks_high = cpu_to_le16(i_blocks >> 32); 2852 raw_inode->i_blocks_high = cpu_to_le16(i_blocks >> 32);
2853 ei->i_flags &= ~EXT4_HUGE_FILE_FL;
2846 } else { 2854 } else {
2847 ext4_error(sb, __FUNCTION__, 2855 /*
2848 "Wrong inode i_blocks count %llu\n", 2856 * i_blocks should be represented in a 48 bit variable
2849 (unsigned long long)inode->i_blocks); 2857 * as multiple of file system block size
2858 */
2859 err = ext4_update_rocompat_feature(handle, sb,
2860 EXT4_FEATURE_RO_COMPAT_HUGE_FILE);
2861 if (err)
2862 goto err_out;
2863 ei->i_flags |= EXT4_HUGE_FILE_FL;
2864 /* i_block is stored in file system block size */
2865 i_blocks = i_blocks >> (inode->i_blkbits - 9);
2866 raw_inode->i_blocks_lo = cpu_to_le32(i_blocks);
2867 raw_inode->i_blocks_high = cpu_to_le16(i_blocks >> 32);
2850 } 2868 }
2851err_out: 2869err_out:
2852 return err; 2870 return err;