diff options
Diffstat (limited to 'fs/ocfs2/localalloc.c')
-rw-r--r-- | fs/ocfs2/localalloc.c | 64 |
1 files changed, 53 insertions, 11 deletions
diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index 7e7dd65d97ef..7fe8149a0002 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c | |||
@@ -52,7 +52,8 @@ static u32 ocfs2_local_alloc_count_bits(struct ocfs2_dinode *alloc); | |||
52 | 52 | ||
53 | static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb, | 53 | static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb, |
54 | struct ocfs2_dinode *alloc, | 54 | struct ocfs2_dinode *alloc, |
55 | u32 numbits); | 55 | u32 *numbits, |
56 | struct ocfs2_alloc_reservation *resv); | ||
56 | 57 | ||
57 | static void ocfs2_clear_local_alloc(struct ocfs2_dinode *alloc); | 58 | static void ocfs2_clear_local_alloc(struct ocfs2_dinode *alloc); |
58 | 59 | ||
@@ -262,6 +263,8 @@ void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb) | |||
262 | 263 | ||
263 | osb->local_alloc_state = OCFS2_LA_DISABLED; | 264 | osb->local_alloc_state = OCFS2_LA_DISABLED; |
264 | 265 | ||
266 | ocfs2_resmap_uninit(&osb->osb_la_resmap); | ||
267 | |||
265 | main_bm_inode = ocfs2_get_system_file_inode(osb, | 268 | main_bm_inode = ocfs2_get_system_file_inode(osb, |
266 | GLOBAL_BITMAP_SYSTEM_INODE, | 269 | GLOBAL_BITMAP_SYSTEM_INODE, |
267 | OCFS2_INVALID_SLOT); | 270 | OCFS2_INVALID_SLOT); |
@@ -493,7 +496,7 @@ static int ocfs2_local_alloc_in_range(struct inode *inode, | |||
493 | alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data; | 496 | alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data; |
494 | la = OCFS2_LOCAL_ALLOC(alloc); | 497 | la = OCFS2_LOCAL_ALLOC(alloc); |
495 | 498 | ||
496 | start = ocfs2_local_alloc_find_clear_bits(osb, alloc, bits_wanted); | 499 | start = ocfs2_local_alloc_find_clear_bits(osb, alloc, &bits_wanted, NULL); |
497 | if (start == -1) { | 500 | if (start == -1) { |
498 | mlog_errno(-ENOSPC); | 501 | mlog_errno(-ENOSPC); |
499 | return 0; | 502 | return 0; |
@@ -659,7 +662,8 @@ int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb, | |||
659 | alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data; | 662 | alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data; |
660 | la = OCFS2_LOCAL_ALLOC(alloc); | 663 | la = OCFS2_LOCAL_ALLOC(alloc); |
661 | 664 | ||
662 | start = ocfs2_local_alloc_find_clear_bits(osb, alloc, bits_wanted); | 665 | start = ocfs2_local_alloc_find_clear_bits(osb, alloc, &bits_wanted, |
666 | ac->ac_resv); | ||
663 | if (start == -1) { | 667 | if (start == -1) { |
664 | /* TODO: Shouldn't we just BUG here? */ | 668 | /* TODO: Shouldn't we just BUG here? */ |
665 | status = -ENOSPC; | 669 | status = -ENOSPC; |
@@ -669,8 +673,6 @@ int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb, | |||
669 | 673 | ||
670 | bitmap = la->la_bitmap; | 674 | bitmap = la->la_bitmap; |
671 | *bit_off = le32_to_cpu(la->la_bm_off) + start; | 675 | *bit_off = le32_to_cpu(la->la_bm_off) + start; |
672 | /* local alloc is always contiguous by nature -- we never | ||
673 | * delete bits from it! */ | ||
674 | *num_bits = bits_wanted; | 676 | *num_bits = bits_wanted; |
675 | 677 | ||
676 | status = ocfs2_journal_access_di(handle, | 678 | status = ocfs2_journal_access_di(handle, |
@@ -682,6 +684,9 @@ int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb, | |||
682 | goto bail; | 684 | goto bail; |
683 | } | 685 | } |
684 | 686 | ||
687 | ocfs2_resmap_claimed_bits(&osb->osb_la_resmap, ac->ac_resv, start, | ||
688 | bits_wanted); | ||
689 | |||
685 | while(bits_wanted--) | 690 | while(bits_wanted--) |
686 | ocfs2_set_bit(start++, bitmap); | 691 | ocfs2_set_bit(start++, bitmap); |
687 | 692 | ||
@@ -711,13 +716,17 @@ static u32 ocfs2_local_alloc_count_bits(struct ocfs2_dinode *alloc) | |||
711 | } | 716 | } |
712 | 717 | ||
713 | static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb, | 718 | static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb, |
714 | struct ocfs2_dinode *alloc, | 719 | struct ocfs2_dinode *alloc, |
715 | u32 numbits) | 720 | u32 *numbits, |
721 | struct ocfs2_alloc_reservation *resv) | ||
716 | { | 722 | { |
717 | int numfound, bitoff, left, startoff, lastzero; | 723 | int numfound, bitoff, left, startoff, lastzero; |
724 | int local_resv = 0; | ||
725 | struct ocfs2_alloc_reservation r; | ||
718 | void *bitmap = NULL; | 726 | void *bitmap = NULL; |
727 | struct ocfs2_reservation_map *resmap = &osb->osb_la_resmap; | ||
719 | 728 | ||
720 | mlog_entry("(numbits wanted = %u)\n", numbits); | 729 | mlog_entry("(numbits wanted = %u)\n", *numbits); |
721 | 730 | ||
722 | if (!alloc->id1.bitmap1.i_total) { | 731 | if (!alloc->id1.bitmap1.i_total) { |
723 | mlog(0, "No bits in my window!\n"); | 732 | mlog(0, "No bits in my window!\n"); |
@@ -725,6 +734,30 @@ static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb, | |||
725 | goto bail; | 734 | goto bail; |
726 | } | 735 | } |
727 | 736 | ||
737 | if (!resv) { | ||
738 | local_resv = 1; | ||
739 | ocfs2_resv_init_once(&r); | ||
740 | ocfs2_resv_set_type(&r, OCFS2_RESV_FLAG_TMP); | ||
741 | resv = &r; | ||
742 | } | ||
743 | |||
744 | numfound = *numbits; | ||
745 | if (ocfs2_resmap_resv_bits(resmap, resv, &bitoff, &numfound) == 0) { | ||
746 | if (numfound < *numbits) | ||
747 | *numbits = numfound; | ||
748 | goto bail; | ||
749 | } | ||
750 | |||
751 | /* | ||
752 | * Code error. While reservations are enabled, local | ||
753 | * allocation should _always_ go through them. | ||
754 | */ | ||
755 | BUG_ON(osb->osb_resv_level != 0); | ||
756 | |||
757 | /* | ||
758 | * Reservations are disabled. Handle this the old way. | ||
759 | */ | ||
760 | |||
728 | bitmap = OCFS2_LOCAL_ALLOC(alloc)->la_bitmap; | 761 | bitmap = OCFS2_LOCAL_ALLOC(alloc)->la_bitmap; |
729 | 762 | ||
730 | numfound = bitoff = startoff = 0; | 763 | numfound = bitoff = startoff = 0; |
@@ -750,7 +783,7 @@ static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb, | |||
750 | startoff = bitoff+1; | 783 | startoff = bitoff+1; |
751 | } | 784 | } |
752 | /* we got everything we needed */ | 785 | /* we got everything we needed */ |
753 | if (numfound == numbits) { | 786 | if (numfound == *numbits) { |
754 | /* mlog(0, "Found it all!\n"); */ | 787 | /* mlog(0, "Found it all!\n"); */ |
755 | break; | 788 | break; |
756 | } | 789 | } |
@@ -759,12 +792,18 @@ static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb, | |||
759 | mlog(0, "Exiting loop, bitoff = %d, numfound = %d\n", bitoff, | 792 | mlog(0, "Exiting loop, bitoff = %d, numfound = %d\n", bitoff, |
760 | numfound); | 793 | numfound); |
761 | 794 | ||
762 | if (numfound == numbits) | 795 | if (numfound == *numbits) { |
763 | bitoff = startoff - numfound; | 796 | bitoff = startoff - numfound; |
764 | else | 797 | *numbits = numfound; |
798 | } else { | ||
799 | numfound = 0; | ||
765 | bitoff = -1; | 800 | bitoff = -1; |
801 | } | ||
766 | 802 | ||
767 | bail: | 803 | bail: |
804 | if (local_resv) | ||
805 | ocfs2_resv_discard(resmap, resv); | ||
806 | |||
768 | mlog_exit(bitoff); | 807 | mlog_exit(bitoff); |
769 | return bitoff; | 808 | return bitoff; |
770 | } | 809 | } |
@@ -1087,6 +1126,9 @@ retry_enospc: | |||
1087 | memset(OCFS2_LOCAL_ALLOC(alloc)->la_bitmap, 0, | 1126 | memset(OCFS2_LOCAL_ALLOC(alloc)->la_bitmap, 0, |
1088 | le16_to_cpu(la->la_size)); | 1127 | le16_to_cpu(la->la_size)); |
1089 | 1128 | ||
1129 | ocfs2_resmap_restart(&osb->osb_la_resmap, cluster_count, | ||
1130 | OCFS2_LOCAL_ALLOC(alloc)->la_bitmap); | ||
1131 | |||
1090 | mlog(0, "New window allocated:\n"); | 1132 | mlog(0, "New window allocated:\n"); |
1091 | mlog(0, "window la_bm_off = %u\n", | 1133 | mlog(0, "window la_bm_off = %u\n", |
1092 | OCFS2_LOCAL_ALLOC(alloc)->la_bm_off); | 1134 | OCFS2_LOCAL_ALLOC(alloc)->la_bm_off); |