diff options
author | Tao Ma <tao.ma@oracle.com> | 2009-08-17 23:43:42 -0400 |
---|---|---|
committer | Joel Becker <joel.becker@oracle.com> | 2009-09-22 23:09:43 -0400 |
commit | 47bca4950bc40fb54e9d41cbbc8b06cd653d2ae2 (patch) | |
tree | 17d36e5b9f330cda55b6ee8ff9a0293bd080040e | |
parent | 5aea1f0ef4024ba28213c10181e1b16ec678c82d (diff) |
ocfs2: Abstract ocfs2 xattr tree extend rec iteration process.
Currently we have ocfs2_iterate_xattr_buckets which can receive
a para and a callback to iterate a series of bucket. It is good.
But actually the 2 callers ocfs2_xattr_tree_list_index_block and
ocfs2_delete_xattr_index_block are almost the same. The only
difference is that the latter need to handle the extent record
also. So add a new function named ocfs2_iterate_xattr_index_block.
It can be given func callback which are used for exten record.
So now we only have one iteration function for the xattr index
block. Ane what's more, it is useful for our future reflink
operations.
Signed-off-by: Tao Ma <tao.ma@oracle.com>
-rw-r--r-- | fs/ocfs2/xattr.c | 147 |
1 files changed, 76 insertions, 71 deletions
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index a9339eb94a2e..bfa7ee208855 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
@@ -157,7 +157,7 @@ static int ocfs2_xattr_index_block_find(struct inode *inode, | |||
157 | struct ocfs2_xattr_search *xs); | 157 | struct ocfs2_xattr_search *xs); |
158 | 158 | ||
159 | static int ocfs2_xattr_tree_list_index_block(struct inode *inode, | 159 | static int ocfs2_xattr_tree_list_index_block(struct inode *inode, |
160 | struct ocfs2_xattr_tree_root *xt, | 160 | struct buffer_head *blk_bh, |
161 | char *buffer, | 161 | char *buffer, |
162 | size_t buffer_size); | 162 | size_t buffer_size); |
163 | 163 | ||
@@ -170,8 +170,23 @@ static int ocfs2_xattr_set_entry_index_block(struct inode *inode, | |||
170 | struct ocfs2_xattr_search *xs, | 170 | struct ocfs2_xattr_search *xs, |
171 | struct ocfs2_xattr_set_ctxt *ctxt); | 171 | struct ocfs2_xattr_set_ctxt *ctxt); |
172 | 172 | ||
173 | static int ocfs2_delete_xattr_index_block(struct inode *inode, | 173 | typedef int (xattr_tree_rec_func)(struct inode *inode, |
174 | struct buffer_head *xb_bh); | 174 | struct buffer_head *root_bh, |
175 | u64 blkno, u32 cpos, u32 len, void *para); | ||
176 | static int ocfs2_iterate_xattr_index_block(struct inode *inode, | ||
177 | struct buffer_head *root_bh, | ||
178 | xattr_tree_rec_func *rec_func, | ||
179 | void *para); | ||
180 | static int ocfs2_delete_xattr_in_bucket(struct inode *inode, | ||
181 | struct ocfs2_xattr_bucket *bucket, | ||
182 | void *para); | ||
183 | static int ocfs2_rm_xattr_cluster(struct inode *inode, | ||
184 | struct buffer_head *root_bh, | ||
185 | u64 blkno, | ||
186 | u32 cpos, | ||
187 | u32 len, | ||
188 | void *para); | ||
189 | |||
175 | static int ocfs2_mv_xattr_buckets(struct inode *inode, handle_t *handle, | 190 | static int ocfs2_mv_xattr_buckets(struct inode *inode, handle_t *handle, |
176 | u64 src_blk, u64 last_blk, u64 to_blk, | 191 | u64 src_blk, u64 last_blk, u64 to_blk, |
177 | unsigned int start_bucket, | 192 | unsigned int start_bucket, |
@@ -870,11 +885,9 @@ static int ocfs2_xattr_block_list(struct inode *inode, | |||
870 | struct ocfs2_xattr_header *header = &xb->xb_attrs.xb_header; | 885 | struct ocfs2_xattr_header *header = &xb->xb_attrs.xb_header; |
871 | ret = ocfs2_xattr_list_entries(inode, header, | 886 | ret = ocfs2_xattr_list_entries(inode, header, |
872 | buffer, buffer_size); | 887 | buffer, buffer_size); |
873 | } else { | 888 | } else |
874 | struct ocfs2_xattr_tree_root *xt = &xb->xb_attrs.xb_root; | 889 | ret = ocfs2_xattr_tree_list_index_block(inode, blk_bh, |
875 | ret = ocfs2_xattr_tree_list_index_block(inode, xt, | ||
876 | buffer, buffer_size); | 890 | buffer, buffer_size); |
877 | } | ||
878 | 891 | ||
879 | brelse(blk_bh); | 892 | brelse(blk_bh); |
880 | 893 | ||
@@ -1801,7 +1814,10 @@ static int ocfs2_xattr_block_remove(struct inode *inode, | |||
1801 | struct ocfs2_xattr_header *header = &(xb->xb_attrs.xb_header); | 1814 | struct ocfs2_xattr_header *header = &(xb->xb_attrs.xb_header); |
1802 | ret = ocfs2_remove_value_outside(inode, &vb, header); | 1815 | ret = ocfs2_remove_value_outside(inode, &vb, header); |
1803 | } else | 1816 | } else |
1804 | ret = ocfs2_delete_xattr_index_block(inode, blk_bh); | 1817 | ret = ocfs2_iterate_xattr_index_block(inode, |
1818 | blk_bh, | ||
1819 | ocfs2_rm_xattr_cluster, | ||
1820 | NULL); | ||
1805 | 1821 | ||
1806 | return ret; | 1822 | return ret; |
1807 | } | 1823 | } |
@@ -3298,22 +3314,19 @@ static int ocfs2_list_xattr_bucket(struct inode *inode, | |||
3298 | return ret; | 3314 | return ret; |
3299 | } | 3315 | } |
3300 | 3316 | ||
3301 | static int ocfs2_xattr_tree_list_index_block(struct inode *inode, | 3317 | static int ocfs2_iterate_xattr_index_block(struct inode *inode, |
3302 | struct ocfs2_xattr_tree_root *xt, | 3318 | struct buffer_head *blk_bh, |
3303 | char *buffer, | 3319 | xattr_tree_rec_func *rec_func, |
3304 | size_t buffer_size) | 3320 | void *para) |
3305 | { | 3321 | { |
3306 | struct ocfs2_extent_list *el = &xt->xt_list; | 3322 | struct ocfs2_xattr_block *xb = |
3323 | (struct ocfs2_xattr_block *)blk_bh->b_data; | ||
3324 | struct ocfs2_extent_list *el = &xb->xb_attrs.xb_root.xt_list; | ||
3307 | int ret = 0; | 3325 | int ret = 0; |
3308 | u32 name_hash = UINT_MAX, e_cpos = 0, num_clusters = 0; | 3326 | u32 name_hash = UINT_MAX, e_cpos = 0, num_clusters = 0; |
3309 | u64 p_blkno = 0; | 3327 | u64 p_blkno = 0; |
3310 | struct ocfs2_xattr_tree_list xl = { | ||
3311 | .buffer = buffer, | ||
3312 | .buffer_size = buffer_size, | ||
3313 | .result = 0, | ||
3314 | }; | ||
3315 | 3328 | ||
3316 | if (le16_to_cpu(el->l_next_free_rec) == 0) | 3329 | if (!el->l_next_free_rec || !rec_func) |
3317 | return 0; | 3330 | return 0; |
3318 | 3331 | ||
3319 | while (name_hash > 0) { | 3332 | while (name_hash > 0) { |
@@ -3321,16 +3334,15 @@ static int ocfs2_xattr_tree_list_index_block(struct inode *inode, | |||
3321 | &e_cpos, &num_clusters, el); | 3334 | &e_cpos, &num_clusters, el); |
3322 | if (ret) { | 3335 | if (ret) { |
3323 | mlog_errno(ret); | 3336 | mlog_errno(ret); |
3324 | goto out; | 3337 | break; |
3325 | } | 3338 | } |
3326 | 3339 | ||
3327 | ret = ocfs2_iterate_xattr_buckets(inode, p_blkno, num_clusters, | 3340 | ret = rec_func(inode, blk_bh, p_blkno, e_cpos, |
3328 | ocfs2_list_xattr_bucket, | 3341 | num_clusters, para); |
3329 | &xl); | ||
3330 | if (ret) { | 3342 | if (ret) { |
3331 | if (ret != -ERANGE) | 3343 | if (ret != -ERANGE) |
3332 | mlog_errno(ret); | 3344 | mlog_errno(ret); |
3333 | goto out; | 3345 | break; |
3334 | } | 3346 | } |
3335 | 3347 | ||
3336 | if (e_cpos == 0) | 3348 | if (e_cpos == 0) |
@@ -3339,6 +3351,37 @@ static int ocfs2_xattr_tree_list_index_block(struct inode *inode, | |||
3339 | name_hash = e_cpos - 1; | 3351 | name_hash = e_cpos - 1; |
3340 | } | 3352 | } |
3341 | 3353 | ||
3354 | return ret; | ||
3355 | |||
3356 | } | ||
3357 | |||
3358 | static int ocfs2_list_xattr_tree_rec(struct inode *inode, | ||
3359 | struct buffer_head *root_bh, | ||
3360 | u64 blkno, u32 cpos, u32 len, void *para) | ||
3361 | { | ||
3362 | return ocfs2_iterate_xattr_buckets(inode, blkno, len, | ||
3363 | ocfs2_list_xattr_bucket, para); | ||
3364 | } | ||
3365 | |||
3366 | static int ocfs2_xattr_tree_list_index_block(struct inode *inode, | ||
3367 | struct buffer_head *blk_bh, | ||
3368 | char *buffer, | ||
3369 | size_t buffer_size) | ||
3370 | { | ||
3371 | int ret; | ||
3372 | struct ocfs2_xattr_tree_list xl = { | ||
3373 | .buffer = buffer, | ||
3374 | .buffer_size = buffer_size, | ||
3375 | .result = 0, | ||
3376 | }; | ||
3377 | |||
3378 | ret = ocfs2_iterate_xattr_index_block(inode, blk_bh, | ||
3379 | ocfs2_list_xattr_tree_rec, &xl); | ||
3380 | if (ret) { | ||
3381 | mlog_errno(ret); | ||
3382 | goto out; | ||
3383 | } | ||
3384 | |||
3342 | ret = xl.result; | 3385 | ret = xl.result; |
3343 | out: | 3386 | out: |
3344 | return ret; | 3387 | return ret; |
@@ -4897,7 +4940,8 @@ static int ocfs2_rm_xattr_cluster(struct inode *inode, | |||
4897 | struct buffer_head *root_bh, | 4940 | struct buffer_head *root_bh, |
4898 | u64 blkno, | 4941 | u64 blkno, |
4899 | u32 cpos, | 4942 | u32 cpos, |
4900 | u32 len) | 4943 | u32 len, |
4944 | void *para) | ||
4901 | { | 4945 | { |
4902 | int ret; | 4946 | int ret; |
4903 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 4947 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
@@ -4909,6 +4953,13 @@ static int ocfs2_rm_xattr_cluster(struct inode *inode, | |||
4909 | struct ocfs2_cached_dealloc_ctxt dealloc; | 4953 | struct ocfs2_cached_dealloc_ctxt dealloc; |
4910 | struct ocfs2_extent_tree et; | 4954 | struct ocfs2_extent_tree et; |
4911 | 4955 | ||
4956 | ret = ocfs2_iterate_xattr_buckets(inode, blkno, len, | ||
4957 | ocfs2_delete_xattr_in_bucket, NULL); | ||
4958 | if (ret) { | ||
4959 | mlog_errno(ret); | ||
4960 | return ret; | ||
4961 | } | ||
4962 | |||
4912 | ocfs2_init_xattr_tree_extent_tree(&et, INODE_CACHE(inode), root_bh); | 4963 | ocfs2_init_xattr_tree_extent_tree(&et, INODE_CACHE(inode), root_bh); |
4913 | 4964 | ||
4914 | ocfs2_init_dealloc_ctxt(&dealloc); | 4965 | ocfs2_init_dealloc_ctxt(&dealloc); |
@@ -5331,52 +5382,6 @@ static int ocfs2_delete_xattr_in_bucket(struct inode *inode, | |||
5331 | return ret; | 5382 | return ret; |
5332 | } | 5383 | } |
5333 | 5384 | ||
5334 | static int ocfs2_delete_xattr_index_block(struct inode *inode, | ||
5335 | struct buffer_head *xb_bh) | ||
5336 | { | ||
5337 | struct ocfs2_xattr_block *xb = | ||
5338 | (struct ocfs2_xattr_block *)xb_bh->b_data; | ||
5339 | struct ocfs2_extent_list *el = &xb->xb_attrs.xb_root.xt_list; | ||
5340 | int ret = 0; | ||
5341 | u32 name_hash = UINT_MAX, e_cpos, num_clusters; | ||
5342 | u64 p_blkno; | ||
5343 | |||
5344 | if (le16_to_cpu(el->l_next_free_rec) == 0) | ||
5345 | return 0; | ||
5346 | |||
5347 | while (name_hash > 0) { | ||
5348 | ret = ocfs2_xattr_get_rec(inode, name_hash, &p_blkno, | ||
5349 | &e_cpos, &num_clusters, el); | ||
5350 | if (ret) { | ||
5351 | mlog_errno(ret); | ||
5352 | goto out; | ||
5353 | } | ||
5354 | |||
5355 | ret = ocfs2_iterate_xattr_buckets(inode, p_blkno, num_clusters, | ||
5356 | ocfs2_delete_xattr_in_bucket, | ||
5357 | NULL); | ||
5358 | if (ret) { | ||
5359 | mlog_errno(ret); | ||
5360 | goto out; | ||
5361 | } | ||
5362 | |||
5363 | ret = ocfs2_rm_xattr_cluster(inode, xb_bh, | ||
5364 | p_blkno, e_cpos, num_clusters); | ||
5365 | if (ret) { | ||
5366 | mlog_errno(ret); | ||
5367 | break; | ||
5368 | } | ||
5369 | |||
5370 | if (e_cpos == 0) | ||
5371 | break; | ||
5372 | |||
5373 | name_hash = e_cpos - 1; | ||
5374 | } | ||
5375 | |||
5376 | out: | ||
5377 | return ret; | ||
5378 | } | ||
5379 | |||
5380 | /* | 5385 | /* |
5381 | * Whenever we modify a xattr value root in the bucket(e.g, CoW | 5386 | * Whenever we modify a xattr value root in the bucket(e.g, CoW |
5382 | * or change the extent record flag), we need to recalculate | 5387 | * or change the extent record flag), we need to recalculate |