aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ocfs2/xattr.c197
1 files changed, 43 insertions, 154 deletions
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index b1f2a164e7dc..64700c3fc244 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -2301,9 +2301,12 @@ static int ocfs2_xattr_bucket_find(struct inode *inode,
2301 2301
2302 /* 2302 /*
2303 * Check whether the hash of the last entry in our 2303 * Check whether the hash of the last entry in our
2304 * bucket is larger than the search one. 2304 * bucket is larger than the search one. for an empty
2305 * bucket, the last one is also the first one.
2305 */ 2306 */
2306 xe = &xh->xh_entries[le16_to_cpu(xh->xh_count) - 1]; 2307 if (xh->xh_count)
2308 xe = &xh->xh_entries[le16_to_cpu(xh->xh_count) - 1];
2309
2307 last_hash = le32_to_cpu(xe->xe_name_hash); 2310 last_hash = le32_to_cpu(xe->xe_name_hash);
2308 2311
2309 /* record lower_bh which may be the insert place. */ 2312 /* record lower_bh which may be the insert place. */
@@ -2450,7 +2453,8 @@ static int ocfs2_iterate_xattr_buckets(struct inode *inode,
2450 if (i == 0) 2453 if (i == 0)
2451 num_buckets = le16_to_cpu(bucket.xh->xh_num_buckets); 2454 num_buckets = le16_to_cpu(bucket.xh->xh_num_buckets);
2452 2455
2453 mlog(0, "iterating xattr bucket %llu\n", blkno); 2456 mlog(0, "iterating xattr bucket %llu, first hash %u\n", blkno,
2457 le32_to_cpu(bucket.xh->xh_entries[0].xe_name_hash));
2454 if (func) { 2458 if (func) {
2455 ret = func(inode, &bucket, para); 2459 ret = func(inode, &bucket, para);
2456 if (ret) { 2460 if (ret) {
@@ -3915,8 +3919,6 @@ static inline char *ocfs2_xattr_bucket_get_val(struct inode *inode,
3915 3919
3916/* 3920/*
3917 * Handle the normal xattr set, including replace, delete and new. 3921 * Handle the normal xattr set, including replace, delete and new.
3918 * When the bucket is empty, "is_empty" is set and the caller can
3919 * free this bucket.
3920 * 3922 *
3921 * Note: "local" indicates the real data's locality. So we can't 3923 * Note: "local" indicates the real data's locality. So we can't
3922 * just its bucket locality by its length. 3924 * just its bucket locality by its length.
@@ -3925,8 +3927,7 @@ static void ocfs2_xattr_set_entry_normal(struct inode *inode,
3925 struct ocfs2_xattr_info *xi, 3927 struct ocfs2_xattr_info *xi,
3926 struct ocfs2_xattr_search *xs, 3928 struct ocfs2_xattr_search *xs,
3927 u32 name_hash, 3929 u32 name_hash,
3928 int local, 3930 int local)
3929 int *is_empty)
3930{ 3931{
3931 struct ocfs2_xattr_entry *last, *xe; 3932 struct ocfs2_xattr_entry *last, *xe;
3932 int name_len = strlen(xi->name); 3933 int name_len = strlen(xi->name);
@@ -3979,14 +3980,23 @@ static void ocfs2_xattr_set_entry_normal(struct inode *inode,
3979 ocfs2_xattr_set_local(xe, local); 3980 ocfs2_xattr_set_local(xe, local);
3980 return; 3981 return;
3981 } else { 3982 } else {
3982 /* Remove the old entry. */ 3983 /*
3984 * Remove the old entry if there is more than one.
3985 * We don't remove the last entry so that we can
3986 * use it to indicate the hash value of the empty
3987 * bucket.
3988 */
3983 last -= 1; 3989 last -= 1;
3984 memmove(xe, xe + 1,
3985 (void *)last - (void *)xe);
3986 memset(last, 0, sizeof(struct ocfs2_xattr_entry));
3987 le16_add_cpu(&xh->xh_count, -1); 3990 le16_add_cpu(&xh->xh_count, -1);
3988 if (xh->xh_count == 0 && is_empty) 3991 if (xh->xh_count) {
3989 *is_empty = 1; 3992 memmove(xe, xe + 1,
3993 (void *)last - (void *)xe);
3994 memset(last, 0,
3995 sizeof(struct ocfs2_xattr_entry));
3996 } else
3997 xh->xh_free_start =
3998 cpu_to_le16(OCFS2_XATTR_BUCKET_SIZE);
3999
3990 return; 4000 return;
3991 } 4001 }
3992 } else { 4002 } else {
@@ -3994,7 +4004,7 @@ static void ocfs2_xattr_set_entry_normal(struct inode *inode,
3994 int low = 0, high = count - 1, tmp; 4004 int low = 0, high = count - 1, tmp;
3995 struct ocfs2_xattr_entry *tmp_xe; 4005 struct ocfs2_xattr_entry *tmp_xe;
3996 4006
3997 while (low <= high) { 4007 while (low <= high && count) {
3998 tmp = (low + high) / 2; 4008 tmp = (low + high) / 2;
3999 tmp_xe = &xh->xh_entries[tmp]; 4009 tmp_xe = &xh->xh_entries[tmp];
4000 4010
@@ -4090,8 +4100,7 @@ static int ocfs2_xattr_set_entry_in_bucket(struct inode *inode,
4090 struct ocfs2_xattr_info *xi, 4100 struct ocfs2_xattr_info *xi,
4091 struct ocfs2_xattr_search *xs, 4101 struct ocfs2_xattr_search *xs,
4092 u32 name_hash, 4102 u32 name_hash,
4093 int local, 4103 int local)
4094 int *bucket_empty)
4095{ 4104{
4096 int i, ret; 4105 int i, ret;
4097 handle_t *handle = NULL; 4106 handle_t *handle = NULL;
@@ -4130,8 +4139,7 @@ static int ocfs2_xattr_set_entry_in_bucket(struct inode *inode,
4130 } 4139 }
4131 } 4140 }
4132 4141
4133 ocfs2_xattr_set_entry_normal(inode, xi, xs, name_hash, 4142 ocfs2_xattr_set_entry_normal(inode, xi, xs, name_hash, local);
4134 local, bucket_empty);
4135 4143
4136 /*Only dirty the blocks we have touched in set xattr. */ 4144 /*Only dirty the blocks we have touched in set xattr. */
4137 ret = ocfs2_xattr_bucket_handle_journal(inode, handle, xs, 4145 ret = ocfs2_xattr_bucket_handle_journal(inode, handle, xs,
@@ -4280,69 +4288,6 @@ static int ocfs2_xattr_bucket_set_value_outside(struct inode *inode,
4280 return __ocfs2_xattr_set_value_outside(inode, xv, val, value_len); 4288 return __ocfs2_xattr_set_value_outside(inode, xv, val, value_len);
4281} 4289}
4282 4290
4283/*
4284 * Remove the xattr bucket pointed by bucket_bh.
4285 * All the buckets after it in the same xattr extent rec will be
4286 * move forward one by one.
4287 */
4288static int ocfs2_rm_xattr_bucket(struct inode *inode,
4289 struct buffer_head *first_bh,
4290 struct ocfs2_xattr_bucket *bucket)
4291{
4292 int ret = 0, credits;
4293 struct ocfs2_xattr_header *xh =
4294 (struct ocfs2_xattr_header *)first_bh->b_data;
4295 u16 bucket_num = le16_to_cpu(xh->xh_num_buckets);
4296 u64 end, start = bucket->bhs[0]->b_blocknr;
4297 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
4298 handle_t *handle;
4299 u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
4300
4301 end = first_bh->b_blocknr + (bucket_num - 1) * blk_per_bucket;
4302
4303 mlog(0, "rm xattr bucket %llu\n", start);
4304 /*
4305 * We need to update the first xattr_header and all the buckets starting
4306 * from start in this xattr rec.
4307 *
4308 * XXX: Should we empty the old last bucket here?
4309 */
4310 credits = 1 + end - start;
4311 handle = ocfs2_start_trans(osb, credits);
4312 if (IS_ERR(handle)) {
4313 ret = PTR_ERR(handle);
4314 mlog_errno(ret);
4315 return ret;
4316 }
4317
4318 ret = ocfs2_journal_access(handle, inode, first_bh,
4319 OCFS2_JOURNAL_ACCESS_WRITE);
4320 if (ret) {
4321 mlog_errno(ret);
4322 goto out_commit;
4323 }
4324
4325
4326 while (start < end) {
4327 ret = ocfs2_cp_xattr_bucket(inode, handle,
4328 start + blk_per_bucket,
4329 start, 0);
4330 if (ret) {
4331 mlog_errno(ret);
4332 goto out_commit;
4333 }
4334 start += blk_per_bucket;
4335 }
4336
4337 /* update the first_bh. */
4338 xh->xh_num_buckets = cpu_to_le16(bucket_num - 1);
4339 ocfs2_journal_dirty(handle, first_bh);
4340
4341out_commit:
4342 ocfs2_commit_trans(osb, handle);
4343 return ret;
4344}
4345
4346static int ocfs2_rm_xattr_cluster(struct inode *inode, 4291static int ocfs2_rm_xattr_cluster(struct inode *inode,
4347 struct buffer_head *root_bh, 4292 struct buffer_head *root_bh,
4348 u64 blkno, 4293 u64 blkno,
@@ -4432,57 +4377,6 @@ out:
4432 return ret; 4377 return ret;
4433} 4378}
4434 4379
4435/*
4436 * Free the xattr bucket indicated by xs->bucket and if all the buckets
4437 * in the clusters is free, free the clusters also.
4438 */
4439static int ocfs2_xattr_bucket_shrink(struct inode *inode,
4440 struct ocfs2_xattr_info *xi,
4441 struct ocfs2_xattr_search *xs,
4442 u32 name_hash)
4443{
4444 int ret;
4445 u32 e_cpos, num_clusters;
4446 u64 p_blkno;
4447 struct buffer_head *first_bh = NULL;
4448 struct ocfs2_xattr_header *first_xh;
4449 struct ocfs2_xattr_block *xb =
4450 (struct ocfs2_xattr_block *)xs->xattr_bh->b_data;
4451
4452 BUG_ON(xs->header->xh_count != 0);
4453
4454 ret = ocfs2_xattr_get_rec(inode, name_hash, &p_blkno,
4455 &e_cpos, &num_clusters,
4456 &xb->xb_attrs.xb_root.xt_list);
4457 if (ret) {
4458 mlog_errno(ret);
4459 return ret;
4460 }
4461
4462 ret = ocfs2_read_block(OCFS2_SB(inode->i_sb), p_blkno,
4463 &first_bh, OCFS2_BH_CACHED, inode);
4464 if (ret) {
4465 mlog_errno(ret);
4466 return ret;
4467 }
4468
4469 ret = ocfs2_rm_xattr_bucket(inode, first_bh, &xs->bucket);
4470 if (ret) {
4471 mlog_errno(ret);
4472 goto out;
4473 }
4474
4475 first_xh = (struct ocfs2_xattr_header *)first_bh->b_data;
4476 if (first_xh->xh_num_buckets == 0)
4477 ret = ocfs2_rm_xattr_cluster(inode, xs->xattr_bh,
4478 p_blkno, e_cpos,
4479 num_clusters);
4480
4481out:
4482 brelse(first_bh);
4483 return ret;
4484}
4485
4486static void ocfs2_xattr_bucket_remove_xs(struct inode *inode, 4380static void ocfs2_xattr_bucket_remove_xs(struct inode *inode,
4487 struct ocfs2_xattr_search *xs) 4381 struct ocfs2_xattr_search *xs)
4488{ 4382{
@@ -4534,7 +4428,7 @@ static int ocfs2_xattr_set_in_bucket(struct inode *inode,
4534 struct ocfs2_xattr_info *xi, 4428 struct ocfs2_xattr_info *xi,
4535 struct ocfs2_xattr_search *xs) 4429 struct ocfs2_xattr_search *xs)
4536{ 4430{
4537 int ret, local = 1, bucket_empty = 0; 4431 int ret, local = 1;
4538 size_t value_len; 4432 size_t value_len;
4539 char *val = (char *)xi->value; 4433 char *val = (char *)xi->value;
4540 struct ocfs2_xattr_entry *xe = xs->here; 4434 struct ocfs2_xattr_entry *xe = xs->here;
@@ -4580,34 +4474,29 @@ static int ocfs2_xattr_set_in_bucket(struct inode *inode,
4580 xi->value_len = OCFS2_XATTR_ROOT_SIZE; 4474 xi->value_len = OCFS2_XATTR_ROOT_SIZE;
4581 } 4475 }
4582 4476
4583 ret = ocfs2_xattr_set_entry_in_bucket(inode, xi, xs, name_hash, 4477 ret = ocfs2_xattr_set_entry_in_bucket(inode, xi, xs, name_hash, local);
4584 local, &bucket_empty);
4585 if (ret) { 4478 if (ret) {
4586 mlog_errno(ret); 4479 mlog_errno(ret);
4587 goto out; 4480 goto out;
4588 } 4481 }
4589 4482
4590 if (value_len > OCFS2_XATTR_INLINE_SIZE) { 4483 if (value_len <= OCFS2_XATTR_INLINE_SIZE)
4591 /* allocate the space now for the outside block storage. */ 4484 goto out;
4592 ret = ocfs2_xattr_bucket_value_truncate_xs(inode, xs,
4593 value_len);
4594 if (ret) {
4595 mlog_errno(ret);
4596 4485
4597 if (xs->not_found) { 4486 /* allocate the space now for the outside block storage. */
4598 /* 4487 ret = ocfs2_xattr_bucket_value_truncate_xs(inode, xs,
4599 * We can't allocate enough clusters for outside 4488 value_len);
4600 * storage and we have allocated xattr already, 4489 if (ret) {
4601 * so need to remove it. 4490 mlog_errno(ret);
4602 */ 4491
4603 ocfs2_xattr_bucket_remove_xs(inode, xs); 4492 if (xs->not_found) {
4604 } 4493 /*
4605 goto out; 4494 * We can't allocate enough clusters for outside
4495 * storage and we have allocated xattr already,
4496 * so need to remove it.
4497 */
4498 ocfs2_xattr_bucket_remove_xs(inode, xs);
4606 } 4499 }
4607 } else {
4608 if (bucket_empty)
4609 ret = ocfs2_xattr_bucket_shrink(inode, xi,
4610 xs, name_hash);
4611 goto out; 4500 goto out;
4612 } 4501 }
4613 4502