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>
This commit is contained in:
committed by
Theodore Ts'o
parent
a48380f769
commit
0fc1b45147
@@ -1603,17 +1603,50 @@ static void ext4_orphan_cleanup (struct super_block * sb,
|
||||
|
||||
/*
|
||||
* Maximal file size. There is a direct, and {,double-,triple-}indirect
|
||||
* block limit, and also a limit of (2^32 - 1) 512-byte sectors in i_blocks.
|
||||
* We need to be 1 filesystem block less than the 2^32 sector limit.
|
||||
* block limit, and also a limit of (2^48 - 1) 512-byte sectors in i_blocks.
|
||||
* We need to be 1 filesystem block less than the 2^48 sector limit.
|
||||
*/
|
||||
static loff_t ext4_max_size(int bits)
|
||||
{
|
||||
loff_t res = EXT4_NDIR_BLOCKS;
|
||||
/* This constant is calculated to be the largest file size for a
|
||||
* dense, 4k-blocksize file such that the total number of
|
||||
int meta_blocks;
|
||||
loff_t upper_limit;
|
||||
/* This is calculated to be the largest file size for a
|
||||
* dense, file such that the total number of
|
||||
* sectors in the file, including data and all indirect blocks,
|
||||
* does not exceed 2^32. */
|
||||
const loff_t upper_limit = 0x1ff7fffd000LL;
|
||||
* does not exceed 2^48 -1
|
||||
* __u32 i_blocks_lo and _u16 i_blocks_high representing the
|
||||
* total number of 512 bytes blocks of the file
|
||||
*/
|
||||
|
||||
if (sizeof(blkcnt_t) < sizeof(u64)) {
|
||||
/*
|
||||
* CONFIG_LSF is not enabled implies the inode
|
||||
* i_block represent total blocks in 512 bytes
|
||||
* 32 == size of vfs inode i_blocks * 8
|
||||
*/
|
||||
upper_limit = (1LL << 32) - 1;
|
||||
|
||||
/* total blocks in file system block size */
|
||||
upper_limit >>= (bits - 9);
|
||||
|
||||
} else {
|
||||
/* We use 48 bit ext4_inode i_blocks */
|
||||
upper_limit = (1LL << 48) - 1;
|
||||
|
||||
/* total blocks in file system block size */
|
||||
upper_limit >>= (bits - 9);
|
||||
}
|
||||
|
||||
/* indirect blocks */
|
||||
meta_blocks = 1;
|
||||
/* double indirect blocks */
|
||||
meta_blocks += 1 + (1LL << (bits-2));
|
||||
/* tripple indirect blocks */
|
||||
meta_blocks += 1 + (1LL << (bits-2)) + (1LL << (2*(bits-2)));
|
||||
|
||||
upper_limit -= meta_blocks;
|
||||
upper_limit <<= bits;
|
||||
|
||||
res += 1LL << (bits-2);
|
||||
res += 1LL << (2*(bits-2));
|
||||
@@ -1621,6 +1654,10 @@ static loff_t ext4_max_size(int bits)
|
||||
res <<= bits;
|
||||
if (res > upper_limit)
|
||||
res = upper_limit;
|
||||
|
||||
if (res > MAX_LFS_FILESIZE)
|
||||
res = MAX_LFS_FILESIZE;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1789,6 +1826,19 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
|
||||
sb->s_id, le32_to_cpu(features));
|
||||
goto failed_mount;
|
||||
}
|
||||
if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) {
|
||||
/*
|
||||
* Large file size enabled file system can only be
|
||||
* mount if kernel is build with CONFIG_LSF
|
||||
*/
|
||||
if (sizeof(root->i_blocks) < sizeof(u64) &&
|
||||
!(sb->s_flags & MS_RDONLY)) {
|
||||
printk(KERN_ERR "EXT4-fs: %s: Filesystem with huge "
|
||||
"files cannot be mounted read-write "
|
||||
"without CONFIG_LSF.\n", sb->s_id);
|
||||
goto failed_mount;
|
||||
}
|
||||
}
|
||||
blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size);
|
||||
|
||||
if (blocksize < EXT4_MIN_BLOCK_SIZE ||
|
||||
|
Reference in New Issue
Block a user