aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_file.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_file.c')
-rw-r--r--fs/xfs/xfs_file.c71
1 files changed, 19 insertions, 52 deletions
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 35703a801372..5fb5a0958a14 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -1043,49 +1043,17 @@ xfs_find_get_desired_pgoff(
1043 1043
1044 index = startoff >> PAGE_SHIFT; 1044 index = startoff >> PAGE_SHIFT;
1045 endoff = XFS_FSB_TO_B(mp, map->br_startoff + map->br_blockcount); 1045 endoff = XFS_FSB_TO_B(mp, map->br_startoff + map->br_blockcount);
1046 end = endoff >> PAGE_SHIFT; 1046 end = (endoff - 1) >> PAGE_SHIFT;
1047 do { 1047 do {
1048 int want; 1048 int want;
1049 unsigned nr_pages; 1049 unsigned nr_pages;
1050 unsigned int i; 1050 unsigned int i;
1051 1051
1052 want = min_t(pgoff_t, end - index, PAGEVEC_SIZE); 1052 want = min_t(pgoff_t, end - index, PAGEVEC_SIZE - 1) + 1;
1053 nr_pages = pagevec_lookup(&pvec, inode->i_mapping, index, 1053 nr_pages = pagevec_lookup(&pvec, inode->i_mapping, index,
1054 want); 1054 want);
1055 /* 1055 if (nr_pages == 0)
1056 * No page mapped into given range. If we are searching holes
1057 * and if this is the first time we got into the loop, it means
1058 * that the given offset is landed in a hole, return it.
1059 *
1060 * If we have already stepped through some block buffers to find
1061 * holes but they all contains data. In this case, the last
1062 * offset is already updated and pointed to the end of the last
1063 * mapped page, if it does not reach the endpoint to search,
1064 * that means there should be a hole between them.
1065 */
1066 if (nr_pages == 0) {
1067 /* Data search found nothing */
1068 if (type == DATA_OFF)
1069 break;
1070
1071 ASSERT(type == HOLE_OFF);
1072 if (lastoff == startoff || lastoff < endoff) {
1073 found = true;
1074 *offset = lastoff;
1075 }
1076 break;
1077 }
1078
1079 /*
1080 * At lease we found one page. If this is the first time we
1081 * step into the loop, and if the first page index offset is
1082 * greater than the given search offset, a hole was found.
1083 */
1084 if (type == HOLE_OFF && lastoff == startoff &&
1085 lastoff < page_offset(pvec.pages[0])) {
1086 found = true;
1087 break; 1056 break;
1088 }
1089 1057
1090 for (i = 0; i < nr_pages; i++) { 1058 for (i = 0; i < nr_pages; i++) {
1091 struct page *page = pvec.pages[i]; 1059 struct page *page = pvec.pages[i];
@@ -1098,18 +1066,18 @@ xfs_find_get_desired_pgoff(
1098 * file mapping. However, page->index will not change 1066 * file mapping. However, page->index will not change
1099 * because we have a reference on the page. 1067 * because we have a reference on the page.
1100 * 1068 *
1101 * Searching done if the page index is out of range. 1069 * If current page offset is beyond where we've ended,
1102 * If the current offset is not reaches the end of 1070 * we've found a hole.
1103 * the specified search range, there should be a hole
1104 * between them.
1105 */ 1071 */
1106 if (page->index > end) { 1072 if (type == HOLE_OFF && lastoff < endoff &&
1107 if (type == HOLE_OFF && lastoff < endoff) { 1073 lastoff < page_offset(pvec.pages[i])) {
1108 *offset = lastoff; 1074 found = true;
1109 found = true; 1075 *offset = lastoff;
1110 }
1111 goto out; 1076 goto out;
1112 } 1077 }
1078 /* Searching done if the page index is out of range. */
1079 if (page->index > end)
1080 goto out;
1113 1081
1114 lock_page(page); 1082 lock_page(page);
1115 /* 1083 /*
@@ -1151,21 +1119,20 @@ xfs_find_get_desired_pgoff(
1151 1119
1152 /* 1120 /*
1153 * The number of returned pages less than our desired, search 1121 * The number of returned pages less than our desired, search
1154 * done. In this case, nothing was found for searching data, 1122 * done.
1155 * but we found a hole behind the last offset.
1156 */ 1123 */
1157 if (nr_pages < want) { 1124 if (nr_pages < want)
1158 if (type == HOLE_OFF) {
1159 *offset = lastoff;
1160 found = true;
1161 }
1162 break; 1125 break;
1163 }
1164 1126
1165 index = pvec.pages[i - 1]->index + 1; 1127 index = pvec.pages[i - 1]->index + 1;
1166 pagevec_release(&pvec); 1128 pagevec_release(&pvec);
1167 } while (index <= end); 1129 } while (index <= end);
1168 1130
1131 /* No page at lastoff and we are not done - we found a hole. */
1132 if (type == HOLE_OFF && lastoff < endoff) {
1133 *offset = lastoff;
1134 found = true;
1135 }
1169out: 1136out:
1170 pagevec_release(&pvec); 1137 pagevec_release(&pvec);
1171 return found; 1138 return found;