]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - src/patches/suse-2.6.27.31/patches.suse/ocfs2-Add-extent-tree-operation-for-x.patch
Reenabled linux-xen, added patches for Xen Kernel Version 2.6.27.31,
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.suse / ocfs2-Add-extent-tree-operation-for-x.patch
1 From: Tao Ma <tao.ma@oracle.com>
2 Subject: [PATCH 07/16] ocfs2: Add extent tree operation for xattr value btrees
3 Patch-mainline: 2.6.28?
4 References: FATE302067
5
6 Add some thin wrappers around ocfs2_insert_extent() for each of the 3
7 different btree types, ocfs2_inode_insert_extent(),
8 ocfs2_xattr_value_insert_extent() and ocfs2_xattr_tree_insert_extent(). The
9 last is for the xattr index btree, which will be used in a followup patch.
10
11 All the old callers in file.c etc will call ocfs2_dinode_insert_extent(),
12 while the other two handle the xattr issue. And the init of extent tree are
13 handled by these functions.
14
15 When storing xattr value which is too large, we will allocate some clusters
16 for it and here ocfs2_extent_list and ocfs2_extent_rec will also be used. In
17 order to re-use the b-tree operation code, a new parameter named "private"
18 is added into ocfs2_extent_tree and it is used to indicate the root of
19 ocfs2_exent_list. The reason is that we can't deduce the root from the
20 buffer_head now. It may be in an inode, an ocfs2_xattr_block or even worse,
21 in any place in an ocfs2_xattr_bucket.
22
23 Signed-off-by: Tao Ma <tao.ma@oracle.com>
24 Signed-off-by: Mark Fasheh <mfasheh@suse.com>
25 ---
26 fs/ocfs2/Makefile | 3 +-
27 fs/ocfs2/alloc.c | 184 +++++++++++++++++++++-----
28 fs/ocfs2/alloc.h | 42 ++++--
29 fs/ocfs2/aops.c | 5 +-
30 fs/ocfs2/cluster/masklog.c | 1 +
31 fs/ocfs2/cluster/masklog.h | 1 +
32 fs/ocfs2/dir.c | 11 +-
33 fs/ocfs2/extent_map.c | 60 +++++++++
34 fs/ocfs2/extent_map.h | 3 +
35 fs/ocfs2/file.c | 9 +-
36 fs/ocfs2/suballoc.c | 5 +-
37 fs/ocfs2/suballoc.h | 3 +-
38 fs/ocfs2/xattr.c | 305 ++++++++++++++++++++++++++++++++++++++++++++
39 13 files changed, 568 insertions(+), 64 deletions(-)
40 create mode 100644 fs/ocfs2/xattr.c
41
42 Index: linux-2.6.26/fs/ocfs2/Makefile
43 ===================================================================
44 --- linux-2.6.26.orig/fs/ocfs2/Makefile
45 +++ linux-2.6.26/fs/ocfs2/Makefile
46 @@ -34,7 +34,8 @@ ocfs2-objs := \
47 symlink.o \
48 sysfile.o \
49 uptodate.o \
50 - ver.o
51 + ver.o \
52 + xattr.o \
53
54 ocfs2_stackglue-objs := stackglue.o
55 ocfs2_stack_o2cb-objs := stack_o2cb.o
56 Index: linux-2.6.26/fs/ocfs2/alloc.c
57 ===================================================================
58 --- linux-2.6.26.orig/fs/ocfs2/alloc.c
59 +++ linux-2.6.26/fs/ocfs2/alloc.c
60 @@ -78,6 +78,7 @@ struct ocfs2_extent_tree {
61 struct ocfs2_extent_tree_operations *eops;
62 struct buffer_head *root_bh;
63 struct ocfs2_extent_list *root_el;
64 + void *private;
65 };
66
67 static void ocfs2_dinode_set_last_eb_blk(struct ocfs2_extent_tree *et,
68 @@ -136,9 +137,50 @@ static struct ocfs2_extent_tree_operatio
69 .sanity_check = ocfs2_dinode_sanity_check,
70 };
71
72 +static void ocfs2_xattr_value_set_last_eb_blk(struct ocfs2_extent_tree *et,
73 + u64 blkno)
74 +{
75 + struct ocfs2_xattr_value_root *xv =
76 + (struct ocfs2_xattr_value_root *)et->private;
77 +
78 + xv->xr_last_eb_blk = cpu_to_le64(blkno);
79 +}
80 +
81 +static u64 ocfs2_xattr_value_get_last_eb_blk(struct ocfs2_extent_tree *et)
82 +{
83 + struct ocfs2_xattr_value_root *xv =
84 + (struct ocfs2_xattr_value_root *) et->private;
85 +
86 + return le64_to_cpu(xv->xr_last_eb_blk);
87 +}
88 +
89 +static void ocfs2_xattr_value_update_clusters(struct inode *inode,
90 + struct ocfs2_extent_tree *et,
91 + u32 clusters)
92 +{
93 + struct ocfs2_xattr_value_root *xv =
94 + (struct ocfs2_xattr_value_root *)et->private;
95 +
96 + le32_add_cpu(&xv->xr_clusters, clusters);
97 +}
98 +
99 +static int ocfs2_xattr_value_sanity_check(struct inode *inode,
100 + struct ocfs2_extent_tree *et)
101 +{
102 + return 0;
103 +}
104 +
105 +static struct ocfs2_extent_tree_operations ocfs2_xattr_et_ops = {
106 + .set_last_eb_blk = ocfs2_xattr_value_set_last_eb_blk,
107 + .get_last_eb_blk = ocfs2_xattr_value_get_last_eb_blk,
108 + .update_clusters = ocfs2_xattr_value_update_clusters,
109 + .sanity_check = ocfs2_xattr_value_sanity_check,
110 +};
111 +
112 static struct ocfs2_extent_tree*
113 ocfs2_new_extent_tree(struct buffer_head *bh,
114 - enum ocfs2_extent_tree_type et_type)
115 + enum ocfs2_extent_tree_type et_type,
116 + void *private)
117 {
118 struct ocfs2_extent_tree *et;
119
120 @@ -149,12 +191,16 @@ static struct ocfs2_extent_tree*
121 et->type = et_type;
122 get_bh(bh);
123 et->root_bh = bh;
124 + et->private = private;
125
126 - /* current we only support dinode extent. */
127 - BUG_ON(et->type != OCFS2_DINODE_EXTENT);
128 if (et_type == OCFS2_DINODE_EXTENT) {
129 et->root_el = &((struct ocfs2_dinode *)bh->b_data)->id2.i_list;
130 et->eops = &ocfs2_dinode_et_ops;
131 + } else if (et_type == OCFS2_XATTR_VALUE_EXTENT) {
132 + struct ocfs2_xattr_value_root *xv =
133 + (struct ocfs2_xattr_value_root *) private;
134 + et->root_el = &xv->xr_list;
135 + et->eops = &ocfs2_xattr_et_ops;
136 }
137
138 return et;
139 @@ -495,7 +541,8 @@ struct ocfs2_merge_ctxt {
140 int ocfs2_num_free_extents(struct ocfs2_super *osb,
141 struct inode *inode,
142 struct buffer_head *root_bh,
143 - enum ocfs2_extent_tree_type type)
144 + enum ocfs2_extent_tree_type type,
145 + void *private)
146 {
147 int retval;
148 struct ocfs2_extent_list *el = NULL;
149 @@ -517,6 +564,12 @@ int ocfs2_num_free_extents(struct ocfs2_
150 if (fe->i_last_eb_blk)
151 last_eb_blk = le64_to_cpu(fe->i_last_eb_blk);
152 el = &fe->id2.i_list;
153 + } else if (type == OCFS2_XATTR_VALUE_EXTENT) {
154 + struct ocfs2_xattr_value_root *xv =
155 + (struct ocfs2_xattr_value_root *) private;
156 +
157 + last_eb_blk = le64_to_cpu(xv->xr_last_eb_blk);
158 + el = &xv->xr_list;
159 }
160
161 if (last_eb_blk) {
162 @@ -4218,33 +4271,25 @@ out:
163 *
164 * The caller needs to update fe->i_clusters
165 */
166 -int ocfs2_insert_extent(struct ocfs2_super *osb,
167 - handle_t *handle,
168 - struct inode *inode,
169 - struct buffer_head *root_bh,
170 - u32 cpos,
171 - u64 start_blk,
172 - u32 new_clusters,
173 - u8 flags,
174 - struct ocfs2_alloc_context *meta_ac,
175 - enum ocfs2_extent_tree_type et_type)
176 +static int ocfs2_insert_extent(struct ocfs2_super *osb,
177 + handle_t *handle,
178 + struct inode *inode,
179 + struct buffer_head *root_bh,
180 + u32 cpos,
181 + u64 start_blk,
182 + u32 new_clusters,
183 + u8 flags,
184 + struct ocfs2_alloc_context *meta_ac,
185 + struct ocfs2_extent_tree *et)
186 {
187 int status;
188 int uninitialized_var(free_records);
189 struct buffer_head *last_eb_bh = NULL;
190 struct ocfs2_insert_type insert = {0, };
191 struct ocfs2_extent_rec rec;
192 - struct ocfs2_extent_tree *et = NULL;
193
194 BUG_ON(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL);
195
196 - et = ocfs2_new_extent_tree(root_bh, et_type);
197 - if (!et) {
198 - status = -ENOMEM;
199 - mlog_errno(status);
200 - goto bail;
201 - }
202 -
203 mlog(0, "add %u clusters at position %u to inode %llu\n",
204 new_clusters, cpos, (unsigned long long)OCFS2_I(inode)->ip_blkno);
205
206 @@ -4296,9 +4341,68 @@ bail:
207 if (last_eb_bh)
208 brelse(last_eb_bh);
209
210 + mlog_exit(status);
211 + return status;
212 +}
213 +
214 +int ocfs2_dinode_insert_extent(struct ocfs2_super *osb,
215 + handle_t *handle,
216 + struct inode *inode,
217 + struct buffer_head *root_bh,
218 + u32 cpos,
219 + u64 start_blk,
220 + u32 new_clusters,
221 + u8 flags,
222 + struct ocfs2_alloc_context *meta_ac)
223 +{
224 + int status;
225 + struct ocfs2_extent_tree *et = NULL;
226 +
227 + et = ocfs2_new_extent_tree(root_bh, OCFS2_DINODE_EXTENT, NULL);
228 + if (!et) {
229 + status = -ENOMEM;
230 + mlog_errno(status);
231 + goto bail;
232 + }
233 +
234 + status = ocfs2_insert_extent(osb, handle, inode, root_bh,
235 + cpos, start_blk, new_clusters,
236 + flags, meta_ac, et);
237 +
238 if (et)
239 ocfs2_free_extent_tree(et);
240 - mlog_exit(status);
241 +bail:
242 + return status;
243 +}
244 +
245 +int ocfs2_xattr_value_insert_extent(struct ocfs2_super *osb,
246 + handle_t *handle,
247 + struct inode *inode,
248 + struct buffer_head *root_bh,
249 + u32 cpos,
250 + u64 start_blk,
251 + u32 new_clusters,
252 + u8 flags,
253 + struct ocfs2_alloc_context *meta_ac,
254 + void *private)
255 +{
256 + int status;
257 + struct ocfs2_extent_tree *et = NULL;
258 +
259 + et = ocfs2_new_extent_tree(root_bh, OCFS2_XATTR_VALUE_EXTENT, private);
260 + if (!et) {
261 + status = -ENOMEM;
262 + mlog_errno(status);
263 + goto bail;
264 + }
265 +
266 + status = ocfs2_insert_extent(osb, handle, inode, root_bh,
267 + cpos, start_blk, new_clusters,
268 + flags, meta_ac, et);
269 +
270 + if (et)
271 + ocfs2_free_extent_tree(et);
272 +bail:
273 return status;
274 }
275
276 @@ -4320,7 +4424,8 @@ int ocfs2_add_clusters_in_btree(struct o
277 struct ocfs2_alloc_context *data_ac,
278 struct ocfs2_alloc_context *meta_ac,
279 enum ocfs2_alloc_restarted *reason_ret,
280 - enum ocfs2_extent_tree_type type)
281 + enum ocfs2_extent_tree_type type,
282 + void *private)
283 {
284 int status = 0;
285 int free_extents;
286 @@ -4334,7 +4439,8 @@ int ocfs2_add_clusters_in_btree(struct o
287 if (mark_unwritten)
288 flags = OCFS2_EXT_UNWRITTEN;
289
290 - free_extents = ocfs2_num_free_extents(osb, inode, root_bh, type);
291 + free_extents = ocfs2_num_free_extents(osb, inode, root_bh, type,
292 + private);
293 if (free_extents < 0) {
294 status = free_extents;
295 mlog_errno(status);
296 @@ -4381,9 +4487,16 @@ int ocfs2_add_clusters_in_btree(struct o
297 block = ocfs2_clusters_to_blocks(osb->sb, bit_off);
298 mlog(0, "Allocating %u clusters at block %u for inode %llu\n",
299 num_bits, bit_off, (unsigned long long)OCFS2_I(inode)->ip_blkno);
300 - status = ocfs2_insert_extent(osb, handle, inode, root_bh,
301 - *logical_offset, block, num_bits,
302 - flags, meta_ac, type);
303 + if (type == OCFS2_DINODE_EXTENT)
304 + status = ocfs2_dinode_insert_extent(osb, handle, inode, root_bh,
305 + *logical_offset, block,
306 + num_bits, flags, meta_ac);
307 + else
308 + status = ocfs2_xattr_value_insert_extent(osb, handle,
309 + inode, root_bh,
310 + *logical_offset,
311 + block, num_bits, flags,
312 + meta_ac, private);
313 if (status < 0) {
314 mlog_errno(status);
315 goto leave;
316 @@ -4664,7 +4777,8 @@ int ocfs2_mark_extent_written(struct ino
317 handle_t *handle, u32 cpos, u32 len, u32 phys,
318 struct ocfs2_alloc_context *meta_ac,
319 struct ocfs2_cached_dealloc_ctxt *dealloc,
320 - enum ocfs2_extent_tree_type et_type)
321 + enum ocfs2_extent_tree_type et_type,
322 + void *private)
323 {
324 int ret, index;
325 u64 start_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys);
326 @@ -4685,7 +4799,7 @@ int ocfs2_mark_extent_written(struct ino
327 goto out;
328 }
329
330 - et = ocfs2_new_extent_tree(root_bh, et_type);
331 + et = ocfs2_new_extent_tree(root_bh, et_type, private);
332 if (!et) {
333 ret = -ENOMEM;
334 mlog_errno(ret);
335 @@ -4973,7 +5087,8 @@ int ocfs2_remove_extent(struct inode *in
336 u32 cpos, u32 len, handle_t *handle,
337 struct ocfs2_alloc_context *meta_ac,
338 struct ocfs2_cached_dealloc_ctxt *dealloc,
339 - enum ocfs2_extent_tree_type et_type)
340 + enum ocfs2_extent_tree_type et_type,
341 + void *private)
342 {
343 int ret, index;
344 u32 rec_range, trunc_range;
345 @@ -4982,7 +5097,7 @@ int ocfs2_remove_extent(struct inode *in
346 struct ocfs2_path *path = NULL;
347 struct ocfs2_extent_tree *et = NULL;
348
349 - et = ocfs2_new_extent_tree(root_bh, et_type);
350 + et = ocfs2_new_extent_tree(root_bh, et_type, private);
351 if (!et) {
352 ret = -ENOMEM;
353 mlog_errno(ret);
354 @@ -6617,9 +6732,8 @@ int ocfs2_convert_inline_data_to_extents
355 * this proves to be false, we could always re-build
356 * the in-inode data from our pages.
357 */
358 - ret = ocfs2_insert_extent(osb, handle, inode, di_bh,
359 - 0, block, 1, 0,
360 - NULL, OCFS2_DINODE_EXTENT);
361 + ret = ocfs2_dinode_insert_extent(osb, handle, inode, di_bh,
362 + 0, block, 1, 0, NULL);
363 if (ret) {
364 mlog_errno(ret);
365 goto out_commit;
366 Index: linux-2.6.26/fs/ocfs2/alloc.h
367 ===================================================================
368 --- linux-2.6.26.orig/fs/ocfs2/alloc.h
369 +++ linux-2.6.26/fs/ocfs2/alloc.h
370 @@ -28,19 +28,29 @@
371
372 enum ocfs2_extent_tree_type {
373 OCFS2_DINODE_EXTENT = 0,
374 + OCFS2_XATTR_VALUE_EXTENT,
375 };
376
377 struct ocfs2_alloc_context;
378 -int ocfs2_insert_extent(struct ocfs2_super *osb,
379 - handle_t *handle,
380 - struct inode *inode,
381 - struct buffer_head *root_bh,
382 - u32 cpos,
383 - u64 start_blk,
384 - u32 new_clusters,
385 - u8 flags,
386 - struct ocfs2_alloc_context *meta_ac,
387 - enum ocfs2_extent_tree_type et_type);
388 +int ocfs2_dinode_insert_extent(struct ocfs2_super *osb,
389 + handle_t *handle,
390 + struct inode *inode,
391 + struct buffer_head *root_bh,
392 + u32 cpos,
393 + u64 start_blk,
394 + u32 new_clusters,
395 + u8 flags,
396 + struct ocfs2_alloc_context *meta_ac);
397 +int ocfs2_xattr_value_insert_extent(struct ocfs2_super *osb,
398 + handle_t *handle,
399 + struct inode *inode,
400 + struct buffer_head *root_bh,
401 + u32 cpos,
402 + u64 start_blk,
403 + u32 new_clusters,
404 + u8 flags,
405 + struct ocfs2_alloc_context *meta_ac,
406 + void *private);
407 enum ocfs2_alloc_restarted {
408 RESTART_NONE = 0,
409 RESTART_TRANS,
410 @@ -57,22 +67,26 @@ int ocfs2_add_clusters_in_btree(struct o
411 struct ocfs2_alloc_context *data_ac,
412 struct ocfs2_alloc_context *meta_ac,
413 enum ocfs2_alloc_restarted *reason_ret,
414 - enum ocfs2_extent_tree_type type);
415 + enum ocfs2_extent_tree_type type,
416 + void *private);
417 struct ocfs2_cached_dealloc_ctxt;
418 int ocfs2_mark_extent_written(struct inode *inode, struct buffer_head *root_bh,
419 handle_t *handle, u32 cpos, u32 len, u32 phys,
420 struct ocfs2_alloc_context *meta_ac,
421 struct ocfs2_cached_dealloc_ctxt *dealloc,
422 - enum ocfs2_extent_tree_type et_type);
423 + enum ocfs2_extent_tree_type et_type,
424 + void *private);
425 int ocfs2_remove_extent(struct inode *inode, struct buffer_head *root_bh,
426 u32 cpos, u32 len, handle_t *handle,
427 struct ocfs2_alloc_context *meta_ac,
428 struct ocfs2_cached_dealloc_ctxt *dealloc,
429 - enum ocfs2_extent_tree_type et_type);
430 + enum ocfs2_extent_tree_type et_type,
431 + void *private);
432 int ocfs2_num_free_extents(struct ocfs2_super *osb,
433 struct inode *inode,
434 struct buffer_head *root_bh,
435 - enum ocfs2_extent_tree_type et_type);
436 + enum ocfs2_extent_tree_type et_type,
437 + void *private);
438
439 /*
440 * how many new metadata chunks would an allocation need at maximum?
441 Index: linux-2.6.26/fs/ocfs2/aops.c
442 ===================================================================
443 --- linux-2.6.26.orig/fs/ocfs2/aops.c
444 +++ linux-2.6.26/fs/ocfs2/aops.c
445 @@ -1279,7 +1279,7 @@ static int ocfs2_write_cluster(struct ad
446 ret = ocfs2_mark_extent_written(inode, wc->w_di_bh,
447 wc->w_handle, cpos, 1, phys,
448 meta_ac, &wc->w_dealloc,
449 - OCFS2_DINODE_EXTENT);
450 + OCFS2_DINODE_EXTENT, NULL);
451 if (ret < 0) {
452 mlog_errno(ret);
453 goto out;
454 @@ -1721,7 +1721,8 @@ int ocfs2_write_begin_nolock(struct addr
455
456 ret = ocfs2_lock_allocators(inode, wc->w_di_bh, &di->id2.i_list,
457 clusters_to_alloc, extents_to_split,
458 - &data_ac, &meta_ac);
459 + &data_ac, &meta_ac,
460 + OCFS2_DINODE_EXTENT, NULL);
461 if (ret) {
462 mlog_errno(ret);
463 goto out;
464 Index: linux-2.6.26/fs/ocfs2/cluster/masklog.c
465 ===================================================================
466 --- linux-2.6.26.orig/fs/ocfs2/cluster/masklog.c
467 +++ linux-2.6.26/fs/ocfs2/cluster/masklog.c
468 @@ -109,6 +109,7 @@ static struct mlog_attribute mlog_attrs[
469 define_mask(CONN),
470 define_mask(QUORUM),
471 define_mask(EXPORT),
472 + define_mask(XATTR),
473 define_mask(ERROR),
474 define_mask(NOTICE),
475 define_mask(KTHREAD),
476 Index: linux-2.6.26/fs/ocfs2/cluster/masklog.h
477 ===================================================================
478 --- linux-2.6.26.orig/fs/ocfs2/cluster/masklog.h
479 +++ linux-2.6.26/fs/ocfs2/cluster/masklog.h
480 @@ -112,6 +112,7 @@
481 #define ML_CONN 0x0000000004000000ULL /* net connection management */
482 #define ML_QUORUM 0x0000000008000000ULL /* net connection quorum */
483 #define ML_EXPORT 0x0000000010000000ULL /* ocfs2 export operations */
484 +#define ML_XATTR 0x0000000020000000ULL /* ocfs2 extended attributes */
485 /* bits that are infrequently given and frequently matched in the high word */
486 #define ML_ERROR 0x0000000100000000ULL /* sent to KERN_ERR */
487 #define ML_NOTICE 0x0000000200000000ULL /* setn to KERN_NOTICE */
488 Index: linux-2.6.26/fs/ocfs2/dir.c
489 ===================================================================
490 --- linux-2.6.26.orig/fs/ocfs2/dir.c
491 +++ linux-2.6.26/fs/ocfs2/dir.c
492 @@ -1305,8 +1305,8 @@ static int ocfs2_expand_inline_dir(struc
493 * This should never fail as our extent list is empty and all
494 * related blocks have been journaled already.
495 */
496 - ret = ocfs2_insert_extent(osb, handle, dir, di_bh, 0, blkno, len, 0,
497 - NULL, OCFS2_DINODE_EXTENT);
498 + ret = ocfs2_dinode_insert_extent(osb, handle, dir, di_bh, 0, blkno,
499 + len, 0, NULL);
500 if (ret) {
501 mlog_errno(ret);
502 goto out_commit;
503 @@ -1337,8 +1337,8 @@ static int ocfs2_expand_inline_dir(struc
504 }
505 blkno = ocfs2_clusters_to_blocks(dir->i_sb, bit_off);
506
507 - ret = ocfs2_insert_extent(osb, handle, dir, di_bh, 1, blkno,
508 - len, 0, NULL, OCFS2_DINODE_EXTENT);
509 + ret = ocfs2_dinode_insert_extent(osb, handle, dir, di_bh, 1,
510 + blkno, len, 0, NULL);
511 if (ret) {
512 mlog_errno(ret);
513 goto out_commit;
514 @@ -1482,7 +1482,8 @@ static int ocfs2_extend_dir(struct ocfs2
515 spin_unlock(&OCFS2_I(dir)->ip_lock);
516 num_free_extents = ocfs2_num_free_extents(osb, dir,
517 parent_fe_bh,
518 - OCFS2_DINODE_EXTENT);
519 + OCFS2_DINODE_EXTENT,
520 + NULL);
521 if (num_free_extents < 0) {
522 status = num_free_extents;
523 mlog_errno(status);
524 Index: linux-2.6.26/fs/ocfs2/extent_map.c
525 ===================================================================
526 --- linux-2.6.26.orig/fs/ocfs2/extent_map.c
527 +++ linux-2.6.26/fs/ocfs2/extent_map.c
528 @@ -373,6 +373,66 @@ out:
529 return ret;
530 }
531
532 +int ocfs2_xattr_get_clusters(struct inode *inode, u32 v_cluster,
533 + u32 *p_cluster, u32 *num_clusters,
534 + struct ocfs2_extent_list *el)
535 +{
536 + int ret = 0, i;
537 + struct buffer_head *eb_bh = NULL;
538 + struct ocfs2_extent_block *eb;
539 + struct ocfs2_extent_rec *rec;
540 + u32 coff;
541 +
542 + if (el->l_tree_depth) {
543 + ret = ocfs2_find_leaf(inode, el, v_cluster, &eb_bh);
544 + if (ret) {
545 + mlog_errno(ret);
546 + goto out;
547 + }
548 +
549 + eb = (struct ocfs2_extent_block *) eb_bh->b_data;
550 + el = &eb->h_list;
551 +
552 + if (el->l_tree_depth) {
553 + ocfs2_error(inode->i_sb,
554 + "Inode %lu has non zero tree depth in "
555 + "xattr leaf block %llu\n", inode->i_ino,
556 + (unsigned long long)eb_bh->b_blocknr);
557 + ret = -EROFS;
558 + goto out;
559 + }
560 + }
561 +
562 + i = ocfs2_search_extent_list(el, v_cluster);
563 + if (i == -1) {
564 + ret = -EROFS;
565 + mlog_errno(ret);
566 + goto out;
567 + } else {
568 + rec = &el->l_recs[i];
569 + BUG_ON(v_cluster < le32_to_cpu(rec->e_cpos));
570 +
571 + if (!rec->e_blkno) {
572 + ocfs2_error(inode->i_sb, "Inode %lu has bad extent "
573 + "record (%u, %u, 0) in xattr", inode->i_ino,
574 + le32_to_cpu(rec->e_cpos),
575 + ocfs2_rec_clusters(el, rec));
576 + ret = -EROFS;
577 + goto out;
578 + }
579 + coff = v_cluster - le32_to_cpu(rec->e_cpos);
580 + *p_cluster = ocfs2_blocks_to_clusters(inode->i_sb,
581 + le64_to_cpu(rec->e_blkno));
582 + *p_cluster = *p_cluster + coff;
583 + if (num_clusters)
584 + *num_clusters = ocfs2_rec_clusters(el, rec) - coff;
585 + }
586 +out:
587 + if (eb_bh)
588 + brelse(eb_bh);
589 + return ret;
590 +}
591 +
592 int ocfs2_get_clusters(struct inode *inode, u32 v_cluster,
593 u32 *p_cluster, u32 *num_clusters,
594 unsigned int *extent_flags)
595 Index: linux-2.6.26/fs/ocfs2/extent_map.h
596 ===================================================================
597 --- linux-2.6.26.orig/fs/ocfs2/extent_map.h
598 +++ linux-2.6.26/fs/ocfs2/extent_map.h
599 @@ -50,4 +50,7 @@ int ocfs2_get_clusters(struct inode *ino
600 int ocfs2_extent_map_get_blocks(struct inode *inode, u64 v_blkno, u64 *p_blkno,
601 u64 *ret_count, unsigned int *extent_flags);
602
603 +int ocfs2_xattr_get_clusters(struct inode *inode, u32 v_cluster,
604 + u32 *p_cluster, u32 *num_clusters,
605 + struct ocfs2_extent_list *el);
606 #endif /* _EXTENT_MAP_H */
607 Index: linux-2.6.26/fs/ocfs2/file.c
608 ===================================================================
609 --- linux-2.6.26.orig/fs/ocfs2/file.c
610 +++ linux-2.6.26/fs/ocfs2/file.c
611 @@ -515,7 +515,7 @@ int ocfs2_add_inode_data(struct ocfs2_su
612 clusters_to_add, mark_unwritten,
613 fe_bh, el, handle,
614 data_ac, meta_ac, reason_ret,
615 - OCFS2_DINODE_EXTENT);
616 + OCFS2_DINODE_EXTENT, NULL);
617 }
618
619 static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start,
620 @@ -565,7 +565,7 @@ restart_all:
621 clusters_to_add);
622 status = ocfs2_lock_allocators(inode, bh, &fe->id2.i_list,
623 clusters_to_add, 0, &data_ac,
624 - &meta_ac);
625 + &meta_ac, OCFS2_DINODE_EXTENT, NULL);
626 if (status) {
627 mlog_errno(status);
628 goto leave;
629 @@ -1237,7 +1237,8 @@ static int __ocfs2_remove_inode_range(st
630 struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
631
632 ret = ocfs2_lock_allocators(inode, di_bh, &di->id2.i_list,
633 - 0, 1, NULL, &meta_ac);
634 + 0, 1, NULL, &meta_ac,
635 + OCFS2_DINODE_EXTENT, NULL);
636 if (ret) {
637 mlog_errno(ret);
638 return ret;
639 @@ -1268,7 +1269,7 @@ static int __ocfs2_remove_inode_range(st
640 }
641
642 ret = ocfs2_remove_extent(inode, di_bh, cpos, len, handle, meta_ac,
643 - dealloc, OCFS2_DINODE_EXTENT);
644 + dealloc, OCFS2_DINODE_EXTENT, NULL);
645 if (ret) {
646 mlog_errno(ret);
647 goto out_commit;
648 Index: linux-2.6.26/fs/ocfs2/suballoc.c
649 ===================================================================
650 --- linux-2.6.26.orig/fs/ocfs2/suballoc.c
651 +++ linux-2.6.26/fs/ocfs2/suballoc.c
652 @@ -1906,7 +1906,8 @@ int ocfs2_lock_allocators(struct inode *
653 struct ocfs2_extent_list *root_el,
654 u32 clusters_to_add, u32 extents_to_split,
655 struct ocfs2_alloc_context **data_ac,
656 - struct ocfs2_alloc_context **meta_ac)
657 + struct ocfs2_alloc_context **meta_ac,
658 + enum ocfs2_extent_tree_type type, void *private)
659 {
660 int ret = 0, num_free_extents;
661 unsigned int max_recs_needed = clusters_to_add + 2 * extents_to_split;
662 @@ -1919,7 +1920,7 @@ int ocfs2_lock_allocators(struct inode *
663 BUG_ON(clusters_to_add != 0 && data_ac == NULL);
664
665 num_free_extents = ocfs2_num_free_extents(osb, inode, root_bh,
666 - OCFS2_DINODE_EXTENT);
667 + type, private);
668 if (num_free_extents < 0) {
669 ret = num_free_extents;
670 mlog_errno(ret);
671 Index: linux-2.6.26/fs/ocfs2/suballoc.h
672 ===================================================================
673 --- linux-2.6.26.orig/fs/ocfs2/suballoc.h
674 +++ linux-2.6.26/fs/ocfs2/suballoc.h
675 @@ -165,5 +165,6 @@ int ocfs2_lock_allocators(struct inode *
676 struct ocfs2_extent_list *root_el,
677 u32 clusters_to_add, u32 extents_to_split,
678 struct ocfs2_alloc_context **data_ac,
679 - struct ocfs2_alloc_context **meta_ac);
680 + struct ocfs2_alloc_context **meta_ac,
681 + enum ocfs2_extent_tree_type type, void *private);
682 #endif /* _CHAINALLOC_H_ */
683 Index: linux-2.6.26/fs/ocfs2/xattr.c
684 ===================================================================
685 --- /dev/null
686 +++ linux-2.6.26/fs/ocfs2/xattr.c
687 @@ -0,0 +1,305 @@
688 +/* -*- mode: c; c-basic-offset: 8; -*-
689 + * vim: noexpandtab sw=8 ts=8 sts=0:
690 + *
691 + * xattr.c
692 + *
693 + * Copyright (C) 2008 Oracle. All rights reserved.
694 + *
695 + * This program is free software; you can redistribute it and/or
696 + * modify it under the terms of the GNU General Public
697 + * License as published by the Free Software Foundation; either
698 + * version 2 of the License, or (at your option) any later version.
699 + *
700 + * This program is distributed in the hope that it will be useful,
701 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
702 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
703 + * General Public License for more details.
704 + *
705 + * You should have received a copy of the GNU General Public
706 + * License along with this program; if not, write to the
707 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
708 + * Boston, MA 021110-1307, USA.
709 + */
710 +
711 +#define MLOG_MASK_PREFIX ML_XATTR
712 +#include <cluster/masklog.h>
713 +
714 +#include "ocfs2.h"
715 +#include "alloc.h"
716 +#include "dlmglue.h"
717 +#include "file.h"
718 +#include "inode.h"
719 +#include "journal.h"
720 +#include "ocfs2_fs.h"
721 +#include "suballoc.h"
722 +#include "uptodate.h"
723 +#include "buffer_head_io.h"
724 +
725 +static int ocfs2_xattr_extend_allocation(struct inode *inode,
726 + u32 clusters_to_add,
727 + struct buffer_head *xattr_bh,
728 + struct ocfs2_xattr_value_root *xv)
729 +{
730 + int status = 0;
731 + int restart_func = 0;
732 + int credits = 0;
733 + handle_t *handle = NULL;
734 + struct ocfs2_alloc_context *data_ac = NULL;
735 + struct ocfs2_alloc_context *meta_ac = NULL;
736 + enum ocfs2_alloc_restarted why;
737 + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
738 + struct ocfs2_extent_list *root_el = &xv->xr_list;
739 + u32 prev_clusters, logical_start = le32_to_cpu(xv->xr_clusters);
740 +
741 + mlog(0, "(clusters_to_add for xattr= %u)\n", clusters_to_add);
742 +
743 +restart_all:
744 +
745 + status = ocfs2_lock_allocators(inode, xattr_bh, root_el,
746 + clusters_to_add, 0, &data_ac,
747 + &meta_ac, OCFS2_XATTR_VALUE_EXTENT, xv);
748 + if (status) {
749 + mlog_errno(status);
750 + goto leave;
751 + }
752 +
753 + credits = ocfs2_calc_extend_credits(osb->sb, root_el, clusters_to_add);
754 + handle = ocfs2_start_trans(osb, credits);
755 + if (IS_ERR(handle)) {
756 + status = PTR_ERR(handle);
757 + handle = NULL;
758 + mlog_errno(status);
759 + goto leave;
760 + }
761 +
762 +restarted_transaction:
763 + status = ocfs2_journal_access(handle, inode, xattr_bh,
764 + OCFS2_JOURNAL_ACCESS_WRITE);
765 + if (status < 0) {
766 + mlog_errno(status);
767 + goto leave;
768 + }
769 +
770 + prev_clusters = le32_to_cpu(xv->xr_clusters);
771 + status = ocfs2_add_clusters_in_btree(osb,
772 + inode,
773 + &logical_start,
774 + clusters_to_add,
775 + 0,
776 + xattr_bh,
777 + root_el,
778 + handle,
779 + data_ac,
780 + meta_ac,
781 + &why,
782 + OCFS2_XATTR_VALUE_EXTENT,
783 + xv);
784 + if ((status < 0) && (status != -EAGAIN)) {
785 + if (status != -ENOSPC)
786 + mlog_errno(status);
787 + goto leave;
788 + }
789 +
790 + status = ocfs2_journal_dirty(handle, xattr_bh);
791 + if (status < 0) {
792 + mlog_errno(status);
793 + goto leave;
794 + }
795 +
796 + clusters_to_add -= le32_to_cpu(xv->xr_clusters) - prev_clusters;
797 +
798 + if (why != RESTART_NONE && clusters_to_add) {
799 + if (why == RESTART_META) {
800 + mlog(0, "restarting function.\n");
801 + restart_func = 1;
802 + } else {
803 + BUG_ON(why != RESTART_TRANS);
804 +
805 + mlog(0, "restarting transaction.\n");
806 + /* TODO: This can be more intelligent. */
807 + credits = ocfs2_calc_extend_credits(osb->sb,
808 + root_el,
809 + clusters_to_add);
810 + status = ocfs2_extend_trans(handle, credits);
811 + if (status < 0) {
812 + /* handle still has to be committed at
813 + * this point. */
814 + status = -ENOMEM;
815 + mlog_errno(status);
816 + goto leave;
817 + }
818 + goto restarted_transaction;
819 + }
820 + }
821 +
822 +leave:
823 + if (handle) {
824 + ocfs2_commit_trans(osb, handle);
825 + handle = NULL;
826 + }
827 + if (data_ac) {
828 + ocfs2_free_alloc_context(data_ac);
829 + data_ac = NULL;
830 + }
831 + if (meta_ac) {
832 + ocfs2_free_alloc_context(meta_ac);
833 + meta_ac = NULL;
834 + }
835 + if ((!status) && restart_func) {
836 + restart_func = 0;
837 + goto restart_all;
838 + }
839 +
840 + return status;
841 +}
842 +
843 +static int __ocfs2_remove_xattr_range(struct inode *inode,
844 + struct buffer_head *root_bh,
845 + struct ocfs2_xattr_value_root *xv,
846 + u32 cpos, u32 phys_cpos, u32 len,
847 + struct ocfs2_cached_dealloc_ctxt *dealloc)
848 +{
849 + int ret;
850 + u64 phys_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys_cpos);
851 + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
852 + struct inode *tl_inode = osb->osb_tl_inode;
853 + handle_t *handle;
854 + struct ocfs2_alloc_context *meta_ac = NULL;
855 +
856 + ret = ocfs2_lock_allocators(inode, root_bh, &xv->xr_list,
857 + 0, 1, NULL, &meta_ac,
858 + OCFS2_XATTR_VALUE_EXTENT, xv);
859 + if (ret) {
860 + mlog_errno(ret);
861 + return ret;
862 + }
863 +
864 + mutex_lock(&tl_inode->i_mutex);
865 +
866 + if (ocfs2_truncate_log_needs_flush(osb)) {
867 + ret = __ocfs2_flush_truncate_log(osb);
868 + if (ret < 0) {
869 + mlog_errno(ret);
870 + goto out;
871 + }
872 + }
873 +
874 + handle = ocfs2_start_trans(osb, OCFS2_REMOVE_EXTENT_CREDITS);
875 + if (IS_ERR(handle)) {
876 + ret = PTR_ERR(handle);
877 + mlog_errno(ret);
878 + goto out;
879 + }
880 +
881 + ret = ocfs2_journal_access(handle, inode, root_bh,
882 + OCFS2_JOURNAL_ACCESS_WRITE);
883 + if (ret) {
884 + mlog_errno(ret);
885 + goto out_commit;
886 + }
887 +
888 + ret = ocfs2_remove_extent(inode, root_bh, cpos, len, handle, meta_ac,
889 + dealloc, OCFS2_XATTR_VALUE_EXTENT, xv);
890 + if (ret) {
891 + mlog_errno(ret);
892 + goto out_commit;
893 + }
894 +
895 + le32_add_cpu(&xv->xr_clusters, -len);
896 +
897 + ret = ocfs2_journal_dirty(handle, root_bh);
898 + if (ret) {
899 + mlog_errno(ret);
900 + goto out_commit;
901 + }
902 +
903 + ret = ocfs2_truncate_log_append(osb, handle, phys_blkno, len);
904 + if (ret)
905 + mlog_errno(ret);
906 +
907 +out_commit:
908 + ocfs2_commit_trans(osb, handle);
909 +out:
910 + mutex_unlock(&tl_inode->i_mutex);
911 +
912 + if (meta_ac)
913 + ocfs2_free_alloc_context(meta_ac);
914 +
915 + return ret;
916 +}
917 +
918 +static int ocfs2_xattr_shrink_size(struct inode *inode,
919 + u32 old_clusters,
920 + u32 new_clusters,
921 + struct buffer_head *root_bh,
922 + struct ocfs2_xattr_value_root *xv)
923 +{
924 + int ret = 0;
925 + u32 trunc_len, cpos, phys_cpos, alloc_size;
926 + u64 block;
927 + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
928 + struct ocfs2_cached_dealloc_ctxt dealloc;
929 +
930 + ocfs2_init_dealloc_ctxt(&dealloc);
931 +
932 + if (old_clusters <= new_clusters)
933 + return 0;
934 +
935 + cpos = new_clusters;
936 + trunc_len = old_clusters - new_clusters;
937 + while (trunc_len) {
938 + ret = ocfs2_xattr_get_clusters(inode, cpos, &phys_cpos,
939 + &alloc_size, &xv->xr_list);
940 + if (ret) {
941 + mlog_errno(ret);
942 + goto out;
943 + }
944 +
945 + if (alloc_size > trunc_len)
946 + alloc_size = trunc_len;
947 +
948 + ret = __ocfs2_remove_xattr_range(inode, root_bh, xv, cpos,
949 + phys_cpos, alloc_size,
950 + &dealloc);
951 + if (ret) {
952 + mlog_errno(ret);
953 + goto out;
954 + }
955 +
956 + block = ocfs2_clusters_to_blocks(inode->i_sb, phys_cpos);
957 + ocfs2_remove_xattr_clusters_from_cache(inode, block,
958 + alloc_size);
959 + cpos += alloc_size;
960 + trunc_len -= alloc_size;
961 + }
962 +
963 +out:
964 + ocfs2_schedule_truncate_log_flush(osb, 1);
965 + ocfs2_run_deallocs(osb, &dealloc);
966 +
967 + return ret;
968 +}
969 +
970 +static int ocfs2_xattr_value_truncate(struct inode *inode,
971 + struct buffer_head *root_bh,
972 + struct ocfs2_xattr_value_root *xv,
973 + int len)
974 +{
975 + int ret;
976 + u32 new_clusters = ocfs2_clusters_for_bytes(inode->i_sb, len);
977 + u32 old_clusters = le32_to_cpu(xv->xr_clusters);
978 +
979 + if (new_clusters == old_clusters)
980 + return 0;
981 +
982 + if (new_clusters > old_clusters)
983 + ret = ocfs2_xattr_extend_allocation(inode,
984 + new_clusters - old_clusters,
985 + root_bh, xv);
986 + else
987 + ret = ocfs2_xattr_shrink_size(inode,
988 + old_clusters, new_clusters,
989 + root_bh, xv);
990 +
991 + return ret;
992 +}