aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/xattr.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ocfs2/xattr.c')
-rw-r--r--fs/ocfs2/xattr.c85
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 */
4238static int ocfs2_extend_xattr_bucket(struct inode *inode, 4243static 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
4295out: 4303out:
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
4378out: 4402out:
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