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 | |
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')
-rw-r--r-- | fs/ext4/inode.c | 58 | ||||
-rw-r--r-- | fs/ext4/super.c | 62 |
2 files changed, 112 insertions, 8 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 != |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 7be27dbe76bf..2b9dc96ec43e 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -1603,17 +1603,50 @@ static void ext4_orphan_cleanup (struct super_block * sb, | |||
1603 | 1603 | ||
1604 | /* | 1604 | /* |
1605 | * Maximal file size. There is a direct, and {,double-,triple-}indirect | 1605 | * Maximal file size. There is a direct, and {,double-,triple-}indirect |
1606 | * block limit, and also a limit of (2^32 - 1) 512-byte sectors in i_blocks. | 1606 | * block limit, and also a limit of (2^48 - 1) 512-byte sectors in i_blocks. |
1607 | * We need to be 1 filesystem block less than the 2^32 sector limit. | 1607 | * We need to be 1 filesystem block less than the 2^48 sector limit. |
1608 | */ | 1608 | */ |
1609 | static loff_t ext4_max_size(int bits) | 1609 | static loff_t ext4_max_size(int bits) |
1610 | { | 1610 | { |
1611 | loff_t res = EXT4_NDIR_BLOCKS; | 1611 | loff_t res = EXT4_NDIR_BLOCKS; |
1612 | /* This constant is calculated to be the largest file size for a | 1612 | int meta_blocks; |
1613 | * dense, 4k-blocksize file such that the total number of | 1613 | loff_t upper_limit; |
1614 | /* This is calculated to be the largest file size for a | ||
1615 | * dense, file such that the total number of | ||
1614 | * sectors in the file, including data and all indirect blocks, | 1616 | * sectors in the file, including data and all indirect blocks, |
1615 | * does not exceed 2^32. */ | 1617 | * does not exceed 2^48 -1 |
1616 | const loff_t upper_limit = 0x1ff7fffd000LL; | 1618 | * __u32 i_blocks_lo and _u16 i_blocks_high representing the |
1619 | * total number of 512 bytes blocks of the file | ||
1620 | */ | ||
1621 | |||
1622 | if (sizeof(blkcnt_t) < sizeof(u64)) { | ||
1623 | /* | ||
1624 | * CONFIG_LSF is not enabled implies the inode | ||
1625 | * i_block represent total blocks in 512 bytes | ||
1626 | * 32 == size of vfs inode i_blocks * 8 | ||
1627 | */ | ||
1628 | upper_limit = (1LL << 32) - 1; | ||
1629 | |||
1630 | /* total blocks in file system block size */ | ||
1631 | upper_limit >>= (bits - 9); | ||
1632 | |||
1633 | } else { | ||
1634 | /* We use 48 bit ext4_inode i_blocks */ | ||
1635 | upper_limit = (1LL << 48) - 1; | ||
1636 | |||
1637 | /* total blocks in file system block size */ | ||
1638 | upper_limit >>= (bits - 9); | ||
1639 | } | ||
1640 | |||
1641 | /* indirect blocks */ | ||
1642 | meta_blocks = 1; | ||
1643 | /* double indirect blocks */ | ||
1644 | meta_blocks += 1 + (1LL << (bits-2)); | ||
1645 | /* tripple indirect blocks */ | ||
1646 | meta_blocks += 1 + (1LL << (bits-2)) + (1LL << (2*(bits-2))); | ||
1647 | |||
1648 | upper_limit -= meta_blocks; | ||
1649 | upper_limit <<= bits; | ||
1617 | 1650 | ||
1618 | res += 1LL << (bits-2); | 1651 | res += 1LL << (bits-2); |
1619 | res += 1LL << (2*(bits-2)); | 1652 | res += 1LL << (2*(bits-2)); |
@@ -1621,6 +1654,10 @@ static loff_t ext4_max_size(int bits) | |||
1621 | res <<= bits; | 1654 | res <<= bits; |
1622 | if (res > upper_limit) | 1655 | if (res > upper_limit) |
1623 | res = upper_limit; | 1656 | res = upper_limit; |
1657 | |||
1658 | if (res > MAX_LFS_FILESIZE) | ||
1659 | res = MAX_LFS_FILESIZE; | ||
1660 | |||
1624 | return res; | 1661 | return res; |
1625 | } | 1662 | } |
1626 | 1663 | ||
@@ -1789,6 +1826,19 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent) | |||
1789 | sb->s_id, le32_to_cpu(features)); | 1826 | sb->s_id, le32_to_cpu(features)); |
1790 | goto failed_mount; | 1827 | goto failed_mount; |
1791 | } | 1828 | } |
1829 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) { | ||
1830 | /* | ||
1831 | * Large file size enabled file system can only be | ||
1832 | * mount if kernel is build with CONFIG_LSF | ||
1833 | */ | ||
1834 | if (sizeof(root->i_blocks) < sizeof(u64) && | ||
1835 | !(sb->s_flags & MS_RDONLY)) { | ||
1836 | printk(KERN_ERR "EXT4-fs: %s: Filesystem with huge " | ||
1837 | "files cannot be mounted read-write " | ||
1838 | "without CONFIG_LSF.\n", sb->s_id); | ||
1839 | goto failed_mount; | ||
1840 | } | ||
1841 | } | ||
1792 | blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size); | 1842 | blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size); |
1793 | 1843 | ||
1794 | if (blocksize < EXT4_MIN_BLOCK_SIZE || | 1844 | if (blocksize < EXT4_MIN_BLOCK_SIZE || |