diff options
-rw-r--r-- | fs/ocfs2/xattr.c | 85 |
1 files changed, 55 insertions, 30 deletions
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index df53a2ce2de5..ed1e95967565 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
@@ -3905,7 +3905,7 @@ static int ocfs2_cp_xattr_bucket(struct inode *inode, | |||
3905 | mlog_errno(ret); | 3905 | mlog_errno(ret); |
3906 | goto out; | 3906 | goto out; |
3907 | } | 3907 | } |
3908 | 3908 | ||
3909 | ret = ocfs2_read_xattr_bucket(s_bucket, s_blkno); | 3909 | ret = ocfs2_read_xattr_bucket(s_bucket, s_blkno); |
3910 | if (ret) | 3910 | if (ret) |
3911 | goto out; | 3911 | goto out; |
@@ -4232,37 +4232,45 @@ leave: | |||
4232 | } | 4232 | } |
4233 | 4233 | ||
4234 | /* | 4234 | /* |
4235 | * Extend a new xattr bucket and move xattrs to the end one by one until | 4235 | * We are given an extent. 'first' is the bucket at the very front of |
4236 | * We meet with start_bh. Only move half of the xattrs to the bucket after it. | 4236 | * the extent. The extent has space for an additional bucket past |
4237 | * bucket_xh(first)->xh_num_buckets. 'target_blkno' is the block number | ||
4238 | * of the target bucket. We wish to shift every bucket past the target | ||
4239 | * down one, filling in that additional space. When we get back to the | ||
4240 | * target, we split the target between itself and the now-empty bucket | ||
4241 | * at target+1 (aka, target_blkno + blks_per_bucket). | ||
4237 | */ | 4242 | */ |
4238 | static int ocfs2_extend_xattr_bucket(struct inode *inode, | 4243 | static int ocfs2_extend_xattr_bucket(struct inode *inode, |
4239 | handle_t *handle, | 4244 | handle_t *handle, |
4240 | struct buffer_head *first_bh, | 4245 | struct ocfs2_xattr_bucket *first, |
4241 | struct buffer_head *start_bh, | 4246 | u64 target_blk, |
4242 | u32 num_clusters) | 4247 | u32 num_clusters) |
4243 | { | 4248 | { |
4244 | int ret, credits; | 4249 | int ret, credits; |
4245 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 4250 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
4246 | u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb); | 4251 | u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb); |
4247 | u64 start_blk = start_bh->b_blocknr, end_blk; | 4252 | u64 end_blk; |
4248 | u32 num_buckets = num_clusters * ocfs2_xattr_buckets_per_cluster(osb); | 4253 | u16 new_bucket = le16_to_cpu(bucket_xh(first)->xh_num_buckets); |
4249 | struct ocfs2_xattr_header *first_xh = | ||
4250 | (struct ocfs2_xattr_header *)first_bh->b_data; | ||
4251 | u16 bucket = le16_to_cpu(first_xh->xh_num_buckets); | ||
4252 | 4254 | ||
4253 | mlog(0, "extend xattr bucket in %llu, xattr extend rec starting " | 4255 | mlog(0, "extend xattr bucket in %llu, xattr extend rec starting " |
4254 | "from %llu, len = %u\n", (unsigned long long)start_blk, | 4256 | "from %llu, len = %u\n", (unsigned long long)target_blk, |
4255 | (unsigned long long)first_bh->b_blocknr, num_clusters); | 4257 | (unsigned long long)bucket_blkno(first), num_clusters); |
4256 | 4258 | ||
4257 | BUG_ON(bucket >= num_buckets); | 4259 | /* The extent must have room for an additional bucket */ |
4260 | BUG_ON(new_bucket >= | ||
4261 | (num_clusters * ocfs2_xattr_buckets_per_cluster(osb))); | ||
4258 | 4262 | ||
4259 | end_blk = first_bh->b_blocknr + (bucket - 1) * blk_per_bucket; | 4263 | /* end_blk points to the last existing bucket */ |
4264 | end_blk = bucket_blkno(first) + ((new_bucket - 1) * blk_per_bucket); | ||
4260 | 4265 | ||
4261 | /* | 4266 | /* |
4262 | * We will touch all the buckets after the start_bh(include it). | 4267 | * end_blk is the start of the last existing bucket. |
4263 | * Then we add one more bucket. | 4268 | * Thus, (end_blk - target_blk) covers the target bucket and |
4269 | * every bucket after it up to, but not including, the last | ||
4270 | * existing bucket. Then we add the last existing bucket, the | ||
4271 | * new bucket, and the first bucket (3 * blk_per_bucket). | ||
4264 | */ | 4272 | */ |
4265 | credits = end_blk - start_blk + 3 * blk_per_bucket + 1 + | 4273 | credits = (end_blk - target_blk) + (3 * blk_per_bucket) + |
4266 | handle->h_buffer_credits; | 4274 | handle->h_buffer_credits; |
4267 | ret = ocfs2_extend_trans(handle, credits); | 4275 | ret = ocfs2_extend_trans(handle, credits); |
4268 | if (ret) { | 4276 | if (ret) { |
@@ -4270,14 +4278,14 @@ static int ocfs2_extend_xattr_bucket(struct inode *inode, | |||
4270 | goto out; | 4278 | goto out; |
4271 | } | 4279 | } |
4272 | 4280 | ||
4273 | ret = ocfs2_journal_access(handle, inode, first_bh, | 4281 | ret = ocfs2_xattr_bucket_journal_access(handle, first, |
4274 | OCFS2_JOURNAL_ACCESS_WRITE); | 4282 | OCFS2_JOURNAL_ACCESS_WRITE); |
4275 | if (ret) { | 4283 | if (ret) { |
4276 | mlog_errno(ret); | 4284 | mlog_errno(ret); |
4277 | goto out; | 4285 | goto out; |
4278 | } | 4286 | } |
4279 | 4287 | ||
4280 | while (end_blk != start_blk) { | 4288 | while (end_blk != target_blk) { |
4281 | ret = ocfs2_cp_xattr_bucket(inode, handle, end_blk, | 4289 | ret = ocfs2_cp_xattr_bucket(inode, handle, end_blk, |
4282 | end_blk + blk_per_bucket, 0); | 4290 | end_blk + blk_per_bucket, 0); |
4283 | if (ret) | 4291 | if (ret) |
@@ -4285,12 +4293,12 @@ static int ocfs2_extend_xattr_bucket(struct inode *inode, | |||
4285 | end_blk -= blk_per_bucket; | 4293 | end_blk -= blk_per_bucket; |
4286 | } | 4294 | } |
4287 | 4295 | ||
4288 | /* Move half of the xattr in start_blk to the next bucket. */ | 4296 | /* Move half of the xattr in target_blkno to the next bucket. */ |
4289 | ret = ocfs2_divide_xattr_bucket(inode, handle, start_blk, | 4297 | ret = ocfs2_divide_xattr_bucket(inode, handle, target_blk, |
4290 | start_blk + blk_per_bucket, NULL, 0); | 4298 | target_blk + blk_per_bucket, NULL, 0); |
4291 | 4299 | ||
4292 | le16_add_cpu(&first_xh->xh_num_buckets, 1); | 4300 | le16_add_cpu(&bucket_xh(first)->xh_num_buckets, 1); |
4293 | ocfs2_journal_dirty(handle, first_bh); | 4301 | ocfs2_xattr_bucket_journal_dirty(handle, first); |
4294 | 4302 | ||
4295 | out: | 4303 | out: |
4296 | return ret; | 4304 | return ret; |
@@ -4324,10 +4332,19 @@ static int ocfs2_add_new_xattr_bucket(struct inode *inode, | |||
4324 | int ret, num_buckets, extend = 1; | 4332 | int ret, num_buckets, extend = 1; |
4325 | u64 p_blkno; | 4333 | u64 p_blkno; |
4326 | u32 e_cpos, num_clusters; | 4334 | u32 e_cpos, num_clusters; |
4335 | /* The bucket at the front of the extent */ | ||
4336 | struct ocfs2_xattr_bucket *first; | ||
4327 | 4337 | ||
4328 | mlog(0, "Add new xattr bucket starting form %llu\n", | 4338 | mlog(0, "Add new xattr bucket starting form %llu\n", |
4329 | (unsigned long long)header_bh->b_blocknr); | 4339 | (unsigned long long)header_bh->b_blocknr); |
4330 | 4340 | ||
4341 | first = ocfs2_xattr_bucket_new(inode); | ||
4342 | if (!first) { | ||
4343 | ret = -ENOMEM; | ||
4344 | mlog_errno(ret); | ||
4345 | goto out; | ||
4346 | } | ||
4347 | |||
4331 | /* | 4348 | /* |
4332 | * Add refrence for header_bh here because it may be | 4349 | * Add refrence for header_bh here because it may be |
4333 | * changed in ocfs2_add_new_xattr_cluster and we need | 4350 | * changed in ocfs2_add_new_xattr_cluster and we need |
@@ -4367,17 +4384,25 @@ static int ocfs2_add_new_xattr_bucket(struct inode *inode, | |||
4367 | } | 4384 | } |
4368 | } | 4385 | } |
4369 | 4386 | ||
4370 | if (extend) | 4387 | if (extend) { |
4388 | /* These bucket reads should be cached */ | ||
4389 | ret = ocfs2_read_xattr_bucket(first, first_bh->b_blocknr); | ||
4390 | if (ret) { | ||
4391 | mlog_errno(ret); | ||
4392 | goto out; | ||
4393 | } | ||
4371 | ret = ocfs2_extend_xattr_bucket(inode, | 4394 | ret = ocfs2_extend_xattr_bucket(inode, |
4372 | ctxt->handle, | 4395 | ctxt->handle, |
4373 | first_bh, | 4396 | first, header_bh->b_blocknr, |
4374 | header_bh, | ||
4375 | num_clusters); | 4397 | num_clusters); |
4376 | if (ret) | 4398 | if (ret) |
4377 | mlog_errno(ret); | 4399 | mlog_errno(ret); |
4400 | } | ||
4401 | |||
4378 | out: | 4402 | out: |
4379 | brelse(first_bh); | 4403 | brelse(first_bh); |
4380 | brelse(header_bh); | 4404 | brelse(header_bh); |
4405 | ocfs2_xattr_bucket_free(first); | ||
4381 | return ret; | 4406 | return ret; |
4382 | } | 4407 | } |
4383 | 4408 | ||