diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/ext4_fs_extents.h | 31 |
1 files changed, 27 insertions, 4 deletions
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 | ||
191 | static inline void ext4_ext_mark_uninitialized(struct ext4_extent *ext) | 209 | static 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 | ||
196 | static inline int ext4_ext_is_uninitialized(struct ext4_extent *ext) | 216 | static 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 | ||
201 | static inline int ext4_ext_get_actual_len(struct ext4_extent *ext) | 222 | static 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 | ||
206 | extern int ext4_extent_tree_init(handle_t *, struct inode *); | 229 | extern int ext4_extent_tree_init(handle_t *, struct inode *); |