More patch description fixups. Standardize case.
[ext4-patch-queue.git] / 48-bit-i_blocks.patch
blobf79107b7ec41d17cbc151f7a6519659ef3925226
1 ext4: Add support for 48 bit inode i_blocks.
3 From: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
5 Use the __le16 l_i_reserved1 field of the linux2 struct of ext4_inode
6 to represet the higher 16 bits for i_blocks. With this change max_file
7 size becomes (2**48 -1 )* 512 bytes.
9 We add a RO_COMPAT feature to the super block to indicate that inode
10 have i_blocks represented as a split 48 bits. Super block with this
11 feature set cannot be mounted read write on a kernel with CONFIG_LSF
12 disabled.
14 Super block flag EXT4_FEATURE_RO_COMPAT_HUGE_FILE
16 Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
17 ---
19 fs/ext4/inode.c | 58 ++++++++++++++++++++++++++++++++++++++++++--
20 fs/ext4/super.c | 62 ++++++++++++++++++++++++++++++++++++++++++-----
21 include/linux/ext4_fs.h | 10 +++++---
22 3 files changed, 119 insertions(+), 11 deletions(-)
25 diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
26 index e663455..bb89fe7 100644
27 --- a/fs/ext4/inode.c
28 +++ b/fs/ext4/inode.c
29 @@ -2667,6 +2667,22 @@ void ext4_get_inode_flags(struct ext4_inode_info *ei)
30 if (flags & S_DIRSYNC)
31 ei->i_flags |= EXT4_DIRSYNC_FL;
33 +static blkcnt_t ext4_inode_blocks(struct ext4_inode *raw_inode,
34 + struct ext4_inode_info *ei)
36 + blkcnt_t i_blocks ;
37 + struct super_block *sb = ei->vfs_inode.i_sb;
39 + if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
40 + EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) {
41 + /* we are using combined 48 bit field */
42 + i_blocks = ((u64)le16_to_cpu(raw_inode->i_blocks_high)) << 32 |
43 + le32_to_cpu(raw_inode->i_blocks_lo);
44 + return i_blocks;
45 + } else {
46 + return le32_to_cpu(raw_inode->i_blocks_lo);
47 + }
50 void ext4_read_inode(struct inode * inode)
52 @@ -2715,8 +2731,8 @@ void ext4_read_inode(struct inode * inode)
53 * recovery code: that's fine, we're about to complete
54 * the process of deleting those. */
56 - inode->i_blocks = le32_to_cpu(raw_inode->i_blocks);
57 ei->i_flags = le32_to_cpu(raw_inode->i_flags);
58 + inode->i_blocks = ext4_inode_blocks(raw_inode, ei);
59 ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl_lo);
60 if (EXT4_SB(inode->i_sb)->s_es->s_creator_os !=
61 cpu_to_le32(EXT4_OS_HURD)) {
62 @@ -2799,6 +2815,43 @@ bad_inode:
63 return;
66 +static int ext4_inode_blocks_set(handle_t *handle,
67 + struct ext4_inode *raw_inode,
68 + struct ext4_inode_info *ei)
70 + struct inode *inode = &(ei->vfs_inode);
71 + u64 i_blocks = inode->i_blocks;
72 + struct super_block *sb = inode->i_sb;
73 + int err = 0;
75 + if (i_blocks <= ~0U) {
76 + /*
77 + * i_blocks can be represnted in a 32 bit variable
78 + * as multiple of 512 bytes
79 + */
80 + raw_inode->i_blocks_lo = cpu_to_le32((u32)i_blocks);
81 + raw_inode->i_blocks_high = 0;
82 + } else if (i_blocks <= 0xffffffffffffULL) {
83 + /*
84 + * i_blocks can be represented in a 48 bit variable
85 + * as multiple of 512 bytes
86 + */
87 + err = ext4_update_rocompat_feature(handle, sb,
88 + EXT4_FEATURE_RO_COMPAT_HUGE_FILE);
89 + if (err)
90 + goto err_out;
91 + /* i_block is stored in the split 48 bit fields */
92 + raw_inode->i_blocks_lo = cpu_to_le32((u32)i_blocks);
93 + raw_inode->i_blocks_high = cpu_to_le16(i_blocks >> 32);
94 + } else {
95 + ext4_error(sb, __FUNCTION__,
96 + "Wrong inode i_blocks count %llu\n",
97 + (unsigned long long)inode->i_blocks);
98 + }
99 +err_out:
100 + return err;
104 * Post the struct inode info into an on-disk inode location in the
105 * buffer-cache. This gobbles the caller's reference to the
106 @@ -2853,7 +2906,8 @@ static int ext4_do_update_inode(handle_t *handle,
107 EXT4_INODE_SET_XTIME(i_atime, inode, raw_inode);
108 EXT4_EINODE_SET_XTIME(i_crtime, ei, raw_inode);
110 - raw_inode->i_blocks = cpu_to_le32(inode->i_blocks);
111 + if (ext4_inode_blocks_set(handle, raw_inode, ei))
112 + goto out_brelse;
113 raw_inode->i_dtime = cpu_to_le32(ei->i_dtime);
114 raw_inode->i_flags = cpu_to_le32(ei->i_flags);
115 if (EXT4_SB(inode->i_sb)->s_es->s_creator_os !=
116 diff --git a/fs/ext4/super.c b/fs/ext4/super.c
117 index 7be27db..2b9dc96 100644
118 --- a/fs/ext4/super.c
119 +++ b/fs/ext4/super.c
120 @@ -1603,17 +1603,50 @@ static void ext4_orphan_cleanup (struct super_block * sb,
123 * Maximal file size. There is a direct, and {,double-,triple-}indirect
124 - * block limit, and also a limit of (2^32 - 1) 512-byte sectors in i_blocks.
125 - * We need to be 1 filesystem block less than the 2^32 sector limit.
126 + * block limit, and also a limit of (2^48 - 1) 512-byte sectors in i_blocks.
127 + * We need to be 1 filesystem block less than the 2^48 sector limit.
129 static loff_t ext4_max_size(int bits)
131 loff_t res = EXT4_NDIR_BLOCKS;
132 - /* This constant is calculated to be the largest file size for a
133 - * dense, 4k-blocksize file such that the total number of
134 + int meta_blocks;
135 + loff_t upper_limit;
136 + /* This is calculated to be the largest file size for a
137 + * dense, file such that the total number of
138 * sectors in the file, including data and all indirect blocks,
139 - * does not exceed 2^32. */
140 - const loff_t upper_limit = 0x1ff7fffd000LL;
141 + * does not exceed 2^48 -1
142 + * __u32 i_blocks_lo and _u16 i_blocks_high representing the
143 + * total number of 512 bytes blocks of the file
144 + */
146 + if (sizeof(blkcnt_t) < sizeof(u64)) {
147 + /*
148 + * CONFIG_LSF is not enabled implies the inode
149 + * i_block represent total blocks in 512 bytes
150 + * 32 == size of vfs inode i_blocks * 8
151 + */
152 + upper_limit = (1LL << 32) - 1;
154 + /* total blocks in file system block size */
155 + upper_limit >>= (bits - 9);
157 + } else {
158 + /* We use 48 bit ext4_inode i_blocks */
159 + upper_limit = (1LL << 48) - 1;
161 + /* total blocks in file system block size */
162 + upper_limit >>= (bits - 9);
165 + /* indirect blocks */
166 + meta_blocks = 1;
167 + /* double indirect blocks */
168 + meta_blocks += 1 + (1LL << (bits-2));
169 + /* tripple indirect blocks */
170 + meta_blocks += 1 + (1LL << (bits-2)) + (1LL << (2*(bits-2)));
172 + upper_limit -= meta_blocks;
173 + upper_limit <<= bits;
175 res += 1LL << (bits-2);
176 res += 1LL << (2*(bits-2));
177 @@ -1621,6 +1654,10 @@ static loff_t ext4_max_size(int bits)
178 res <<= bits;
179 if (res > upper_limit)
180 res = upper_limit;
182 + if (res > MAX_LFS_FILESIZE)
183 + res = MAX_LFS_FILESIZE;
185 return res;
188 @@ -1789,6 +1826,19 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
189 sb->s_id, le32_to_cpu(features));
190 goto failed_mount;
192 + if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) {
193 + /*
194 + * Large file size enabled file system can only be
195 + * mount if kernel is build with CONFIG_LSF
196 + */
197 + if (sizeof(root->i_blocks) < sizeof(u64) &&
198 + !(sb->s_flags & MS_RDONLY)) {
199 + printk(KERN_ERR "EXT4-fs: %s: Filesystem with huge "
200 + "files cannot be mounted read-write "
201 + "without CONFIG_LSF.\n", sb->s_id);
202 + goto failed_mount;
205 blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size);
207 if (blocksize < EXT4_MIN_BLOCK_SIZE ||
208 diff --git a/include/linux/ext4_fs.h b/include/linux/ext4_fs.h
209 index a8f3fae..be25eca 100644
210 --- a/include/linux/ext4_fs.h
211 +++ b/include/linux/ext4_fs.h
212 @@ -282,7 +282,7 @@ struct ext4_inode {
213 __le32 i_dtime; /* Deletion Time */
214 __le16 i_gid; /* Low 16 bits of Group Id */
215 __le16 i_links_count; /* Links count */
216 - __le32 i_blocks; /* Blocks count */
217 + __le32 i_blocks_lo; /* Blocks count */
218 __le32 i_flags; /* File flags */
219 union {
220 struct {
221 @@ -302,7 +302,7 @@ struct ext4_inode {
222 __le32 i_obso_faddr; /* Obsoleted fragment address */
223 union {
224 struct {
225 - __le16 l_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */
226 + __le16 l_i_blocks_high; /* were l_i_reserved1 */
227 __le16 l_i_file_acl_high;
228 __le16 l_i_uid_high; /* these 2 fields */
229 __le16 l_i_gid_high; /* were reserved2[0] */
230 @@ -404,6 +404,7 @@ do { \
231 #if defined(__KERNEL__) || defined(__linux__)
232 #define i_reserved1 osd1.linux1.l_i_reserved1
233 #define i_file_acl_high osd2.linux2.l_i_file_acl_high
234 +#define i_blocks_high osd2.linux2.l_i_blocks_high
235 #define i_uid_low i_uid
236 #define i_gid_low i_gid
237 #define i_uid_high osd2.linux2.l_i_uid_high
238 @@ -670,6 +671,7 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
239 #define EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
240 #define EXT4_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
241 #define EXT4_FEATURE_RO_COMPAT_BTREE_DIR 0x0004
242 +#define EXT4_FEATURE_RO_COMPAT_HUGE_FILE 0x0008
243 #define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010
244 #define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020
245 #define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040
246 @@ -681,6 +683,7 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
247 #define EXT4_FEATURE_INCOMPAT_META_BG 0x0010
248 #define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */
249 #define EXT4_FEATURE_INCOMPAT_64BIT 0x0080
250 +#define EXT4_FEATURE_INCOMPAT_MMP 0x0100
251 #define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200
253 #define EXT4_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
254 @@ -695,7 +698,8 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
255 EXT4_FEATURE_RO_COMPAT_GDT_CSUM| \
256 EXT4_FEATURE_RO_COMPAT_DIR_NLINK | \
257 EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE | \
258 - EXT4_FEATURE_RO_COMPAT_BTREE_DIR)
259 + EXT4_FEATURE_RO_COMPAT_BTREE_DIR |\
260 + EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
263 * Default values for user and/or group using reserved blocks