Skip to content

Commit

Permalink
ext4: Support large files
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Aneesh Kumar K.V authored and Theodore Ts'o committed Jan 29, 2008
1 parent 0fc1b45 commit 8180a56
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 11 deletions.
32 changes: 25 additions & 7 deletions fs/ext4/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -2671,14 +2671,20 @@ static blkcnt_t ext4_inode_blocks(struct ext4_inode *raw_inode,
struct ext4_inode_info *ei)
{
blkcnt_t i_blocks ;
struct super_block *sb = ei->vfs_inode.i_sb;
struct inode *inode = &(ei->vfs_inode);
struct super_block *sb = inode->i_sb;

if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) {
/* we are using combined 48 bit field */
i_blocks = ((u64)le16_to_cpu(raw_inode->i_blocks_high)) << 32 |
le32_to_cpu(raw_inode->i_blocks_lo);
return i_blocks;
if (ei->i_flags & EXT4_HUGE_FILE_FL) {
/* i_blocks represent file system block size */
return i_blocks << (inode->i_blkbits - 9);
} else {
return i_blocks;
}
} else {
return le32_to_cpu(raw_inode->i_blocks_lo);
}
Expand Down Expand Up @@ -2829,8 +2835,9 @@ static int ext4_inode_blocks_set(handle_t *handle,
* i_blocks can be represnted in a 32 bit variable
* as multiple of 512 bytes
*/
raw_inode->i_blocks_lo = cpu_to_le32((u32)i_blocks);
raw_inode->i_blocks_lo = cpu_to_le32(i_blocks);
raw_inode->i_blocks_high = 0;
ei->i_flags &= ~EXT4_HUGE_FILE_FL;
} else if (i_blocks <= 0xffffffffffffULL) {
/*
* i_blocks can be represented in a 48 bit variable
Expand All @@ -2841,12 +2848,23 @@ static int ext4_inode_blocks_set(handle_t *handle,
if (err)
goto err_out;
/* i_block is stored in the split 48 bit fields */
raw_inode->i_blocks_lo = cpu_to_le32((u32)i_blocks);
raw_inode->i_blocks_lo = cpu_to_le32(i_blocks);
raw_inode->i_blocks_high = cpu_to_le16(i_blocks >> 32);
ei->i_flags &= ~EXT4_HUGE_FILE_FL;
} else {
ext4_error(sb, __FUNCTION__,
"Wrong inode i_blocks count %llu\n",
(unsigned long long)inode->i_blocks);
/*
* i_blocks should be represented in a 48 bit variable
* as multiple of file system block size
*/
err = ext4_update_rocompat_feature(handle, sb,
EXT4_FEATURE_RO_COMPAT_HUGE_FILE);
if (err)
goto err_out;
ei->i_flags |= EXT4_HUGE_FILE_FL;
/* i_block is stored in file system block size */
i_blocks = i_blocks >> (inode->i_blkbits - 9);
raw_inode->i_blocks_lo = cpu_to_le32(i_blocks);
raw_inode->i_blocks_high = cpu_to_le16(i_blocks >> 32);
}
err_out:
return err;
Expand Down
9 changes: 6 additions & 3 deletions fs/ext4/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -1631,11 +1631,14 @@ static loff_t ext4_max_size(int bits)
upper_limit >>= (bits - 9);

} else {
/* We use 48 bit ext4_inode i_blocks */
/*
* We use 48 bit ext4_inode i_blocks
* With EXT4_HUGE_FILE_FL set the i_blocks
* represent total number of blocks in
* file system block size
*/
upper_limit = (1LL << 48) - 1;

/* total blocks in file system block size */
upper_limit >>= (bits - 9);
}

/* indirect blocks */
Expand Down
3 changes: 2 additions & 1 deletion include/linux/ext4_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,9 @@ struct ext4_group_desc
#define EXT4_NOTAIL_FL 0x00008000 /* file tail should not be merged */
#define EXT4_DIRSYNC_FL 0x00010000 /* dirsync behaviour (directories only) */
#define EXT4_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/
#define EXT4_RESERVED_FL 0x80000000 /* reserved for ext4 lib */
#define EXT4_HUGE_FILE_FL 0x00040000 /* Set to each huge file */
#define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */
#define EXT4_RESERVED_FL 0x80000000 /* reserved for ext4 lib */

#define EXT4_FL_USER_VISIBLE 0x000BDFFF /* User visible flags */
#define EXT4_FL_USER_MODIFIABLE 0x000380FF /* User modifiable flags */
Expand Down

0 comments on commit 8180a56

Please sign in to comment.