diff options
Diffstat (limited to 'fs/ext4/super.c')
-rw-r--r-- | fs/ext4/super.c | 62 |
1 files changed, 56 insertions, 6 deletions
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 || |