diff options
Diffstat (limited to 'fs/ocfs2/suballoc.c')
| -rw-r--r-- | fs/ocfs2/suballoc.c | 300 |
1 files changed, 213 insertions, 87 deletions
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index c30b644d9572..19ba00f28547 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c | |||
| @@ -51,7 +51,7 @@ | |||
| 51 | #define ALLOC_NEW_GROUP 0x1 | 51 | #define ALLOC_NEW_GROUP 0x1 |
| 52 | #define ALLOC_GROUPS_FROM_GLOBAL 0x2 | 52 | #define ALLOC_GROUPS_FROM_GLOBAL 0x2 |
| 53 | 53 | ||
| 54 | #define OCFS2_MAX_INODES_TO_STEAL 1024 | 54 | #define OCFS2_MAX_TO_STEAL 1024 |
| 55 | 55 | ||
| 56 | static inline void ocfs2_debug_bg(struct ocfs2_group_desc *bg); | 56 | static inline void ocfs2_debug_bg(struct ocfs2_group_desc *bg); |
| 57 | static inline void ocfs2_debug_suballoc_inode(struct ocfs2_dinode *fe); | 57 | static inline void ocfs2_debug_suballoc_inode(struct ocfs2_dinode *fe); |
| @@ -95,13 +95,6 @@ static inline int ocfs2_block_group_set_bits(handle_t *handle, | |||
| 95 | struct buffer_head *group_bh, | 95 | struct buffer_head *group_bh, |
| 96 | unsigned int bit_off, | 96 | unsigned int bit_off, |
| 97 | unsigned int num_bits); | 97 | unsigned int num_bits); |
| 98 | static inline int ocfs2_block_group_clear_bits(handle_t *handle, | ||
| 99 | struct inode *alloc_inode, | ||
| 100 | struct ocfs2_group_desc *bg, | ||
| 101 | struct buffer_head *group_bh, | ||
| 102 | unsigned int bit_off, | ||
| 103 | unsigned int num_bits); | ||
| 104 | |||
| 105 | static int ocfs2_relink_block_group(handle_t *handle, | 98 | static int ocfs2_relink_block_group(handle_t *handle, |
| 106 | struct inode *alloc_inode, | 99 | struct inode *alloc_inode, |
| 107 | struct buffer_head *fe_bh, | 100 | struct buffer_head *fe_bh, |
| @@ -152,7 +145,7 @@ static u32 ocfs2_bits_per_group(struct ocfs2_chain_list *cl) | |||
| 152 | 145 | ||
| 153 | #define do_error(fmt, ...) \ | 146 | #define do_error(fmt, ...) \ |
| 154 | do{ \ | 147 | do{ \ |
| 155 | if (clean_error) \ | 148 | if (resize) \ |
| 156 | mlog(ML_ERROR, fmt "\n", ##__VA_ARGS__); \ | 149 | mlog(ML_ERROR, fmt "\n", ##__VA_ARGS__); \ |
| 157 | else \ | 150 | else \ |
| 158 | ocfs2_error(sb, fmt, ##__VA_ARGS__); \ | 151 | ocfs2_error(sb, fmt, ##__VA_ARGS__); \ |
| @@ -160,7 +153,7 @@ static u32 ocfs2_bits_per_group(struct ocfs2_chain_list *cl) | |||
| 160 | 153 | ||
| 161 | static int ocfs2_validate_gd_self(struct super_block *sb, | 154 | static int ocfs2_validate_gd_self(struct super_block *sb, |
| 162 | struct buffer_head *bh, | 155 | struct buffer_head *bh, |
| 163 | int clean_error) | 156 | int resize) |
| 164 | { | 157 | { |
| 165 | struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data; | 158 | struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data; |
| 166 | 159 | ||
| @@ -211,7 +204,7 @@ static int ocfs2_validate_gd_self(struct super_block *sb, | |||
| 211 | static int ocfs2_validate_gd_parent(struct super_block *sb, | 204 | static int ocfs2_validate_gd_parent(struct super_block *sb, |
| 212 | struct ocfs2_dinode *di, | 205 | struct ocfs2_dinode *di, |
| 213 | struct buffer_head *bh, | 206 | struct buffer_head *bh, |
| 214 | int clean_error) | 207 | int resize) |
| 215 | { | 208 | { |
| 216 | unsigned int max_bits; | 209 | unsigned int max_bits; |
| 217 | struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data; | 210 | struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data; |
| @@ -233,8 +226,11 @@ static int ocfs2_validate_gd_parent(struct super_block *sb, | |||
| 233 | return -EINVAL; | 226 | return -EINVAL; |
| 234 | } | 227 | } |
| 235 | 228 | ||
| 236 | if (le16_to_cpu(gd->bg_chain) >= | 229 | /* In resize, we may meet the case bg_chain == cl_next_free_rec. */ |
| 237 | le16_to_cpu(di->id2.i_chain.cl_next_free_rec)) { | 230 | if ((le16_to_cpu(gd->bg_chain) > |
| 231 | le16_to_cpu(di->id2.i_chain.cl_next_free_rec)) || | ||
| 232 | ((le16_to_cpu(gd->bg_chain) == | ||
| 233 | le16_to_cpu(di->id2.i_chain.cl_next_free_rec)) && !resize)) { | ||
| 238 | do_error("Group descriptor #%llu has bad chain %u", | 234 | do_error("Group descriptor #%llu has bad chain %u", |
| 239 | (unsigned long long)bh->b_blocknr, | 235 | (unsigned long long)bh->b_blocknr, |
| 240 | le16_to_cpu(gd->bg_chain)); | 236 | le16_to_cpu(gd->bg_chain)); |
| @@ -637,12 +633,113 @@ bail: | |||
| 637 | return status; | 633 | return status; |
| 638 | } | 634 | } |
| 639 | 635 | ||
| 636 | static void ocfs2_init_inode_steal_slot(struct ocfs2_super *osb) | ||
| 637 | { | ||
| 638 | spin_lock(&osb->osb_lock); | ||
| 639 | osb->s_inode_steal_slot = OCFS2_INVALID_SLOT; | ||
| 640 | spin_unlock(&osb->osb_lock); | ||
| 641 | atomic_set(&osb->s_num_inodes_stolen, 0); | ||
| 642 | } | ||
| 643 | |||
| 644 | static void ocfs2_init_meta_steal_slot(struct ocfs2_super *osb) | ||
| 645 | { | ||
| 646 | spin_lock(&osb->osb_lock); | ||
| 647 | osb->s_meta_steal_slot = OCFS2_INVALID_SLOT; | ||
| 648 | spin_unlock(&osb->osb_lock); | ||
| 649 | atomic_set(&osb->s_num_meta_stolen, 0); | ||
| 650 | } | ||
| 651 | |||
| 652 | void ocfs2_init_steal_slots(struct ocfs2_super *osb) | ||
| 653 | { | ||
| 654 | ocfs2_init_inode_steal_slot(osb); | ||
| 655 | ocfs2_init_meta_steal_slot(osb); | ||
| 656 | } | ||
| 657 | |||
| 658 | static void __ocfs2_set_steal_slot(struct ocfs2_super *osb, int slot, int type) | ||
| 659 | { | ||
| 660 | spin_lock(&osb->osb_lock); | ||
| 661 | if (type == INODE_ALLOC_SYSTEM_INODE) | ||
| 662 | osb->s_inode_steal_slot = slot; | ||
| 663 | else if (type == EXTENT_ALLOC_SYSTEM_INODE) | ||
| 664 | osb->s_meta_steal_slot = slot; | ||
| 665 | spin_unlock(&osb->osb_lock); | ||
| 666 | } | ||
| 667 | |||
| 668 | static int __ocfs2_get_steal_slot(struct ocfs2_super *osb, int type) | ||
| 669 | { | ||
| 670 | int slot = OCFS2_INVALID_SLOT; | ||
| 671 | |||
| 672 | spin_lock(&osb->osb_lock); | ||
| 673 | if (type == INODE_ALLOC_SYSTEM_INODE) | ||
| 674 | slot = osb->s_inode_steal_slot; | ||
| 675 | else if (type == EXTENT_ALLOC_SYSTEM_INODE) | ||
| 676 | slot = osb->s_meta_steal_slot; | ||
| 677 | spin_unlock(&osb->osb_lock); | ||
| 678 | |||
| 679 | return slot; | ||
| 680 | } | ||
| 681 | |||
| 682 | static int ocfs2_get_inode_steal_slot(struct ocfs2_super *osb) | ||
| 683 | { | ||
| 684 | return __ocfs2_get_steal_slot(osb, INODE_ALLOC_SYSTEM_INODE); | ||
| 685 | } | ||
| 686 | |||
| 687 | static int ocfs2_get_meta_steal_slot(struct ocfs2_super *osb) | ||
| 688 | { | ||
| 689 | return __ocfs2_get_steal_slot(osb, EXTENT_ALLOC_SYSTEM_INODE); | ||
| 690 | } | ||
| 691 | |||
| 692 | static int ocfs2_steal_resource(struct ocfs2_super *osb, | ||
| 693 | struct ocfs2_alloc_context *ac, | ||
| 694 | int type) | ||
| 695 | { | ||
| 696 | int i, status = -ENOSPC; | ||
| 697 | int slot = __ocfs2_get_steal_slot(osb, type); | ||
| 698 | |||
| 699 | /* Start to steal resource from the first slot after ours. */ | ||
| 700 | if (slot == OCFS2_INVALID_SLOT) | ||
| 701 | slot = osb->slot_num + 1; | ||
| 702 | |||
| 703 | for (i = 0; i < osb->max_slots; i++, slot++) { | ||
| 704 | if (slot == osb->max_slots) | ||
| 705 | slot = 0; | ||
| 706 | |||
| 707 | if (slot == osb->slot_num) | ||
| 708 | continue; | ||
| 709 | |||
| 710 | status = ocfs2_reserve_suballoc_bits(osb, ac, | ||
| 711 | type, | ||
| 712 | (u32)slot, NULL, | ||
| 713 | NOT_ALLOC_NEW_GROUP); | ||
| 714 | if (status >= 0) { | ||
| 715 | __ocfs2_set_steal_slot(osb, slot, type); | ||
| 716 | break; | ||
| 717 | } | ||
| 718 | |||
| 719 | ocfs2_free_ac_resource(ac); | ||
| 720 | } | ||
| 721 | |||
| 722 | return status; | ||
| 723 | } | ||
| 724 | |||
| 725 | static int ocfs2_steal_inode(struct ocfs2_super *osb, | ||
| 726 | struct ocfs2_alloc_context *ac) | ||
| 727 | { | ||
| 728 | return ocfs2_steal_resource(osb, ac, INODE_ALLOC_SYSTEM_INODE); | ||
| 729 | } | ||
| 730 | |||
| 731 | static int ocfs2_steal_meta(struct ocfs2_super *osb, | ||
| 732 | struct ocfs2_alloc_context *ac) | ||
| 733 | { | ||
| 734 | return ocfs2_steal_resource(osb, ac, EXTENT_ALLOC_SYSTEM_INODE); | ||
| 735 | } | ||
| 736 | |||
| 640 | int ocfs2_reserve_new_metadata_blocks(struct ocfs2_super *osb, | 737 | int ocfs2_reserve_new_metadata_blocks(struct ocfs2_super *osb, |
| 641 | int blocks, | 738 | int blocks, |
| 642 | struct ocfs2_alloc_context **ac) | 739 | struct ocfs2_alloc_context **ac) |
| 643 | { | 740 | { |
| 644 | int status; | 741 | int status; |
| 645 | u32 slot; | 742 | int slot = ocfs2_get_meta_steal_slot(osb); |
| 646 | 743 | ||
| 647 | *ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL); | 744 | *ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL); |
| 648 | if (!(*ac)) { | 745 | if (!(*ac)) { |
| @@ -653,12 +750,34 @@ int ocfs2_reserve_new_metadata_blocks(struct ocfs2_super *osb, | |||
| 653 | 750 | ||
| 654 | (*ac)->ac_bits_wanted = blocks; | 751 | (*ac)->ac_bits_wanted = blocks; |
| 655 | (*ac)->ac_which = OCFS2_AC_USE_META; | 752 | (*ac)->ac_which = OCFS2_AC_USE_META; |
| 656 | slot = osb->slot_num; | ||
| 657 | (*ac)->ac_group_search = ocfs2_block_group_search; | 753 | (*ac)->ac_group_search = ocfs2_block_group_search; |
| 658 | 754 | ||
| 755 | if (slot != OCFS2_INVALID_SLOT && | ||
| 756 | atomic_read(&osb->s_num_meta_stolen) < OCFS2_MAX_TO_STEAL) | ||
| 757 | goto extent_steal; | ||
| 758 | |||
| 759 | atomic_set(&osb->s_num_meta_stolen, 0); | ||
| 659 | status = ocfs2_reserve_suballoc_bits(osb, (*ac), | 760 | status = ocfs2_reserve_suballoc_bits(osb, (*ac), |
| 660 | EXTENT_ALLOC_SYSTEM_INODE, | 761 | EXTENT_ALLOC_SYSTEM_INODE, |
| 661 | slot, NULL, ALLOC_NEW_GROUP); | 762 | (u32)osb->slot_num, NULL, |
| 763 | ALLOC_NEW_GROUP); | ||
| 764 | |||
| 765 | |||
| 766 | if (status >= 0) { | ||
| 767 | status = 0; | ||
| 768 | if (slot != OCFS2_INVALID_SLOT) | ||
| 769 | ocfs2_init_meta_steal_slot(osb); | ||
| 770 | goto bail; | ||
| 771 | } else if (status < 0 && status != -ENOSPC) { | ||
| 772 | mlog_errno(status); | ||
| 773 | goto bail; | ||
| 774 | } | ||
| 775 | |||
| 776 | ocfs2_free_ac_resource(*ac); | ||
| 777 | |||
| 778 | extent_steal: | ||
| 779 | status = ocfs2_steal_meta(osb, *ac); | ||
| 780 | atomic_inc(&osb->s_num_meta_stolen); | ||
| 662 | if (status < 0) { | 781 | if (status < 0) { |
| 663 | if (status != -ENOSPC) | 782 | if (status != -ENOSPC) |
| 664 | mlog_errno(status); | 783 | mlog_errno(status); |
| @@ -685,43 +804,11 @@ int ocfs2_reserve_new_metadata(struct ocfs2_super *osb, | |||
| 685 | ac); | 804 | ac); |
| 686 | } | 805 | } |
| 687 | 806 | ||
| 688 | static int ocfs2_steal_inode_from_other_nodes(struct ocfs2_super *osb, | ||
| 689 | struct ocfs2_alloc_context *ac) | ||
| 690 | { | ||
| 691 | int i, status = -ENOSPC; | ||
| 692 | s16 slot = ocfs2_get_inode_steal_slot(osb); | ||
| 693 | |||
| 694 | /* Start to steal inodes from the first slot after ours. */ | ||
| 695 | if (slot == OCFS2_INVALID_SLOT) | ||
| 696 | slot = osb->slot_num + 1; | ||
| 697 | |||
| 698 | for (i = 0; i < osb->max_slots; i++, slot++) { | ||
| 699 | if (slot == osb->max_slots) | ||
| 700 | slot = 0; | ||
| 701 | |||
| 702 | if (slot == osb->slot_num) | ||
| 703 | continue; | ||
| 704 | |||
| 705 | status = ocfs2_reserve_suballoc_bits(osb, ac, | ||
| 706 | INODE_ALLOC_SYSTEM_INODE, | ||
| 707 | slot, NULL, | ||
| 708 | NOT_ALLOC_NEW_GROUP); | ||
| 709 | if (status >= 0) { | ||
| 710 | ocfs2_set_inode_steal_slot(osb, slot); | ||
| 711 | break; | ||
| 712 | } | ||
| 713 | |||
| 714 | ocfs2_free_ac_resource(ac); | ||
| 715 | } | ||
| 716 | |||
| 717 | return status; | ||
| 718 | } | ||
| 719 | |||
| 720 | int ocfs2_reserve_new_inode(struct ocfs2_super *osb, | 807 | int ocfs2_reserve_new_inode(struct ocfs2_super *osb, |
| 721 | struct ocfs2_alloc_context **ac) | 808 | struct ocfs2_alloc_context **ac) |
| 722 | { | 809 | { |
| 723 | int status; | 810 | int status; |
| 724 | s16 slot = ocfs2_get_inode_steal_slot(osb); | 811 | int slot = ocfs2_get_inode_steal_slot(osb); |
| 725 | u64 alloc_group; | 812 | u64 alloc_group; |
| 726 | 813 | ||
| 727 | *ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL); | 814 | *ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL); |
| @@ -754,14 +841,14 @@ int ocfs2_reserve_new_inode(struct ocfs2_super *osb, | |||
| 754 | * need to check our slots to see whether there is some space for us. | 841 | * need to check our slots to see whether there is some space for us. |
| 755 | */ | 842 | */ |
| 756 | if (slot != OCFS2_INVALID_SLOT && | 843 | if (slot != OCFS2_INVALID_SLOT && |
| 757 | atomic_read(&osb->s_num_inodes_stolen) < OCFS2_MAX_INODES_TO_STEAL) | 844 | atomic_read(&osb->s_num_inodes_stolen) < OCFS2_MAX_TO_STEAL) |
| 758 | goto inode_steal; | 845 | goto inode_steal; |
| 759 | 846 | ||
| 760 | atomic_set(&osb->s_num_inodes_stolen, 0); | 847 | atomic_set(&osb->s_num_inodes_stolen, 0); |
| 761 | alloc_group = osb->osb_inode_alloc_group; | 848 | alloc_group = osb->osb_inode_alloc_group; |
| 762 | status = ocfs2_reserve_suballoc_bits(osb, *ac, | 849 | status = ocfs2_reserve_suballoc_bits(osb, *ac, |
| 763 | INODE_ALLOC_SYSTEM_INODE, | 850 | INODE_ALLOC_SYSTEM_INODE, |
| 764 | osb->slot_num, | 851 | (u32)osb->slot_num, |
| 765 | &alloc_group, | 852 | &alloc_group, |
| 766 | ALLOC_NEW_GROUP | | 853 | ALLOC_NEW_GROUP | |
| 767 | ALLOC_GROUPS_FROM_GLOBAL); | 854 | ALLOC_GROUPS_FROM_GLOBAL); |
| @@ -789,7 +876,7 @@ int ocfs2_reserve_new_inode(struct ocfs2_super *osb, | |||
| 789 | ocfs2_free_ac_resource(*ac); | 876 | ocfs2_free_ac_resource(*ac); |
| 790 | 877 | ||
| 791 | inode_steal: | 878 | inode_steal: |
| 792 | status = ocfs2_steal_inode_from_other_nodes(osb, *ac); | 879 | status = ocfs2_steal_inode(osb, *ac); |
| 793 | atomic_inc(&osb->s_num_inodes_stolen); | 880 | atomic_inc(&osb->s_num_inodes_stolen); |
| 794 | if (status < 0) { | 881 | if (status < 0) { |
| 795 | if (status != -ENOSPC) | 882 | if (status != -ENOSPC) |
| @@ -1884,18 +1971,18 @@ int ocfs2_claim_clusters(struct ocfs2_super *osb, | |||
| 1884 | bits_wanted, cluster_start, num_clusters); | 1971 | bits_wanted, cluster_start, num_clusters); |
| 1885 | } | 1972 | } |
| 1886 | 1973 | ||
| 1887 | static inline int ocfs2_block_group_clear_bits(handle_t *handle, | 1974 | static int ocfs2_block_group_clear_bits(handle_t *handle, |
| 1888 | struct inode *alloc_inode, | 1975 | struct inode *alloc_inode, |
| 1889 | struct ocfs2_group_desc *bg, | 1976 | struct ocfs2_group_desc *bg, |
| 1890 | struct buffer_head *group_bh, | 1977 | struct buffer_head *group_bh, |
| 1891 | unsigned int bit_off, | 1978 | unsigned int bit_off, |
| 1892 | unsigned int num_bits) | 1979 | unsigned int num_bits, |
| 1980 | void (*undo_fn)(unsigned int bit, | ||
| 1981 | unsigned long *bmap)) | ||
| 1893 | { | 1982 | { |
| 1894 | int status; | 1983 | int status; |
| 1895 | unsigned int tmp; | 1984 | unsigned int tmp; |
| 1896 | int journal_type = OCFS2_JOURNAL_ACCESS_WRITE; | ||
| 1897 | struct ocfs2_group_desc *undo_bg = NULL; | 1985 | struct ocfs2_group_desc *undo_bg = NULL; |
| 1898 | int cluster_bitmap = 0; | ||
| 1899 | 1986 | ||
| 1900 | mlog_entry_void(); | 1987 | mlog_entry_void(); |
| 1901 | 1988 | ||
| @@ -1905,20 +1992,18 @@ static inline int ocfs2_block_group_clear_bits(handle_t *handle, | |||
| 1905 | 1992 | ||
| 1906 | mlog(0, "off = %u, num = %u\n", bit_off, num_bits); | 1993 | mlog(0, "off = %u, num = %u\n", bit_off, num_bits); |
| 1907 | 1994 | ||
| 1908 | if (ocfs2_is_cluster_bitmap(alloc_inode)) | 1995 | BUG_ON(undo_fn && !ocfs2_is_cluster_bitmap(alloc_inode)); |
| 1909 | journal_type = OCFS2_JOURNAL_ACCESS_UNDO; | ||
| 1910 | |||
| 1911 | status = ocfs2_journal_access_gd(handle, INODE_CACHE(alloc_inode), | 1996 | status = ocfs2_journal_access_gd(handle, INODE_CACHE(alloc_inode), |
| 1912 | group_bh, journal_type); | 1997 | group_bh, |
| 1998 | undo_fn ? | ||
| 1999 | OCFS2_JOURNAL_ACCESS_UNDO : | ||
| 2000 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
| 1913 | if (status < 0) { | 2001 | if (status < 0) { |
| 1914 | mlog_errno(status); | 2002 | mlog_errno(status); |
| 1915 | goto bail; | 2003 | goto bail; |
| 1916 | } | 2004 | } |
| 1917 | 2005 | ||
| 1918 | if (ocfs2_is_cluster_bitmap(alloc_inode)) | 2006 | if (undo_fn) { |
| 1919 | cluster_bitmap = 1; | ||
| 1920 | |||
| 1921 | if (cluster_bitmap) { | ||
| 1922 | jbd_lock_bh_state(group_bh); | 2007 | jbd_lock_bh_state(group_bh); |
| 1923 | undo_bg = (struct ocfs2_group_desc *) | 2008 | undo_bg = (struct ocfs2_group_desc *) |
| 1924 | bh2jh(group_bh)->b_committed_data; | 2009 | bh2jh(group_bh)->b_committed_data; |
| @@ -1929,13 +2014,13 @@ static inline int ocfs2_block_group_clear_bits(handle_t *handle, | |||
| 1929 | while(tmp--) { | 2014 | while(tmp--) { |
| 1930 | ocfs2_clear_bit((bit_off + tmp), | 2015 | ocfs2_clear_bit((bit_off + tmp), |
| 1931 | (unsigned long *) bg->bg_bitmap); | 2016 | (unsigned long *) bg->bg_bitmap); |
| 1932 | if (cluster_bitmap) | 2017 | if (undo_fn) |
| 1933 | ocfs2_set_bit(bit_off + tmp, | 2018 | undo_fn(bit_off + tmp, |
| 1934 | (unsigned long *) undo_bg->bg_bitmap); | 2019 | (unsigned long *) undo_bg->bg_bitmap); |
| 1935 | } | 2020 | } |
| 1936 | le16_add_cpu(&bg->bg_free_bits_count, num_bits); | 2021 | le16_add_cpu(&bg->bg_free_bits_count, num_bits); |
| 1937 | 2022 | ||
| 1938 | if (cluster_bitmap) | 2023 | if (undo_fn) |
| 1939 | jbd_unlock_bh_state(group_bh); | 2024 | jbd_unlock_bh_state(group_bh); |
| 1940 | 2025 | ||
| 1941 | status = ocfs2_journal_dirty(handle, group_bh); | 2026 | status = ocfs2_journal_dirty(handle, group_bh); |
| @@ -1948,12 +2033,14 @@ bail: | |||
| 1948 | /* | 2033 | /* |
| 1949 | * expects the suballoc inode to already be locked. | 2034 | * expects the suballoc inode to already be locked. |
| 1950 | */ | 2035 | */ |
| 1951 | int ocfs2_free_suballoc_bits(handle_t *handle, | 2036 | static int _ocfs2_free_suballoc_bits(handle_t *handle, |
| 1952 | struct inode *alloc_inode, | 2037 | struct inode *alloc_inode, |
| 1953 | struct buffer_head *alloc_bh, | 2038 | struct buffer_head *alloc_bh, |
| 1954 | unsigned int start_bit, | 2039 | unsigned int start_bit, |
| 1955 | u64 bg_blkno, | 2040 | u64 bg_blkno, |
| 1956 | unsigned int count) | 2041 | unsigned int count, |
| 2042 | void (*undo_fn)(unsigned int bit, | ||
| 2043 | unsigned long *bitmap)) | ||
| 1957 | { | 2044 | { |
| 1958 | int status = 0; | 2045 | int status = 0; |
| 1959 | u32 tmp_used; | 2046 | u32 tmp_used; |
| @@ -1988,7 +2075,7 @@ int ocfs2_free_suballoc_bits(handle_t *handle, | |||
| 1988 | 2075 | ||
| 1989 | status = ocfs2_block_group_clear_bits(handle, alloc_inode, | 2076 | status = ocfs2_block_group_clear_bits(handle, alloc_inode, |
| 1990 | group, group_bh, | 2077 | group, group_bh, |
| 1991 | start_bit, count); | 2078 | start_bit, count, undo_fn); |
| 1992 | if (status < 0) { | 2079 | if (status < 0) { |
| 1993 | mlog_errno(status); | 2080 | mlog_errno(status); |
| 1994 | goto bail; | 2081 | goto bail; |
| @@ -2019,6 +2106,17 @@ bail: | |||
| 2019 | return status; | 2106 | return status; |
| 2020 | } | 2107 | } |
| 2021 | 2108 | ||
| 2109 | int ocfs2_free_suballoc_bits(handle_t *handle, | ||
| 2110 | struct inode *alloc_inode, | ||
| 2111 | struct buffer_head *alloc_bh, | ||
| 2112 | unsigned int start_bit, | ||
| 2113 | u64 bg_blkno, | ||
| 2114 | unsigned int count) | ||
| 2115 | { | ||
| 2116 | return _ocfs2_free_suballoc_bits(handle, alloc_inode, alloc_bh, | ||
| 2117 | start_bit, bg_blkno, count, NULL); | ||
| 2118 | } | ||
| 2119 | |||
| 2022 | int ocfs2_free_dinode(handle_t *handle, | 2120 | int ocfs2_free_dinode(handle_t *handle, |
| 2023 | struct inode *inode_alloc_inode, | 2121 | struct inode *inode_alloc_inode, |
| 2024 | struct buffer_head *inode_alloc_bh, | 2122 | struct buffer_head *inode_alloc_bh, |
| @@ -2032,11 +2130,13 @@ int ocfs2_free_dinode(handle_t *handle, | |||
| 2032 | inode_alloc_bh, bit, bg_blkno, 1); | 2130 | inode_alloc_bh, bit, bg_blkno, 1); |
| 2033 | } | 2131 | } |
| 2034 | 2132 | ||
| 2035 | int ocfs2_free_clusters(handle_t *handle, | 2133 | static int _ocfs2_free_clusters(handle_t *handle, |
| 2036 | struct inode *bitmap_inode, | 2134 | struct inode *bitmap_inode, |
| 2037 | struct buffer_head *bitmap_bh, | 2135 | struct buffer_head *bitmap_bh, |
| 2038 | u64 start_blk, | 2136 | u64 start_blk, |
| 2039 | unsigned int num_clusters) | 2137 | unsigned int num_clusters, |
| 2138 | void (*undo_fn)(unsigned int bit, | ||
| 2139 | unsigned long *bitmap)) | ||
| 2040 | { | 2140 | { |
| 2041 | int status; | 2141 | int status; |
| 2042 | u16 bg_start_bit; | 2142 | u16 bg_start_bit; |
| @@ -2063,9 +2163,9 @@ int ocfs2_free_clusters(handle_t *handle, | |||
| 2063 | mlog(0, "bg_blkno = %llu, bg_start_bit = %u\n", | 2163 | mlog(0, "bg_blkno = %llu, bg_start_bit = %u\n", |
| 2064 | (unsigned long long)bg_blkno, bg_start_bit); | 2164 | (unsigned long long)bg_blkno, bg_start_bit); |
| 2065 | 2165 | ||
| 2066 | status = ocfs2_free_suballoc_bits(handle, bitmap_inode, bitmap_bh, | 2166 | status = _ocfs2_free_suballoc_bits(handle, bitmap_inode, bitmap_bh, |
| 2067 | bg_start_bit, bg_blkno, | 2167 | bg_start_bit, bg_blkno, |
| 2068 | num_clusters); | 2168 | num_clusters, undo_fn); |
| 2069 | if (status < 0) { | 2169 | if (status < 0) { |
| 2070 | mlog_errno(status); | 2170 | mlog_errno(status); |
| 2071 | goto out; | 2171 | goto out; |
| @@ -2079,6 +2179,32 @@ out: | |||
| 2079 | return status; | 2179 | return status; |
| 2080 | } | 2180 | } |
| 2081 | 2181 | ||
| 2182 | int ocfs2_free_clusters(handle_t *handle, | ||
| 2183 | struct inode *bitmap_inode, | ||
| 2184 | struct buffer_head *bitmap_bh, | ||
| 2185 | u64 start_blk, | ||
| 2186 | unsigned int num_clusters) | ||
| 2187 | { | ||
| 2188 | return _ocfs2_free_clusters(handle, bitmap_inode, bitmap_bh, | ||
| 2189 | start_blk, num_clusters, | ||
| 2190 | _ocfs2_set_bit); | ||
| 2191 | } | ||
| 2192 | |||
| 2193 | /* | ||
| 2194 | * Give never-used clusters back to the global bitmap. We don't need | ||
| 2195 | * to protect these bits in the undo buffer. | ||
| 2196 | */ | ||
| 2197 | int ocfs2_release_clusters(handle_t *handle, | ||
| 2198 | struct inode *bitmap_inode, | ||
| 2199 | struct buffer_head *bitmap_bh, | ||
| 2200 | u64 start_blk, | ||
| 2201 | unsigned int num_clusters) | ||
| 2202 | { | ||
| 2203 | return _ocfs2_free_clusters(handle, bitmap_inode, bitmap_bh, | ||
| 2204 | start_blk, num_clusters, | ||
| 2205 | _ocfs2_clear_bit); | ||
| 2206 | } | ||
| 2207 | |||
| 2082 | static inline void ocfs2_debug_bg(struct ocfs2_group_desc *bg) | 2208 | static inline void ocfs2_debug_bg(struct ocfs2_group_desc *bg) |
| 2083 | { | 2209 | { |
| 2084 | printk("Block Group:\n"); | 2210 | printk("Block Group:\n"); |
