diff options
-rw-r--r-- | fs/ocfs2/xattr.c | 105 |
1 files changed, 32 insertions, 73 deletions
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index 4b247047b7aa..5a5a1bd7eede 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
@@ -4148,11 +4148,10 @@ static int ocfs2_adjust_xattr_cross_cluster(struct inode *inode, | |||
4148 | */ | 4148 | */ |
4149 | static int ocfs2_add_new_xattr_cluster(struct inode *inode, | 4149 | static int ocfs2_add_new_xattr_cluster(struct inode *inode, |
4150 | struct buffer_head *root_bh, | 4150 | struct buffer_head *root_bh, |
4151 | struct buffer_head **first_bh, | 4151 | struct ocfs2_xattr_bucket *first, |
4152 | struct buffer_head **header_bh, | 4152 | struct ocfs2_xattr_bucket *target, |
4153 | u32 *num_clusters, | 4153 | u32 *num_clusters, |
4154 | u32 prev_cpos, | 4154 | u32 prev_cpos, |
4155 | u64 prev_blkno, | ||
4156 | int *extend, | 4155 | int *extend, |
4157 | struct ocfs2_xattr_set_ctxt *ctxt) | 4156 | struct ocfs2_xattr_set_ctxt *ctxt) |
4158 | { | 4157 | { |
@@ -4164,38 +4163,14 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode, | |||
4164 | handle_t *handle = ctxt->handle; | 4163 | handle_t *handle = ctxt->handle; |
4165 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 4164 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
4166 | struct ocfs2_extent_tree et; | 4165 | struct ocfs2_extent_tree et; |
4167 | struct ocfs2_xattr_bucket *first, *target; | ||
4168 | 4166 | ||
4169 | mlog(0, "Add new xattr cluster for %llu, previous xattr hash = %u, " | 4167 | mlog(0, "Add new xattr cluster for %llu, previous xattr hash = %u, " |
4170 | "previous xattr blkno = %llu\n", | 4168 | "previous xattr blkno = %llu\n", |
4171 | (unsigned long long)OCFS2_I(inode)->ip_blkno, | 4169 | (unsigned long long)OCFS2_I(inode)->ip_blkno, |
4172 | prev_cpos, (unsigned long long)prev_blkno); | 4170 | prev_cpos, (unsigned long long)bucket_blkno(first)); |
4173 | 4171 | ||
4174 | ocfs2_init_xattr_tree_extent_tree(&et, inode, root_bh); | 4172 | ocfs2_init_xattr_tree_extent_tree(&et, inode, root_bh); |
4175 | 4173 | ||
4176 | /* The first bucket of the original extent */ | ||
4177 | first = ocfs2_xattr_bucket_new(inode); | ||
4178 | /* The target bucket for insert */ | ||
4179 | target = ocfs2_xattr_bucket_new(inode); | ||
4180 | if (!first || !target) { | ||
4181 | ret = -ENOMEM; | ||
4182 | mlog_errno(ret); | ||
4183 | goto leave; | ||
4184 | } | ||
4185 | |||
4186 | BUG_ON(prev_blkno != (*first_bh)->b_blocknr); | ||
4187 | ret = ocfs2_read_xattr_bucket(first, prev_blkno); | ||
4188 | if (ret) { | ||
4189 | mlog_errno(ret); | ||
4190 | goto leave; | ||
4191 | } | ||
4192 | |||
4193 | ret = ocfs2_read_xattr_bucket(target, (*header_bh)->b_blocknr); | ||
4194 | if (ret) { | ||
4195 | mlog_errno(ret); | ||
4196 | goto leave; | ||
4197 | } | ||
4198 | |||
4199 | ret = ocfs2_journal_access(handle, inode, root_bh, | 4174 | ret = ocfs2_journal_access(handle, inode, root_bh, |
4200 | OCFS2_JOURNAL_ACCESS_WRITE); | 4175 | OCFS2_JOURNAL_ACCESS_WRITE); |
4201 | if (ret < 0) { | 4176 | if (ret < 0) { |
@@ -4217,7 +4192,7 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode, | |||
4217 | mlog(0, "Allocating %u clusters at block %u for xattr in inode %llu\n", | 4192 | mlog(0, "Allocating %u clusters at block %u for xattr in inode %llu\n", |
4218 | num_bits, bit_off, (unsigned long long)OCFS2_I(inode)->ip_blkno); | 4193 | num_bits, bit_off, (unsigned long long)OCFS2_I(inode)->ip_blkno); |
4219 | 4194 | ||
4220 | if (prev_blkno + prev_clusters * bpc == block && | 4195 | if (bucket_blkno(first) + (prev_clusters * bpc) == block && |
4221 | (prev_clusters + num_bits) << osb->s_clustersize_bits <= | 4196 | (prev_clusters + num_bits) << osb->s_clustersize_bits <= |
4222 | OCFS2_MAX_XATTR_TREE_LEAF_SIZE) { | 4197 | OCFS2_MAX_XATTR_TREE_LEAF_SIZE) { |
4223 | /* | 4198 | /* |
@@ -4246,17 +4221,6 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode, | |||
4246 | mlog_errno(ret); | 4221 | mlog_errno(ret); |
4247 | goto leave; | 4222 | goto leave; |
4248 | } | 4223 | } |
4249 | |||
4250 | /* Did first+target get moved? */ | ||
4251 | if (prev_blkno != bucket_blkno(first)) { | ||
4252 | brelse(*first_bh); | ||
4253 | *first_bh = first->bu_bhs[0]; | ||
4254 | get_bh(*first_bh); | ||
4255 | |||
4256 | brelse(*header_bh); | ||
4257 | *header_bh = target->bu_bhs[0]; | ||
4258 | get_bh(*header_bh); | ||
4259 | } | ||
4260 | } | 4224 | } |
4261 | 4225 | ||
4262 | mlog(0, "Insert %u clusters at block %llu for xattr at %u\n", | 4226 | mlog(0, "Insert %u clusters at block %llu for xattr at %u\n", |
@@ -4273,8 +4237,6 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode, | |||
4273 | mlog_errno(ret); | 4237 | mlog_errno(ret); |
4274 | 4238 | ||
4275 | leave: | 4239 | leave: |
4276 | ocfs2_xattr_bucket_free(first); | ||
4277 | ocfs2_xattr_bucket_free(target); | ||
4278 | return ret; | 4240 | return ret; |
4279 | } | 4241 | } |
4280 | 4242 | ||
@@ -4357,16 +4319,16 @@ out: | |||
4357 | * We will move all the buckets starting from header_bh to the next place. As | 4319 | * We will move all the buckets starting from header_bh to the next place. As |
4358 | * for this one, half num of its xattrs will be moved to the next one. | 4320 | * for this one, half num of its xattrs will be moved to the next one. |
4359 | * | 4321 | * |
4360 | * We will allocate a new cluster if current cluster is full and adjust | 4322 | * We will allocate a new cluster if current cluster is full. The |
4361 | * header_bh and first_bh if the insert place is moved to the new cluster. | 4323 | * underlying calls will make sure that there is space at the target |
4324 | * bucket, shifting buckets around if necessary. 'target' may be updated | ||
4325 | * by those calls. | ||
4362 | */ | 4326 | */ |
4363 | static int ocfs2_add_new_xattr_bucket(struct inode *inode, | 4327 | static int ocfs2_add_new_xattr_bucket(struct inode *inode, |
4364 | struct buffer_head *xb_bh, | 4328 | struct buffer_head *xb_bh, |
4365 | struct buffer_head *header_bh, | 4329 | struct buffer_head *header_bh, |
4366 | struct ocfs2_xattr_set_ctxt *ctxt) | 4330 | struct ocfs2_xattr_set_ctxt *ctxt) |
4367 | { | 4331 | { |
4368 | struct ocfs2_xattr_header *first_xh = NULL; | ||
4369 | struct buffer_head *first_bh = NULL; | ||
4370 | struct ocfs2_xattr_block *xb = | 4332 | struct ocfs2_xattr_block *xb = |
4371 | (struct ocfs2_xattr_block *)xb_bh->b_data; | 4333 | (struct ocfs2_xattr_block *)xb_bh->b_data; |
4372 | struct ocfs2_xattr_tree_root *xb_root = &xb->xb_attrs.xb_root; | 4334 | struct ocfs2_xattr_tree_root *xb_root = &xb->xb_attrs.xb_root; |
@@ -4374,31 +4336,26 @@ static int ocfs2_add_new_xattr_bucket(struct inode *inode, | |||
4374 | struct ocfs2_xattr_header *xh = | 4336 | struct ocfs2_xattr_header *xh = |
4375 | (struct ocfs2_xattr_header *)header_bh->b_data; | 4337 | (struct ocfs2_xattr_header *)header_bh->b_data; |
4376 | u32 name_hash = le32_to_cpu(xh->xh_entries[0].xe_name_hash); | 4338 | u32 name_hash = le32_to_cpu(xh->xh_entries[0].xe_name_hash); |
4377 | struct super_block *sb = inode->i_sb; | 4339 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
4378 | struct ocfs2_super *osb = OCFS2_SB(sb); | ||
4379 | int ret, num_buckets, extend = 1; | 4340 | int ret, num_buckets, extend = 1; |
4380 | u64 p_blkno; | 4341 | u64 p_blkno; |
4381 | u32 e_cpos, num_clusters; | 4342 | u32 e_cpos, num_clusters; |
4382 | /* The bucket at the front of the extent */ | 4343 | /* The bucket at the front of the extent */ |
4383 | struct ocfs2_xattr_bucket *first; | 4344 | struct ocfs2_xattr_bucket *first, *target; |
4384 | 4345 | ||
4385 | mlog(0, "Add new xattr bucket starting form %llu\n", | 4346 | mlog(0, "Add new xattr bucket starting form %llu\n", |
4386 | (unsigned long long)header_bh->b_blocknr); | 4347 | (unsigned long long)header_bh->b_blocknr); |
4387 | 4348 | ||
4349 | /* The first bucket of the original extent */ | ||
4388 | first = ocfs2_xattr_bucket_new(inode); | 4350 | first = ocfs2_xattr_bucket_new(inode); |
4389 | if (!first) { | 4351 | /* The target bucket for insert */ |
4352 | target = ocfs2_xattr_bucket_new(inode); | ||
4353 | if (!first || !target) { | ||
4390 | ret = -ENOMEM; | 4354 | ret = -ENOMEM; |
4391 | mlog_errno(ret); | 4355 | mlog_errno(ret); |
4392 | goto out; | 4356 | goto out; |
4393 | } | 4357 | } |
4394 | 4358 | ||
4395 | /* | ||
4396 | * Add refrence for header_bh here because it may be | ||
4397 | * changed in ocfs2_add_new_xattr_cluster and we need | ||
4398 | * to free it in the end. | ||
4399 | */ | ||
4400 | get_bh(header_bh); | ||
4401 | |||
4402 | ret = ocfs2_xattr_get_rec(inode, name_hash, &p_blkno, &e_cpos, | 4359 | ret = ocfs2_xattr_get_rec(inode, name_hash, &p_blkno, &e_cpos, |
4403 | &num_clusters, el); | 4360 | &num_clusters, el); |
4404 | if (ret) { | 4361 | if (ret) { |
@@ -4406,23 +4363,30 @@ static int ocfs2_add_new_xattr_bucket(struct inode *inode, | |||
4406 | goto out; | 4363 | goto out; |
4407 | } | 4364 | } |
4408 | 4365 | ||
4409 | ret = ocfs2_read_block(inode, p_blkno, &first_bh, NULL); | 4366 | ret = ocfs2_read_xattr_bucket(first, p_blkno); |
4410 | if (ret) { | 4367 | if (ret) { |
4411 | mlog_errno(ret); | 4368 | mlog_errno(ret); |
4412 | goto out; | 4369 | goto out; |
4413 | } | 4370 | } |
4414 | 4371 | ||
4415 | num_buckets = ocfs2_xattr_buckets_per_cluster(osb) * num_clusters; | 4372 | ret = ocfs2_read_xattr_bucket(target, header_bh->b_blocknr); |
4416 | first_xh = (struct ocfs2_xattr_header *)first_bh->b_data; | 4373 | if (ret) { |
4374 | mlog_errno(ret); | ||
4375 | goto out; | ||
4376 | } | ||
4417 | 4377 | ||
4418 | if (num_buckets == le16_to_cpu(first_xh->xh_num_buckets)) { | 4378 | num_buckets = ocfs2_xattr_buckets_per_cluster(osb) * num_clusters; |
4379 | if (num_buckets == le16_to_cpu(bucket_xh(first)->xh_num_buckets)) { | ||
4380 | /* | ||
4381 | * This can move first+target if the target bucket moves | ||
4382 | * to the new extent. | ||
4383 | */ | ||
4419 | ret = ocfs2_add_new_xattr_cluster(inode, | 4384 | ret = ocfs2_add_new_xattr_cluster(inode, |
4420 | xb_bh, | 4385 | xb_bh, |
4421 | &first_bh, | 4386 | first, |
4422 | &header_bh, | 4387 | target, |
4423 | &num_clusters, | 4388 | &num_clusters, |
4424 | e_cpos, | 4389 | e_cpos, |
4425 | p_blkno, | ||
4426 | &extend, | 4390 | &extend, |
4427 | ctxt); | 4391 | ctxt); |
4428 | if (ret) { | 4392 | if (ret) { |
@@ -4432,24 +4396,19 @@ static int ocfs2_add_new_xattr_bucket(struct inode *inode, | |||
4432 | } | 4396 | } |
4433 | 4397 | ||
4434 | if (extend) { | 4398 | if (extend) { |
4435 | /* These bucket reads should be cached */ | ||
4436 | ret = ocfs2_read_xattr_bucket(first, first_bh->b_blocknr); | ||
4437 | if (ret) { | ||
4438 | mlog_errno(ret); | ||
4439 | goto out; | ||
4440 | } | ||
4441 | ret = ocfs2_extend_xattr_bucket(inode, | 4399 | ret = ocfs2_extend_xattr_bucket(inode, |
4442 | ctxt->handle, | 4400 | ctxt->handle, |
4443 | first, header_bh->b_blocknr, | 4401 | first, |
4402 | bucket_blkno(target), | ||
4444 | num_clusters); | 4403 | num_clusters); |
4445 | if (ret) | 4404 | if (ret) |
4446 | mlog_errno(ret); | 4405 | mlog_errno(ret); |
4447 | } | 4406 | } |
4448 | 4407 | ||
4449 | out: | 4408 | out: |
4450 | brelse(first_bh); | ||
4451 | brelse(header_bh); | ||
4452 | ocfs2_xattr_bucket_free(first); | 4409 | ocfs2_xattr_bucket_free(first); |
4410 | ocfs2_xattr_bucket_free(target); | ||
4411 | |||
4453 | return ret; | 4412 | return ret; |
4454 | } | 4413 | } |
4455 | 4414 | ||