aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_alloc.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2010-12-10 10:04:11 -0500
committerAlex Elder <aelder@sgi.com>2010-12-16 17:06:15 -0500
commit489a150f6454e2cd93d9e0ee6d7c5a361844f62a (patch)
tree18deded59797caaec9f01ef5a3eb66a765bef29f /fs/xfs/xfs_alloc.c
parent9f9baab38dacd11fe6095a1e59f3783a305f7020 (diff)
xfs: factor duplicate code in xfs_alloc_ag_vextent_near into a helper
Add a new xfs_alloc_find_best_extent that does a forward/backward search in the allocation btree. That code previously was existed two times in xfs_alloc_ag_vextent_near, once for each search direction. Based on an earlier patch from Dave Chinner. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Alex Elder <aelder@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_alloc.c')
-rw-r--r--fs/xfs/xfs_alloc.c293
1 files changed, 113 insertions, 180 deletions
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index d9133f10d2b1..fa8723f5870a 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -665,6 +665,95 @@ error0:
665} 665}
666 666
667/* 667/*
668 * Search the btree in a given direction via the search cursor and compare
669 * the records found against the good extent we've already found.
670 */
671STATIC int
672xfs_alloc_find_best_extent(
673 struct xfs_alloc_arg *args, /* allocation argument structure */
674 struct xfs_btree_cur **gcur, /* good cursor */
675 struct xfs_btree_cur **scur, /* searching cursor */
676 xfs_agblock_t gdiff, /* difference for search comparison */
677 xfs_agblock_t *sbno, /* extent found by search */
678 xfs_extlen_t *slen,
679 xfs_extlen_t *slena, /* aligned length */
680 int dir) /* 0 = search right, 1 = search left */
681{
682 xfs_agblock_t bno;
683 xfs_agblock_t new;
684 xfs_agblock_t sdiff;
685 int error;
686 int i;
687
688 /* The good extent is perfect, no need to search. */
689 if (!gdiff)
690 goto out_use_good;
691
692 /*
693 * Look until we find a better one, run out of space or run off the end.
694 */
695 do {
696 error = xfs_alloc_get_rec(*scur, sbno, slen, &i);
697 if (error)
698 goto error0;
699 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
700 xfs_alloc_compute_aligned(*sbno, *slen, args->alignment,
701 args->minlen, &bno, slena);
702
703 /*
704 * The good extent is closer than this one.
705 */
706 if (!dir) {
707 if (bno >= args->agbno + gdiff)
708 goto out_use_good;
709 } else {
710 if (bno <= args->agbno - gdiff)
711 goto out_use_good;
712 }
713
714 /*
715 * Same distance, compare length and pick the best.
716 */
717 if (*slena >= args->minlen) {
718 args->len = XFS_EXTLEN_MIN(*slena, args->maxlen);
719 xfs_alloc_fix_len(args);
720
721 sdiff = xfs_alloc_compute_diff(args->agbno, args->len,
722 args->alignment, *sbno,
723 *slen, &new);
724
725 /*
726 * Choose closer size and invalidate other cursor.
727 */
728 if (sdiff < gdiff)
729 goto out_use_search;
730 goto out_use_good;
731 }
732
733 if (!dir)
734 error = xfs_btree_increment(*scur, 0, &i);
735 else
736 error = xfs_btree_decrement(*scur, 0, &i);
737 if (error)
738 goto error0;
739 } while (i);
740
741out_use_good:
742 xfs_btree_del_cursor(*scur, XFS_BTREE_NOERROR);
743 *scur = NULL;
744 return 0;
745
746out_use_search:
747 xfs_btree_del_cursor(*gcur, XFS_BTREE_NOERROR);
748 *gcur = NULL;
749 return 0;
750
751error0:
752 /* caller invalidates cursors */
753 return error;
754}
755
756/*
668 * Allocate a variable extent near bno in the allocation group agno. 757 * Allocate a variable extent near bno in the allocation group agno.
669 * Extent's length (returned in len) will be between minlen and maxlen, 758 * Extent's length (returned in len) will be between minlen and maxlen,
670 * and of the form k * prod + mod unless there's nothing that large. 759 * and of the form k * prod + mod unless there's nothing that large.
@@ -931,203 +1020,45 @@ xfs_alloc_ag_vextent_near(
931 } 1020 }
932 } 1021 }
933 } while (bno_cur_lt || bno_cur_gt); 1022 } while (bno_cur_lt || bno_cur_gt);
1023
934 /* 1024 /*
935 * Got both cursors still active, need to find better entry. 1025 * Got both cursors still active, need to find better entry.
936 */ 1026 */
937 if (bno_cur_lt && bno_cur_gt) { 1027 if (bno_cur_lt && bno_cur_gt) {
938 /*
939 * Left side is long enough, look for a right side entry.
940 */
941 if (ltlena >= args->minlen) { 1028 if (ltlena >= args->minlen) {
942 /* 1029 /*
943 * Fix up the length. 1030 * Left side is good, look for a right side entry.
944 */ 1031 */
945 args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen); 1032 args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen);
946 xfs_alloc_fix_len(args); 1033 xfs_alloc_fix_len(args);
947 rlen = args->len; 1034 ltdiff = xfs_alloc_compute_diff(args->agbno, args->len,
948 ltdiff = xfs_alloc_compute_diff(args->agbno, rlen,
949 args->alignment, ltbno, ltlen, &ltnew); 1035 args->alignment, ltbno, ltlen, &ltnew);
1036
1037 error = xfs_alloc_find_best_extent(args,
1038 &bno_cur_lt, &bno_cur_gt,
1039 ltdiff, &gtbno, &gtlen, &gtlena,
1040 0 /* search right */);
1041 } else {
1042 ASSERT(gtlena >= args->minlen);
1043
950 /* 1044 /*
951 * Not perfect. 1045 * Right side is good, look for a left side entry.
952 */
953 if (ltdiff) {
954 /*
955 * Look until we find a better one, run out of
956 * space, or run off the end.
957 */
958 while (bno_cur_lt && bno_cur_gt) {
959 if ((error = xfs_alloc_get_rec(
960 bno_cur_gt, &gtbno,
961 &gtlen, &i)))
962 goto error0;
963 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
964 xfs_alloc_compute_aligned(gtbno, gtlen,
965 args->alignment, args->minlen,
966 &gtbnoa, &gtlena);
967 /*
968 * The left one is clearly better.
969 */
970 if (gtbnoa >= args->agbno + ltdiff) {
971 xfs_btree_del_cursor(
972 bno_cur_gt,
973 XFS_BTREE_NOERROR);
974 bno_cur_gt = NULL;
975 break;
976 }
977 /*
978 * If we reach a big enough entry,
979 * compare the two and pick the best.
980 */
981 if (gtlena >= args->minlen) {
982 args->len =
983 XFS_EXTLEN_MIN(gtlena,
984 args->maxlen);
985 xfs_alloc_fix_len(args);
986 rlen = args->len;
987 gtdiff = xfs_alloc_compute_diff(
988 args->agbno, rlen,
989 args->alignment,
990 gtbno, gtlen, &gtnew);
991 /*
992 * Right side is better.
993 */
994 if (gtdiff < ltdiff) {
995 xfs_btree_del_cursor(
996 bno_cur_lt,
997 XFS_BTREE_NOERROR);
998 bno_cur_lt = NULL;
999 }
1000 /*
1001 * Left side is better.
1002 */
1003 else {
1004 xfs_btree_del_cursor(
1005 bno_cur_gt,
1006 XFS_BTREE_NOERROR);
1007 bno_cur_gt = NULL;
1008 }
1009 break;
1010 }
1011 /*
1012 * Fell off the right end.
1013 */
1014 if ((error = xfs_btree_increment(
1015 bno_cur_gt, 0, &i)))
1016 goto error0;
1017 if (!i) {
1018 xfs_btree_del_cursor(
1019 bno_cur_gt,
1020 XFS_BTREE_NOERROR);
1021 bno_cur_gt = NULL;
1022 break;
1023 }
1024 }
1025 }
1026 /*
1027 * The left side is perfect, trash the right side.
1028 */
1029 else {
1030 xfs_btree_del_cursor(bno_cur_gt,
1031 XFS_BTREE_NOERROR);
1032 bno_cur_gt = NULL;
1033 }
1034 }
1035 /*
1036 * It's the right side that was found first, look left.
1037 */
1038 else {
1039 /*
1040 * Fix up the length.
1041 */ 1046 */
1042 args->len = XFS_EXTLEN_MIN(gtlena, args->maxlen); 1047 args->len = XFS_EXTLEN_MIN(gtlena, args->maxlen);
1043 xfs_alloc_fix_len(args); 1048 xfs_alloc_fix_len(args);
1044 rlen = args->len; 1049 gtdiff = xfs_alloc_compute_diff(args->agbno, args->len,
1045 gtdiff = xfs_alloc_compute_diff(args->agbno, rlen,
1046 args->alignment, gtbno, gtlen, &gtnew); 1050 args->alignment, gtbno, gtlen, &gtnew);
1047 /* 1051
1048 * Right side entry isn't perfect. 1052 error = xfs_alloc_find_best_extent(args,
1049 */ 1053 &bno_cur_gt, &bno_cur_lt,
1050 if (gtdiff) { 1054 gtdiff, &ltbno, &ltlen, &ltlena,
1051 /* 1055 1 /* search left */);
1052 * Look until we find a better one, run out of
1053 * space, or run off the end.
1054 */
1055 while (bno_cur_lt && bno_cur_gt) {
1056 if ((error = xfs_alloc_get_rec(
1057 bno_cur_lt, &ltbno,
1058 &ltlen, &i)))
1059 goto error0;
1060 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
1061 xfs_alloc_compute_aligned(ltbno, ltlen,
1062 args->alignment, args->minlen,
1063 &ltbnoa, &ltlena);
1064 /*
1065 * The right one is clearly better.
1066 */
1067 if (ltbnoa <= args->agbno - gtdiff) {
1068 xfs_btree_del_cursor(
1069 bno_cur_lt,
1070 XFS_BTREE_NOERROR);
1071 bno_cur_lt = NULL;
1072 break;
1073 }
1074 /*
1075 * If we reach a big enough entry,
1076 * compare the two and pick the best.
1077 */
1078 if (ltlena >= args->minlen) {
1079 args->len = XFS_EXTLEN_MIN(
1080 ltlena, args->maxlen);
1081 xfs_alloc_fix_len(args);
1082 rlen = args->len;
1083 ltdiff = xfs_alloc_compute_diff(
1084 args->agbno, rlen,
1085 args->alignment,
1086 ltbno, ltlen, &ltnew);
1087 /*
1088 * Left side is better.
1089 */
1090 if (ltdiff < gtdiff) {
1091 xfs_btree_del_cursor(
1092 bno_cur_gt,
1093 XFS_BTREE_NOERROR);
1094 bno_cur_gt = NULL;
1095 }
1096 /*
1097 * Right side is better.
1098 */
1099 else {
1100 xfs_btree_del_cursor(
1101 bno_cur_lt,
1102 XFS_BTREE_NOERROR);
1103 bno_cur_lt = NULL;
1104 }
1105 break;
1106 }
1107 /*
1108 * Fell off the left end.
1109 */
1110 if ((error = xfs_btree_decrement(
1111 bno_cur_lt, 0, &i)))
1112 goto error0;
1113 if (!i) {
1114 xfs_btree_del_cursor(bno_cur_lt,
1115 XFS_BTREE_NOERROR);
1116 bno_cur_lt = NULL;
1117 break;
1118 }
1119 }
1120 }
1121 /*
1122 * The right side is perfect, trash the left side.
1123 */
1124 else {
1125 xfs_btree_del_cursor(bno_cur_lt,
1126 XFS_BTREE_NOERROR);
1127 bno_cur_lt = NULL;
1128 }
1129 } 1056 }
1057
1058 if (error)
1059 goto error0;
1130 } 1060 }
1061
1131 /* 1062 /*
1132 * If we couldn't get anything, give up. 1063 * If we couldn't get anything, give up.
1133 */ 1064 */
@@ -1136,6 +1067,7 @@ xfs_alloc_ag_vextent_near(
1136 args->agbno = NULLAGBLOCK; 1067 args->agbno = NULLAGBLOCK;
1137 return 0; 1068 return 0;
1138 } 1069 }
1070
1139 /* 1071 /*
1140 * At this point we have selected a freespace entry, either to the 1072 * At this point we have selected a freespace entry, either to the
1141 * left or to the right. If it's on the right, copy all the 1073 * left or to the right. If it's on the right, copy all the
@@ -1152,6 +1084,7 @@ xfs_alloc_ag_vextent_near(
1152 j = 1; 1084 j = 1;
1153 } else 1085 } else
1154 j = 0; 1086 j = 0;
1087
1155 /* 1088 /*
1156 * Fix up the length and compute the useful address. 1089 * Fix up the length and compute the useful address.
1157 */ 1090 */