aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2008-01-28 23:58:27 -0500
committerTheodore Ts'o <tytso@mit.edu>2008-01-28 23:58:27 -0500
commit8180a5627d126362c2f64e4fa886d6f608d9632a (patch)
tree1b3a3261f72f8245afdd87088703641c76f60392 /fs
parent0fc1b451471dfc3cabd6e99ef441df9804616e63 (diff)
ext4: Support large files
This patch converts ext4_inode i_blocks to represent total blocks occupied by the inode in file system block size. Earlier the variable used to represent this in 512 byte block size. This actually limited the total size of the file. The feature is enabled transparently when we write an inode whose i_blocks cannot be represnted as 512 byte units in a 48 bit variable. inode flag EXT4_HUGE_FILE_FL Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/ext4/inode.c32
-rw-r--r--fs/ext4/super.c9
2 files changed, 31 insertions, 10 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;
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 */