]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.25/patches.suse/ocfs2-xattr-Reserve-meta-data-at-the-beginning-of-o.patch
Updated xen patches taken from suse.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.suse / ocfs2-xattr-Reserve-meta-data-at-the-beginning-of-o.patch
1 From: Tao Ma <tao.ma@oracle.com>
2 Date: Wed, 12 Nov 2008 08:27:00 +0800
3 Subject: ocfs2/xattr: Reserve meta/data at the beginning of ocfs2_xattr_set.
4 Patch-mainline: 2.6.29
5
6 In ocfs2 xattr set, we reserve metadata and clusters in any place
7 they are needed. It is time-consuming and ineffective, so this
8 patch try to reserve metadata and clusters at the beginning of
9 ocfs2_xattr_set.
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.h | 4 +
15 fs/ocfs2/xattr.c | 483 ++++++++++++++++++++++++++++++++++++++++--------------
16 2 files changed, 361 insertions(+), 126 deletions(-)
17
18 diff --git a/fs/ocfs2/alloc.h b/fs/ocfs2/alloc.h
19 index c301cf2..3eb735e 100644
20 --- a/fs/ocfs2/alloc.h
21 +++ b/fs/ocfs2/alloc.h
22 @@ -176,6 +176,10 @@ static inline void ocfs2_init_dealloc_ctxt(struct ocfs2_cached_dealloc_ctxt *c)
23 }
24 int ocfs2_cache_cluster_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt,
25 u64 blkno, unsigned int bit);
26 +static inline int ocfs2_dealloc_has_cluster(struct ocfs2_cached_dealloc_ctxt *c)
27 +{
28 + return c->c_global_allocator != NULL;
29 +}
30 int ocfs2_run_deallocs(struct ocfs2_super *osb,
31 struct ocfs2_cached_dealloc_ctxt *ctxt);
32
33 diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
34 index f1da381..4fd201a 100644
35 --- a/fs/ocfs2/xattr.c
36 +++ b/fs/ocfs2/xattr.c
37 @@ -71,6 +71,12 @@ struct ocfs2_xattr_bucket {
38 int bu_blocks;
39 };
40
41 +struct ocfs2_xattr_set_ctxt {
42 + struct ocfs2_alloc_context *meta_ac;
43 + struct ocfs2_alloc_context *data_ac;
44 + struct ocfs2_cached_dealloc_ctxt dealloc;
45 +};
46 +
47 #define OCFS2_XATTR_ROOT_SIZE (sizeof(struct ocfs2_xattr_def_value_root))
48 #define OCFS2_XATTR_INLINE_SIZE 80
49
50 @@ -133,11 +139,13 @@ static int ocfs2_xattr_tree_list_index_block(struct inode *inode,
51 size_t buffer_size);
52
53 static int ocfs2_xattr_create_index_block(struct inode *inode,
54 - struct ocfs2_xattr_search *xs);
55 + struct ocfs2_xattr_search *xs,
56 + struct ocfs2_xattr_set_ctxt *ctxt);
57
58 static int ocfs2_xattr_set_entry_index_block(struct inode *inode,
59 struct ocfs2_xattr_info *xi,
60 - struct ocfs2_xattr_search *xs);
61 + struct ocfs2_xattr_search *xs,
62 + struct ocfs2_xattr_set_ctxt *ctxt);
63
64 static int ocfs2_delete_xattr_index_block(struct inode *inode,
65 struct buffer_head *xb_bh);
66 @@ -334,14 +342,13 @@ static void ocfs2_xattr_hash_entry(struct inode *inode,
67 static int ocfs2_xattr_extend_allocation(struct inode *inode,
68 u32 clusters_to_add,
69 struct buffer_head *xattr_bh,
70 - struct ocfs2_xattr_value_root *xv)
71 + struct ocfs2_xattr_value_root *xv,
72 + struct ocfs2_xattr_set_ctxt *ctxt)
73 {
74 int status = 0;
75 int restart_func = 0;
76 int credits = 0;
77 handle_t *handle = NULL;
78 - struct ocfs2_alloc_context *data_ac = NULL;
79 - struct ocfs2_alloc_context *meta_ac = NULL;
80 enum ocfs2_alloc_restarted why;
81 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
82 u32 prev_clusters, logical_start = le32_to_cpu(xv->xr_clusters);
83 @@ -353,13 +360,6 @@ static int ocfs2_xattr_extend_allocation(struct inode *inode,
84
85 restart_all:
86
87 - status = ocfs2_lock_allocators(inode, &et, clusters_to_add, 0,
88 - &data_ac, &meta_ac);
89 - if (status) {
90 - mlog_errno(status);
91 - goto leave;
92 - }
93 -
94 credits = ocfs2_calc_extend_credits(osb->sb, et.et_root_el,
95 clusters_to_add);
96 handle = ocfs2_start_trans(osb, credits);
97 @@ -386,8 +386,8 @@ restarted_transaction:
98 0,
99 &et,
100 handle,
101 - data_ac,
102 - meta_ac,
103 + ctxt->data_ac,
104 + ctxt->meta_ac,
105 &why);
106 if ((status < 0) && (status != -EAGAIN)) {
107 if (status != -ENOSPC)
108 @@ -432,14 +432,6 @@ leave:
109 ocfs2_commit_trans(osb, handle);
110 handle = NULL;
111 }
112 - if (data_ac) {
113 - ocfs2_free_alloc_context(data_ac);
114 - data_ac = NULL;
115 - }
116 - if (meta_ac) {
117 - ocfs2_free_alloc_context(meta_ac);
118 - meta_ac = NULL;
119 - }
120 if ((!status) && restart_func) {
121 restart_func = 0;
122 goto restart_all;
123 @@ -452,23 +444,16 @@ static int __ocfs2_remove_xattr_range(struct inode *inode,
124 struct buffer_head *root_bh,
125 struct ocfs2_xattr_value_root *xv,
126 u32 cpos, u32 phys_cpos, u32 len,
127 - struct ocfs2_cached_dealloc_ctxt *dealloc)
128 + struct ocfs2_xattr_set_ctxt *ctxt)
129 {
130 int ret;
131 u64 phys_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys_cpos);
132 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
133 handle_t *handle;
134 - struct ocfs2_alloc_context *meta_ac = NULL;
135 struct ocfs2_extent_tree et;
136
137 ocfs2_init_xattr_value_extent_tree(&et, inode, root_bh, xv);
138
139 - ret = ocfs2_lock_allocators(inode, &et, 0, 1, NULL, &meta_ac);
140 - if (ret) {
141 - mlog_errno(ret);
142 - return ret;
143 - }
144 -
145 handle = ocfs2_start_trans(osb, OCFS2_REMOVE_EXTENT_CREDITS);
146 if (IS_ERR(handle)) {
147 ret = PTR_ERR(handle);
148 @@ -483,8 +468,8 @@ static int __ocfs2_remove_xattr_range(struct inode *inode,
149 goto out_commit;
150 }
151
152 - ret = ocfs2_remove_extent(inode, &et, cpos, len, handle, meta_ac,
153 - dealloc);
154 + ret = ocfs2_remove_extent(inode, &et, cpos, len, handle, ctxt->meta_ac,
155 + &ctxt->dealloc);
156 if (ret) {
157 mlog_errno(ret);
158 goto out_commit;
159 @@ -498,17 +483,13 @@ static int __ocfs2_remove_xattr_range(struct inode *inode,
160 goto out_commit;
161 }
162
163 - ret = ocfs2_cache_cluster_dealloc(dealloc, phys_blkno, len);
164 + ret = ocfs2_cache_cluster_dealloc(&ctxt->dealloc, phys_blkno, len);
165 if (ret)
166 mlog_errno(ret);
167
168 out_commit:
169 ocfs2_commit_trans(osb, handle);
170 out:
171 -
172 - if (meta_ac)
173 - ocfs2_free_alloc_context(meta_ac);
174 -
175 return ret;
176 }
177
178 @@ -516,15 +497,12 @@ static int ocfs2_xattr_shrink_size(struct inode *inode,
179 u32 old_clusters,
180 u32 new_clusters,
181 struct buffer_head *root_bh,
182 - struct ocfs2_xattr_value_root *xv)
183 + struct ocfs2_xattr_value_root *xv,
184 + struct ocfs2_xattr_set_ctxt *ctxt)
185 {
186 int ret = 0;
187 u32 trunc_len, cpos, phys_cpos, alloc_size;
188 u64 block;
189 - struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
190 - struct ocfs2_cached_dealloc_ctxt dealloc;
191 -
192 - ocfs2_init_dealloc_ctxt(&dealloc);
193
194 if (old_clusters <= new_clusters)
195 return 0;
196 @@ -544,7 +522,7 @@ static int ocfs2_xattr_shrink_size(struct inode *inode,
197
198 ret = __ocfs2_remove_xattr_range(inode, root_bh, xv, cpos,
199 phys_cpos, alloc_size,
200 - &dealloc);
201 + ctxt);
202 if (ret) {
203 mlog_errno(ret);
204 goto out;
205 @@ -558,16 +536,14 @@ static int ocfs2_xattr_shrink_size(struct inode *inode,
206 }
207
208 out:
209 - ocfs2_schedule_truncate_log_flush(osb, 1);
210 - ocfs2_run_deallocs(osb, &dealloc);
211 -
212 return ret;
213 }
214
215 static int ocfs2_xattr_value_truncate(struct inode *inode,
216 struct buffer_head *root_bh,
217 struct ocfs2_xattr_value_root *xv,
218 - int len)
219 + int len,
220 + struct ocfs2_xattr_set_ctxt *ctxt)
221 {
222 int ret;
223 u32 new_clusters = ocfs2_clusters_for_bytes(inode->i_sb, len);
224 @@ -579,11 +555,11 @@ static int ocfs2_xattr_value_truncate(struct inode *inode,
225 if (new_clusters > old_clusters)
226 ret = ocfs2_xattr_extend_allocation(inode,
227 new_clusters - old_clusters,
228 - root_bh, xv);
229 + root_bh, xv, ctxt);
230 else
231 ret = ocfs2_xattr_shrink_size(inode,
232 old_clusters, new_clusters,
233 - root_bh, xv);
234 + root_bh, xv, ctxt);
235
236 return ret;
237 }
238 @@ -1167,6 +1143,7 @@ out:
239 static int ocfs2_xattr_set_value_outside(struct inode *inode,
240 struct ocfs2_xattr_info *xi,
241 struct ocfs2_xattr_search *xs,
242 + struct ocfs2_xattr_set_ctxt *ctxt,
243 size_t offs)
244 {
245 size_t name_len = strlen(xi->name);
246 @@ -1186,7 +1163,7 @@ static int ocfs2_xattr_set_value_outside(struct inode *inode,
247 xv->xr_list.l_next_free_rec = 0;
248
249 ret = ocfs2_xattr_value_truncate(inode, xs->xattr_bh, xv,
250 - xi->value_len);
251 + xi->value_len, ctxt);
252 if (ret < 0) {
253 mlog_errno(ret);
254 return ret;
255 @@ -1317,6 +1294,7 @@ static void ocfs2_xattr_set_entry_local(struct inode *inode,
256 static int ocfs2_xattr_set_entry(struct inode *inode,
257 struct ocfs2_xattr_info *xi,
258 struct ocfs2_xattr_search *xs,
259 + struct ocfs2_xattr_set_ctxt *ctxt,
260 int flag)
261 {
262 struct ocfs2_xattr_entry *last;
263 @@ -1387,7 +1365,7 @@ static int ocfs2_xattr_set_entry(struct inode *inode,
264 if (ocfs2_xattr_is_local(xs->here) && size == size_l) {
265 /* Replace existing local xattr with tree root */
266 ret = ocfs2_xattr_set_value_outside(inode, xi, xs,
267 - offs);
268 + ctxt, offs);
269 if (ret < 0)
270 mlog_errno(ret);
271 goto out;
272 @@ -1406,7 +1384,8 @@ static int ocfs2_xattr_set_entry(struct inode *inode,
273 ret = ocfs2_xattr_value_truncate(inode,
274 xs->xattr_bh,
275 xv,
276 - xi->value_len);
277 + xi->value_len,
278 + ctxt);
279 if (ret < 0) {
280 mlog_errno(ret);
281 goto out;
282 @@ -1436,7 +1415,8 @@ static int ocfs2_xattr_set_entry(struct inode *inode,
283 ret = ocfs2_xattr_value_truncate(inode,
284 xs->xattr_bh,
285 xv,
286 - 0);
287 + 0,
288 + ctxt);
289 if (ret < 0)
290 mlog_errno(ret);
291 }
292 @@ -1531,7 +1511,7 @@ out_commit:
293 * This is the second step for value size > INLINE_SIZE.
294 */
295 size_t offs = le16_to_cpu(xs->here->xe_name_offset);
296 - ret = ocfs2_xattr_set_value_outside(inode, xi, xs, offs);
297 + ret = ocfs2_xattr_set_value_outside(inode, xi, xs, ctxt, offs);
298 if (ret < 0) {
299 int ret2;
300
301 @@ -1555,6 +1535,10 @@ static int ocfs2_remove_value_outside(struct inode*inode,
302 struct ocfs2_xattr_header *header)
303 {
304 int ret = 0, i;
305 + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
306 + struct ocfs2_xattr_set_ctxt ctxt = { NULL, NULL, };
307 +
308 + ocfs2_init_dealloc_ctxt(&ctxt.dealloc);
309
310 for (i = 0; i < le16_to_cpu(header->xh_count); i++) {
311 struct ocfs2_xattr_entry *entry = &header->xh_entries[i];
312 @@ -1567,14 +1551,17 @@ static int ocfs2_remove_value_outside(struct inode*inode,
313 le16_to_cpu(entry->xe_name_offset);
314 xv = (struct ocfs2_xattr_value_root *)
315 (val + OCFS2_XATTR_SIZE(entry->xe_name_len));
316 - ret = ocfs2_xattr_value_truncate(inode, bh, xv, 0);
317 + ret = ocfs2_xattr_value_truncate(inode, bh, xv,
318 + 0, &ctxt);
319 if (ret < 0) {
320 mlog_errno(ret);
321 - return ret;
322 + break;
323 }
324 }
325 }
326
327 + ocfs2_schedule_truncate_log_flush(osb, 1);
328 + ocfs2_run_deallocs(osb, &ctxt.dealloc);
329 return ret;
330 }
331
332 @@ -1836,7 +1823,8 @@ static int ocfs2_xattr_ibody_find(struct inode *inode,
333 */
334 static int ocfs2_xattr_ibody_set(struct inode *inode,
335 struct ocfs2_xattr_info *xi,
336 - struct ocfs2_xattr_search *xs)
337 + struct ocfs2_xattr_search *xs,
338 + struct ocfs2_xattr_set_ctxt *ctxt)
339 {
340 struct ocfs2_inode_info *oi = OCFS2_I(inode);
341 struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data;
342 @@ -1853,7 +1841,7 @@ static int ocfs2_xattr_ibody_set(struct inode *inode,
343 }
344 }
345
346 - ret = ocfs2_xattr_set_entry(inode, xi, xs,
347 + ret = ocfs2_xattr_set_entry(inode, xi, xs, ctxt,
348 (OCFS2_INLINE_XATTR_FL | OCFS2_HAS_XATTR_FL));
349 out:
350 up_write(&oi->ip_alloc_sem);
351 @@ -1926,12 +1914,12 @@ cleanup:
352 */
353 static int ocfs2_xattr_block_set(struct inode *inode,
354 struct ocfs2_xattr_info *xi,
355 - struct ocfs2_xattr_search *xs)
356 + struct ocfs2_xattr_search *xs,
357 + struct ocfs2_xattr_set_ctxt *ctxt)
358 {
359 struct buffer_head *new_bh = NULL;
360 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
361 struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data;
362 - struct ocfs2_alloc_context *meta_ac = NULL;
363 handle_t *handle = NULL;
364 struct ocfs2_xattr_block *xblk = NULL;
365 u16 suballoc_bit_start;
366 @@ -1940,15 +1928,6 @@ static int ocfs2_xattr_block_set(struct inode *inode,
367 int ret;
368
369 if (!xs->xattr_bh) {
370 - /*
371 - * Alloc one external block for extended attribute
372 - * outside of inode.
373 - */
374 - ret = ocfs2_reserve_new_metadata_blocks(osb, 1, &meta_ac);
375 - if (ret < 0) {
376 - mlog_errno(ret);
377 - goto out;
378 - }
379 handle = ocfs2_start_trans(osb,
380 OCFS2_XATTR_BLOCK_CREATE_CREDITS);
381 if (IS_ERR(handle)) {
382 @@ -1963,7 +1942,7 @@ static int ocfs2_xattr_block_set(struct inode *inode,
383 goto out_commit;
384 }
385
386 - ret = ocfs2_claim_metadata(osb, handle, meta_ac, 1,
387 + ret = ocfs2_claim_metadata(osb, handle, ctxt->meta_ac, 1,
388 &suballoc_bit_start, &num_got,
389 &first_blkno);
390 if (ret < 0) {
391 @@ -1996,7 +1975,6 @@ static int ocfs2_xattr_block_set(struct inode *inode,
392 xs->end = (void *)xblk + inode->i_sb->s_blocksize;
393 xs->here = xs->header->xh_entries;
394
395 -
396 ret = ocfs2_journal_dirty(handle, new_bh);
397 if (ret < 0) {
398 mlog_errno(ret);
399 @@ -2009,8 +1987,6 @@ static int ocfs2_xattr_block_set(struct inode *inode,
400 out_commit:
401 ocfs2_commit_trans(osb, handle);
402 out:
403 - if (meta_ac)
404 - ocfs2_free_alloc_context(meta_ac);
405 if (ret < 0)
406 return ret;
407 } else
408 @@ -2018,22 +1994,266 @@ out:
409
410 if (!(le16_to_cpu(xblk->xb_flags) & OCFS2_XATTR_INDEXED)) {
411 /* Set extended attribute into external block */
412 - ret = ocfs2_xattr_set_entry(inode, xi, xs, OCFS2_HAS_XATTR_FL);
413 + ret = ocfs2_xattr_set_entry(inode, xi, xs, ctxt,
414 + OCFS2_HAS_XATTR_FL);
415 if (!ret || ret != -ENOSPC)
416 goto end;
417
418 - ret = ocfs2_xattr_create_index_block(inode, xs);
419 + ret = ocfs2_xattr_create_index_block(inode, xs, ctxt);
420 if (ret)
421 goto end;
422 }
423
424 - ret = ocfs2_xattr_set_entry_index_block(inode, xi, xs);
425 + ret = ocfs2_xattr_set_entry_index_block(inode, xi, xs, ctxt);
426
427 end:
428
429 return ret;
430 }
431
432 +/* Check whether the new xattr can be inserted into the inode. */
433 +static int ocfs2_xattr_can_be_in_inode(struct inode *inode,
434 + struct ocfs2_xattr_info *xi,
435 + struct ocfs2_xattr_search *xs)
436 +{
437 + u64 value_size;
438 + struct ocfs2_xattr_entry *last;
439 + int free, i;
440 + size_t min_offs = xs->end - xs->base;
441 +
442 + if (!xs->header)
443 + return 0;
444 +
445 + last = xs->header->xh_entries;
446 +
447 + for (i = 0; i < le16_to_cpu(xs->header->xh_count); i++) {
448 + size_t offs = le16_to_cpu(last->xe_name_offset);
449 + if (offs < min_offs)
450 + min_offs = offs;
451 + last += 1;
452 + }
453 +
454 + free = min_offs - ((void *)last - xs->base) - sizeof(__u32);
455 + if (free < 0)
456 + return 0;
457 +
458 + BUG_ON(!xs->not_found);
459 +
460 + if (xi->value_len > OCFS2_XATTR_INLINE_SIZE)
461 + value_size = OCFS2_XATTR_ROOT_SIZE;
462 + else
463 + value_size = OCFS2_XATTR_SIZE(xi->value_len);
464 +
465 + if (free >= sizeof(struct ocfs2_xattr_entry) +
466 + OCFS2_XATTR_SIZE(strlen(xi->name)) + value_size)
467 + return 1;
468 +
469 + return 0;
470 +}
471 +
472 +static int ocfs2_calc_xattr_set_need(struct inode *inode,
473 + struct ocfs2_dinode *di,
474 + struct ocfs2_xattr_info *xi,
475 + struct ocfs2_xattr_search *xis,
476 + struct ocfs2_xattr_search *xbs,
477 + int *clusters_need,
478 + int *meta_need)
479 +{
480 + int ret = 0, old_in_xb = 0;
481 + int clusters_add = 0, meta_add = 0;
482 + struct buffer_head *bh = NULL;
483 + struct ocfs2_xattr_block *xb = NULL;
484 + struct ocfs2_xattr_entry *xe = NULL;
485 + struct ocfs2_xattr_value_root *xv = NULL;
486 + char *base = NULL;
487 + int name_offset, name_len = 0;
488 + u32 new_clusters = ocfs2_clusters_for_bytes(inode->i_sb,
489 + xi->value_len);
490 + u64 value_size;
491 +
492 + /*
493 + * delete a xattr doesn't need metadata and cluster allocation.
494 + * so return.
495 + */
496 + if (!xi->value)
497 + goto out;
498 +
499 + if (xis->not_found && xbs->not_found) {
500 + if (xi->value_len > OCFS2_XATTR_INLINE_SIZE)
501 + clusters_add += new_clusters;
502 +
503 + goto meta_guess;
504 + }
505 +
506 + if (!xis->not_found) {
507 + xe = xis->here;
508 + name_offset = le16_to_cpu(xe->xe_name_offset);
509 + name_len = OCFS2_XATTR_SIZE(xe->xe_name_len);
510 + base = xis->base;
511 + } else {
512 + int i, block_off;
513 + xb = (struct ocfs2_xattr_block *)xbs->xattr_bh->b_data;
514 + xe = xbs->here;
515 + name_offset = le16_to_cpu(xe->xe_name_offset);
516 + name_len = OCFS2_XATTR_SIZE(xe->xe_name_len);
517 + i = xbs->here - xbs->header->xh_entries;
518 + old_in_xb = 1;
519 +
520 + if (le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED) {
521 + ret = ocfs2_xattr_bucket_get_name_value(inode,
522 + bucket_xh(xbs->bucket),
523 + i, &block_off,
524 + &name_offset);
525 + base = bucket_block(xbs->bucket, block_off);
526 + } else
527 + base = xbs->base;
528 + }
529 +
530 + /* do cluster allocation guess first. */
531 + value_size = le64_to_cpu(xe->xe_value_size);
532 +
533 + if (old_in_xb) {
534 + /*
535 + * In xattr set, we always try to set the xe in inode first,
536 + * so if it can be inserted into inode successfully, the old
537 + * one will be removed from the xattr block, and this xattr
538 + * will be inserted into inode as a new xattr in inode.
539 + */
540 + if (ocfs2_xattr_can_be_in_inode(inode, xi, xis)) {
541 + clusters_add += new_clusters;
542 + goto out;
543 + }
544 + }
545 +
546 + if (xi->value_len > OCFS2_XATTR_INLINE_SIZE) {
547 + /* the new values will be stored outside. */
548 + u32 old_clusters = 0;
549 +
550 + if (!ocfs2_xattr_is_local(xe)) {
551 + old_clusters = ocfs2_clusters_for_bytes(inode->i_sb,
552 + value_size);
553 + xv = (struct ocfs2_xattr_value_root *)
554 + (base + name_offset + name_len);
555 + } else
556 + xv = &def_xv.xv;
557 +
558 + if (old_clusters >= new_clusters)
559 + goto out;
560 + else {
561 + meta_add += ocfs2_extend_meta_needed(&xv->xr_list);
562 + clusters_add += new_clusters - old_clusters;
563 + goto out;
564 + }
565 + } else {
566 + /*
567 + * Now the new value will be stored inside. So if the new
568 + * value is smaller than the size of value root or the old
569 + * value, we don't need any allocation, otherwise we have
570 + * to guess metadata allocation.
571 + */
572 + if ((ocfs2_xattr_is_local(xe) && value_size >= xi->value_len) ||
573 + (!ocfs2_xattr_is_local(xe) &&
574 + OCFS2_XATTR_ROOT_SIZE >= xi->value_len))
575 + goto out;
576 + }
577 +
578 +meta_guess:
579 + /* calculate metadata allocation. */
580 + if (di->i_xattr_loc) {
581 + if (!xbs->xattr_bh) {
582 + ret = ocfs2_read_block(inode,
583 + le64_to_cpu(di->i_xattr_loc),
584 + &bh);
585 + if (ret) {
586 + mlog_errno(ret);
587 + goto out;
588 + }
589 +
590 + xb = (struct ocfs2_xattr_block *)bh->b_data;
591 + } else
592 + xb = (struct ocfs2_xattr_block *)xbs->xattr_bh->b_data;
593 +
594 + if (le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED) {
595 + struct ocfs2_extent_list *el =
596 + &xb->xb_attrs.xb_root.xt_list;
597 + meta_add += ocfs2_extend_meta_needed(el);
598 + }
599 +
600 + /*
601 + * This cluster will be used either for new bucket or for
602 + * new xattr block.
603 + * If the cluster size is the same as the bucket size, one
604 + * more is needed since we may need to extend the bucket
605 + * also.
606 + */
607 + clusters_add += 1;
608 + if (OCFS2_XATTR_BUCKET_SIZE ==
609 + OCFS2_SB(inode->i_sb)->s_clustersize)
610 + clusters_add += 1;
611 + } else
612 + meta_add += 1;
613 +out:
614 + if (clusters_need)
615 + *clusters_need = clusters_add;
616 + if (meta_need)
617 + *meta_need = meta_add;
618 + brelse(bh);
619 + return ret;
620 +}
621 +
622 +static int ocfs2_init_xattr_set_ctxt(struct inode *inode,
623 + struct ocfs2_dinode *di,
624 + struct ocfs2_xattr_info *xi,
625 + struct ocfs2_xattr_search *xis,
626 + struct ocfs2_xattr_search *xbs,
627 + struct ocfs2_xattr_set_ctxt *ctxt)
628 +{
629 + int clusters_add, meta_add, ret;
630 + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
631 +
632 + memset(ctxt, 0, sizeof(struct ocfs2_xattr_set_ctxt));
633 +
634 + ocfs2_init_dealloc_ctxt(&ctxt->dealloc);
635 +
636 + ret = ocfs2_calc_xattr_set_need(inode, di, xi, xis, xbs,
637 + &clusters_add, &meta_add);
638 + if (ret) {
639 + mlog_errno(ret);
640 + return ret;
641 + }
642 +
643 + mlog(0, "Set xattr %s, reserve meta blocks = %d, clusters = %d\n",
644 + xi->name, meta_add, clusters_add);
645 +
646 + if (meta_add) {
647 + ret = ocfs2_reserve_new_metadata_blocks(osb, meta_add,
648 + &ctxt->meta_ac);
649 + if (ret) {
650 + mlog_errno(ret);
651 + goto out;
652 + }
653 + }
654 +
655 + if (clusters_add) {
656 + ret = ocfs2_reserve_clusters(osb, clusters_add, &ctxt->data_ac);
657 + if (ret)
658 + mlog_errno(ret);
659 + }
660 +out:
661 + if (ret) {
662 + if (ctxt->meta_ac) {
663 + ocfs2_free_alloc_context(ctxt->meta_ac);
664 + ctxt->meta_ac = NULL;
665 + }
666 +
667 + /*
668 + * We cannot have an error and a non null ctxt->data_ac.
669 + */
670 + }
671 +
672 + return ret;
673 +}
674 +
675 /*
676 * ocfs2_xattr_set()
677 *
678 @@ -2051,6 +2271,8 @@ int ocfs2_xattr_set(struct inode *inode,
679 struct buffer_head *di_bh = NULL;
680 struct ocfs2_dinode *di;
681 int ret;
682 + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
683 + struct ocfs2_xattr_set_ctxt ctxt = { NULL, NULL, };
684
685 struct ocfs2_xattr_info xi = {
686 .name_index = name_index,
687 @@ -2115,15 +2337,21 @@ int ocfs2_xattr_set(struct inode *inode,
688 goto cleanup;
689 }
690
691 + ret = ocfs2_init_xattr_set_ctxt(inode, di, &xi, &xis, &xbs, &ctxt);
692 + if (ret) {
693 + mlog_errno(ret);
694 + goto cleanup;
695 + }
696 +
697 if (!value) {
698 /* Remove existing extended attribute */
699 if (!xis.not_found)
700 - ret = ocfs2_xattr_ibody_set(inode, &xi, &xis);
701 + ret = ocfs2_xattr_ibody_set(inode, &xi, &xis, &ctxt);
702 else if (!xbs.not_found)
703 - ret = ocfs2_xattr_block_set(inode, &xi, &xbs);
704 + ret = ocfs2_xattr_block_set(inode, &xi, &xbs, &ctxt);
705 } else {
706 /* We always try to set extended attribute into inode first*/
707 - ret = ocfs2_xattr_ibody_set(inode, &xi, &xis);
708 + ret = ocfs2_xattr_ibody_set(inode, &xi, &xis, &ctxt);
709 if (!ret && !xbs.not_found) {
710 /*
711 * If succeed and that extended attribute existing in
712 @@ -2131,7 +2359,7 @@ int ocfs2_xattr_set(struct inode *inode,
713 */
714 xi.value = NULL;
715 xi.value_len = 0;
716 - ret = ocfs2_xattr_block_set(inode, &xi, &xbs);
717 + ret = ocfs2_xattr_block_set(inode, &xi, &xbs, &ctxt);
718 } else if (ret == -ENOSPC) {
719 if (di->i_xattr_loc && !xbs.xattr_bh) {
720 ret = ocfs2_xattr_block_find(inode, name_index,
721 @@ -2143,9 +2371,9 @@ int ocfs2_xattr_set(struct inode *inode,
722 * If no space in inode, we will set extended attribute
723 * into external block.
724 */
725 - ret = ocfs2_xattr_block_set(inode, &xi, &xbs);
726 + ret = ocfs2_xattr_block_set(inode, &xi, &xbs, &ctxt);
727 if (ret)
728 - goto cleanup;
729 + goto free;
730 if (!xis.not_found) {
731 /*
732 * If succeed and that extended attribute
733 @@ -2153,10 +2381,19 @@ int ocfs2_xattr_set(struct inode *inode,
734 */
735 xi.value = NULL;
736 xi.value_len = 0;
737 - ret = ocfs2_xattr_ibody_set(inode, &xi, &xis);
738 + ret = ocfs2_xattr_ibody_set(inode, &xi,
739 + &xis, &ctxt);
740 }
741 }
742 }
743 +free:
744 + if (ctxt.data_ac)
745 + ocfs2_free_alloc_context(ctxt.data_ac);
746 + if (ctxt.meta_ac)
747 + ocfs2_free_alloc_context(ctxt.meta_ac);
748 + if (ocfs2_dealloc_has_cluster(&ctxt.dealloc))
749 + ocfs2_schedule_truncate_log_flush(osb, 1);
750 + ocfs2_run_deallocs(osb, &ctxt.dealloc);
751 cleanup:
752 up_write(&OCFS2_I(inode)->ip_xattr_sem);
753 ocfs2_inode_unlock(inode, 1);
754 @@ -2734,7 +2971,8 @@ static void ocfs2_xattr_update_xattr_search(struct inode *inode,
755 }
756
757 static int ocfs2_xattr_create_index_block(struct inode *inode,
758 - struct ocfs2_xattr_search *xs)
759 + struct ocfs2_xattr_search *xs,
760 + struct ocfs2_xattr_set_ctxt *ctxt)
761 {
762 int ret, credits = OCFS2_SUBALLOC_ALLOC;
763 u32 bit_off, len;
764 @@ -2742,7 +2980,6 @@ static int ocfs2_xattr_create_index_block(struct inode *inode,
765 handle_t *handle;
766 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
767 struct ocfs2_inode_info *oi = OCFS2_I(inode);
768 - struct ocfs2_alloc_context *data_ac;
769 struct buffer_head *xb_bh = xs->xattr_bh;
770 struct ocfs2_xattr_block *xb =
771 (struct ocfs2_xattr_block *)xb_bh->b_data;
772 @@ -2755,12 +2992,6 @@ static int ocfs2_xattr_create_index_block(struct inode *inode,
773 BUG_ON(xb_flags & OCFS2_XATTR_INDEXED);
774 BUG_ON(!xs->bucket);
775
776 - ret = ocfs2_reserve_clusters(osb, 1, &data_ac);
777 - if (ret) {
778 - mlog_errno(ret);
779 - goto out;
780 - }
781 -
782 /*
783 * XXX:
784 * We can use this lock for now, and maybe move to a dedicated mutex
785 @@ -2787,7 +3018,8 @@ static int ocfs2_xattr_create_index_block(struct inode *inode,
786 goto out_commit;
787 }
788
789 - ret = ocfs2_claim_clusters(osb, handle, data_ac, 1, &bit_off, &len);
790 + ret = __ocfs2_claim_clusters(osb, handle, ctxt->data_ac,
791 + 1, 1, &bit_off, &len);
792 if (ret) {
793 mlog_errno(ret);
794 goto out_commit;
795 @@ -2850,10 +3082,6 @@ out_commit:
796 out_sem:
797 up_write(&oi->ip_alloc_sem);
798
799 -out:
800 - if (data_ac)
801 - ocfs2_free_alloc_context(data_ac);
802 -
803 return ret;
804 }
805
806 @@ -3614,7 +3842,8 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode,
807 u32 *num_clusters,
808 u32 prev_cpos,
809 u64 prev_blkno,
810 - int *extend)
811 + int *extend,
812 + struct ocfs2_xattr_set_ctxt *ctxt)
813 {
814 int ret, credits;
815 u16 bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1);
816 @@ -3622,8 +3851,6 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode,
817 u32 clusters_to_add = 1, bit_off, num_bits, v_start = 0;
818 u64 block;
819 handle_t *handle = NULL;
820 - struct ocfs2_alloc_context *data_ac = NULL;
821 - struct ocfs2_alloc_context *meta_ac = NULL;
822 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
823 struct ocfs2_extent_tree et;
824
825 @@ -3634,13 +3861,6 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode,
826
827 ocfs2_init_xattr_tree_extent_tree(&et, inode, root_bh);
828
829 - ret = ocfs2_lock_allocators(inode, &et, clusters_to_add, 0,
830 - &data_ac, &meta_ac);
831 - if (ret) {
832 - mlog_errno(ret);
833 - goto leave;
834 - }
835 -
836 credits = ocfs2_calc_extend_credits(osb->sb, et.et_root_el,
837 clusters_to_add);
838 handle = ocfs2_start_trans(osb, credits);
839 @@ -3658,7 +3878,7 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode,
840 goto leave;
841 }
842
843 - ret = __ocfs2_claim_clusters(osb, handle, data_ac, 1,
844 + ret = __ocfs2_claim_clusters(osb, handle, ctxt->data_ac, 1,
845 clusters_to_add, &bit_off, &num_bits);
846 if (ret < 0) {
847 if (ret != -ENOSPC)
848 @@ -3719,7 +3939,7 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode,
849 mlog(0, "Insert %u clusters at block %llu for xattr at %u\n",
850 num_bits, (unsigned long long)block, v_start);
851 ret = ocfs2_insert_extent(osb, handle, inode, &et, v_start, block,
852 - num_bits, 0, meta_ac);
853 + num_bits, 0, ctxt->meta_ac);
854 if (ret < 0) {
855 mlog_errno(ret);
856 goto leave;
857 @@ -3734,10 +3954,6 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode,
858 leave:
859 if (handle)
860 ocfs2_commit_trans(osb, handle);
861 - if (data_ac)
862 - ocfs2_free_alloc_context(data_ac);
863 - if (meta_ac)
864 - ocfs2_free_alloc_context(meta_ac);
865
866 return ret;
867 }
868 @@ -3821,7 +4037,8 @@ out:
869 */
870 static int ocfs2_add_new_xattr_bucket(struct inode *inode,
871 struct buffer_head *xb_bh,
872 - struct buffer_head *header_bh)
873 + struct buffer_head *header_bh,
874 + struct ocfs2_xattr_set_ctxt *ctxt)
875 {
876 struct ocfs2_xattr_header *first_xh = NULL;
877 struct buffer_head *first_bh = NULL;
878 @@ -3872,7 +4089,8 @@ static int ocfs2_add_new_xattr_bucket(struct inode *inode,
879 &num_clusters,
880 e_cpos,
881 p_blkno,
882 - &extend);
883 + &extend,
884 + ctxt);
885 if (ret) {
886 mlog_errno(ret);
887 goto out;
888 @@ -4147,7 +4365,8 @@ out:
889 static int ocfs2_xattr_bucket_value_truncate(struct inode *inode,
890 struct buffer_head *header_bh,
891 int xe_off,
892 - int len)
893 + int len,
894 + struct ocfs2_xattr_set_ctxt *ctxt)
895 {
896 int ret, offset;
897 u64 value_blk;
898 @@ -4182,7 +4401,7 @@ static int ocfs2_xattr_bucket_value_truncate(struct inode *inode,
899
900 mlog(0, "truncate %u in xattr bucket %llu to %d bytes.\n",
901 xe_off, (unsigned long long)header_bh->b_blocknr, len);
902 - ret = ocfs2_xattr_value_truncate(inode, value_bh, xv, len);
903 + ret = ocfs2_xattr_value_truncate(inode, value_bh, xv, len, ctxt);
904 if (ret) {
905 mlog_errno(ret);
906 goto out;
907 @@ -4200,8 +4419,9 @@ out:
908 }
909
910 static int ocfs2_xattr_bucket_value_truncate_xs(struct inode *inode,
911 - struct ocfs2_xattr_search *xs,
912 - int len)
913 + struct ocfs2_xattr_search *xs,
914 + int len,
915 + struct ocfs2_xattr_set_ctxt *ctxt)
916 {
917 int ret, offset;
918 struct ocfs2_xattr_entry *xe = xs->here;
919 @@ -4211,7 +4431,7 @@ static int ocfs2_xattr_bucket_value_truncate_xs(struct inode *inode,
920
921 offset = xe - xh->xh_entries;
922 ret = ocfs2_xattr_bucket_value_truncate(inode, xs->bucket->bu_bhs[0],
923 - offset, len);
924 + offset, len, ctxt);
925 if (ret)
926 mlog_errno(ret);
927
928 @@ -4375,7 +4595,8 @@ out_commit:
929 */
930 static int ocfs2_xattr_set_in_bucket(struct inode *inode,
931 struct ocfs2_xattr_info *xi,
932 - struct ocfs2_xattr_search *xs)
933 + struct ocfs2_xattr_search *xs,
934 + struct ocfs2_xattr_set_ctxt *ctxt)
935 {
936 int ret, local = 1;
937 size_t value_len;
938 @@ -4403,7 +4624,8 @@ static int ocfs2_xattr_set_in_bucket(struct inode *inode,
939 value_len = 0;
940
941 ret = ocfs2_xattr_bucket_value_truncate_xs(inode, xs,
942 - value_len);
943 + value_len,
944 + ctxt);
945 if (ret)
946 goto out;
947
948 @@ -4434,7 +4656,7 @@ static int ocfs2_xattr_set_in_bucket(struct inode *inode,
949
950 /* allocate the space now for the outside block storage. */
951 ret = ocfs2_xattr_bucket_value_truncate_xs(inode, xs,
952 - value_len);
953 + value_len, ctxt);
954 if (ret) {
955 mlog_errno(ret);
956
957 @@ -4485,7 +4707,8 @@ static int ocfs2_check_xattr_bucket_collision(struct inode *inode,
958
959 static int ocfs2_xattr_set_entry_index_block(struct inode *inode,
960 struct ocfs2_xattr_info *xi,
961 - struct ocfs2_xattr_search *xs)
962 + struct ocfs2_xattr_search *xs,
963 + struct ocfs2_xattr_set_ctxt *ctxt)
964 {
965 struct ocfs2_xattr_header *xh;
966 struct ocfs2_xattr_entry *xe;
967 @@ -4603,7 +4826,8 @@ try_again:
968
969 ret = ocfs2_add_new_xattr_bucket(inode,
970 xs->xattr_bh,
971 - xs->bucket->bu_bhs[0]);
972 + xs->bucket->bu_bhs[0],
973 + ctxt);
974 if (ret) {
975 mlog_errno(ret);
976 goto out;
977 @@ -4622,7 +4846,7 @@ try_again:
978 }
979
980 xattr_set:
981 - ret = ocfs2_xattr_set_in_bucket(inode, xi, xs);
982 + ret = ocfs2_xattr_set_in_bucket(inode, xi, xs, ctxt);
983 out:
984 mlog_exit(ret);
985 return ret;
986 @@ -4636,6 +4860,10 @@ static int ocfs2_delete_xattr_in_bucket(struct inode *inode,
987 struct ocfs2_xattr_header *xh = bucket_xh(bucket);
988 u16 i;
989 struct ocfs2_xattr_entry *xe;
990 + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
991 + struct ocfs2_xattr_set_ctxt ctxt = {NULL, NULL,};
992 +
993 + ocfs2_init_dealloc_ctxt(&ctxt.dealloc);
994
995 for (i = 0; i < le16_to_cpu(xh->xh_count); i++) {
996 xe = &xh->xh_entries[i];
997 @@ -4644,13 +4872,16 @@ static int ocfs2_delete_xattr_in_bucket(struct inode *inode,
998
999 ret = ocfs2_xattr_bucket_value_truncate(inode,
1000 bucket->bu_bhs[0],
1001 - i, 0);
1002 + i, 0, &ctxt);
1003 if (ret) {
1004 mlog_errno(ret);
1005 break;
1006 }
1007 }
1008
1009 + ocfs2_schedule_truncate_log_flush(osb, 1);
1010 + ocfs2_run_deallocs(osb, &ctxt.dealloc);
1011 +
1012 return ret;
1013 }
1014
1015 --
1016 1.5.6
1017