aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/ext4_fs_extents.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/ext4_fs_extents.h')
-rw-r--r--include/linux/ext4_fs_extents.h31
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
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 *);