diff options
author | Tao Ma <tao.ma@oracle.com> | 2008-08-18 05:38:44 -0400 |
---|---|---|
committer | Mark Fasheh <mfasheh@suse.com> | 2008-10-13 16:57:58 -0400 |
commit | e7d4cb6bc19658646357eeff134645cd9bc3479f (patch) | |
tree | 4e24321e5c28fb90dffa1f396972fddb3c458e58 /fs/ocfs2/file.c | |
parent | 811f933df1e55615fd0bb4818f31e3868a8e6e23 (diff) |
ocfs2: Abstract ocfs2_extent_tree in b-tree operations.
In the old extent tree operation, we take the hypothesis that we
are using the ocfs2_extent_list in ocfs2_dinode as the tree root.
As xattr will also use ocfs2_extent_list to store large value
for a xattr entry, we refactor the tree operation so that xattr
can use it directly.
The refactoring includes 4 steps:
1. Abstract set/get of last_eb_blk and update_clusters since they may
be stored in different location for dinode and xattr.
2. Add a new structure named ocfs2_extent_tree to indicate the
extent tree the operation will work on.
3. Remove all the use of fe_bh and di, use root_bh and root_el in
extent tree instead. So now all the fe_bh is replaced with
et->root_bh, el with root_el accordingly.
4. Make ocfs2_lock_allocators generic. Now it is limited to be only used
in file extend allocation. But the whole function is useful when we want
to store large EAs.
Note: This patch doesn't touch ocfs2_commit_truncate() since it is not used
for anything other than truncate inode data btrees.
Signed-off-by: Tao Ma <tao.ma@oracle.com>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Diffstat (limited to 'fs/ocfs2/file.c')
-rw-r--r-- | fs/ocfs2/file.c | 104 |
1 files changed, 13 insertions, 91 deletions
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index a31bba6c5575..f567cc53d9bc 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -521,7 +521,8 @@ int ocfs2_do_extend_allocation(struct ocfs2_super *osb, | |||
521 | if (mark_unwritten) | 521 | if (mark_unwritten) |
522 | flags = OCFS2_EXT_UNWRITTEN; | 522 | flags = OCFS2_EXT_UNWRITTEN; |
523 | 523 | ||
524 | free_extents = ocfs2_num_free_extents(osb, inode, fe_bh); | 524 | free_extents = ocfs2_num_free_extents(osb, inode, fe_bh, |
525 | OCFS2_DINODE_EXTENT); | ||
525 | if (free_extents < 0) { | 526 | if (free_extents < 0) { |
526 | status = free_extents; | 527 | status = free_extents; |
527 | mlog_errno(status); | 528 | mlog_errno(status); |
@@ -570,7 +571,7 @@ int ocfs2_do_extend_allocation(struct ocfs2_super *osb, | |||
570 | num_bits, bit_off, (unsigned long long)OCFS2_I(inode)->ip_blkno); | 571 | num_bits, bit_off, (unsigned long long)OCFS2_I(inode)->ip_blkno); |
571 | status = ocfs2_insert_extent(osb, handle, inode, fe_bh, | 572 | status = ocfs2_insert_extent(osb, handle, inode, fe_bh, |
572 | *logical_offset, block, num_bits, | 573 | *logical_offset, block, num_bits, |
573 | flags, meta_ac); | 574 | flags, meta_ac, OCFS2_DINODE_EXTENT); |
574 | if (status < 0) { | 575 | if (status < 0) { |
575 | mlog_errno(status); | 576 | mlog_errno(status); |
576 | goto leave; | 577 | goto leave; |
@@ -599,92 +600,6 @@ leave: | |||
599 | return status; | 600 | return status; |
600 | } | 601 | } |
601 | 602 | ||
602 | /* | ||
603 | * For a given allocation, determine which allocators will need to be | ||
604 | * accessed, and lock them, reserving the appropriate number of bits. | ||
605 | * | ||
606 | * Sparse file systems call this from ocfs2_write_begin_nolock() | ||
607 | * and ocfs2_allocate_unwritten_extents(). | ||
608 | * | ||
609 | * File systems which don't support holes call this from | ||
610 | * ocfs2_extend_allocation(). | ||
611 | */ | ||
612 | int ocfs2_lock_allocators(struct inode *inode, struct buffer_head *di_bh, | ||
613 | u32 clusters_to_add, u32 extents_to_split, | ||
614 | struct ocfs2_alloc_context **data_ac, | ||
615 | struct ocfs2_alloc_context **meta_ac) | ||
616 | { | ||
617 | int ret = 0, num_free_extents; | ||
618 | unsigned int max_recs_needed = clusters_to_add + 2 * extents_to_split; | ||
619 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
620 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; | ||
621 | |||
622 | *meta_ac = NULL; | ||
623 | if (data_ac) | ||
624 | *data_ac = NULL; | ||
625 | |||
626 | BUG_ON(clusters_to_add != 0 && data_ac == NULL); | ||
627 | |||
628 | mlog(0, "extend inode %llu, i_size = %lld, di->i_clusters = %u, " | ||
629 | "clusters_to_add = %u, extents_to_split = %u\n", | ||
630 | (unsigned long long)OCFS2_I(inode)->ip_blkno, (long long)i_size_read(inode), | ||
631 | le32_to_cpu(di->i_clusters), clusters_to_add, extents_to_split); | ||
632 | |||
633 | num_free_extents = ocfs2_num_free_extents(osb, inode, di_bh); | ||
634 | if (num_free_extents < 0) { | ||
635 | ret = num_free_extents; | ||
636 | mlog_errno(ret); | ||
637 | goto out; | ||
638 | } | ||
639 | |||
640 | /* | ||
641 | * Sparse allocation file systems need to be more conservative | ||
642 | * with reserving room for expansion - the actual allocation | ||
643 | * happens while we've got a journal handle open so re-taking | ||
644 | * a cluster lock (because we ran out of room for another | ||
645 | * extent) will violate ordering rules. | ||
646 | * | ||
647 | * Most of the time we'll only be seeing this 1 cluster at a time | ||
648 | * anyway. | ||
649 | * | ||
650 | * Always lock for any unwritten extents - we might want to | ||
651 | * add blocks during a split. | ||
652 | */ | ||
653 | if (!num_free_extents || | ||
654 | (ocfs2_sparse_alloc(osb) && num_free_extents < max_recs_needed)) { | ||
655 | ret = ocfs2_reserve_new_metadata(osb, &di->id2.i_list, meta_ac); | ||
656 | if (ret < 0) { | ||
657 | if (ret != -ENOSPC) | ||
658 | mlog_errno(ret); | ||
659 | goto out; | ||
660 | } | ||
661 | } | ||
662 | |||
663 | if (clusters_to_add == 0) | ||
664 | goto out; | ||
665 | |||
666 | ret = ocfs2_reserve_clusters(osb, clusters_to_add, data_ac); | ||
667 | if (ret < 0) { | ||
668 | if (ret != -ENOSPC) | ||
669 | mlog_errno(ret); | ||
670 | goto out; | ||
671 | } | ||
672 | |||
673 | out: | ||
674 | if (ret) { | ||
675 | if (*meta_ac) { | ||
676 | ocfs2_free_alloc_context(*meta_ac); | ||
677 | *meta_ac = NULL; | ||
678 | } | ||
679 | |||
680 | /* | ||
681 | * We cannot have an error and a non null *data_ac. | ||
682 | */ | ||
683 | } | ||
684 | |||
685 | return ret; | ||
686 | } | ||
687 | |||
688 | static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start, | 603 | static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start, |
689 | u32 clusters_to_add, int mark_unwritten) | 604 | u32 clusters_to_add, int mark_unwritten) |
690 | { | 605 | { |
@@ -725,7 +640,13 @@ static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start, | |||
725 | restart_all: | 640 | restart_all: |
726 | BUG_ON(le32_to_cpu(fe->i_clusters) != OCFS2_I(inode)->ip_clusters); | 641 | BUG_ON(le32_to_cpu(fe->i_clusters) != OCFS2_I(inode)->ip_clusters); |
727 | 642 | ||
728 | status = ocfs2_lock_allocators(inode, bh, clusters_to_add, 0, &data_ac, | 643 | mlog(0, "extend inode %llu, i_size = %lld, di->i_clusters = %u, " |
644 | "clusters_to_add = %u\n", | ||
645 | (unsigned long long)OCFS2_I(inode)->ip_blkno, | ||
646 | (long long)i_size_read(inode), le32_to_cpu(fe->i_clusters), | ||
647 | clusters_to_add); | ||
648 | status = ocfs2_lock_allocators(inode, bh, &fe->id2.i_list, | ||
649 | clusters_to_add, 0, &data_ac, | ||
729 | &meta_ac); | 650 | &meta_ac); |
730 | if (status) { | 651 | if (status) { |
731 | mlog_errno(status); | 652 | mlog_errno(status); |
@@ -1397,7 +1318,8 @@ static int __ocfs2_remove_inode_range(struct inode *inode, | |||
1397 | struct ocfs2_alloc_context *meta_ac = NULL; | 1318 | struct ocfs2_alloc_context *meta_ac = NULL; |
1398 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; | 1319 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; |
1399 | 1320 | ||
1400 | ret = ocfs2_lock_allocators(inode, di_bh, 0, 1, NULL, &meta_ac); | 1321 | ret = ocfs2_lock_allocators(inode, di_bh, &di->id2.i_list, |
1322 | 0, 1, NULL, &meta_ac); | ||
1401 | if (ret) { | 1323 | if (ret) { |
1402 | mlog_errno(ret); | 1324 | mlog_errno(ret); |
1403 | return ret; | 1325 | return ret; |
@@ -1428,7 +1350,7 @@ static int __ocfs2_remove_inode_range(struct inode *inode, | |||
1428 | } | 1350 | } |
1429 | 1351 | ||
1430 | ret = ocfs2_remove_extent(inode, di_bh, cpos, len, handle, meta_ac, | 1352 | ret = ocfs2_remove_extent(inode, di_bh, cpos, len, handle, meta_ac, |
1431 | dealloc); | 1353 | dealloc, OCFS2_DINODE_EXTENT); |
1432 | if (ret) { | 1354 | if (ret) { |
1433 | mlog_errno(ret); | 1355 | mlog_errno(ret); |
1434 | goto out_commit; | 1356 | goto out_commit; |