aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmit Arora <aarora@in.ibm.com>2007-07-18 09:02:56 -0400
committerTheodore Ts'o <tytso@mit.edu>2007-07-18 09:02:56 -0400
commit749269facaf87f6e516c3af12763e03181b9c139 (patch)
tree5c8a2091d4b1ce7636de404a1366bd174b4634fd
parent56055d3ae4cc7fa6d2b10885f20269de8a989ed7 (diff)
Change on-disk format to support 2^15 uninitialized extents
This change was suggested by Andreas Dilger. This patch changes the EXT_MAX_LEN value and extent code which marks/checks uninitialized extents. With this change it will be possible to have initialized extents with 2^15 blocks (earlier the max blocks we could have was 2^15 - 1). This way we can have better extent-to-block alignment. Now, maximum number of blocks we can have in an initialized extent is 2^15 and in an uninitialized extent is 2^15 - 1. Signed-off-by: Amit Arora <aarora@in.ibm.com>
-rw-r--r--fs/ext4/extents.c28
-rw-r--r--include/linux/ext4_fs_extents.h31
2 files changed, 52 insertions, 7 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index ded3d469f978..77146b826a13 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -1107,7 +1107,7 @@ static int
1107ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1, 1107ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1,
1108 struct ext4_extent *ex2) 1108 struct ext4_extent *ex2)
1109{ 1109{
1110 unsigned short ext1_ee_len, ext2_ee_len; 1110 unsigned short ext1_ee_len, ext2_ee_len, max_len;
1111 1111
1112 /* 1112 /*
1113 * Make sure that either both extents are uninitialized, or 1113 * Make sure that either both extents are uninitialized, or
@@ -1116,6 +1116,11 @@ ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1,
1116 if (ext4_ext_is_uninitialized(ex1) ^ ext4_ext_is_uninitialized(ex2)) 1116 if (ext4_ext_is_uninitialized(ex1) ^ ext4_ext_is_uninitialized(ex2))
1117 return 0; 1117 return 0;
1118 1118
1119 if (ext4_ext_is_uninitialized(ex1))
1120 max_len = EXT_UNINIT_MAX_LEN;
1121 else
1122 max_len = EXT_INIT_MAX_LEN;
1123
1119 ext1_ee_len = ext4_ext_get_actual_len(ex1); 1124 ext1_ee_len = ext4_ext_get_actual_len(ex1);
1120 ext2_ee_len = ext4_ext_get_actual_len(ex2); 1125 ext2_ee_len = ext4_ext_get_actual_len(ex2);
1121 1126
@@ -1128,7 +1133,7 @@ ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1,
1128 * as an RO_COMPAT feature, refuse to merge to extents if 1133 * as an RO_COMPAT feature, refuse to merge to extents if
1129 * this can result in the top bit of ee_len being set. 1134 * this can result in the top bit of ee_len being set.
1130 */ 1135 */
1131 if (ext1_ee_len + ext2_ee_len > EXT_MAX_LEN) 1136 if (ext1_ee_len + ext2_ee_len > max_len)
1132 return 0; 1137 return 0;
1133#ifdef AGGRESSIVE_TEST 1138#ifdef AGGRESSIVE_TEST
1134 if (le16_to_cpu(ex1->ee_len) >= 4) 1139 if (le16_to_cpu(ex1->ee_len) >= 4)
@@ -1815,7 +1820,11 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
1815 1820
1816 ex->ee_block = cpu_to_le32(block); 1821 ex->ee_block = cpu_to_le32(block);
1817 ex->ee_len = cpu_to_le16(num); 1822 ex->ee_len = cpu_to_le16(num);
1818 if (uninitialized) 1823 /*
1824 * Do not mark uninitialized if all the blocks in the
1825 * extent have been removed.
1826 */
1827 if (uninitialized && num)
1819 ext4_ext_mark_uninitialized(ex); 1828 ext4_ext_mark_uninitialized(ex);
1820 1829
1821 err = ext4_ext_dirty(handle, inode, path + depth); 1830 err = ext4_ext_dirty(handle, inode, path + depth);
@@ -2308,6 +2317,19 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
2308 /* allocate new block */ 2317 /* allocate new block */
2309 goal = ext4_ext_find_goal(inode, path, iblock); 2318 goal = ext4_ext_find_goal(inode, path, iblock);
2310 2319
2320 /*
2321 * See if request is beyond maximum number of blocks we can have in
2322 * a single extent. For an initialized extent this limit is
2323 * EXT_INIT_MAX_LEN and for an uninitialized extent this limit is
2324 * EXT_UNINIT_MAX_LEN.
2325 */
2326 if (max_blocks > EXT_INIT_MAX_LEN &&
2327 create != EXT4_CREATE_UNINITIALIZED_EXT)
2328 max_blocks = EXT_INIT_MAX_LEN;
2329 else if (max_blocks > EXT_UNINIT_MAX_LEN &&
2330 create == EXT4_CREATE_UNINITIALIZED_EXT)
2331 max_blocks = EXT_UNINIT_MAX_LEN;
2332
2311 /* Check if we can really insert (iblock)::(iblock+max_blocks) extent */ 2333 /* Check if we can really insert (iblock)::(iblock+max_blocks) extent */
2312 newex.ee_block = cpu_to_le32(iblock); 2334 newex.ee_block = cpu_to_le32(iblock);
2313 newex.ee_len = cpu_to_le16(max_blocks); 2335 newex.ee_len = cpu_to_le16(max_blocks);
diff --git a/include/linux/ext4_fs_extents.h b/include/linux/ext4_fs_extents.h
index edf49ec89eac..81406f3655d4 100644
--- a/include/linux/ext4_fs_extents.h
+++ b/include/linux/ext4_fs_extents.h
@@ -141,7 +141,25 @@ typedef int (*ext_prepare_callback)(struct inode *, struct ext4_ext_path *,
141 141
142#define EXT_MAX_BLOCK 0xffffffff 142#define EXT_MAX_BLOCK 0xffffffff
143 143
144#define EXT_MAX_LEN ((1UL << 15) - 1) 144/*
145 * EXT_INIT_MAX_LEN is the maximum number of blocks we can have in an
146 * initialized extent. This is 2^15 and not (2^16 - 1), since we use the
147 * MSB of ee_len field in the extent datastructure to signify if this
148 * particular extent is an initialized extent or an uninitialized (i.e.
149 * preallocated).
150 * EXT_UNINIT_MAX_LEN is the maximum number of blocks we can have in an
151 * uninitialized extent.
152 * If ee_len is <= 0x8000, it is an initialized extent. Otherwise, it is an
153 * uninitialized one. In other words, if MSB of ee_len is set, it is an
154 * uninitialized extent with only one special scenario when ee_len = 0x8000.
155 * In this case we can not have an uninitialized extent of zero length and
156 * thus we make it as a special case of initialized extent with 0x8000 length.
157 * This way we get better extent-to-group alignment for initialized extents.
158 * Hence, the maximum number of blocks we can have in an *initialized*
159 * extent is 2^15 (32768) and in an *uninitialized* extent is 2^15-1 (32767).
160 */
161#define EXT_INIT_MAX_LEN (1UL << 15)
162#define EXT_UNINIT_MAX_LEN (EXT_INIT_MAX_LEN - 1)
145 163
146 164
147#define EXT_FIRST_EXTENT(__hdr__) \ 165#define EXT_FIRST_EXTENT(__hdr__) \
@@ -190,17 +208,22 @@ ext4_ext_invalidate_cache(struct inode *inode)
190 208
191static inline void ext4_ext_mark_uninitialized(struct ext4_extent *ext) 209static inline void ext4_ext_mark_uninitialized(struct ext4_extent *ext)
192{ 210{
193 ext->ee_len |= cpu_to_le16(0x8000); 211 /* We can not have an uninitialized extent of zero length! */
212 BUG_ON((le16_to_cpu(ext->ee_len) & ~EXT_INIT_MAX_LEN) == 0);
213 ext->ee_len |= cpu_to_le16(EXT_INIT_MAX_LEN);
194} 214}
195 215
196static inline int ext4_ext_is_uninitialized(struct ext4_extent *ext) 216static inline int ext4_ext_is_uninitialized(struct ext4_extent *ext)
197{ 217{
198 return (int)(le16_to_cpu((ext)->ee_len) & 0x8000); 218 /* Extent with ee_len of 0x8000 is treated as an initialized extent */
219 return (le16_to_cpu(ext->ee_len) > EXT_INIT_MAX_LEN);
199} 220}
200 221
201static inline int ext4_ext_get_actual_len(struct ext4_extent *ext) 222static inline int ext4_ext_get_actual_len(struct ext4_extent *ext)
202{ 223{
203 return (int)(le16_to_cpu((ext)->ee_len) & 0x7FFF); 224 return (le16_to_cpu(ext->ee_len) <= EXT_INIT_MAX_LEN ?
225 le16_to_cpu(ext->ee_len) :
226 (le16_to_cpu(ext->ee_len) - EXT_INIT_MAX_LEN));
204} 227}
205 228
206extern int ext4_extent_tree_init(handle_t *, struct inode *); 229extern int ext4_extent_tree_init(handle_t *, struct inode *);