aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/xattr.c
diff options
context:
space:
mode:
authorJoel Becker <joel.becker@oracle.com>2009-08-19 00:03:24 -0400
committerJoel Becker <joel.becker@oracle.com>2010-02-26 18:41:12 -0500
commitc5d95df5f78312c879f3058059c98a08821897a5 (patch)
treeae8b3549b50a664b1f48d8608488362a8597d9a5 /fs/ocfs2/xattr.c
parentbca5e9bd1eb2a9422a2ff29e822a956310653754 (diff)
ocfs2: Let ocfs2_xa_prepare_entry() do space checks.
ocfs2_xattr_set_in_bucket() doesn't need to do its own hacky space checking. Let's let ocfs2_xa_prepare_entry() (via ocfs2_xa_set()) do the more accurate work. Whenever it doesn't have space, ocfs2_xattr_set_in_bucket() can try to get more space. Signed-off-by: Joel Becker <joel.becker@oracle.com>
Diffstat (limited to 'fs/ocfs2/xattr.c')
-rw-r--r--fs/ocfs2/xattr.c270
1 files changed, 93 insertions, 177 deletions
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index 98c18fbfc28..e7630a77a6c 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -322,14 +322,6 @@ static inline u16 ocfs2_blocks_per_xattr_bucket(struct super_block *sb)
322 return OCFS2_XATTR_BUCKET_SIZE / (1 << sb->s_blocksize_bits); 322 return OCFS2_XATTR_BUCKET_SIZE / (1 << sb->s_blocksize_bits);
323} 323}
324 324
325static inline u16 ocfs2_xattr_max_xe_in_bucket(struct super_block *sb)
326{
327 u16 len = sb->s_blocksize -
328 offsetof(struct ocfs2_xattr_header, xh_entries);
329
330 return len / sizeof(struct ocfs2_xattr_entry);
331}
332
333#define bucket_blkno(_b) ((_b)->bu_bhs[0]->b_blocknr) 325#define bucket_blkno(_b) ((_b)->bu_bhs[0]->b_blocknr)
334#define bucket_block(_b, _n) ((_b)->bu_bhs[(_n)]->b_data) 326#define bucket_block(_b, _n) ((_b)->bu_bhs[(_n)]->b_data)
335#define bucket_xh(_b) ((struct ocfs2_xattr_header *)bucket_block((_b), 0)) 327#define bucket_xh(_b) ((struct ocfs2_xattr_header *)bucket_block((_b), 0))
@@ -5418,42 +5410,6 @@ out:
5418} 5410}
5419 5411
5420/* 5412/*
5421 * Set the xattr name/value in the bucket specified in xs.
5422 */
5423static int ocfs2_xattr_set_in_bucket(struct inode *inode,
5424 struct ocfs2_xattr_info *xi,
5425 struct ocfs2_xattr_search *xs,
5426 struct ocfs2_xattr_set_ctxt *ctxt)
5427{
5428 int ret;
5429 u64 blkno;
5430 struct ocfs2_xa_loc loc;
5431
5432 if (!xs->bucket->bu_bhs[1]) {
5433 blkno = bucket_blkno(xs->bucket);
5434 ocfs2_xattr_bucket_relse(xs->bucket);
5435 ret = ocfs2_read_xattr_bucket(xs->bucket, blkno);
5436 if (ret) {
5437 mlog_errno(ret);
5438 goto out;
5439 }
5440 }
5441
5442 ocfs2_init_xattr_bucket_xa_loc(&loc, xs->bucket,
5443 xs->not_found ? NULL : xs->here);
5444 ret = ocfs2_xa_set(&loc, xi, ctxt);
5445 if (ret) {
5446 if (ret != -ENOSPC)
5447 mlog_errno(ret);
5448 goto out;
5449 }
5450 xs->here = loc.xl_entry;
5451
5452out:
5453 return ret;
5454}
5455
5456/*
5457 * check whether the xattr bucket is filled up with the same hash value. 5413 * check whether the xattr bucket is filled up with the same hash value.
5458 * If we want to insert the xattr with the same hash, return -ENOSPC. 5414 * If we want to insert the xattr with the same hash, return -ENOSPC.
5459 * If we want to insert a xattr with different hash value, go ahead 5415 * If we want to insert a xattr with different hash value, go ahead
@@ -5481,156 +5437,116 @@ static int ocfs2_check_xattr_bucket_collision(struct inode *inode,
5481 return 0; 5437 return 0;
5482} 5438}
5483 5439
5484static int ocfs2_xattr_set_entry_index_block(struct inode *inode, 5440/*
5485 struct ocfs2_xattr_info *xi, 5441 * Try to set the entry in the current bucket. If we fail, the caller
5486 struct ocfs2_xattr_search *xs, 5442 * will handle getting us another bucket.
5487 struct ocfs2_xattr_set_ctxt *ctxt) 5443 */
5444static int ocfs2_xattr_set_entry_bucket(struct inode *inode,
5445 struct ocfs2_xattr_info *xi,
5446 struct ocfs2_xattr_search *xs,
5447 struct ocfs2_xattr_set_ctxt *ctxt)
5488{ 5448{
5489 struct ocfs2_xattr_header *xh; 5449 int ret;
5490 struct ocfs2_xattr_entry *xe; 5450 struct ocfs2_xa_loc loc;
5491 u16 count, header_size, xh_free_start;
5492 int free, max_free, need, old;
5493 size_t value_size = 0;
5494 size_t blocksize = inode->i_sb->s_blocksize;
5495 int ret, allocation = 0;
5496
5497 mlog_entry("Set xattr %s in xattr index block\n", xi->xi_name);
5498
5499try_again:
5500 xh = xs->header;
5501 count = le16_to_cpu(xh->xh_count);
5502 xh_free_start = le16_to_cpu(xh->xh_free_start);
5503 header_size = sizeof(struct ocfs2_xattr_header) +
5504 count * sizeof(struct ocfs2_xattr_entry);
5505 max_free = OCFS2_XATTR_BUCKET_SIZE - header_size -
5506 le16_to_cpu(xh->xh_name_value_len) - OCFS2_XATTR_HEADER_GAP;
5507
5508 mlog_bug_on_msg(header_size > blocksize, "bucket %llu has header size "
5509 "of %u which exceed block size\n",
5510 (unsigned long long)bucket_blkno(xs->bucket),
5511 header_size);
5512 5451
5513 if (xi->xi_value && xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE) 5452 mlog_entry("Set xattr %s in xattr bucket\n", xi->xi_name);
5514 value_size = OCFS2_XATTR_ROOT_SIZE;
5515 else if (xi->xi_value)
5516 value_size = OCFS2_XATTR_SIZE(xi->xi_value_len);
5517 5453
5518 if (xs->not_found) 5454 ocfs2_init_xattr_bucket_xa_loc(&loc, xs->bucket,
5519 need = sizeof(struct ocfs2_xattr_entry) + 5455 xs->not_found ? NULL : xs->here);
5520 OCFS2_XATTR_SIZE(xi->xi_name_len) + value_size; 5456 ret = ocfs2_xa_set(&loc, xi, ctxt);
5521 else { 5457 if (!ret) {
5522 need = value_size + OCFS2_XATTR_SIZE(xi->xi_name_len); 5458 xs->here = loc.xl_entry;
5459 goto out;
5460 }
5461 if (ret != -ENOSPC) {
5462 mlog_errno(ret);
5463 goto out;
5464 }
5523 5465
5524 /* 5466 /* Ok, we need space. Let's try defragmenting the bucket. */
5525 * We only replace the old value if the new length is smaller 5467 ret = ocfs2_defrag_xattr_bucket(inode, ctxt->handle,
5526 * than the old one. Otherwise we will allocate new space in the 5468 xs->bucket);
5527 * bucket to store it. 5469 if (ret) {
5528 */ 5470 mlog_errno(ret);
5529 xe = xs->here; 5471 goto out;
5530 if (ocfs2_xattr_is_local(xe)) 5472 }
5531 old = OCFS2_XATTR_SIZE(le64_to_cpu(xe->xe_value_size));
5532 else
5533 old = OCFS2_XATTR_SIZE(OCFS2_XATTR_ROOT_SIZE);
5534 5473
5535 if (old >= value_size) 5474 ret = ocfs2_xa_set(&loc, xi, ctxt);
5536 need = 0; 5475 if (!ret) {
5476 xs->here = loc.xl_entry;
5477 goto out;
5537 } 5478 }
5479 if (ret != -ENOSPC)
5480 mlog_errno(ret);
5538 5481
5539 free = xh_free_start - header_size - OCFS2_XATTR_HEADER_GAP;
5540 /*
5541 * We need to make sure the new name/value pair
5542 * can exist in the same block.
5543 */
5544 if (xh_free_start % blocksize < need)
5545 free -= xh_free_start % blocksize;
5546
5547 mlog(0, "xs->not_found = %d, in xattr bucket %llu: free = %d, "
5548 "need = %d, max_free = %d, xh_free_start = %u, xh_name_value_len ="
5549 " %u\n", xs->not_found,
5550 (unsigned long long)bucket_blkno(xs->bucket),
5551 free, need, max_free, le16_to_cpu(xh->xh_free_start),
5552 le16_to_cpu(xh->xh_name_value_len));
5553
5554 if (free < need ||
5555 (xs->not_found &&
5556 count == ocfs2_xattr_max_xe_in_bucket(inode->i_sb))) {
5557 if (need <= max_free &&
5558 count < ocfs2_xattr_max_xe_in_bucket(inode->i_sb)) {
5559 /*
5560 * We can create the space by defragment. Since only the
5561 * name/value will be moved, the xe shouldn't be changed
5562 * in xs.
5563 */
5564 ret = ocfs2_defrag_xattr_bucket(inode, ctxt->handle,
5565 xs->bucket);
5566 if (ret) {
5567 mlog_errno(ret);
5568 goto out;
5569 }
5570 5482
5571 xh_free_start = le16_to_cpu(xh->xh_free_start); 5483out:
5572 free = xh_free_start - header_size 5484 mlog_exit(ret);
5573 - OCFS2_XATTR_HEADER_GAP; 5485 return ret;
5574 if (xh_free_start % blocksize < need) 5486}
5575 free -= xh_free_start % blocksize;
5576 5487
5577 if (free >= need) 5488static int ocfs2_xattr_set_entry_index_block(struct inode *inode,
5578 goto xattr_set; 5489 struct ocfs2_xattr_info *xi,
5490 struct ocfs2_xattr_search *xs,
5491 struct ocfs2_xattr_set_ctxt *ctxt)
5492{
5493 int ret;
5579 5494
5580 mlog(0, "Can't get enough space for xattr insert by " 5495 mlog_entry("Set xattr %s in xattr index block\n", xi->xi_name);
5581 "defragment. Need %u bytes, but we have %d, so "
5582 "allocate new bucket for it.\n", need, free);
5583 }
5584 5496
5585 /* 5497 ret = ocfs2_xattr_set_entry_bucket(inode, xi, xs, ctxt);
5586 * We have to add new buckets or clusters and one 5498 if (!ret)
5587 * allocation should leave us enough space for insert. 5499 goto out;
5588 */ 5500 if (ret != -ENOSPC) {
5589 BUG_ON(allocation); 5501 mlog_errno(ret);
5502 goto out;
5503 }
5590 5504
5591 /* 5505 /* Ack, need more space. Let's try to get another bucket! */
5592 * We do not allow for overlapping ranges between buckets. And
5593 * the maximum number of collisions we will allow for then is
5594 * one bucket's worth, so check it here whether we need to
5595 * add a new bucket for the insert.
5596 */
5597 ret = ocfs2_check_xattr_bucket_collision(inode,
5598 xs->bucket,
5599 xi->xi_name);
5600 if (ret) {
5601 mlog_errno(ret);
5602 goto out;
5603 }
5604 5506
5605 ret = ocfs2_add_new_xattr_bucket(inode, 5507 /*
5606 xs->xattr_bh, 5508 * We do not allow for overlapping ranges between buckets. And
5509 * the maximum number of collisions we will allow for then is
5510 * one bucket's worth, so check it here whether we need to
5511 * add a new bucket for the insert.
5512 */
5513 ret = ocfs2_check_xattr_bucket_collision(inode,
5607 xs->bucket, 5514 xs->bucket,
5608 ctxt); 5515 xi->xi_name);
5609 if (ret) { 5516 if (ret) {
5610 mlog_errno(ret); 5517 mlog_errno(ret);
5611 goto out; 5518 goto out;
5612 } 5519 }
5613 5520
5614 /* 5521 ret = ocfs2_add_new_xattr_bucket(inode,
5615 * ocfs2_add_new_xattr_bucket() will have updated 5522 xs->xattr_bh,
5616 * xs->bucket if it moved, but it will not have updated 5523 xs->bucket,
5617 * any of the other search fields. Thus, we drop it and 5524 ctxt);
5618 * re-search. Everything should be cached, so it'll be 5525 if (ret) {
5619 * quick. 5526 mlog_errno(ret);
5620 */ 5527 goto out;
5621 ocfs2_xattr_bucket_relse(xs->bucket);
5622 ret = ocfs2_xattr_index_block_find(inode, xs->xattr_bh,
5623 xi->xi_name_index,
5624 xi->xi_name, xs);
5625 if (ret && ret != -ENODATA)
5626 goto out;
5627 xs->not_found = ret;
5628 allocation = 1;
5629 goto try_again;
5630 } 5528 }
5631 5529
5632xattr_set: 5530 /*
5633 ret = ocfs2_xattr_set_in_bucket(inode, xi, xs, ctxt); 5531 * ocfs2_add_new_xattr_bucket() will have updated
5532 * xs->bucket if it moved, but it will not have updated
5533 * any of the other search fields. Thus, we drop it and
5534 * re-search. Everything should be cached, so it'll be
5535 * quick.
5536 */
5537 ocfs2_xattr_bucket_relse(xs->bucket);
5538 ret = ocfs2_xattr_index_block_find(inode, xs->xattr_bh,
5539 xi->xi_name_index,
5540 xi->xi_name, xs);
5541 if (ret && ret != -ENODATA)
5542 goto out;
5543 xs->not_found = ret;
5544
5545 /* Ok, we have a new bucket, let's try again */
5546 ret = ocfs2_xattr_set_entry_bucket(inode, xi, xs, ctxt);
5547 if (ret && (ret != -ENOSPC))
5548 mlog_errno(ret);
5549
5634out: 5550out:
5635 mlog_exit(ret); 5551 mlog_exit(ret);
5636 return ret; 5552 return ret;