aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/file.c18
-rw-r--r--fs/btrfs/free-space-cache.c8
2 files changed, 19 insertions, 7 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 8eb1f3c1b647..870150547f5c 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1291,7 +1291,8 @@ out:
1291 * on error we return an unlocked page and the error value 1291 * on error we return an unlocked page and the error value
1292 * on success we return a locked page and 0 1292 * on success we return a locked page and 0
1293 */ 1293 */
1294static int prepare_uptodate_page(struct page *page, u64 pos, 1294static int prepare_uptodate_page(struct inode *inode,
1295 struct page *page, u64 pos,
1295 bool force_uptodate) 1296 bool force_uptodate)
1296{ 1297{
1297 int ret = 0; 1298 int ret = 0;
@@ -1306,6 +1307,10 @@ static int prepare_uptodate_page(struct page *page, u64 pos,
1306 unlock_page(page); 1307 unlock_page(page);
1307 return -EIO; 1308 return -EIO;
1308 } 1309 }
1310 if (page->mapping != inode->i_mapping) {
1311 unlock_page(page);
1312 return -EAGAIN;
1313 }
1309 } 1314 }
1310 return 0; 1315 return 0;
1311} 1316}
@@ -1324,6 +1329,7 @@ static noinline int prepare_pages(struct inode *inode, struct page **pages,
1324 int faili; 1329 int faili;
1325 1330
1326 for (i = 0; i < num_pages; i++) { 1331 for (i = 0; i < num_pages; i++) {
1332again:
1327 pages[i] = find_or_create_page(inode->i_mapping, index + i, 1333 pages[i] = find_or_create_page(inode->i_mapping, index + i,
1328 mask | __GFP_WRITE); 1334 mask | __GFP_WRITE);
1329 if (!pages[i]) { 1335 if (!pages[i]) {
@@ -1333,13 +1339,17 @@ static noinline int prepare_pages(struct inode *inode, struct page **pages,
1333 } 1339 }
1334 1340
1335 if (i == 0) 1341 if (i == 0)
1336 err = prepare_uptodate_page(pages[i], pos, 1342 err = prepare_uptodate_page(inode, pages[i], pos,
1337 force_uptodate); 1343 force_uptodate);
1338 if (i == num_pages - 1) 1344 if (!err && i == num_pages - 1)
1339 err = prepare_uptodate_page(pages[i], 1345 err = prepare_uptodate_page(inode, pages[i],
1340 pos + write_bytes, false); 1346 pos + write_bytes, false);
1341 if (err) { 1347 if (err) {
1342 page_cache_release(pages[i]); 1348 page_cache_release(pages[i]);
1349 if (err == -EAGAIN) {
1350 err = 0;
1351 goto again;
1352 }
1343 faili = i - 1; 1353 faili = i - 1;
1344 goto fail; 1354 goto fail;
1345 } 1355 }
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
index 7a91770d8bb2..f331ef7d573a 100644
--- a/fs/btrfs/free-space-cache.c
+++ b/fs/btrfs/free-space-cache.c
@@ -2972,7 +2972,7 @@ setup_cluster_bitmap(struct btrfs_block_group_cache *block_group,
2972 u64 cont1_bytes, u64 min_bytes) 2972 u64 cont1_bytes, u64 min_bytes)
2973{ 2973{
2974 struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; 2974 struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
2975 struct btrfs_free_space *entry; 2975 struct btrfs_free_space *entry = NULL;
2976 int ret = -ENOSPC; 2976 int ret = -ENOSPC;
2977 u64 bitmap_offset = offset_to_bitmap(ctl, offset); 2977 u64 bitmap_offset = offset_to_bitmap(ctl, offset);
2978 2978
@@ -2983,8 +2983,10 @@ setup_cluster_bitmap(struct btrfs_block_group_cache *block_group,
2983 * The bitmap that covers offset won't be in the list unless offset 2983 * The bitmap that covers offset won't be in the list unless offset
2984 * is just its start offset. 2984 * is just its start offset.
2985 */ 2985 */
2986 entry = list_first_entry(bitmaps, struct btrfs_free_space, list); 2986 if (!list_empty(bitmaps))
2987 if (entry->offset != bitmap_offset) { 2987 entry = list_first_entry(bitmaps, struct btrfs_free_space, list);
2988
2989 if (!entry || entry->offset != bitmap_offset) {
2988 entry = tree_search_offset(ctl, bitmap_offset, 1, 0); 2990 entry = tree_search_offset(ctl, bitmap_offset, 1, 0);
2989 if (entry && list_empty(&entry->list)) 2991 if (entry && list_empty(&entry->list))
2990 list_add(&entry->list, bitmaps); 2992 list_add(&entry->list, bitmaps);