diff options
author | Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | 2008-01-28 23:58:26 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2008-01-28 23:58:26 -0500 |
commit | 0fc1b451471dfc3cabd6e99ef441df9804616e63 (patch) | |
tree | b018b6ddc5bb5f02b985b06c11f0c01adb38167a /fs/ext4/inode.c | |
parent | a48380f769dfed6163fb82a68b13bd562ea1e027 (diff) |
ext4: Add support for 48 bit inode i_blocks.
Use the __le16 l_i_reserved1 field of the linux2 struct of ext4_inode
to represet the higher 16 bits for i_blocks. With this change max_file
size becomes (2**48 -1 )* 512 bytes.
We add a RO_COMPAT feature to the super block to indicate that inode
have i_blocks represented as a split 48 bits. Super block with this
feature set cannot be mounted read write on a kernel with CONFIG_LSF
disabled.
Super block flag EXT4_FEATURE_RO_COMPAT_HUGE_FILE
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r-- | fs/ext4/inode.c | 58 |
1 files changed, 56 insertions, 2 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index e6634550cfc8..bb89fe727bb1 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -2667,6 +2667,22 @@ void ext4_get_inode_flags(struct ext4_inode_info *ei) | |||
2667 | if (flags & S_DIRSYNC) | 2667 | if (flags & S_DIRSYNC) |
2668 | ei->i_flags |= EXT4_DIRSYNC_FL; | 2668 | ei->i_flags |= EXT4_DIRSYNC_FL; |
2669 | } | 2669 | } |
2670 | static blkcnt_t ext4_inode_blocks(struct ext4_inode *raw_inode, | ||
2671 | struct ext4_inode_info *ei) | ||
2672 | { | ||
2673 | blkcnt_t i_blocks ; | ||
2674 | struct super_block *sb = ei->vfs_inode.i_sb; | ||
2675 | |||
2676 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, | ||
2677 | EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) { | ||
2678 | /* we are using combined 48 bit field */ | ||
2679 | i_blocks = ((u64)le16_to_cpu(raw_inode->i_blocks_high)) << 32 | | ||
2680 | le32_to_cpu(raw_inode->i_blocks_lo); | ||
2681 | return i_blocks; | ||
2682 | } else { | ||
2683 | return le32_to_cpu(raw_inode->i_blocks_lo); | ||
2684 | } | ||
2685 | } | ||
2670 | 2686 | ||
2671 | void ext4_read_inode(struct inode * inode) | 2687 | void ext4_read_inode(struct inode * inode) |
2672 | { | 2688 | { |
@@ -2715,8 +2731,8 @@ void ext4_read_inode(struct inode * inode) | |||
2715 | * recovery code: that's fine, we're about to complete | 2731 | * recovery code: that's fine, we're about to complete |
2716 | * the process of deleting those. */ | 2732 | * the process of deleting those. */ |
2717 | } | 2733 | } |
2718 | inode->i_blocks = le32_to_cpu(raw_inode->i_blocks); | ||
2719 | ei->i_flags = le32_to_cpu(raw_inode->i_flags); | 2734 | ei->i_flags = le32_to_cpu(raw_inode->i_flags); |
2735 | inode->i_blocks = ext4_inode_blocks(raw_inode, ei); | ||
2720 | ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl_lo); | 2736 | ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl_lo); |
2721 | if (EXT4_SB(inode->i_sb)->s_es->s_creator_os != | 2737 | if (EXT4_SB(inode->i_sb)->s_es->s_creator_os != |
2722 | cpu_to_le32(EXT4_OS_HURD)) { | 2738 | cpu_to_le32(EXT4_OS_HURD)) { |
@@ -2799,6 +2815,43 @@ bad_inode: | |||
2799 | return; | 2815 | return; |
2800 | } | 2816 | } |
2801 | 2817 | ||
2818 | static int ext4_inode_blocks_set(handle_t *handle, | ||
2819 | struct ext4_inode *raw_inode, | ||
2820 | struct ext4_inode_info *ei) | ||
2821 | { | ||
2822 | struct inode *inode = &(ei->vfs_inode); | ||
2823 | u64 i_blocks = inode->i_blocks; | ||
2824 | struct super_block *sb = inode->i_sb; | ||
2825 | int err = 0; | ||
2826 | |||
2827 | if (i_blocks <= ~0U) { | ||
2828 | /* | ||
2829 | * i_blocks can be represnted in a 32 bit variable | ||
2830 | * as multiple of 512 bytes | ||
2831 | */ | ||
2832 | raw_inode->i_blocks_lo = cpu_to_le32((u32)i_blocks); | ||
2833 | raw_inode->i_blocks_high = 0; | ||
2834 | } else if (i_blocks <= 0xffffffffffffULL) { | ||
2835 | /* | ||
2836 | * i_blocks can be represented in a 48 bit variable | ||
2837 | * as multiple of 512 bytes | ||
2838 | */ | ||
2839 | err = ext4_update_rocompat_feature(handle, sb, | ||
2840 | EXT4_FEATURE_RO_COMPAT_HUGE_FILE); | ||
2841 | if (err) | ||
2842 | goto err_out; | ||
2843 | /* i_block is stored in the split 48 bit fields */ | ||
2844 | raw_inode->i_blocks_lo = cpu_to_le32((u32)i_blocks); | ||
2845 | raw_inode->i_blocks_high = cpu_to_le16(i_blocks >> 32); | ||
2846 | } else { | ||
2847 | ext4_error(sb, __FUNCTION__, | ||
2848 | "Wrong inode i_blocks count %llu\n", | ||
2849 | (unsigned long long)inode->i_blocks); | ||
2850 | } | ||
2851 | err_out: | ||
2852 | return err; | ||
2853 | } | ||
2854 | |||
2802 | /* | 2855 | /* |
2803 | * Post the struct inode info into an on-disk inode location in the | 2856 | * Post the struct inode info into an on-disk inode location in the |
2804 | * buffer-cache. This gobbles the caller's reference to the | 2857 | * buffer-cache. This gobbles the caller's reference to the |
@@ -2853,7 +2906,8 @@ static int ext4_do_update_inode(handle_t *handle, | |||
2853 | EXT4_INODE_SET_XTIME(i_atime, inode, raw_inode); | 2906 | EXT4_INODE_SET_XTIME(i_atime, inode, raw_inode); |
2854 | EXT4_EINODE_SET_XTIME(i_crtime, ei, raw_inode); | 2907 | EXT4_EINODE_SET_XTIME(i_crtime, ei, raw_inode); |
2855 | 2908 | ||
2856 | raw_inode->i_blocks = cpu_to_le32(inode->i_blocks); | 2909 | if (ext4_inode_blocks_set(handle, raw_inode, ei)) |
2910 | goto out_brelse; | ||
2857 | raw_inode->i_dtime = cpu_to_le32(ei->i_dtime); | 2911 | raw_inode->i_dtime = cpu_to_le32(ei->i_dtime); |
2858 | raw_inode->i_flags = cpu_to_le32(ei->i_flags); | 2912 | raw_inode->i_flags = cpu_to_le32(ei->i_flags); |
2859 | if (EXT4_SB(inode->i_sb)->s_es->s_creator_os != | 2913 | if (EXT4_SB(inode->i_sb)->s_es->s_creator_os != |