aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2
diff options
context:
space:
mode:
authorTao Ma <tao.ma@oracle.com>2008-08-18 05:38:48 -0400
committerMark Fasheh <mfasheh@suse.com>2008-10-13 19:57:01 -0400
commitf56654c435c06f2b2bd5751889b1a08a3add7d6c (patch)
treeb186d68aedc5dda7afe435f5a68c03937ae382ff /fs/ocfs2
parentac11c827192272eabb68b8f4cf844066461d9690 (diff)
ocfs2: Add extent tree operation for xattr value btrees
Add some thin wrappers around ocfs2_insert_extent() for each of the 3 different btree types, ocfs2_inode_insert_extent(), ocfs2_xattr_value_insert_extent() and ocfs2_xattr_tree_insert_extent(). The last is for the xattr index btree, which will be used in a followup patch. All the old callers in file.c etc will call ocfs2_dinode_insert_extent(), while the other two handle the xattr issue. And the init of extent tree are handled by these functions. When storing xattr value which is too large, we will allocate some clusters for it and here ocfs2_extent_list and ocfs2_extent_rec will also be used. In order to re-use the b-tree operation code, a new parameter named "private" is added into ocfs2_extent_tree and it is used to indicate the root of ocfs2_exent_list. The reason is that we can't deduce the root from the buffer_head now. It may be in an inode, an ocfs2_xattr_block or even worse, in any place in an ocfs2_xattr_bucket. Signed-off-by: Tao Ma <tao.ma@oracle.com> Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Diffstat (limited to 'fs/ocfs2')
-rw-r--r--fs/ocfs2/Makefile3
-rw-r--r--fs/ocfs2/alloc.c184
-rw-r--r--fs/ocfs2/alloc.h42
-rw-r--r--fs/ocfs2/aops.c5
-rw-r--r--fs/ocfs2/cluster/masklog.c1
-rw-r--r--fs/ocfs2/cluster/masklog.h1
-rw-r--r--fs/ocfs2/dir.c11
-rw-r--r--fs/ocfs2/extent_map.c60
-rw-r--r--fs/ocfs2/extent_map.h4
-rw-r--r--fs/ocfs2/file.c9
-rw-r--r--fs/ocfs2/suballoc.c5
-rw-r--r--fs/ocfs2/suballoc.h3
-rw-r--r--fs/ocfs2/xattr.c305
13 files changed, 569 insertions, 64 deletions
diff --git a/fs/ocfs2/Makefile b/fs/ocfs2/Makefile
index f6956de56fdb..af63980319c3 100644
--- a/fs/ocfs2/Makefile
+++ b/fs/ocfs2/Makefile
@@ -34,7 +34,8 @@ ocfs2-objs := \
34 symlink.o \ 34 symlink.o \
35 sysfile.o \ 35 sysfile.o \
36 uptodate.o \ 36 uptodate.o \
37 ver.o 37 ver.o \
38 xattr.o \
38 39
39ocfs2_stackglue-objs := stackglue.o 40ocfs2_stackglue-objs := stackglue.o
40ocfs2_stack_o2cb-objs := stack_o2cb.o 41ocfs2_stack_o2cb-objs := stack_o2cb.o
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index cacfc118b71c..e45421fee204 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -78,6 +78,7 @@ struct ocfs2_extent_tree {
78 struct ocfs2_extent_tree_operations *eops; 78 struct ocfs2_extent_tree_operations *eops;
79 struct buffer_head *root_bh; 79 struct buffer_head *root_bh;
80 struct ocfs2_extent_list *root_el; 80 struct ocfs2_extent_list *root_el;
81 void *private;
81}; 82};
82 83
83static void ocfs2_dinode_set_last_eb_blk(struct ocfs2_extent_tree *et, 84static void ocfs2_dinode_set_last_eb_blk(struct ocfs2_extent_tree *et,
@@ -136,9 +137,50 @@ static struct ocfs2_extent_tree_operations ocfs2_dinode_et_ops = {
136 .sanity_check = ocfs2_dinode_sanity_check, 137 .sanity_check = ocfs2_dinode_sanity_check,
137}; 138};
138 139
140static void ocfs2_xattr_value_set_last_eb_blk(struct ocfs2_extent_tree *et,
141 u64 blkno)
142{
143 struct ocfs2_xattr_value_root *xv =
144 (struct ocfs2_xattr_value_root *)et->private;
145
146 xv->xr_last_eb_blk = cpu_to_le64(blkno);
147}
148
149static u64 ocfs2_xattr_value_get_last_eb_blk(struct ocfs2_extent_tree *et)
150{
151 struct ocfs2_xattr_value_root *xv =
152 (struct ocfs2_xattr_value_root *) et->private;
153
154 return le64_to_cpu(xv->xr_last_eb_blk);
155}
156
157static void ocfs2_xattr_value_update_clusters(struct inode *inode,
158 struct ocfs2_extent_tree *et,
159 u32 clusters)
160{
161 struct ocfs2_xattr_value_root *xv =
162 (struct ocfs2_xattr_value_root *)et->private;
163
164 le32_add_cpu(&xv->xr_clusters, clusters);
165}
166
167static int ocfs2_xattr_value_sanity_check(struct inode *inode,
168 struct ocfs2_extent_tree *et)
169{
170 return 0;
171}
172
173static struct ocfs2_extent_tree_operations ocfs2_xattr_et_ops = {
174 .set_last_eb_blk = ocfs2_xattr_value_set_last_eb_blk,
175 .get_last_eb_blk = ocfs2_xattr_value_get_last_eb_blk,
176 .update_clusters = ocfs2_xattr_value_update_clusters,
177 .sanity_check = ocfs2_xattr_value_sanity_check,
178};
179
139static struct ocfs2_extent_tree* 180static struct ocfs2_extent_tree*
140 ocfs2_new_extent_tree(struct buffer_head *bh, 181 ocfs2_new_extent_tree(struct buffer_head *bh,
141 enum ocfs2_extent_tree_type et_type) 182 enum ocfs2_extent_tree_type et_type,
183 void *private)
142{ 184{
143 struct ocfs2_extent_tree *et; 185 struct ocfs2_extent_tree *et;
144 186
@@ -149,12 +191,16 @@ static struct ocfs2_extent_tree*
149 et->type = et_type; 191 et->type = et_type;
150 get_bh(bh); 192 get_bh(bh);
151 et->root_bh = bh; 193 et->root_bh = bh;
194 et->private = private;
152 195
153 /* current we only support dinode extent. */
154 BUG_ON(et->type != OCFS2_DINODE_EXTENT);
155 if (et_type == OCFS2_DINODE_EXTENT) { 196 if (et_type == OCFS2_DINODE_EXTENT) {
156 et->root_el = &((struct ocfs2_dinode *)bh->b_data)->id2.i_list; 197 et->root_el = &((struct ocfs2_dinode *)bh->b_data)->id2.i_list;
157 et->eops = &ocfs2_dinode_et_ops; 198 et->eops = &ocfs2_dinode_et_ops;
199 } else if (et_type == OCFS2_XATTR_VALUE_EXTENT) {
200 struct ocfs2_xattr_value_root *xv =
201 (struct ocfs2_xattr_value_root *) private;
202 et->root_el = &xv->xr_list;
203 et->eops = &ocfs2_xattr_et_ops;
158 } 204 }
159 205
160 return et; 206 return et;
@@ -495,7 +541,8 @@ struct ocfs2_merge_ctxt {
495int ocfs2_num_free_extents(struct ocfs2_super *osb, 541int ocfs2_num_free_extents(struct ocfs2_super *osb,
496 struct inode *inode, 542 struct inode *inode,
497 struct buffer_head *root_bh, 543 struct buffer_head *root_bh,
498 enum ocfs2_extent_tree_type type) 544 enum ocfs2_extent_tree_type type,
545 void *private)
499{ 546{
500 int retval; 547 int retval;
501 struct ocfs2_extent_list *el = NULL; 548 struct ocfs2_extent_list *el = NULL;
@@ -517,6 +564,12 @@ int ocfs2_num_free_extents(struct ocfs2_super *osb,
517 if (fe->i_last_eb_blk) 564 if (fe->i_last_eb_blk)
518 last_eb_blk = le64_to_cpu(fe->i_last_eb_blk); 565 last_eb_blk = le64_to_cpu(fe->i_last_eb_blk);
519 el = &fe->id2.i_list; 566 el = &fe->id2.i_list;
567 } else if (type == OCFS2_XATTR_VALUE_EXTENT) {
568 struct ocfs2_xattr_value_root *xv =
569 (struct ocfs2_xattr_value_root *) private;
570
571 last_eb_blk = le64_to_cpu(xv->xr_last_eb_blk);
572 el = &xv->xr_list;
520 } 573 }
521 574
522 if (last_eb_blk) { 575 if (last_eb_blk) {
@@ -4209,33 +4262,25 @@ out:
4209 * 4262 *
4210 * The caller needs to update fe->i_clusters 4263 * The caller needs to update fe->i_clusters
4211 */ 4264 */
4212int ocfs2_insert_extent(struct ocfs2_super *osb, 4265static int ocfs2_insert_extent(struct ocfs2_super *osb,
4213 handle_t *handle, 4266 handle_t *handle,
4214 struct inode *inode, 4267 struct inode *inode,
4215 struct buffer_head *root_bh, 4268 struct buffer_head *root_bh,
4216 u32 cpos, 4269 u32 cpos,
4217 u64 start_blk, 4270 u64 start_blk,
4218 u32 new_clusters, 4271 u32 new_clusters,
4219 u8 flags, 4272 u8 flags,
4220 struct ocfs2_alloc_context *meta_ac, 4273 struct ocfs2_alloc_context *meta_ac,
4221 enum ocfs2_extent_tree_type et_type) 4274 struct ocfs2_extent_tree *et)
4222{ 4275{
4223 int status; 4276 int status;
4224 int uninitialized_var(free_records); 4277 int uninitialized_var(free_records);
4225 struct buffer_head *last_eb_bh = NULL; 4278 struct buffer_head *last_eb_bh = NULL;
4226 struct ocfs2_insert_type insert = {0, }; 4279 struct ocfs2_insert_type insert = {0, };
4227 struct ocfs2_extent_rec rec; 4280 struct ocfs2_extent_rec rec;
4228 struct ocfs2_extent_tree *et = NULL;
4229 4281
4230 BUG_ON(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL); 4282 BUG_ON(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL);
4231 4283
4232 et = ocfs2_new_extent_tree(root_bh, et_type);
4233 if (!et) {
4234 status = -ENOMEM;
4235 mlog_errno(status);
4236 goto bail;
4237 }
4238
4239 mlog(0, "add %u clusters at position %u to inode %llu\n", 4284 mlog(0, "add %u clusters at position %u to inode %llu\n",
4240 new_clusters, cpos, (unsigned long long)OCFS2_I(inode)->ip_blkno); 4285 new_clusters, cpos, (unsigned long long)OCFS2_I(inode)->ip_blkno);
4241 4286
@@ -4287,9 +4332,68 @@ bail:
4287 if (last_eb_bh) 4332 if (last_eb_bh)
4288 brelse(last_eb_bh); 4333 brelse(last_eb_bh);
4289 4334
4335 mlog_exit(status);
4336 return status;
4337}
4338
4339int ocfs2_dinode_insert_extent(struct ocfs2_super *osb,
4340 handle_t *handle,
4341 struct inode *inode,
4342 struct buffer_head *root_bh,
4343 u32 cpos,
4344 u64 start_blk,
4345 u32 new_clusters,
4346 u8 flags,
4347 struct ocfs2_alloc_context *meta_ac)
4348{
4349 int status;
4350 struct ocfs2_extent_tree *et = NULL;
4351
4352 et = ocfs2_new_extent_tree(root_bh, OCFS2_DINODE_EXTENT, NULL);
4353 if (!et) {
4354 status = -ENOMEM;
4355 mlog_errno(status);
4356 goto bail;
4357 }
4358
4359 status = ocfs2_insert_extent(osb, handle, inode, root_bh,
4360 cpos, start_blk, new_clusters,
4361 flags, meta_ac, et);
4362
4290 if (et) 4363 if (et)
4291 ocfs2_free_extent_tree(et); 4364 ocfs2_free_extent_tree(et);
4292 mlog_exit(status); 4365bail:
4366 return status;
4367}
4368
4369int ocfs2_xattr_value_insert_extent(struct ocfs2_super *osb,
4370 handle_t *handle,
4371 struct inode *inode,
4372 struct buffer_head *root_bh,
4373 u32 cpos,
4374 u64 start_blk,
4375 u32 new_clusters,
4376 u8 flags,
4377 struct ocfs2_alloc_context *meta_ac,
4378 void *private)
4379{
4380 int status;
4381 struct ocfs2_extent_tree *et = NULL;
4382
4383 et = ocfs2_new_extent_tree(root_bh, OCFS2_XATTR_VALUE_EXTENT, private);
4384 if (!et) {
4385 status = -ENOMEM;
4386 mlog_errno(status);
4387 goto bail;
4388 }
4389
4390 status = ocfs2_insert_extent(osb, handle, inode, root_bh,
4391 cpos, start_blk, new_clusters,
4392 flags, meta_ac, et);
4393
4394 if (et)
4395 ocfs2_free_extent_tree(et);
4396bail:
4293 return status; 4397 return status;
4294} 4398}
4295 4399
@@ -4311,7 +4415,8 @@ int ocfs2_add_clusters_in_btree(struct ocfs2_super *osb,
4311 struct ocfs2_alloc_context *data_ac, 4415 struct ocfs2_alloc_context *data_ac,
4312 struct ocfs2_alloc_context *meta_ac, 4416 struct ocfs2_alloc_context *meta_ac,
4313 enum ocfs2_alloc_restarted *reason_ret, 4417 enum ocfs2_alloc_restarted *reason_ret,
4314 enum ocfs2_extent_tree_type type) 4418 enum ocfs2_extent_tree_type type,
4419 void *private)
4315{ 4420{
4316 int status = 0; 4421 int status = 0;
4317 int free_extents; 4422 int free_extents;
@@ -4325,7 +4430,8 @@ int ocfs2_add_clusters_in_btree(struct ocfs2_super *osb,
4325 if (mark_unwritten) 4430 if (mark_unwritten)
4326 flags = OCFS2_EXT_UNWRITTEN; 4431 flags = OCFS2_EXT_UNWRITTEN;
4327 4432
4328 free_extents = ocfs2_num_free_extents(osb, inode, root_bh, type); 4433 free_extents = ocfs2_num_free_extents(osb, inode, root_bh, type,
4434 private);
4329 if (free_extents < 0) { 4435 if (free_extents < 0) {
4330 status = free_extents; 4436 status = free_extents;
4331 mlog_errno(status); 4437 mlog_errno(status);
@@ -4372,9 +4478,16 @@ int ocfs2_add_clusters_in_btree(struct ocfs2_super *osb,
4372 block = ocfs2_clusters_to_blocks(osb->sb, bit_off); 4478 block = ocfs2_clusters_to_blocks(osb->sb, bit_off);
4373 mlog(0, "Allocating %u clusters at block %u for inode %llu\n", 4479 mlog(0, "Allocating %u clusters at block %u for inode %llu\n",
4374 num_bits, bit_off, (unsigned long long)OCFS2_I(inode)->ip_blkno); 4480 num_bits, bit_off, (unsigned long long)OCFS2_I(inode)->ip_blkno);
4375 status = ocfs2_insert_extent(osb, handle, inode, root_bh, 4481 if (type == OCFS2_DINODE_EXTENT)
4376 *logical_offset, block, num_bits, 4482 status = ocfs2_dinode_insert_extent(osb, handle, inode, root_bh,
4377 flags, meta_ac, type); 4483 *logical_offset, block,
4484 num_bits, flags, meta_ac);
4485 else
4486 status = ocfs2_xattr_value_insert_extent(osb, handle,
4487 inode, root_bh,
4488 *logical_offset,
4489 block, num_bits, flags,
4490 meta_ac, private);
4378 if (status < 0) { 4491 if (status < 0) {
4379 mlog_errno(status); 4492 mlog_errno(status);
4380 goto leave; 4493 goto leave;
@@ -4655,7 +4768,8 @@ int ocfs2_mark_extent_written(struct inode *inode, struct buffer_head *root_bh,
4655 handle_t *handle, u32 cpos, u32 len, u32 phys, 4768 handle_t *handle, u32 cpos, u32 len, u32 phys,
4656 struct ocfs2_alloc_context *meta_ac, 4769 struct ocfs2_alloc_context *meta_ac,
4657 struct ocfs2_cached_dealloc_ctxt *dealloc, 4770 struct ocfs2_cached_dealloc_ctxt *dealloc,
4658 enum ocfs2_extent_tree_type et_type) 4771 enum ocfs2_extent_tree_type et_type,
4772 void *private)
4659{ 4773{
4660 int ret, index; 4774 int ret, index;
4661 u64 start_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys); 4775 u64 start_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys);
@@ -4676,7 +4790,7 @@ int ocfs2_mark_extent_written(struct inode *inode, struct buffer_head *root_bh,
4676 goto out; 4790 goto out;
4677 } 4791 }
4678 4792
4679 et = ocfs2_new_extent_tree(root_bh, et_type); 4793 et = ocfs2_new_extent_tree(root_bh, et_type, private);
4680 if (!et) { 4794 if (!et) {
4681 ret = -ENOMEM; 4795 ret = -ENOMEM;
4682 mlog_errno(ret); 4796 mlog_errno(ret);
@@ -4964,7 +5078,8 @@ int ocfs2_remove_extent(struct inode *inode, struct buffer_head *root_bh,
4964 u32 cpos, u32 len, handle_t *handle, 5078 u32 cpos, u32 len, handle_t *handle,
4965 struct ocfs2_alloc_context *meta_ac, 5079 struct ocfs2_alloc_context *meta_ac,
4966 struct ocfs2_cached_dealloc_ctxt *dealloc, 5080 struct ocfs2_cached_dealloc_ctxt *dealloc,
4967 enum ocfs2_extent_tree_type et_type) 5081 enum ocfs2_extent_tree_type et_type,
5082 void *private)
4968{ 5083{
4969 int ret, index; 5084 int ret, index;
4970 u32 rec_range, trunc_range; 5085 u32 rec_range, trunc_range;
@@ -4973,7 +5088,7 @@ int ocfs2_remove_extent(struct inode *inode, struct buffer_head *root_bh,
4973 struct ocfs2_path *path = NULL; 5088 struct ocfs2_path *path = NULL;
4974 struct ocfs2_extent_tree *et = NULL; 5089 struct ocfs2_extent_tree *et = NULL;
4975 5090
4976 et = ocfs2_new_extent_tree(root_bh, et_type); 5091 et = ocfs2_new_extent_tree(root_bh, et_type, private);
4977 if (!et) { 5092 if (!et) {
4978 ret = -ENOMEM; 5093 ret = -ENOMEM;
4979 mlog_errno(ret); 5094 mlog_errno(ret);
@@ -6608,9 +6723,8 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,
6608 * this proves to be false, we could always re-build 6723 * this proves to be false, we could always re-build
6609 * the in-inode data from our pages. 6724 * the in-inode data from our pages.
6610 */ 6725 */
6611 ret = ocfs2_insert_extent(osb, handle, inode, di_bh, 6726 ret = ocfs2_dinode_insert_extent(osb, handle, inode, di_bh,
6612 0, block, 1, 0, 6727 0, block, 1, 0, NULL);
6613 NULL, OCFS2_DINODE_EXTENT);
6614 if (ret) { 6728 if (ret) {
6615 mlog_errno(ret); 6729 mlog_errno(ret);
6616 goto out_commit; 6730 goto out_commit;
diff --git a/fs/ocfs2/alloc.h b/fs/ocfs2/alloc.h
index 5e090c5d8498..ec7baeb2ea7d 100644
--- a/fs/ocfs2/alloc.h
+++ b/fs/ocfs2/alloc.h
@@ -28,19 +28,29 @@
28 28
29enum ocfs2_extent_tree_type { 29enum ocfs2_extent_tree_type {
30 OCFS2_DINODE_EXTENT = 0, 30 OCFS2_DINODE_EXTENT = 0,
31 OCFS2_XATTR_VALUE_EXTENT,
31}; 32};
32 33
33struct ocfs2_alloc_context; 34struct ocfs2_alloc_context;
34int ocfs2_insert_extent(struct ocfs2_super *osb, 35int ocfs2_dinode_insert_extent(struct ocfs2_super *osb,
35 handle_t *handle, 36 handle_t *handle,
36 struct inode *inode, 37 struct inode *inode,
37 struct buffer_head *root_bh, 38 struct buffer_head *root_bh,
38 u32 cpos, 39 u32 cpos,
39 u64 start_blk, 40 u64 start_blk,
40 u32 new_clusters, 41 u32 new_clusters,
41 u8 flags, 42 u8 flags,
42 struct ocfs2_alloc_context *meta_ac, 43 struct ocfs2_alloc_context *meta_ac);
43 enum ocfs2_extent_tree_type et_type); 44int ocfs2_xattr_value_insert_extent(struct ocfs2_super *osb,
45 handle_t *handle,
46 struct inode *inode,
47 struct buffer_head *root_bh,
48 u32 cpos,
49 u64 start_blk,
50 u32 new_clusters,
51 u8 flags,
52 struct ocfs2_alloc_context *meta_ac,
53 void *private);
44enum ocfs2_alloc_restarted { 54enum ocfs2_alloc_restarted {
45 RESTART_NONE = 0, 55 RESTART_NONE = 0,
46 RESTART_TRANS, 56 RESTART_TRANS,
@@ -57,22 +67,26 @@ int ocfs2_add_clusters_in_btree(struct ocfs2_super *osb,
57 struct ocfs2_alloc_context *data_ac, 67 struct ocfs2_alloc_context *data_ac,
58 struct ocfs2_alloc_context *meta_ac, 68 struct ocfs2_alloc_context *meta_ac,
59 enum ocfs2_alloc_restarted *reason_ret, 69 enum ocfs2_alloc_restarted *reason_ret,
60 enum ocfs2_extent_tree_type type); 70 enum ocfs2_extent_tree_type type,
71 void *private);
61struct ocfs2_cached_dealloc_ctxt; 72struct ocfs2_cached_dealloc_ctxt;
62int ocfs2_mark_extent_written(struct inode *inode, struct buffer_head *root_bh, 73int ocfs2_mark_extent_written(struct inode *inode, struct buffer_head *root_bh,
63 handle_t *handle, u32 cpos, u32 len, u32 phys, 74 handle_t *handle, u32 cpos, u32 len, u32 phys,
64 struct ocfs2_alloc_context *meta_ac, 75 struct ocfs2_alloc_context *meta_ac,
65 struct ocfs2_cached_dealloc_ctxt *dealloc, 76 struct ocfs2_cached_dealloc_ctxt *dealloc,
66 enum ocfs2_extent_tree_type et_type); 77 enum ocfs2_extent_tree_type et_type,
78 void *private);
67int ocfs2_remove_extent(struct inode *inode, struct buffer_head *root_bh, 79int ocfs2_remove_extent(struct inode *inode, struct buffer_head *root_bh,
68 u32 cpos, u32 len, handle_t *handle, 80 u32 cpos, u32 len, handle_t *handle,
69 struct ocfs2_alloc_context *meta_ac, 81 struct ocfs2_alloc_context *meta_ac,
70 struct ocfs2_cached_dealloc_ctxt *dealloc, 82 struct ocfs2_cached_dealloc_ctxt *dealloc,
71 enum ocfs2_extent_tree_type et_type); 83 enum ocfs2_extent_tree_type et_type,
84 void *private);
72int ocfs2_num_free_extents(struct ocfs2_super *osb, 85int ocfs2_num_free_extents(struct ocfs2_super *osb,
73 struct inode *inode, 86 struct inode *inode,
74 struct buffer_head *root_bh, 87 struct buffer_head *root_bh,
75 enum ocfs2_extent_tree_type et_type); 88 enum ocfs2_extent_tree_type et_type,
89 void *private);
76 90
77/* 91/*
78 * how many new metadata chunks would an allocation need at maximum? 92 * how many new metadata chunks would an allocation need at maximum?
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index e7acd2867904..530b1ff599c0 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -1279,7 +1279,7 @@ static int ocfs2_write_cluster(struct address_space *mapping,
1279 ret = ocfs2_mark_extent_written(inode, wc->w_di_bh, 1279 ret = ocfs2_mark_extent_written(inode, wc->w_di_bh,
1280 wc->w_handle, cpos, 1, phys, 1280 wc->w_handle, cpos, 1, phys,
1281 meta_ac, &wc->w_dealloc, 1281 meta_ac, &wc->w_dealloc,
1282 OCFS2_DINODE_EXTENT); 1282 OCFS2_DINODE_EXTENT, NULL);
1283 if (ret < 0) { 1283 if (ret < 0) {
1284 mlog_errno(ret); 1284 mlog_errno(ret);
1285 goto out; 1285 goto out;
@@ -1721,7 +1721,8 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
1721 1721
1722 ret = ocfs2_lock_allocators(inode, wc->w_di_bh, &di->id2.i_list, 1722 ret = ocfs2_lock_allocators(inode, wc->w_di_bh, &di->id2.i_list,
1723 clusters_to_alloc, extents_to_split, 1723 clusters_to_alloc, extents_to_split,
1724 &data_ac, &meta_ac); 1724 &data_ac, &meta_ac,
1725 OCFS2_DINODE_EXTENT, NULL);
1725 if (ret) { 1726 if (ret) {
1726 mlog_errno(ret); 1727 mlog_errno(ret);
1727 goto out; 1728 goto out;
diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c
index 23c732f27529..d8a0cb92cef6 100644
--- a/fs/ocfs2/cluster/masklog.c
+++ b/fs/ocfs2/cluster/masklog.c
@@ -109,6 +109,7 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = {
109 define_mask(CONN), 109 define_mask(CONN),
110 define_mask(QUORUM), 110 define_mask(QUORUM),
111 define_mask(EXPORT), 111 define_mask(EXPORT),
112 define_mask(XATTR),
112 define_mask(ERROR), 113 define_mask(ERROR),
113 define_mask(NOTICE), 114 define_mask(NOTICE),
114 define_mask(KTHREAD), 115 define_mask(KTHREAD),
diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h
index 597e064bb94f..57670c680471 100644
--- a/fs/ocfs2/cluster/masklog.h
+++ b/fs/ocfs2/cluster/masklog.h
@@ -112,6 +112,7 @@
112#define ML_CONN 0x0000000004000000ULL /* net connection management */ 112#define ML_CONN 0x0000000004000000ULL /* net connection management */
113#define ML_QUORUM 0x0000000008000000ULL /* net connection quorum */ 113#define ML_QUORUM 0x0000000008000000ULL /* net connection quorum */
114#define ML_EXPORT 0x0000000010000000ULL /* ocfs2 export operations */ 114#define ML_EXPORT 0x0000000010000000ULL /* ocfs2 export operations */
115#define ML_XATTR 0x0000000020000000ULL /* ocfs2 extended attributes */
115/* bits that are infrequently given and frequently matched in the high word */ 116/* bits that are infrequently given and frequently matched in the high word */
116#define ML_ERROR 0x0000000100000000ULL /* sent to KERN_ERR */ 117#define ML_ERROR 0x0000000100000000ULL /* sent to KERN_ERR */
117#define ML_NOTICE 0x0000000200000000ULL /* setn to KERN_NOTICE */ 118#define ML_NOTICE 0x0000000200000000ULL /* setn to KERN_NOTICE */
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c
index d17c34b0ac6b..5426a02c12bb 100644
--- a/fs/ocfs2/dir.c
+++ b/fs/ocfs2/dir.c
@@ -1305,8 +1305,8 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
1305 * This should never fail as our extent list is empty and all 1305 * This should never fail as our extent list is empty and all
1306 * related blocks have been journaled already. 1306 * related blocks have been journaled already.
1307 */ 1307 */
1308 ret = ocfs2_insert_extent(osb, handle, dir, di_bh, 0, blkno, len, 0, 1308 ret = ocfs2_dinode_insert_extent(osb, handle, dir, di_bh, 0, blkno,
1309 NULL, OCFS2_DINODE_EXTENT); 1309 len, 0, NULL);
1310 if (ret) { 1310 if (ret) {
1311 mlog_errno(ret); 1311 mlog_errno(ret);
1312 goto out_commit; 1312 goto out_commit;
@@ -1337,8 +1337,8 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
1337 } 1337 }
1338 blkno = ocfs2_clusters_to_blocks(dir->i_sb, bit_off); 1338 blkno = ocfs2_clusters_to_blocks(dir->i_sb, bit_off);
1339 1339
1340 ret = ocfs2_insert_extent(osb, handle, dir, di_bh, 1, blkno, 1340 ret = ocfs2_dinode_insert_extent(osb, handle, dir, di_bh, 1,
1341 len, 0, NULL, OCFS2_DINODE_EXTENT); 1341 blkno, len, 0, NULL);
1342 if (ret) { 1342 if (ret) {
1343 mlog_errno(ret); 1343 mlog_errno(ret);
1344 goto out_commit; 1344 goto out_commit;
@@ -1482,7 +1482,8 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
1482 spin_unlock(&OCFS2_I(dir)->ip_lock); 1482 spin_unlock(&OCFS2_I(dir)->ip_lock);
1483 num_free_extents = ocfs2_num_free_extents(osb, dir, 1483 num_free_extents = ocfs2_num_free_extents(osb, dir,
1484 parent_fe_bh, 1484 parent_fe_bh,
1485 OCFS2_DINODE_EXTENT); 1485 OCFS2_DINODE_EXTENT,
1486 NULL);
1486 if (num_free_extents < 0) { 1487 if (num_free_extents < 0) {
1487 status = num_free_extents; 1488 status = num_free_extents;
1488 mlog_errno(status); 1489 mlog_errno(status);
diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c
index aed268e80b49..a7b1cfa735bf 100644
--- a/fs/ocfs2/extent_map.c
+++ b/fs/ocfs2/extent_map.c
@@ -551,6 +551,66 @@ static void ocfs2_relative_extent_offsets(struct super_block *sb,
551 *num_clusters = le16_to_cpu(rec->e_leaf_clusters) - coff; 551 *num_clusters = le16_to_cpu(rec->e_leaf_clusters) - coff;
552} 552}
553 553
554int ocfs2_xattr_get_clusters(struct inode *inode, u32 v_cluster,
555 u32 *p_cluster, u32 *num_clusters,
556 struct ocfs2_extent_list *el)
557{
558 int ret = 0, i;
559 struct buffer_head *eb_bh = NULL;
560 struct ocfs2_extent_block *eb;
561 struct ocfs2_extent_rec *rec;
562 u32 coff;
563
564 if (el->l_tree_depth) {
565 ret = ocfs2_find_leaf(inode, el, v_cluster, &eb_bh);
566 if (ret) {
567 mlog_errno(ret);
568 goto out;
569 }
570
571 eb = (struct ocfs2_extent_block *) eb_bh->b_data;
572 el = &eb->h_list;
573
574 if (el->l_tree_depth) {
575 ocfs2_error(inode->i_sb,
576 "Inode %lu has non zero tree depth in "
577 "xattr leaf block %llu\n", inode->i_ino,
578 (unsigned long long)eb_bh->b_blocknr);
579 ret = -EROFS;
580 goto out;
581 }
582 }
583
584 i = ocfs2_search_extent_list(el, v_cluster);
585 if (i == -1) {
586 ret = -EROFS;
587 mlog_errno(ret);
588 goto out;
589 } else {
590 rec = &el->l_recs[i];
591 BUG_ON(v_cluster < le32_to_cpu(rec->e_cpos));
592
593 if (!rec->e_blkno) {
594 ocfs2_error(inode->i_sb, "Inode %lu has bad extent "
595 "record (%u, %u, 0) in xattr", inode->i_ino,
596 le32_to_cpu(rec->e_cpos),
597 ocfs2_rec_clusters(el, rec));
598 ret = -EROFS;
599 goto out;
600 }
601 coff = v_cluster - le32_to_cpu(rec->e_cpos);
602 *p_cluster = ocfs2_blocks_to_clusters(inode->i_sb,
603 le64_to_cpu(rec->e_blkno));
604 *p_cluster = *p_cluster + coff;
605 if (num_clusters)
606 *num_clusters = ocfs2_rec_clusters(el, rec) - coff;
607 }
608out:
609 if (eb_bh)
610 brelse(eb_bh);
611 return ret;
612}
613
554int ocfs2_get_clusters(struct inode *inode, u32 v_cluster, 614int ocfs2_get_clusters(struct inode *inode, u32 v_cluster,
555 u32 *p_cluster, u32 *num_clusters, 615 u32 *p_cluster, u32 *num_clusters,
556 unsigned int *extent_flags) 616 unsigned int *extent_flags)
diff --git a/fs/ocfs2/extent_map.h b/fs/ocfs2/extent_map.h
index 1b97490e1ea8..1c4aa8b06f34 100644
--- a/fs/ocfs2/extent_map.h
+++ b/fs/ocfs2/extent_map.h
@@ -53,4 +53,8 @@ int ocfs2_extent_map_get_blocks(struct inode *inode, u64 v_blkno, u64 *p_blkno,
53int ocfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, 53int ocfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
54 u64 map_start, u64 map_len); 54 u64 map_start, u64 map_len);
55 55
56int ocfs2_xattr_get_clusters(struct inode *inode, u32 v_cluster,
57 u32 *p_cluster, u32 *num_clusters,
58 struct ocfs2_extent_list *el);
59
56#endif /* _EXTENT_MAP_H */ 60#endif /* _EXTENT_MAP_H */
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 7bb4fde70054..89d8541f85b5 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -515,7 +515,7 @@ int ocfs2_add_inode_data(struct ocfs2_super *osb,
515 clusters_to_add, mark_unwritten, 515 clusters_to_add, mark_unwritten,
516 fe_bh, el, handle, 516 fe_bh, el, handle,
517 data_ac, meta_ac, reason_ret, 517 data_ac, meta_ac, reason_ret,
518 OCFS2_DINODE_EXTENT); 518 OCFS2_DINODE_EXTENT, NULL);
519} 519}
520 520
521static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start, 521static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start,
@@ -565,7 +565,7 @@ restart_all:
565 clusters_to_add); 565 clusters_to_add);
566 status = ocfs2_lock_allocators(inode, bh, &fe->id2.i_list, 566 status = ocfs2_lock_allocators(inode, bh, &fe->id2.i_list,
567 clusters_to_add, 0, &data_ac, 567 clusters_to_add, 0, &data_ac,
568 &meta_ac); 568 &meta_ac, OCFS2_DINODE_EXTENT, NULL);
569 if (status) { 569 if (status) {
570 mlog_errno(status); 570 mlog_errno(status);
571 goto leave; 571 goto leave;
@@ -1237,7 +1237,8 @@ static int __ocfs2_remove_inode_range(struct inode *inode,
1237 struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; 1237 struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
1238 1238
1239 ret = ocfs2_lock_allocators(inode, di_bh, &di->id2.i_list, 1239 ret = ocfs2_lock_allocators(inode, di_bh, &di->id2.i_list,
1240 0, 1, NULL, &meta_ac); 1240 0, 1, NULL, &meta_ac,
1241 OCFS2_DINODE_EXTENT, NULL);
1241 if (ret) { 1242 if (ret) {
1242 mlog_errno(ret); 1243 mlog_errno(ret);
1243 return ret; 1244 return ret;
@@ -1268,7 +1269,7 @@ static int __ocfs2_remove_inode_range(struct inode *inode,
1268 } 1269 }
1269 1270
1270 ret = ocfs2_remove_extent(inode, di_bh, cpos, len, handle, meta_ac, 1271 ret = ocfs2_remove_extent(inode, di_bh, cpos, len, handle, meta_ac,
1271 dealloc, OCFS2_DINODE_EXTENT); 1272 dealloc, OCFS2_DINODE_EXTENT, NULL);
1272 if (ret) { 1273 if (ret) {
1273 mlog_errno(ret); 1274 mlog_errno(ret);
1274 goto out_commit; 1275 goto out_commit;
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c
index b642c825fb7c..bb774d70d268 100644
--- a/fs/ocfs2/suballoc.c
+++ b/fs/ocfs2/suballoc.c
@@ -1909,7 +1909,8 @@ int ocfs2_lock_allocators(struct inode *inode, struct buffer_head *root_bh,
1909 struct ocfs2_extent_list *root_el, 1909 struct ocfs2_extent_list *root_el,
1910 u32 clusters_to_add, u32 extents_to_split, 1910 u32 clusters_to_add, u32 extents_to_split,
1911 struct ocfs2_alloc_context **data_ac, 1911 struct ocfs2_alloc_context **data_ac,
1912 struct ocfs2_alloc_context **meta_ac) 1912 struct ocfs2_alloc_context **meta_ac,
1913 enum ocfs2_extent_tree_type type, void *private)
1913{ 1914{
1914 int ret = 0, num_free_extents; 1915 int ret = 0, num_free_extents;
1915 unsigned int max_recs_needed = clusters_to_add + 2 * extents_to_split; 1916 unsigned int max_recs_needed = clusters_to_add + 2 * extents_to_split;
@@ -1922,7 +1923,7 @@ int ocfs2_lock_allocators(struct inode *inode, struct buffer_head *root_bh,
1922 BUG_ON(clusters_to_add != 0 && data_ac == NULL); 1923 BUG_ON(clusters_to_add != 0 && data_ac == NULL);
1923 1924
1924 num_free_extents = ocfs2_num_free_extents(osb, inode, root_bh, 1925 num_free_extents = ocfs2_num_free_extents(osb, inode, root_bh,
1925 OCFS2_DINODE_EXTENT); 1926 type, private);
1926 if (num_free_extents < 0) { 1927 if (num_free_extents < 0) {
1927 ret = num_free_extents; 1928 ret = num_free_extents;
1928 mlog_errno(ret); 1929 mlog_errno(ret);
diff --git a/fs/ocfs2/suballoc.h b/fs/ocfs2/suballoc.h
index a3e531e62df2..9e026c8afee4 100644
--- a/fs/ocfs2/suballoc.h
+++ b/fs/ocfs2/suballoc.h
@@ -166,5 +166,6 @@ int ocfs2_lock_allocators(struct inode *inode, struct buffer_head *root_bh,
166 struct ocfs2_extent_list *root_el, 166 struct ocfs2_extent_list *root_el,
167 u32 clusters_to_add, u32 extents_to_split, 167 u32 clusters_to_add, u32 extents_to_split,
168 struct ocfs2_alloc_context **data_ac, 168 struct ocfs2_alloc_context **data_ac,
169 struct ocfs2_alloc_context **meta_ac); 169 struct ocfs2_alloc_context **meta_ac,
170 enum ocfs2_extent_tree_type type, void *private);
170#endif /* _CHAINALLOC_H_ */ 171#endif /* _CHAINALLOC_H_ */
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
new file mode 100644
index 000000000000..9604a4cd02bb
--- /dev/null
+++ b/fs/ocfs2/xattr.c
@@ -0,0 +1,305 @@
1/* -*- mode: c; c-basic-offset: 8; -*-
2 * vim: noexpandtab sw=8 ts=8 sts=0:
3 *
4 * xattr.c
5 *
6 * Copyright (C) 2008 Oracle. All rights reserved.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this program; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 021110-1307, USA.
22 */
23
24#define MLOG_MASK_PREFIX ML_XATTR
25#include <cluster/masklog.h>
26
27#include "ocfs2.h"
28#include "alloc.h"
29#include "dlmglue.h"
30#include "file.h"
31#include "inode.h"
32#include "journal.h"
33#include "ocfs2_fs.h"
34#include "suballoc.h"
35#include "uptodate.h"
36#include "buffer_head_io.h"
37
38static int ocfs2_xattr_extend_allocation(struct inode *inode,
39 u32 clusters_to_add,
40 struct buffer_head *xattr_bh,
41 struct ocfs2_xattr_value_root *xv)
42{
43 int status = 0;
44 int restart_func = 0;
45 int credits = 0;
46 handle_t *handle = NULL;
47 struct ocfs2_alloc_context *data_ac = NULL;
48 struct ocfs2_alloc_context *meta_ac = NULL;
49 enum ocfs2_alloc_restarted why;
50 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
51 struct ocfs2_extent_list *root_el = &xv->xr_list;
52 u32 prev_clusters, logical_start = le32_to_cpu(xv->xr_clusters);
53
54 mlog(0, "(clusters_to_add for xattr= %u)\n", clusters_to_add);
55
56restart_all:
57
58 status = ocfs2_lock_allocators(inode, xattr_bh, root_el,
59 clusters_to_add, 0, &data_ac,
60 &meta_ac, OCFS2_XATTR_VALUE_EXTENT, xv);
61 if (status) {
62 mlog_errno(status);
63 goto leave;
64 }
65
66 credits = ocfs2_calc_extend_credits(osb->sb, root_el, clusters_to_add);
67 handle = ocfs2_start_trans(osb, credits);
68 if (IS_ERR(handle)) {
69 status = PTR_ERR(handle);
70 handle = NULL;
71 mlog_errno(status);
72 goto leave;
73 }
74
75restarted_transaction:
76 status = ocfs2_journal_access(handle, inode, xattr_bh,
77 OCFS2_JOURNAL_ACCESS_WRITE);
78 if (status < 0) {
79 mlog_errno(status);
80 goto leave;
81 }
82
83 prev_clusters = le32_to_cpu(xv->xr_clusters);
84 status = ocfs2_add_clusters_in_btree(osb,
85 inode,
86 &logical_start,
87 clusters_to_add,
88 0,
89 xattr_bh,
90 root_el,
91 handle,
92 data_ac,
93 meta_ac,
94 &why,
95 OCFS2_XATTR_VALUE_EXTENT,
96 xv);
97 if ((status < 0) && (status != -EAGAIN)) {
98 if (status != -ENOSPC)
99 mlog_errno(status);
100 goto leave;
101 }
102
103 status = ocfs2_journal_dirty(handle, xattr_bh);
104 if (status < 0) {
105 mlog_errno(status);
106 goto leave;
107 }
108
109 clusters_to_add -= le32_to_cpu(xv->xr_clusters) - prev_clusters;
110
111 if (why != RESTART_NONE && clusters_to_add) {
112 if (why == RESTART_META) {
113 mlog(0, "restarting function.\n");
114 restart_func = 1;
115 } else {
116 BUG_ON(why != RESTART_TRANS);
117
118 mlog(0, "restarting transaction.\n");
119 /* TODO: This can be more intelligent. */
120 credits = ocfs2_calc_extend_credits(osb->sb,
121 root_el,
122 clusters_to_add);
123 status = ocfs2_extend_trans(handle, credits);
124 if (status < 0) {
125 /* handle still has to be committed at
126 * this point. */
127 status = -ENOMEM;
128 mlog_errno(status);
129 goto leave;
130 }
131 goto restarted_transaction;
132 }
133 }
134
135leave:
136 if (handle) {
137 ocfs2_commit_trans(osb, handle);
138 handle = NULL;
139 }
140 if (data_ac) {
141 ocfs2_free_alloc_context(data_ac);
142 data_ac = NULL;
143 }
144 if (meta_ac) {
145 ocfs2_free_alloc_context(meta_ac);
146 meta_ac = NULL;
147 }
148 if ((!status) && restart_func) {
149 restart_func = 0;
150 goto restart_all;
151 }
152
153 return status;
154}
155
156static int __ocfs2_remove_xattr_range(struct inode *inode,
157 struct buffer_head *root_bh,
158 struct ocfs2_xattr_value_root *xv,
159 u32 cpos, u32 phys_cpos, u32 len,
160 struct ocfs2_cached_dealloc_ctxt *dealloc)
161{
162 int ret;
163 u64 phys_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys_cpos);
164 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
165 struct inode *tl_inode = osb->osb_tl_inode;
166 handle_t *handle;
167 struct ocfs2_alloc_context *meta_ac = NULL;
168
169 ret = ocfs2_lock_allocators(inode, root_bh, &xv->xr_list,
170 0, 1, NULL, &meta_ac,
171 OCFS2_XATTR_VALUE_EXTENT, xv);
172 if (ret) {
173 mlog_errno(ret);
174 return ret;
175 }
176
177 mutex_lock(&tl_inode->i_mutex);
178
179 if (ocfs2_truncate_log_needs_flush(osb)) {
180 ret = __ocfs2_flush_truncate_log(osb);
181 if (ret < 0) {
182 mlog_errno(ret);
183 goto out;
184 }
185 }
186
187 handle = ocfs2_start_trans(osb, OCFS2_REMOVE_EXTENT_CREDITS);
188 if (IS_ERR(handle)) {
189 ret = PTR_ERR(handle);
190 mlog_errno(ret);
191 goto out;
192 }
193
194 ret = ocfs2_journal_access(handle, inode, root_bh,
195 OCFS2_JOURNAL_ACCESS_WRITE);
196 if (ret) {
197 mlog_errno(ret);
198 goto out_commit;
199 }
200
201 ret = ocfs2_remove_extent(inode, root_bh, cpos, len, handle, meta_ac,
202 dealloc, OCFS2_XATTR_VALUE_EXTENT, xv);
203 if (ret) {
204 mlog_errno(ret);
205 goto out_commit;
206 }
207
208 le32_add_cpu(&xv->xr_clusters, -len);
209
210 ret = ocfs2_journal_dirty(handle, root_bh);
211 if (ret) {
212 mlog_errno(ret);
213 goto out_commit;
214 }
215
216 ret = ocfs2_truncate_log_append(osb, handle, phys_blkno, len);
217 if (ret)
218 mlog_errno(ret);
219
220out_commit:
221 ocfs2_commit_trans(osb, handle);
222out:
223 mutex_unlock(&tl_inode->i_mutex);
224
225 if (meta_ac)
226 ocfs2_free_alloc_context(meta_ac);
227
228 return ret;
229}
230
231static int ocfs2_xattr_shrink_size(struct inode *inode,
232 u32 old_clusters,
233 u32 new_clusters,
234 struct buffer_head *root_bh,
235 struct ocfs2_xattr_value_root *xv)
236{
237 int ret = 0;
238 u32 trunc_len, cpos, phys_cpos, alloc_size;
239 u64 block;
240 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
241 struct ocfs2_cached_dealloc_ctxt dealloc;
242
243 ocfs2_init_dealloc_ctxt(&dealloc);
244
245 if (old_clusters <= new_clusters)
246 return 0;
247
248 cpos = new_clusters;
249 trunc_len = old_clusters - new_clusters;
250 while (trunc_len) {
251 ret = ocfs2_xattr_get_clusters(inode, cpos, &phys_cpos,
252 &alloc_size, &xv->xr_list);
253 if (ret) {
254 mlog_errno(ret);
255 goto out;
256 }
257
258 if (alloc_size > trunc_len)
259 alloc_size = trunc_len;
260
261 ret = __ocfs2_remove_xattr_range(inode, root_bh, xv, cpos,
262 phys_cpos, alloc_size,
263 &dealloc);
264 if (ret) {
265 mlog_errno(ret);
266 goto out;
267 }
268
269 block = ocfs2_clusters_to_blocks(inode->i_sb, phys_cpos);
270 ocfs2_remove_xattr_clusters_from_cache(inode, block,
271 alloc_size);
272 cpos += alloc_size;
273 trunc_len -= alloc_size;
274 }
275
276out:
277 ocfs2_schedule_truncate_log_flush(osb, 1);
278 ocfs2_run_deallocs(osb, &dealloc);
279
280 return ret;
281}
282
283static int ocfs2_xattr_value_truncate(struct inode *inode,
284 struct buffer_head *root_bh,
285 struct ocfs2_xattr_value_root *xv,
286 int len)
287{
288 int ret;
289 u32 new_clusters = ocfs2_clusters_for_bytes(inode->i_sb, len);
290 u32 old_clusters = le32_to_cpu(xv->xr_clusters);
291
292 if (new_clusters == old_clusters)
293 return 0;
294
295 if (new_clusters > old_clusters)
296 ret = ocfs2_xattr_extend_allocation(inode,
297 new_clusters - old_clusters,
298 root_bh, xv);
299 else
300 ret = ocfs2_xattr_shrink_size(inode,
301 old_clusters, new_clusters,
302 root_bh, xv);
303
304 return ret;
305}