diff options
Diffstat (limited to 'fs')
-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 |