]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | From: Tao Ma <tao.ma@oracle.com> |
2 | Subject: [PATCH 04/16] ocfs2: Make high level btree extend code generic | |
3 | Patch-mainline: 2.6.28? | |
4 | References: FATE302067 | |
5 | ||
6 | Factor out the non-inode specifics of ocfs2_do_extend_allocation() into a more generic | |
7 | function, ocfs2_do_cluster_allocation(). ocfs2_do_extend_allocation calls | |
8 | ocfs2_do_cluster_allocation() now, but the latter can be used for other | |
9 | btree types as well. | |
10 | ||
11 | Signed-off-by: Tao Ma <tao.ma@oracle.com> | |
12 | Signed-off-by: Mark Fasheh <mfasheh@suse.com> | |
13 | --- | |
14 | fs/ocfs2/alloc.c | 110 ++++++++++++++++++++++++++++++++++++++++++++ | |
15 | fs/ocfs2/alloc.h | 17 ++++++ | |
16 | fs/ocfs2/aops.c | 8 +-- | |
17 | fs/ocfs2/dir.c | 6 +- | |
18 | fs/ocfs2/file.c | 136 ++++++++++--------------------------------------------- | |
19 | fs/ocfs2/file.h | 26 ++++------ | |
20 | fs/ocfs2/namei.c | 8 +-- | |
21 | 7 files changed, 176 insertions(+), 135 deletions(-) | |
22 | ||
23 | --- a/fs/ocfs2/alloc.c | |
24 | +++ b/fs/ocfs2/alloc.c | |
25 | @@ -4302,6 +4302,116 @@ bail: | |
26 | return status; | |
27 | } | |
28 | ||
29 | +/* | |
30 | + * Allcate and add clusters into the extent b-tree. | |
31 | + * The new clusters(clusters_to_add) will be inserted at logical_offset. | |
32 | + * The extent b-tree's root is root_el and it should be in root_bh, and | |
33 | + * it is not limited to the file storage. Any extent tree can use this | |
34 | + * function if it implements the proper ocfs2_extent_tree. | |
35 | + */ | |
36 | +int ocfs2_add_clusters_in_btree(struct ocfs2_super *osb, | |
37 | + struct inode *inode, | |
38 | + u32 *logical_offset, | |
39 | + u32 clusters_to_add, | |
40 | + int mark_unwritten, | |
41 | + struct buffer_head *root_bh, | |
42 | + struct ocfs2_extent_list *root_el, | |
43 | + handle_t *handle, | |
44 | + struct ocfs2_alloc_context *data_ac, | |
45 | + struct ocfs2_alloc_context *meta_ac, | |
46 | + enum ocfs2_alloc_restarted *reason_ret, | |
47 | + enum ocfs2_extent_tree_type type) | |
48 | +{ | |
49 | + int status = 0; | |
50 | + int free_extents; | |
51 | + enum ocfs2_alloc_restarted reason = RESTART_NONE; | |
52 | + u32 bit_off, num_bits; | |
53 | + u64 block; | |
54 | + u8 flags = 0; | |
55 | + | |
56 | + BUG_ON(!clusters_to_add); | |
57 | + | |
58 | + if (mark_unwritten) | |
59 | + flags = OCFS2_EXT_UNWRITTEN; | |
60 | + | |
61 | + free_extents = ocfs2_num_free_extents(osb, inode, root_bh, type); | |
62 | + if (free_extents < 0) { | |
63 | + status = free_extents; | |
64 | + mlog_errno(status); | |
65 | + goto leave; | |
66 | + } | |
67 | + | |
68 | + /* there are two cases which could cause us to EAGAIN in the | |
69 | + * we-need-more-metadata case: | |
70 | + * 1) we haven't reserved *any* | |
71 | + * 2) we are so fragmented, we've needed to add metadata too | |
72 | + * many times. */ | |
73 | + if (!free_extents && !meta_ac) { | |
74 | + mlog(0, "we haven't reserved any metadata!\n"); | |
75 | + status = -EAGAIN; | |
76 | + reason = RESTART_META; | |
77 | + goto leave; | |
78 | + } else if ((!free_extents) | |
79 | + && (ocfs2_alloc_context_bits_left(meta_ac) | |
80 | + < ocfs2_extend_meta_needed(root_el))) { | |
81 | + mlog(0, "filesystem is really fragmented...\n"); | |
82 | + status = -EAGAIN; | |
83 | + reason = RESTART_META; | |
84 | + goto leave; | |
85 | + } | |
86 | + | |
87 | + status = __ocfs2_claim_clusters(osb, handle, data_ac, 1, | |
88 | + clusters_to_add, &bit_off, &num_bits); | |
89 | + if (status < 0) { | |
90 | + if (status != -ENOSPC) | |
91 | + mlog_errno(status); | |
92 | + goto leave; | |
93 | + } | |
94 | + | |
95 | + BUG_ON(num_bits > clusters_to_add); | |
96 | + | |
97 | + /* reserve our write early -- insert_extent may update the inode */ | |
98 | + status = ocfs2_journal_access(handle, inode, root_bh, | |
99 | + OCFS2_JOURNAL_ACCESS_WRITE); | |
100 | + if (status < 0) { | |
101 | + mlog_errno(status); | |
102 | + goto leave; | |
103 | + } | |
104 | + | |
105 | + block = ocfs2_clusters_to_blocks(osb->sb, bit_off); | |
106 | + mlog(0, "Allocating %u clusters at block %u for inode %llu\n", | |
107 | + num_bits, bit_off, (unsigned long long)OCFS2_I(inode)->ip_blkno); | |
108 | + status = ocfs2_insert_extent(osb, handle, inode, root_bh, | |
109 | + *logical_offset, block, num_bits, | |
110 | + flags, meta_ac, type); | |
111 | + if (status < 0) { | |
112 | + mlog_errno(status); | |
113 | + goto leave; | |
114 | + } | |
115 | + | |
116 | + status = ocfs2_journal_dirty(handle, root_bh); | |
117 | + if (status < 0) { | |
118 | + mlog_errno(status); | |
119 | + goto leave; | |
120 | + } | |
121 | + | |
122 | + clusters_to_add -= num_bits; | |
123 | + *logical_offset += num_bits; | |
124 | + | |
125 | + if (clusters_to_add) { | |
126 | + mlog(0, "need to alloc once more, wanted = %u\n", | |
127 | + clusters_to_add); | |
128 | + status = -EAGAIN; | |
129 | + reason = RESTART_TRANS; | |
130 | + } | |
131 | + | |
132 | +leave: | |
133 | + mlog_exit(status); | |
134 | + if (reason_ret) | |
135 | + *reason_ret = reason; | |
136 | + return status; | |
137 | +} | |
138 | + | |
139 | static void ocfs2_make_right_split_rec(struct super_block *sb, | |
140 | struct ocfs2_extent_rec *split_rec, | |
141 | u32 cpos, | |
142 | --- a/fs/ocfs2/alloc.h | |
143 | +++ b/fs/ocfs2/alloc.h | |
144 | @@ -41,6 +41,23 @@ int ocfs2_insert_extent(struct ocfs2_sup | |
145 | u8 flags, | |
146 | struct ocfs2_alloc_context *meta_ac, | |
147 | enum ocfs2_extent_tree_type et_type); | |
148 | +enum ocfs2_alloc_restarted { | |
149 | + RESTART_NONE = 0, | |
150 | + RESTART_TRANS, | |
151 | + RESTART_META | |
152 | +}; | |
153 | +int ocfs2_add_clusters_in_btree(struct ocfs2_super *osb, | |
154 | + struct inode *inode, | |
155 | + u32 *logical_offset, | |
156 | + u32 clusters_to_add, | |
157 | + int mark_unwritten, | |
158 | + struct buffer_head *root_bh, | |
159 | + struct ocfs2_extent_list *root_el, | |
160 | + handle_t *handle, | |
161 | + struct ocfs2_alloc_context *data_ac, | |
162 | + struct ocfs2_alloc_context *meta_ac, | |
163 | + enum ocfs2_alloc_restarted *reason_ret, | |
164 | + enum ocfs2_extent_tree_type type); | |
165 | struct ocfs2_cached_dealloc_ctxt; | |
166 | int ocfs2_mark_extent_written(struct inode *inode, struct buffer_head *root_bh, | |
167 | handle_t *handle, u32 cpos, u32 len, u32 phys, | |
168 | --- a/fs/ocfs2/aops.c | |
169 | +++ b/fs/ocfs2/aops.c | |
170 | @@ -1255,10 +1255,10 @@ static int ocfs2_write_cluster(struct ad | |
171 | * any additional semaphores or cluster locks. | |
172 | */ | |
173 | tmp_pos = cpos; | |
174 | - ret = ocfs2_do_extend_allocation(OCFS2_SB(inode->i_sb), inode, | |
175 | - &tmp_pos, 1, 0, wc->w_di_bh, | |
176 | - wc->w_handle, data_ac, | |
177 | - meta_ac, NULL); | |
178 | + ret = ocfs2_add_inode_data(OCFS2_SB(inode->i_sb), inode, | |
179 | + &tmp_pos, 1, 0, wc->w_di_bh, | |
180 | + wc->w_handle, data_ac, | |
181 | + meta_ac, NULL); | |
182 | /* | |
183 | * This shouldn't happen because we must have already | |
184 | * calculated the correct meta data allocation required. The | |
185 | --- a/fs/ocfs2/dir.c | |
186 | +++ b/fs/ocfs2/dir.c | |
187 | @@ -1383,9 +1383,9 @@ static int ocfs2_do_extend_dir(struct su | |
188 | if (extend) { | |
189 | u32 offset = OCFS2_I(dir)->ip_clusters; | |
190 | ||
191 | - status = ocfs2_do_extend_allocation(OCFS2_SB(sb), dir, &offset, | |
192 | - 1, 0, parent_fe_bh, handle, | |
193 | - data_ac, meta_ac, NULL); | |
194 | + status = ocfs2_add_inode_data(OCFS2_SB(sb), dir, &offset, | |
195 | + 1, 0, parent_fe_bh, handle, | |
196 | + data_ac, meta_ac, NULL); | |
197 | BUG_ON(status == -EAGAIN); | |
198 | if (status < 0) { | |
199 | mlog_errno(status); | |
200 | --- a/fs/ocfs2/file.c | |
201 | +++ b/fs/ocfs2/file.c | |
202 | @@ -488,7 +488,7 @@ bail: | |
203 | } | |
204 | ||
205 | /* | |
206 | - * extend allocation only here. | |
207 | + * extend file allocation only here. | |
208 | * we'll update all the disk stuff, and oip->alloc_size | |
209 | * | |
210 | * expect stuff to be locked, a transaction started and enough data / | |
211 | @@ -497,107 +497,25 @@ bail: | |
212 | * Will return -EAGAIN, and a reason if a restart is needed. | |
213 | * If passed in, *reason will always be set, even in error. | |
214 | */ | |
215 | -int ocfs2_do_extend_allocation(struct ocfs2_super *osb, | |
216 | - struct inode *inode, | |
217 | - u32 *logical_offset, | |
218 | - u32 clusters_to_add, | |
219 | - int mark_unwritten, | |
220 | - struct buffer_head *fe_bh, | |
221 | - handle_t *handle, | |
222 | - struct ocfs2_alloc_context *data_ac, | |
223 | - struct ocfs2_alloc_context *meta_ac, | |
224 | - enum ocfs2_alloc_restarted *reason_ret) | |
225 | +int ocfs2_add_inode_data(struct ocfs2_super *osb, | |
226 | + struct inode *inode, | |
227 | + u32 *logical_offset, | |
228 | + u32 clusters_to_add, | |
229 | + int mark_unwritten, | |
230 | + struct buffer_head *fe_bh, | |
231 | + handle_t *handle, | |
232 | + struct ocfs2_alloc_context *data_ac, | |
233 | + struct ocfs2_alloc_context *meta_ac, | |
234 | + enum ocfs2_alloc_restarted *reason_ret) | |
235 | { | |
236 | - int status = 0; | |
237 | - int free_extents; | |
238 | struct ocfs2_dinode *fe = (struct ocfs2_dinode *) fe_bh->b_data; | |
239 | - enum ocfs2_alloc_restarted reason = RESTART_NONE; | |
240 | - u32 bit_off, num_bits; | |
241 | - u64 block; | |
242 | - u8 flags = 0; | |
243 | - | |
244 | - BUG_ON(!clusters_to_add); | |
245 | - | |
246 | - if (mark_unwritten) | |
247 | - flags = OCFS2_EXT_UNWRITTEN; | |
248 | - | |
249 | - free_extents = ocfs2_num_free_extents(osb, inode, fe_bh, | |
250 | - OCFS2_DINODE_EXTENT); | |
251 | - if (free_extents < 0) { | |
252 | - status = free_extents; | |
253 | - mlog_errno(status); | |
254 | - goto leave; | |
255 | - } | |
256 | - | |
257 | - /* there are two cases which could cause us to EAGAIN in the | |
258 | - * we-need-more-metadata case: | |
259 | - * 1) we haven't reserved *any* | |
260 | - * 2) we are so fragmented, we've needed to add metadata too | |
261 | - * many times. */ | |
262 | - if (!free_extents && !meta_ac) { | |
263 | - mlog(0, "we haven't reserved any metadata!\n"); | |
264 | - status = -EAGAIN; | |
265 | - reason = RESTART_META; | |
266 | - goto leave; | |
267 | - } else if ((!free_extents) | |
268 | - && (ocfs2_alloc_context_bits_left(meta_ac) | |
269 | - < ocfs2_extend_meta_needed(&fe->id2.i_list))) { | |
270 | - mlog(0, "filesystem is really fragmented...\n"); | |
271 | - status = -EAGAIN; | |
272 | - reason = RESTART_META; | |
273 | - goto leave; | |
274 | - } | |
275 | - | |
276 | - status = __ocfs2_claim_clusters(osb, handle, data_ac, 1, | |
277 | - clusters_to_add, &bit_off, &num_bits); | |
278 | - if (status < 0) { | |
279 | - if (status != -ENOSPC) | |
280 | - mlog_errno(status); | |
281 | - goto leave; | |
282 | - } | |
283 | - | |
284 | - BUG_ON(num_bits > clusters_to_add); | |
285 | - | |
286 | - /* reserve our write early -- insert_extent may update the inode */ | |
287 | - status = ocfs2_journal_access(handle, inode, fe_bh, | |
288 | - OCFS2_JOURNAL_ACCESS_WRITE); | |
289 | - if (status < 0) { | |
290 | - mlog_errno(status); | |
291 | - goto leave; | |
292 | - } | |
293 | - | |
294 | - block = ocfs2_clusters_to_blocks(osb->sb, bit_off); | |
295 | - mlog(0, "Allocating %u clusters at block %u for inode %llu\n", | |
296 | - num_bits, bit_off, (unsigned long long)OCFS2_I(inode)->ip_blkno); | |
297 | - status = ocfs2_insert_extent(osb, handle, inode, fe_bh, | |
298 | - *logical_offset, block, num_bits, | |
299 | - flags, meta_ac, OCFS2_DINODE_EXTENT); | |
300 | - if (status < 0) { | |
301 | - mlog_errno(status); | |
302 | - goto leave; | |
303 | - } | |
304 | + struct ocfs2_extent_list *el = &fe->id2.i_list; | |
305 | ||
306 | - status = ocfs2_journal_dirty(handle, fe_bh); | |
307 | - if (status < 0) { | |
308 | - mlog_errno(status); | |
309 | - goto leave; | |
310 | - } | |
311 | - | |
312 | - clusters_to_add -= num_bits; | |
313 | - *logical_offset += num_bits; | |
314 | - | |
315 | - if (clusters_to_add) { | |
316 | - mlog(0, "need to alloc once more, clusters = %u, wanted = " | |
317 | - "%u\n", fe->i_clusters, clusters_to_add); | |
318 | - status = -EAGAIN; | |
319 | - reason = RESTART_TRANS; | |
320 | - } | |
321 | - | |
322 | -leave: | |
323 | - mlog_exit(status); | |
324 | - if (reason_ret) | |
325 | - *reason_ret = reason; | |
326 | - return status; | |
327 | + return ocfs2_add_clusters_in_btree(osb, inode, logical_offset, | |
328 | + clusters_to_add, mark_unwritten, | |
329 | + fe_bh, el, handle, | |
330 | + data_ac, meta_ac, reason_ret, | |
331 | + OCFS2_DINODE_EXTENT); | |
332 | } | |
333 | ||
334 | static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start, | |
335 | @@ -676,16 +594,16 @@ restarted_transaction: | |
336 | ||
337 | prev_clusters = OCFS2_I(inode)->ip_clusters; | |
338 | ||
339 | - status = ocfs2_do_extend_allocation(osb, | |
340 | - inode, | |
341 | - &logical_start, | |
342 | - clusters_to_add, | |
343 | - mark_unwritten, | |
344 | - bh, | |
345 | - handle, | |
346 | - data_ac, | |
347 | - meta_ac, | |
348 | - &why); | |
349 | + status = ocfs2_add_inode_data(osb, | |
350 | + inode, | |
351 | + &logical_start, | |
352 | + clusters_to_add, | |
353 | + mark_unwritten, | |
354 | + bh, | |
355 | + handle, | |
356 | + data_ac, | |
357 | + meta_ac, | |
358 | + &why); | |
359 | if ((status < 0) && (status != -EAGAIN)) { | |
360 | if (status != -ENOSPC) | |
361 | mlog_errno(status); | |
362 | --- a/fs/ocfs2/file.h | |
363 | +++ b/fs/ocfs2/file.h | |
364 | @@ -31,6 +31,7 @@ extern const struct file_operations ocfs | |
365 | extern const struct inode_operations ocfs2_file_iops; | |
366 | extern const struct inode_operations ocfs2_special_file_iops; | |
367 | struct ocfs2_alloc_context; | |
368 | +enum ocfs2_alloc_restarted; | |
369 | ||
370 | struct ocfs2_file_private { | |
371 | struct file *fp_file; | |
372 | @@ -38,21 +39,16 @@ struct ocfs2_file_private { | |
373 | struct ocfs2_lock_res fp_flock; | |
374 | }; | |
375 | ||
376 | -enum ocfs2_alloc_restarted { | |
377 | - RESTART_NONE = 0, | |
378 | - RESTART_TRANS, | |
379 | - RESTART_META | |
380 | -}; | |
381 | -int ocfs2_do_extend_allocation(struct ocfs2_super *osb, | |
382 | - struct inode *inode, | |
383 | - u32 *logical_offset, | |
384 | - u32 clusters_to_add, | |
385 | - int mark_unwritten, | |
386 | - struct buffer_head *fe_bh, | |
387 | - handle_t *handle, | |
388 | - struct ocfs2_alloc_context *data_ac, | |
389 | - struct ocfs2_alloc_context *meta_ac, | |
390 | - enum ocfs2_alloc_restarted *reason_ret); | |
391 | +int ocfs2_add_inode_data(struct ocfs2_super *osb, | |
392 | + struct inode *inode, | |
393 | + u32 *logical_offset, | |
394 | + u32 clusters_to_add, | |
395 | + int mark_unwritten, | |
396 | + struct buffer_head *fe_bh, | |
397 | + handle_t *handle, | |
398 | + struct ocfs2_alloc_context *data_ac, | |
399 | + struct ocfs2_alloc_context *meta_ac, | |
400 | + enum ocfs2_alloc_restarted *reason_ret); | |
401 | int ocfs2_extend_no_holes(struct inode *inode, u64 new_i_size, | |
402 | u64 zero_to); | |
403 | int ocfs2_setattr(struct dentry *dentry, struct iattr *attr); | |
404 | --- a/fs/ocfs2/namei.c | |
405 | +++ b/fs/ocfs2/namei.c | |
406 | @@ -1598,10 +1598,10 @@ static int ocfs2_symlink(struct inode *d | |
407 | u32 offset = 0; | |
408 | ||
409 | inode->i_op = &ocfs2_symlink_inode_operations; | |
410 | - status = ocfs2_do_extend_allocation(osb, inode, &offset, 1, 0, | |
411 | - new_fe_bh, | |
412 | - handle, data_ac, NULL, | |
413 | - NULL); | |
414 | + status = ocfs2_add_inode_data(osb, inode, &offset, 1, 0, | |
415 | + new_fe_bh, | |
416 | + handle, data_ac, NULL, | |
417 | + NULL); | |
418 | if (status < 0) { | |
419 | if (status != -ENOSPC && status != -EINTR) { | |
420 | mlog(ML_ERROR, |