diff options
author | Tristan Ye <tristan.ye@oracle.com> | 2011-05-24 05:35:19 -0400 |
---|---|---|
committer | Tristan Ye <tristan.ye@oracle.com> | 2011-05-25 03:17:11 -0400 |
commit | e08477176d5575493ba4c30041245c34f2737ad4 (patch) | |
tree | aedeb0f25df0c5a5ba926cbd0372626d8d0b755f /fs | |
parent | 8473aa8a2b5857b1bdfb57d860594d2eb2b4a0d6 (diff) |
Ocfs2/move_extents: move entire/partial extent.
ocfs2_move_extent() logic will validate the goal_offset_in_block,
where extents to be moved, what's more, it also compromises a bit
to probe the appropriate region around given goal_offset when the
original goal is not able to fit the movement.
Signed-off-by: Tristan Ye <tristan.ye@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ocfs2/move_extents.c | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/fs/ocfs2/move_extents.c b/fs/ocfs2/move_extents.c index 390354a4ecb..ae15c998a82 100644 --- a/fs/ocfs2/move_extents.c +++ b/fs/ocfs2/move_extents.c | |||
@@ -632,3 +632,168 @@ static inline int ocfs2_block_group_set_bits(handle_t *handle, | |||
632 | bail: | 632 | bail: |
633 | return status; | 633 | return status; |
634 | } | 634 | } |
635 | |||
636 | static int ocfs2_move_extent(struct ocfs2_move_extents_context *context, | ||
637 | u32 cpos, u32 phys_cpos, u32 *new_phys_cpos, | ||
638 | u32 len, int ext_flags) | ||
639 | { | ||
640 | int ret, credits = 0, extra_blocks = 0, goal_bit = 0; | ||
641 | handle_t *handle; | ||
642 | struct inode *inode = context->inode; | ||
643 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
644 | struct inode *tl_inode = osb->osb_tl_inode; | ||
645 | struct inode *gb_inode = NULL; | ||
646 | struct buffer_head *gb_bh = NULL; | ||
647 | struct buffer_head *gd_bh = NULL; | ||
648 | struct ocfs2_group_desc *gd; | ||
649 | struct ocfs2_refcount_tree *ref_tree = NULL; | ||
650 | u32 move_max_hop = ocfs2_blocks_to_clusters(inode->i_sb, | ||
651 | context->range->me_threshold); | ||
652 | u64 phys_blkno, new_phys_blkno; | ||
653 | |||
654 | phys_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys_cpos); | ||
655 | |||
656 | if ((ext_flags & OCFS2_EXT_REFCOUNTED) && len) { | ||
657 | |||
658 | BUG_ON(!(OCFS2_I(inode)->ip_dyn_features & | ||
659 | OCFS2_HAS_REFCOUNT_FL)); | ||
660 | |||
661 | BUG_ON(!context->refcount_loc); | ||
662 | |||
663 | ret = ocfs2_lock_refcount_tree(osb, context->refcount_loc, 1, | ||
664 | &ref_tree, NULL); | ||
665 | if (ret) { | ||
666 | mlog_errno(ret); | ||
667 | return ret; | ||
668 | } | ||
669 | |||
670 | ret = ocfs2_prepare_refcount_change_for_del(inode, | ||
671 | context->refcount_loc, | ||
672 | phys_blkno, | ||
673 | len, | ||
674 | &credits, | ||
675 | &extra_blocks); | ||
676 | if (ret) { | ||
677 | mlog_errno(ret); | ||
678 | goto out; | ||
679 | } | ||
680 | } | ||
681 | |||
682 | ret = ocfs2_lock_allocators_move_extents(inode, &context->et, len, 1, | ||
683 | &context->meta_ac, | ||
684 | NULL, extra_blocks, &credits); | ||
685 | if (ret) { | ||
686 | mlog_errno(ret); | ||
687 | goto out; | ||
688 | } | ||
689 | |||
690 | /* | ||
691 | * need to count 2 extra credits for global_bitmap inode and | ||
692 | * group descriptor. | ||
693 | */ | ||
694 | credits += OCFS2_INODE_UPDATE_CREDITS + 1; | ||
695 | |||
696 | /* | ||
697 | * ocfs2_move_extent() didn't reserve any clusters in lock_allocators() | ||
698 | * logic, while we still need to lock the global_bitmap. | ||
699 | */ | ||
700 | gb_inode = ocfs2_get_system_file_inode(osb, GLOBAL_BITMAP_SYSTEM_INODE, | ||
701 | OCFS2_INVALID_SLOT); | ||
702 | if (!gb_inode) { | ||
703 | mlog(ML_ERROR, "unable to get global_bitmap inode\n"); | ||
704 | ret = -EIO; | ||
705 | goto out; | ||
706 | } | ||
707 | |||
708 | mutex_lock(&gb_inode->i_mutex); | ||
709 | |||
710 | ret = ocfs2_inode_lock(gb_inode, &gb_bh, 1); | ||
711 | if (ret) { | ||
712 | mlog_errno(ret); | ||
713 | goto out_unlock_gb_mutex; | ||
714 | } | ||
715 | |||
716 | mutex_lock(&tl_inode->i_mutex); | ||
717 | |||
718 | handle = ocfs2_start_trans(osb, credits); | ||
719 | if (IS_ERR(handle)) { | ||
720 | ret = PTR_ERR(handle); | ||
721 | mlog_errno(ret); | ||
722 | goto out_unlock_tl_inode; | ||
723 | } | ||
724 | |||
725 | new_phys_blkno = ocfs2_clusters_to_blocks(inode->i_sb, *new_phys_cpos); | ||
726 | ret = ocfs2_find_victim_alloc_group(inode, new_phys_blkno, | ||
727 | GLOBAL_BITMAP_SYSTEM_INODE, | ||
728 | OCFS2_INVALID_SLOT, | ||
729 | &goal_bit, &gd_bh); | ||
730 | if (ret) { | ||
731 | mlog_errno(ret); | ||
732 | goto out_commit; | ||
733 | } | ||
734 | |||
735 | /* | ||
736 | * probe the victim cluster group to find a proper | ||
737 | * region to fit wanted movement, it even will perfrom | ||
738 | * a best-effort attempt by compromising to a threshold | ||
739 | * around the goal. | ||
740 | */ | ||
741 | ocfs2_probe_alloc_group(inode, gd_bh, &goal_bit, len, move_max_hop, | ||
742 | new_phys_cpos); | ||
743 | if (!new_phys_cpos) { | ||
744 | ret = -ENOSPC; | ||
745 | goto out_commit; | ||
746 | } | ||
747 | |||
748 | ret = __ocfs2_move_extent(handle, context, cpos, len, phys_cpos, | ||
749 | *new_phys_cpos, ext_flags); | ||
750 | if (ret) { | ||
751 | mlog_errno(ret); | ||
752 | goto out_commit; | ||
753 | } | ||
754 | |||
755 | gd = (struct ocfs2_group_desc *)gd_bh->b_data; | ||
756 | ret = ocfs2_alloc_dinode_update_counts(gb_inode, handle, gb_bh, len, | ||
757 | le16_to_cpu(gd->bg_chain)); | ||
758 | if (ret) { | ||
759 | mlog_errno(ret); | ||
760 | goto out_commit; | ||
761 | } | ||
762 | |||
763 | ret = ocfs2_block_group_set_bits(handle, gb_inode, gd, gd_bh, | ||
764 | goal_bit, len); | ||
765 | if (ret) | ||
766 | mlog_errno(ret); | ||
767 | |||
768 | /* | ||
769 | * Here we should write the new page out first if we are | ||
770 | * in write-back mode. | ||
771 | */ | ||
772 | ret = ocfs2_cow_sync_writeback(inode->i_sb, context->inode, cpos, len); | ||
773 | if (ret) | ||
774 | mlog_errno(ret); | ||
775 | |||
776 | out_commit: | ||
777 | ocfs2_commit_trans(osb, handle); | ||
778 | brelse(gd_bh); | ||
779 | |||
780 | out_unlock_tl_inode: | ||
781 | mutex_unlock(&tl_inode->i_mutex); | ||
782 | |||
783 | ocfs2_inode_unlock(gb_inode, 1); | ||
784 | out_unlock_gb_mutex: | ||
785 | mutex_unlock(&gb_inode->i_mutex); | ||
786 | brelse(gb_bh); | ||
787 | iput(gb_inode); | ||
788 | |||
789 | out: | ||
790 | if (context->meta_ac) { | ||
791 | ocfs2_free_alloc_context(context->meta_ac); | ||
792 | context->meta_ac = NULL; | ||
793 | } | ||
794 | |||
795 | if (ref_tree) | ||
796 | ocfs2_unlock_refcount_tree(osb, ref_tree, 1); | ||
797 | |||
798 | return ret; | ||
799 | } | ||