diff options
-rw-r--r-- | fs/ext4/inode.c | 32 | ||||
-rw-r--r-- | fs/ext4/super.c | 9 | ||||
-rw-r--r-- | include/linux/ext4_fs.h | 3 |
3 files changed, 33 insertions, 11 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 | } |
2851 | err_out: | 2869 | err_out: |
2852 | return err; | 2870 | return err; |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 2b9dc96ec43e..64067de70c6f 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -1631,11 +1631,14 @@ static loff_t ext4_max_size(int bits) | |||
1631 | upper_limit >>= (bits - 9); | 1631 | upper_limit >>= (bits - 9); |
1632 | 1632 | ||
1633 | } else { | 1633 | } else { |
1634 | /* We use 48 bit ext4_inode i_blocks */ | 1634 | /* |
1635 | * We use 48 bit ext4_inode i_blocks | ||
1636 | * With EXT4_HUGE_FILE_FL set the i_blocks | ||
1637 | * represent total number of blocks in | ||
1638 | * file system block size | ||
1639 | */ | ||
1635 | upper_limit = (1LL << 48) - 1; | 1640 | upper_limit = (1LL << 48) - 1; |
1636 | 1641 | ||
1637 | /* total blocks in file system block size */ | ||
1638 | upper_limit >>= (bits - 9); | ||
1639 | } | 1642 | } |
1640 | 1643 | ||
1641 | /* indirect blocks */ | 1644 | /* indirect blocks */ |
diff --git a/include/linux/ext4_fs.h b/include/linux/ext4_fs.h index be25eca9c040..6ae91f40aaa2 100644 --- a/include/linux/ext4_fs.h +++ b/include/linux/ext4_fs.h | |||
@@ -178,8 +178,9 @@ struct ext4_group_desc | |||
178 | #define EXT4_NOTAIL_FL 0x00008000 /* file tail should not be merged */ | 178 | #define EXT4_NOTAIL_FL 0x00008000 /* file tail should not be merged */ |
179 | #define EXT4_DIRSYNC_FL 0x00010000 /* dirsync behaviour (directories only) */ | 179 | #define EXT4_DIRSYNC_FL 0x00010000 /* dirsync behaviour (directories only) */ |
180 | #define EXT4_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/ | 180 | #define EXT4_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/ |
181 | #define EXT4_RESERVED_FL 0x80000000 /* reserved for ext4 lib */ | 181 | #define EXT4_HUGE_FILE_FL 0x00040000 /* Set to each huge file */ |
182 | #define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */ | 182 | #define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */ |
183 | #define EXT4_RESERVED_FL 0x80000000 /* reserved for ext4 lib */ | ||
183 | 184 | ||
184 | #define EXT4_FL_USER_VISIBLE 0x000BDFFF /* User visible flags */ | 185 | #define EXT4_FL_USER_VISIBLE 0x000BDFFF /* User visible flags */ |
185 | #define EXT4_FL_USER_MODIFIABLE 0x000380FF /* User modifiable flags */ | 186 | #define EXT4_FL_USER_MODIFIABLE 0x000380FF /* User modifiable flags */ |