aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux
diff options
context:
space:
mode:
authorAlex Tomas <alex@clusterfs.com>2006-10-11 04:21:03 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-11 14:14:16 -0400
commita86c61812637c7dd0c57e29880cffd477b62f2e7 (patch)
tree10737307293afde2999a887cfeac32c7d7584aa7 /include/linux
parentc3fcc8137ce4296ad6ab94f88bd60cbe03d21527 (diff)
[PATCH] ext3: add extent map support
On disk extents format: /* * this is extent on-disk structure * it's used at the bottom of the tree */ struct ext3_extent { __le32 ee_block; /* first logical block extent covers */ __le16 ee_len; /* number of blocks covered by extent */ __le16 ee_start_hi; /* high 16 bits of physical block */ __le32 ee_start; /* low 32 bigs of physical block */ }; Signed-off-by: Alex Tomas <alex@clusterfs.com> Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/ext4_fs.h33
-rw-r--r--include/linux/ext4_fs_extents.h196
-rw-r--r--include/linux/ext4_fs_i.h13
-rw-r--r--include/linux/ext4_fs_sb.h10
-rw-r--r--include/linux/ext4_jbd2.h15
5 files changed, 260 insertions, 7 deletions
diff --git a/include/linux/ext4_fs.h b/include/linux/ext4_fs.h
index f582cd762caf..b61181aadcbb 100644
--- a/include/linux/ext4_fs.h
+++ b/include/linux/ext4_fs.h
@@ -178,8 +178,9 @@ struct ext4_group_desc
178#define EXT4_DIRSYNC_FL 0x00010000 /* dirsync behaviour (directories only) */ 178#define EXT4_DIRSYNC_FL 0x00010000 /* dirsync behaviour (directories only) */
179#define EXT4_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/ 179#define EXT4_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/
180#define EXT4_RESERVED_FL 0x80000000 /* reserved for ext4 lib */ 180#define EXT4_RESERVED_FL 0x80000000 /* reserved for ext4 lib */
181#define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */
181 182
182#define EXT4_FL_USER_VISIBLE 0x0003DFFF /* User visible flags */ 183#define EXT4_FL_USER_VISIBLE 0x000BDFFF /* User visible flags */
183#define EXT4_FL_USER_MODIFIABLE 0x000380FF /* User modifiable flags */ 184#define EXT4_FL_USER_MODIFIABLE 0x000380FF /* User modifiable flags */
184 185
185/* 186/*
@@ -384,6 +385,7 @@ struct ext4_inode {
384#define EXT4_MOUNT_QUOTA 0x80000 /* Some quota option set */ 385#define EXT4_MOUNT_QUOTA 0x80000 /* Some quota option set */
385#define EXT4_MOUNT_USRQUOTA 0x100000 /* "old" user quota */ 386#define EXT4_MOUNT_USRQUOTA 0x100000 /* "old" user quota */
386#define EXT4_MOUNT_GRPQUOTA 0x200000 /* "old" group quota */ 387#define EXT4_MOUNT_GRPQUOTA 0x200000 /* "old" group quota */
388#define EXT4_MOUNT_EXTENTS 0x400000 /* Extents support */
387 389
388/* Compatibility, for having both ext2_fs.h and ext4_fs.h included at once */ 390/* Compatibility, for having both ext2_fs.h and ext4_fs.h included at once */
389#ifndef _LINUX_EXT2_FS_H 391#ifndef _LINUX_EXT2_FS_H
@@ -582,11 +584,13 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
582#define EXT4_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */ 584#define EXT4_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
583#define EXT4_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */ 585#define EXT4_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
584#define EXT4_FEATURE_INCOMPAT_META_BG 0x0010 586#define EXT4_FEATURE_INCOMPAT_META_BG 0x0010
587#define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */
585 588
586#define EXT4_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR 589#define EXT4_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
587#define EXT4_FEATURE_INCOMPAT_SUPP (EXT4_FEATURE_INCOMPAT_FILETYPE| \ 590#define EXT4_FEATURE_INCOMPAT_SUPP (EXT4_FEATURE_INCOMPAT_FILETYPE| \
588 EXT4_FEATURE_INCOMPAT_RECOVER| \ 591 EXT4_FEATURE_INCOMPAT_RECOVER| \
589 EXT4_FEATURE_INCOMPAT_META_BG) 592 EXT4_FEATURE_INCOMPAT_META_BG| \
593 EXT4_FEATURE_INCOMPAT_EXTENTS)
590#define EXT4_FEATURE_RO_COMPAT_SUPP (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \ 594#define EXT4_FEATURE_RO_COMPAT_SUPP (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \
591 EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \ 595 EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \
592 EXT4_FEATURE_RO_COMPAT_BTREE_DIR) 596 EXT4_FEATURE_RO_COMPAT_BTREE_DIR)
@@ -825,6 +829,9 @@ extern int ext4_get_inode_loc(struct inode *, struct ext4_iloc *);
825extern void ext4_truncate (struct inode *); 829extern void ext4_truncate (struct inode *);
826extern void ext4_set_inode_flags(struct inode *); 830extern void ext4_set_inode_flags(struct inode *);
827extern void ext4_set_aops(struct inode *inode); 831extern void ext4_set_aops(struct inode *inode);
832extern int ext4_writepage_trans_blocks(struct inode *);
833extern int ext4_block_truncate_page(handle_t *handle, struct page *page,
834 struct address_space *mapping, loff_t from);
828 835
829/* ioctl.c */ 836/* ioctl.c */
830extern int ext4_ioctl (struct inode *, struct file *, unsigned int, 837extern int ext4_ioctl (struct inode *, struct file *, unsigned int,
@@ -879,6 +886,28 @@ extern struct inode_operations ext4_special_inode_operations;
879extern struct inode_operations ext4_symlink_inode_operations; 886extern struct inode_operations ext4_symlink_inode_operations;
880extern struct inode_operations ext4_fast_symlink_inode_operations; 887extern struct inode_operations ext4_fast_symlink_inode_operations;
881 888
889/* extents.c */
890extern int ext4_ext_tree_init(handle_t *handle, struct inode *);
891extern int ext4_ext_writepage_trans_blocks(struct inode *, int);
892extern int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
893 ext4_fsblk_t iblock,
894 unsigned long max_blocks, struct buffer_head *bh_result,
895 int create, int extend_disksize);
896extern void ext4_ext_truncate(struct inode *, struct page *);
897extern void ext4_ext_init(struct super_block *);
898extern void ext4_ext_release(struct super_block *);
899static inline int
900ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, sector_t block,
901 unsigned long max_blocks, struct buffer_head *bh,
902 int create, int extend_disksize)
903{
904 if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)
905 return ext4_ext_get_blocks(handle, inode, block, max_blocks,
906 bh, create, extend_disksize);
907 return ext4_get_blocks_handle(handle, inode, block, max_blocks, bh,
908 create, extend_disksize);
909}
910
882 911
883#endif /* __KERNEL__ */ 912#endif /* __KERNEL__ */
884 913
diff --git a/include/linux/ext4_fs_extents.h b/include/linux/ext4_fs_extents.h
new file mode 100644
index 000000000000..8029879e29e2
--- /dev/null
+++ b/include/linux/ext4_fs_extents.h
@@ -0,0 +1,196 @@
1/*
2 * Copyright (c) 2003-2006, Cluster File Systems, Inc, info@clusterfs.com
3 * Written by Alex Tomas <alex@clusterfs.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public Licens
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-
17 */
18
19#ifndef _LINUX_EXT4_EXTENTS
20#define _LINUX_EXT4_EXTENTS
21
22#include <linux/ext4_fs.h>
23
24/*
25 * with AGRESSIVE_TEST defined capacity of index/leaf blocks
26 * become very little, so index split, in-depth growing and
27 * other hard changes happens much more often
28 * this is for debug purposes only
29 */
30#define AGRESSIVE_TEST_
31
32/*
33 * with EXTENTS_STATS defined number of blocks and extents
34 * are collected in truncate path. they'll be showed at
35 * umount time
36 */
37#define EXTENTS_STATS__
38
39/*
40 * if CHECK_BINSEARCH defined, then results of binary search
41 * will be checked by linear search
42 */
43#define CHECK_BINSEARCH__
44
45/*
46 * if EXT_DEBUG is defined you can use 'extdebug' mount option
47 * to get lots of info what's going on
48 */
49#define EXT_DEBUG__
50#ifdef EXT_DEBUG
51#define ext_debug(a...) printk(a)
52#else
53#define ext_debug(a...)
54#endif
55
56/*
57 * if EXT_STATS is defined then stats numbers are collected
58 * these number will be displayed at umount time
59 */
60#define EXT_STATS_
61
62
63/*
64 * ext4_inode has i_block array (60 bytes total)
65 * first 12 bytes store ext4_extent_header
66 * the remain stores array of ext4_extent
67 */
68
69/*
70 * this is extent on-disk structure
71 * it's used at the bottom of the tree
72 */
73struct ext4_extent {
74 __le32 ee_block; /* first logical block extent covers */
75 __le16 ee_len; /* number of blocks covered by extent */
76 __le16 ee_start_hi; /* high 16 bits of physical block */
77 __le32 ee_start; /* low 32 bigs of physical block */
78};
79
80/*
81 * this is index on-disk structure
82 * it's used at all the levels, but the bottom
83 */
84struct ext4_extent_idx {
85 __le32 ei_block; /* index covers logical blocks from 'block' */
86 __le32 ei_leaf; /* pointer to the physical block of the next *
87 * level. leaf or next index could bet here */
88 __le16 ei_leaf_hi; /* high 16 bits of physical block */
89 __u16 ei_unused;
90};
91
92/*
93 * each block (leaves and indexes), even inode-stored has header
94 */
95struct ext4_extent_header {
96 __le16 eh_magic; /* probably will support different formats */
97 __le16 eh_entries; /* number of valid entries */
98 __le16 eh_max; /* capacity of store in entries */
99 __le16 eh_depth; /* has tree real underlaying blocks? */
100 __le32 eh_generation; /* generation of the tree */
101};
102
103#define EXT4_EXT_MAGIC cpu_to_le16(0xf30a)
104
105/*
106 * array of ext4_ext_path contains path to some extent
107 * creation/lookup routines use it for traversal/splitting/etc
108 * truncate uses it to simulate recursive walking
109 */
110struct ext4_ext_path {
111 __u32 p_block;
112 __u16 p_depth;
113 struct ext4_extent *p_ext;
114 struct ext4_extent_idx *p_idx;
115 struct ext4_extent_header *p_hdr;
116 struct buffer_head *p_bh;
117};
118
119/*
120 * structure for external API
121 */
122
123#define EXT4_EXT_CACHE_NO 0
124#define EXT4_EXT_CACHE_GAP 1
125#define EXT4_EXT_CACHE_EXTENT 2
126
127/*
128 * to be called by ext4_ext_walk_space()
129 * negative retcode - error
130 * positive retcode - signal for ext4_ext_walk_space(), see below
131 * callback must return valid extent (passed or newly created)
132 */
133typedef int (*ext_prepare_callback)(struct inode *, struct ext4_ext_path *,
134 struct ext4_ext_cache *,
135 void *);
136
137#define EXT_CONTINUE 0
138#define EXT_BREAK 1
139#define EXT_REPEAT 2
140
141
142#define EXT_MAX_BLOCK 0xffffffff
143
144
145#define EXT_FIRST_EXTENT(__hdr__) \
146 ((struct ext4_extent *) (((char *) (__hdr__)) + \
147 sizeof(struct ext4_extent_header)))
148#define EXT_FIRST_INDEX(__hdr__) \
149 ((struct ext4_extent_idx *) (((char *) (__hdr__)) + \
150 sizeof(struct ext4_extent_header)))
151#define EXT_HAS_FREE_INDEX(__path__) \
152 (le16_to_cpu((__path__)->p_hdr->eh_entries) \
153 < le16_to_cpu((__path__)->p_hdr->eh_max))
154#define EXT_LAST_EXTENT(__hdr__) \
155 (EXT_FIRST_EXTENT((__hdr__)) + le16_to_cpu((__hdr__)->eh_entries) - 1)
156#define EXT_LAST_INDEX(__hdr__) \
157 (EXT_FIRST_INDEX((__hdr__)) + le16_to_cpu((__hdr__)->eh_entries) - 1)
158#define EXT_MAX_EXTENT(__hdr__) \
159 (EXT_FIRST_EXTENT((__hdr__)) + le16_to_cpu((__hdr__)->eh_max) - 1)
160#define EXT_MAX_INDEX(__hdr__) \
161 (EXT_FIRST_INDEX((__hdr__)) + le16_to_cpu((__hdr__)->eh_max) - 1)
162
163static inline struct ext4_extent_header *ext_inode_hdr(struct inode *inode)
164{
165 return (struct ext4_extent_header *) EXT4_I(inode)->i_data;
166}
167
168static inline struct ext4_extent_header *ext_block_hdr(struct buffer_head *bh)
169{
170 return (struct ext4_extent_header *) bh->b_data;
171}
172
173static inline unsigned short ext_depth(struct inode *inode)
174{
175 return le16_to_cpu(ext_inode_hdr(inode)->eh_depth);
176}
177
178static inline void ext4_ext_tree_changed(struct inode *inode)
179{
180 EXT4_I(inode)->i_ext_generation++;
181}
182
183static inline void
184ext4_ext_invalidate_cache(struct inode *inode)
185{
186 EXT4_I(inode)->i_cached_extent.ec_type = EXT4_EXT_CACHE_NO;
187}
188
189extern int ext4_extent_tree_init(handle_t *, struct inode *);
190extern int ext4_ext_calc_credits_for_insert(struct inode *, struct ext4_ext_path *);
191extern int ext4_ext_insert_extent(handle_t *, struct inode *, struct ext4_ext_path *, struct ext4_extent *);
192extern int ext4_ext_walk_space(struct inode *, unsigned long, unsigned long, ext_prepare_callback, void *);
193extern struct ext4_ext_path * ext4_ext_find_extent(struct inode *, int, struct ext4_ext_path *);
194
195#endif /* _LINUX_EXT4_EXTENTS */
196
diff --git a/include/linux/ext4_fs_i.h b/include/linux/ext4_fs_i.h
index 18a6ce98537f..40ce04a52b04 100644
--- a/include/linux/ext4_fs_i.h
+++ b/include/linux/ext4_fs_i.h
@@ -65,6 +65,16 @@ struct ext4_block_alloc_info {
65#define rsv_end rsv_window._rsv_end 65#define rsv_end rsv_window._rsv_end
66 66
67/* 67/*
68 * storage for cached extent
69 */
70struct ext4_ext_cache {
71 __u32 ec_start;
72 __u32 ec_block;
73 __u32 ec_len; /* must be 32bit to return holes */
74 __u32 ec_type;
75};
76
77/*
68 * third extended file system inode data in memory 78 * third extended file system inode data in memory
69 */ 79 */
70struct ext4_inode_info { 80struct ext4_inode_info {
@@ -142,6 +152,9 @@ struct ext4_inode_info {
142 */ 152 */
143 struct mutex truncate_mutex; 153 struct mutex truncate_mutex;
144 struct inode vfs_inode; 154 struct inode vfs_inode;
155
156 unsigned long i_ext_generation;
157 struct ext4_ext_cache i_cached_extent;
145}; 158};
146 159
147#endif /* _LINUX_EXT4_FS_I */ 160#endif /* _LINUX_EXT4_FS_I */
diff --git a/include/linux/ext4_fs_sb.h b/include/linux/ext4_fs_sb.h
index ce4856d70100..ce7a844d6703 100644
--- a/include/linux/ext4_fs_sb.h
+++ b/include/linux/ext4_fs_sb.h
@@ -78,6 +78,16 @@ struct ext4_sb_info {
78 char *s_qf_names[MAXQUOTAS]; /* Names of quota files with journalled quota */ 78 char *s_qf_names[MAXQUOTAS]; /* Names of quota files with journalled quota */
79 int s_jquota_fmt; /* Format of quota to use */ 79 int s_jquota_fmt; /* Format of quota to use */
80#endif 80#endif
81
82#ifdef EXTENTS_STATS
83 /* ext4 extents stats */
84 unsigned long s_ext_min;
85 unsigned long s_ext_max;
86 unsigned long s_depth_max;
87 spinlock_t s_ext_stats_lock;
88 unsigned long s_ext_blocks;
89 unsigned long s_ext_extents;
90#endif
81}; 91};
82 92
83#endif /* _LINUX_EXT4_FS_SB */ 93#endif /* _LINUX_EXT4_FS_SB */
diff --git a/include/linux/ext4_jbd2.h b/include/linux/ext4_jbd2.h
index 99d37557cbb4..aa273f024ad0 100644
--- a/include/linux/ext4_jbd2.h
+++ b/include/linux/ext4_jbd2.h
@@ -26,9 +26,14 @@
26 * 26 *
27 * We may have to touch one inode, one bitmap buffer, up to three 27 * We may have to touch one inode, one bitmap buffer, up to three
28 * indirection blocks, the group and superblock summaries, and the data 28 * indirection blocks, the group and superblock summaries, and the data
29 * block to complete the transaction. */ 29 * block to complete the transaction.
30 *
31 * For extents-enabled fs we may have to allocate and modify upto
32 * 5 levels of tree + root which is stored in inode. */
30 33
31#define EXT4_SINGLEDATA_TRANS_BLOCKS 8U 34#define EXT4_SINGLEDATA_TRANS_BLOCKS(sb) \
35 (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS) \
36 || test_opt(sb, EXTENTS) ? 27U : 8U)
32 37
33/* Extended attribute operations touch at most two data buffers, 38/* Extended attribute operations touch at most two data buffers,
34 * two bitmap buffers, and two group summaries, in addition to the inode 39 * two bitmap buffers, and two group summaries, in addition to the inode
@@ -42,7 +47,7 @@
42 * superblock only gets updated once, of course, so don't bother 47 * superblock only gets updated once, of course, so don't bother
43 * counting that again for the quota updates. */ 48 * counting that again for the quota updates. */
44 49
45#define EXT4_DATA_TRANS_BLOCKS(sb) (EXT4_SINGLEDATA_TRANS_BLOCKS + \ 50#define EXT4_DATA_TRANS_BLOCKS(sb) (EXT4_SINGLEDATA_TRANS_BLOCKS(sb) + \
46 EXT4_XATTR_TRANS_BLOCKS - 2 + \ 51 EXT4_XATTR_TRANS_BLOCKS - 2 + \
47 2*EXT4_QUOTA_TRANS_BLOCKS(sb)) 52 2*EXT4_QUOTA_TRANS_BLOCKS(sb))
48 53
@@ -78,9 +83,9 @@
78/* Amount of blocks needed for quota insert/delete - we do some block writes 83/* Amount of blocks needed for quota insert/delete - we do some block writes
79 * but inode, sb and group updates are done only once */ 84 * but inode, sb and group updates are done only once */
80#define EXT4_QUOTA_INIT_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_INIT_ALLOC*\ 85#define EXT4_QUOTA_INIT_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_INIT_ALLOC*\
81 (EXT4_SINGLEDATA_TRANS_BLOCKS-3)+3+DQUOT_INIT_REWRITE) : 0) 86 (EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)+3+DQUOT_INIT_REWRITE) : 0)
82#define EXT4_QUOTA_DEL_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_DEL_ALLOC*\ 87#define EXT4_QUOTA_DEL_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_DEL_ALLOC*\
83 (EXT4_SINGLEDATA_TRANS_BLOCKS-3)+3+DQUOT_DEL_REWRITE) : 0) 88 (EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)+3+DQUOT_DEL_REWRITE) : 0)
84#else 89#else
85#define EXT4_QUOTA_TRANS_BLOCKS(sb) 0 90#define EXT4_QUOTA_TRANS_BLOCKS(sb) 0
86#define EXT4_QUOTA_INIT_BLOCKS(sb) 0 91#define EXT4_QUOTA_INIT_BLOCKS(sb) 0