diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-01-24 16:13:08 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:03:59 -0400 |
commit | d1310b2e0cd98eb1348553e69b73827b436dca7b (patch) | |
tree | f55e9c380df0f3a7e9fb792b2308b52b632b90aa /fs/btrfs/extent_map.h | |
parent | 5f56406aabdf5444d040c5955effc665b1d0dbaf (diff) |
Btrfs: Split the extent_map code into two parts
There is now extent_map for mapping offsets in the file to disk and
extent_io for state tracking, IO submission and extent_bufers.
The new extent_map code shifts from [start,end] pairs to [start,len], and
pushes the locking out into the caller. This allows a few performance
optimizations and is easier to use.
A number of extent_map usage bugs were fixed, mostly with failing
to remove extent_map entries when changing the file.
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/extent_map.h')
-rw-r--r-- | fs/btrfs/extent_map.h | 214 |
1 files changed, 26 insertions, 188 deletions
diff --git a/fs/btrfs/extent_map.h b/fs/btrfs/extent_map.h index ea60f5447b5b..56314217cfc0 100644 --- a/fs/btrfs/extent_map.h +++ b/fs/btrfs/extent_map.h | |||
@@ -3,215 +3,53 @@ | |||
3 | 3 | ||
4 | #include <linux/rbtree.h> | 4 | #include <linux/rbtree.h> |
5 | 5 | ||
6 | #define EXTENT_MAP_LAST_BYTE (u64)-4 | ||
6 | #define EXTENT_MAP_HOLE (u64)-3 | 7 | #define EXTENT_MAP_HOLE (u64)-3 |
7 | #define EXTENT_MAP_INLINE (u64)-2 | 8 | #define EXTENT_MAP_INLINE (u64)-2 |
8 | #define EXTENT_MAP_DELALLOC (u64)-1 | 9 | #define EXTENT_MAP_DELALLOC (u64)-1 |
9 | 10 | ||
10 | /* bits for the extent state */ | ||
11 | #define EXTENT_DIRTY 1 | ||
12 | #define EXTENT_WRITEBACK (1 << 1) | ||
13 | #define EXTENT_UPTODATE (1 << 2) | ||
14 | #define EXTENT_LOCKED (1 << 3) | ||
15 | #define EXTENT_NEW (1 << 4) | ||
16 | #define EXTENT_DELALLOC (1 << 5) | ||
17 | #define EXTENT_DEFRAG (1 << 6) | ||
18 | #define EXTENT_DEFRAG_DONE (1 << 7) | ||
19 | #define EXTENT_BUFFER_FILLED (1 << 8) | ||
20 | #define EXTENT_CSUM (1 << 9) | ||
21 | #define EXTENT_IOBITS (EXTENT_LOCKED | EXTENT_WRITEBACK) | ||
22 | |||
23 | /* | ||
24 | * page->private values. Every page that is controlled by the extent | ||
25 | * map has page->private set to one. | ||
26 | */ | ||
27 | #define EXTENT_PAGE_PRIVATE 1 | ||
28 | #define EXTENT_PAGE_PRIVATE_FIRST_PAGE 3 | ||
29 | |||
30 | |||
31 | struct extent_map_ops { | ||
32 | int (*fill_delalloc)(struct inode *inode, u64 start, u64 end); | ||
33 | int (*writepage_io_hook)(struct page *page, u64 start, u64 end); | ||
34 | int (*readpage_io_hook)(struct page *page, u64 start, u64 end); | ||
35 | int (*readpage_end_io_hook)(struct page *page, u64 start, u64 end); | ||
36 | void (*writepage_end_io_hook)(struct page *page, u64 start, u64 end); | ||
37 | }; | ||
38 | |||
39 | struct extent_map_tree { | ||
40 | struct rb_root map; | ||
41 | struct rb_root state; | ||
42 | struct address_space *mapping; | ||
43 | u64 dirty_bytes; | ||
44 | rwlock_t lock; | ||
45 | struct extent_map_ops *ops; | ||
46 | spinlock_t lru_lock; | ||
47 | struct list_head buffer_lru; | ||
48 | int lru_size; | ||
49 | }; | ||
50 | |||
51 | /* note, this must start with the same fields as fs/extent_map.c:tree_entry */ | ||
52 | struct extent_map { | 11 | struct extent_map { |
53 | u64 start; | ||
54 | u64 end; /* inclusive */ | ||
55 | int in_tree; | ||
56 | struct rb_node rb_node; | 12 | struct rb_node rb_node; |
57 | /* block_start and block_end are in bytes */ | 13 | |
14 | /* all of these are in bytes */ | ||
15 | u64 start; | ||
16 | u64 len; | ||
58 | u64 block_start; | 17 | u64 block_start; |
59 | u64 block_end; /* inclusive */ | 18 | unsigned long flags; |
60 | struct block_device *bdev; | 19 | struct block_device *bdev; |
61 | atomic_t refs; | 20 | atomic_t refs; |
62 | }; | ||
63 | |||
64 | /* note, this must start with the same fields as fs/extent_map.c:tree_entry */ | ||
65 | struct extent_state { | ||
66 | u64 start; | ||
67 | u64 end; /* inclusive */ | ||
68 | int in_tree; | 21 | int in_tree; |
69 | struct rb_node rb_node; | ||
70 | wait_queue_head_t wq; | ||
71 | atomic_t refs; | ||
72 | unsigned long state; | ||
73 | |||
74 | /* for use by the FS */ | ||
75 | u64 private; | ||
76 | |||
77 | struct list_head list; | ||
78 | }; | 22 | }; |
79 | 23 | ||
80 | struct extent_buffer { | 24 | struct extent_map_tree { |
81 | u64 start; | 25 | struct rb_root map; |
82 | unsigned long len; | 26 | struct extent_map *last; |
83 | char *map_token; | 27 | spinlock_t lock; |
84 | char *kaddr; | ||
85 | unsigned long map_start; | ||
86 | unsigned long map_len; | ||
87 | struct page *first_page; | ||
88 | struct list_head lru; | ||
89 | atomic_t refs; | ||
90 | int flags; | ||
91 | }; | 28 | }; |
92 | 29 | ||
93 | typedef struct extent_map *(get_extent_t)(struct inode *inode, | 30 | static inline u64 extent_map_end(struct extent_map *em) |
94 | struct page *page, | 31 | { |
95 | size_t page_offset, | 32 | if (em->start + em->len < em->start) |
96 | u64 start, u64 end, | 33 | return (u64)-1; |
97 | int create); | 34 | return em->start + em->len; |
35 | } | ||
36 | |||
37 | static inline u64 extent_map_block_end(struct extent_map *em) | ||
38 | { | ||
39 | if (em->block_start + em->len < em->block_start) | ||
40 | return (u64)-1; | ||
41 | return em->block_start + em->len; | ||
42 | } | ||
98 | 43 | ||
99 | void extent_map_tree_init(struct extent_map_tree *tree, | 44 | void extent_map_tree_init(struct extent_map_tree *tree, gfp_t mask); |
100 | struct address_space *mapping, gfp_t mask); | ||
101 | void extent_map_tree_empty_lru(struct extent_map_tree *tree); | ||
102 | struct extent_map *lookup_extent_mapping(struct extent_map_tree *tree, | 45 | struct extent_map *lookup_extent_mapping(struct extent_map_tree *tree, |
103 | u64 start, u64 end); | 46 | u64 start, u64 len); |
104 | int add_extent_mapping(struct extent_map_tree *tree, | 47 | int add_extent_mapping(struct extent_map_tree *tree, |
105 | struct extent_map *em); | 48 | struct extent_map *em); |
106 | int remove_extent_mapping(struct extent_map_tree *tree, struct extent_map *em); | 49 | int remove_extent_mapping(struct extent_map_tree *tree, struct extent_map *em); |
107 | int try_release_extent_mapping(struct extent_map_tree *tree, struct page *page); | 50 | |
108 | int lock_extent(struct extent_map_tree *tree, u64 start, u64 end, gfp_t mask); | ||
109 | int unlock_extent(struct extent_map_tree *tree, u64 start, u64 end, gfp_t mask); | ||
110 | struct extent_map *alloc_extent_map(gfp_t mask); | 51 | struct extent_map *alloc_extent_map(gfp_t mask); |
111 | void free_extent_map(struct extent_map *em); | 52 | void free_extent_map(struct extent_map *em); |
112 | int extent_read_full_page(struct extent_map_tree *tree, struct page *page, | ||
113 | get_extent_t *get_extent); | ||
114 | int __init extent_map_init(void); | 53 | int __init extent_map_init(void); |
115 | void extent_map_exit(void); | 54 | void extent_map_exit(void); |
116 | |||
117 | u64 count_range_bits(struct extent_map_tree *tree, | ||
118 | u64 *start, u64 search_end, | ||
119 | u64 max_bytes, unsigned long bits); | ||
120 | |||
121 | int test_range_bit(struct extent_map_tree *tree, u64 start, u64 end, | ||
122 | int bits, int filled); | ||
123 | int clear_extent_bits(struct extent_map_tree *tree, u64 start, u64 end, | ||
124 | int bits, gfp_t mask); | ||
125 | int set_extent_bits(struct extent_map_tree *tree, u64 start, u64 end, | ||
126 | int bits, gfp_t mask); | ||
127 | int set_extent_uptodate(struct extent_map_tree *tree, u64 start, u64 end, | ||
128 | gfp_t mask); | ||
129 | int set_extent_new(struct extent_map_tree *tree, u64 start, u64 end, | ||
130 | gfp_t mask); | ||
131 | int set_extent_dirty(struct extent_map_tree *tree, u64 start, u64 end, | ||
132 | gfp_t mask); | ||
133 | int clear_extent_dirty(struct extent_map_tree *tree, u64 start, u64 end, | ||
134 | gfp_t mask); | ||
135 | int set_extent_delalloc(struct extent_map_tree *tree, u64 start, u64 end, | ||
136 | gfp_t mask); | ||
137 | int find_first_extent_bit(struct extent_map_tree *tree, u64 start, | ||
138 | u64 *start_ret, u64 *end_ret, int bits); | ||
139 | int extent_invalidatepage(struct extent_map_tree *tree, | ||
140 | struct page *page, unsigned long offset); | ||
141 | int extent_write_full_page(struct extent_map_tree *tree, struct page *page, | ||
142 | get_extent_t *get_extent, | ||
143 | struct writeback_control *wbc); | ||
144 | int extent_writepages(struct extent_map_tree *tree, | ||
145 | struct address_space *mapping, | ||
146 | get_extent_t *get_extent, | ||
147 | struct writeback_control *wbc); | ||
148 | int extent_readpages(struct extent_map_tree *tree, | ||
149 | struct address_space *mapping, | ||
150 | struct list_head *pages, unsigned nr_pages, | ||
151 | get_extent_t get_extent); | ||
152 | int extent_prepare_write(struct extent_map_tree *tree, | ||
153 | struct inode *inode, struct page *page, | ||
154 | unsigned from, unsigned to, get_extent_t *get_extent); | ||
155 | int extent_commit_write(struct extent_map_tree *tree, | ||
156 | struct inode *inode, struct page *page, | ||
157 | unsigned from, unsigned to); | ||
158 | sector_t extent_bmap(struct address_space *mapping, sector_t iblock, | ||
159 | get_extent_t *get_extent); | ||
160 | int set_range_dirty(struct extent_map_tree *tree, u64 start, u64 end); | ||
161 | int set_state_private(struct extent_map_tree *tree, u64 start, u64 private); | ||
162 | int get_state_private(struct extent_map_tree *tree, u64 start, u64 *private); | ||
163 | void set_page_extent_mapped(struct page *page); | ||
164 | |||
165 | struct extent_buffer *alloc_extent_buffer(struct extent_map_tree *tree, | ||
166 | u64 start, unsigned long len, | ||
167 | struct page *page0, | ||
168 | gfp_t mask); | ||
169 | struct extent_buffer *find_extent_buffer(struct extent_map_tree *tree, | ||
170 | u64 start, unsigned long len, | ||
171 | gfp_t mask); | ||
172 | void free_extent_buffer(struct extent_buffer *eb); | ||
173 | int read_extent_buffer_pages(struct extent_map_tree *tree, | ||
174 | struct extent_buffer *eb, u64 start, int wait); | ||
175 | |||
176 | static inline void extent_buffer_get(struct extent_buffer *eb) | ||
177 | { | ||
178 | atomic_inc(&eb->refs); | ||
179 | } | ||
180 | |||
181 | int memcmp_extent_buffer(struct extent_buffer *eb, const void *ptrv, | ||
182 | unsigned long start, | ||
183 | unsigned long len); | ||
184 | void read_extent_buffer(struct extent_buffer *eb, void *dst, | ||
185 | unsigned long start, | ||
186 | unsigned long len); | ||
187 | void write_extent_buffer(struct extent_buffer *eb, const void *src, | ||
188 | unsigned long start, unsigned long len); | ||
189 | void copy_extent_buffer(struct extent_buffer *dst, struct extent_buffer *src, | ||
190 | unsigned long dst_offset, unsigned long src_offset, | ||
191 | unsigned long len); | ||
192 | void memcpy_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset, | ||
193 | unsigned long src_offset, unsigned long len); | ||
194 | void memmove_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset, | ||
195 | unsigned long src_offset, unsigned long len); | ||
196 | void memset_extent_buffer(struct extent_buffer *eb, char c, | ||
197 | unsigned long start, unsigned long len); | ||
198 | int wait_on_extent_buffer_writeback(struct extent_map_tree *tree, | ||
199 | struct extent_buffer *eb); | ||
200 | int clear_extent_buffer_dirty(struct extent_map_tree *tree, | ||
201 | struct extent_buffer *eb); | ||
202 | int set_extent_buffer_dirty(struct extent_map_tree *tree, | ||
203 | struct extent_buffer *eb); | ||
204 | int set_extent_buffer_uptodate(struct extent_map_tree *tree, | ||
205 | struct extent_buffer *eb); | ||
206 | int extent_buffer_uptodate(struct extent_map_tree *tree, | ||
207 | struct extent_buffer *eb); | ||
208 | int map_extent_buffer(struct extent_buffer *eb, unsigned long offset, | ||
209 | unsigned long min_len, char **token, char **map, | ||
210 | unsigned long *map_start, | ||
211 | unsigned long *map_len, int km); | ||
212 | int map_private_extent_buffer(struct extent_buffer *eb, unsigned long offset, | ||
213 | unsigned long min_len, char **token, char **map, | ||
214 | unsigned long *map_start, | ||
215 | unsigned long *map_len, int km); | ||
216 | void unmap_extent_buffer(struct extent_buffer *eb, char *token, int km); | ||
217 | #endif | 55 | #endif |