aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/localalloc.c
diff options
context:
space:
mode:
authorMark Fasheh <mfasheh@suse.com>2009-12-07 16:10:48 -0500
committerJoel Becker <joel.becker@oracle.com>2010-05-05 21:17:30 -0400
commitd02f00cc057809d96c044cc72d5b9809d59f7d49 (patch)
tree44a6d81ecf9fb4b5aa91c0501a8da2ee36890a38 /fs/ocfs2/localalloc.c
parentec20cec7a351584ca6c70ead012e73d61f9a8e04 (diff)
ocfs2: allocation reservations
This patch improves Ocfs2 allocation policy by allowing an inode to reserve a portion of the local alloc bitmap for itself. The reserved portion (allocation window) is advisory in that other allocation windows might steal it if the local alloc bitmap becomes full. Otherwise, the reservations are honored and guaranteed to be free. When the local alloc window is moved to a different portion of the bitmap, existing reservations are discarded. Reservation windows are represented internally by a red-black tree. Within that tree, each node represents the reservation window of one inode. An LRU of active reservations is also maintained. When new data is written, we allocate it from the inodes window. When all bits in a window are exhausted, we allocate a new one as close to the previous one as possible. Should we not find free space, an existing reservation is pulled off the LRU and cannibalized. Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Diffstat (limited to 'fs/ocfs2/localalloc.c')
-rw-r--r--fs/ocfs2/localalloc.c64
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
53static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb, 53static 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
57static void ocfs2_clear_local_alloc(struct ocfs2_dinode *alloc); 58static 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
713static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb, 718static 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
767bail: 803bail:
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);