]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/suse-2.6.27.39/patches.suse/ocfs2-xattr-Reserve-meta-data-at-the-beginning-of-o.patch
Imported linux-2.6.27.39 suse/xen patches.
[ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.suse / ocfs2-xattr-Reserve-meta-data-at-the-beginning-of-o.patch
CommitLineData
2cb7cef9
BS
1From: Tao Ma <tao.ma@oracle.com>
2Date: Wed, 12 Nov 2008 08:27:00 +0800
3Subject: ocfs2/xattr: Reserve meta/data at the beginning of ocfs2_xattr_set.
4Patch-mainline: 2.6.29
5
6In ocfs2 xattr set, we reserve metadata and clusters in any place
7they are needed. It is time-consuming and ineffective, so this
8patch try to reserve metadata and clusters at the beginning of
9ocfs2_xattr_set.
10
11Signed-off-by: Tao Ma <tao.ma@oracle.com>
12Signed-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
18diff --git a/fs/ocfs2/alloc.h b/fs/ocfs2/alloc.h
19index 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
33diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
34index 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--
10161.5.6
1017