aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c53
1 files changed, 32 insertions, 21 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 5d4d5d8db8ef..26b8d3406491 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -23,7 +23,8 @@
23#include "transaction.h" 23#include "transaction.h"
24 24
25static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root 25static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
26 *orig_root, u64 num_blocks, u64 search_start, 26 *orig_root, u64 num_blocks, u64 empty_size,
27 u64 search_start,
27 u64 search_end, u64 hint_block, 28 u64 search_end, u64 hint_block,
28 struct btrfs_key *ins, u64 exclude_start, 29 struct btrfs_key *ins, u64 exclude_start,
29 u64 exclude_nr, int data); 30 u64 exclude_nr, int data);
@@ -379,7 +380,7 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
379 path = btrfs_alloc_path(); 380 path = btrfs_alloc_path();
380 if (!path) 381 if (!path)
381 return -ENOMEM; 382 return -ENOMEM;
382 ret = find_free_extent(trans, root->fs_info->extent_root, 0, 0, 383 ret = find_free_extent(trans, root->fs_info->extent_root, 0, 0, 0,
383 (u64)-1, 0, &ins, 0, 0, 0); 384 (u64)-1, 0, &ins, 0, 0, 0);
384 if (ret) { 385 if (ret) {
385 btrfs_free_path(path); 386 btrfs_free_path(path);
@@ -533,7 +534,7 @@ static int write_one_cache_group(struct btrfs_trans_handle *trans,
533 struct btrfs_block_group_item *bi; 534 struct btrfs_block_group_item *bi;
534 struct btrfs_key ins; 535 struct btrfs_key ins;
535 536
536 ret = find_free_extent(trans, extent_root, 0, 0, (u64)-1, 0, &ins, 537 ret = find_free_extent(trans, extent_root, 0, 0, 0, (u64)-1, 0, &ins,
537 0, 0, 0); 538 0, 0, 0);
538 /* FIXME, set bit to recalc cache groups on next mount */ 539 /* FIXME, set bit to recalc cache groups on next mount */
539 if (ret) 540 if (ret)
@@ -708,6 +709,7 @@ static int update_block_group(struct btrfs_trans_handle *trans,
708static int try_remove_page(struct address_space *mapping, unsigned long index) 709static int try_remove_page(struct address_space *mapping, unsigned long index)
709{ 710{
710 int ret; 711 int ret;
712 return 0;
711 ret = invalidate_mapping_pages(mapping, index, index); 713 ret = invalidate_mapping_pages(mapping, index, index);
712 return ret; 714 return ret;
713} 715}
@@ -866,7 +868,7 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
866 if (!path) 868 if (!path)
867 return -ENOMEM; 869 return -ENOMEM;
868 870
869 ret = find_free_extent(trans, root, 0, 0, (u64)-1, 0, &ins, 0, 0, 0); 871 ret = find_free_extent(trans, root, 0, 0, 0, (u64)-1, 0, &ins, 0, 0, 0);
870 if (ret) { 872 if (ret) {
871 btrfs_free_path(path); 873 btrfs_free_path(path);
872 return ret; 874 return ret;
@@ -983,8 +985,8 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
983 * Any available blocks before search_start are skipped. 985 * Any available blocks before search_start are skipped.
984 */ 986 */
985static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root 987static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
986 *orig_root, u64 num_blocks, u64 search_start, u64 988 *orig_root, u64 num_blocks, u64 empty_size,
987 search_end, u64 hint_block, 989 u64 search_start, u64 search_end, u64 hint_block,
988 struct btrfs_key *ins, u64 exclude_start, 990 struct btrfs_key *ins, u64 exclude_start,
989 u64 exclude_nr, int data) 991 u64 exclude_nr, int data)
990{ 992{
@@ -1042,6 +1044,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
1042 data, 1); 1044 data, 1);
1043 } 1045 }
1044 1046
1047 total_needed += empty_size;
1045 path = btrfs_alloc_path(); 1048 path = btrfs_alloc_path();
1046 1049
1047check_failed: 1050check_failed:
@@ -1157,9 +1160,11 @@ check_pending:
1157 goto error; 1160 goto error;
1158 } 1161 }
1159 search_start = orig_search_start; 1162 search_start = orig_search_start;
1160 if (wrapped) 1163 if (wrapped) {
1164 if (!full_scan)
1165 total_needed -= empty_size;
1161 full_scan = 1; 1166 full_scan = 1;
1162 else 1167 } else
1163 wrapped = 1; 1168 wrapped = 1;
1164 goto new_group; 1169 goto new_group;
1165 } 1170 }
@@ -1238,9 +1243,11 @@ new_group:
1238 ret = -ENOSPC; 1243 ret = -ENOSPC;
1239 goto error; 1244 goto error;
1240 } 1245 }
1241 if (wrapped) 1246 if (wrapped) {
1247 if (!full_scan)
1248 total_needed -= empty_size;
1242 full_scan = 1; 1249 full_scan = 1;
1243 else 1250 } else
1244 wrapped = 1; 1251 wrapped = 1;
1245 } 1252 }
1246 block_group = btrfs_lookup_block_group(info, search_start); 1253 block_group = btrfs_lookup_block_group(info, search_start);
@@ -1264,7 +1271,7 @@ error:
1264 */ 1271 */
1265int btrfs_alloc_extent(struct btrfs_trans_handle *trans, 1272int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
1266 struct btrfs_root *root, u64 owner, 1273 struct btrfs_root *root, u64 owner,
1267 u64 num_blocks, u64 hint_block, 1274 u64 num_blocks, u64 empty_size, u64 hint_block,
1268 u64 search_end, struct btrfs_key *ins, int data) 1275 u64 search_end, struct btrfs_key *ins, int data)
1269{ 1276{
1270 int ret; 1277 int ret;
@@ -1303,7 +1310,7 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
1303 * in the correct block group. 1310 * in the correct block group.
1304 */ 1311 */
1305 if (data) { 1312 if (data) {
1306 ret = find_free_extent(trans, root, 0, 0, 1313 ret = find_free_extent(trans, root, 0, 0, 0,
1307 search_end, 0, &prealloc_key, 0, 0, 0); 1314 search_end, 0, &prealloc_key, 0, 0, 0);
1308 BUG_ON(ret); 1315 BUG_ON(ret);
1309 if (ret) 1316 if (ret)
@@ -1313,8 +1320,8 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
1313 } 1320 }
1314 1321
1315 /* do the real allocation */ 1322 /* do the real allocation */
1316 ret = find_free_extent(trans, root, num_blocks, search_start, 1323 ret = find_free_extent(trans, root, num_blocks, empty_size,
1317 search_end, hint_block, ins, 1324 search_start, search_end, hint_block, ins,
1318 exclude_start, exclude_nr, data); 1325 exclude_start, exclude_nr, data);
1319 BUG_ON(ret); 1326 BUG_ON(ret);
1320 if (ret) 1327 if (ret)
@@ -1333,7 +1340,7 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
1333 exclude_start = ins->objectid; 1340 exclude_start = ins->objectid;
1334 exclude_nr = ins->offset; 1341 exclude_nr = ins->offset;
1335 hint_block = exclude_start + exclude_nr; 1342 hint_block = exclude_start + exclude_nr;
1336 ret = find_free_extent(trans, root, 0, search_start, 1343 ret = find_free_extent(trans, root, 0, 0, search_start,
1337 search_end, hint_block, 1344 search_end, hint_block,
1338 &prealloc_key, exclude_start, 1345 &prealloc_key, exclude_start,
1339 exclude_nr, 0); 1346 exclude_nr, 0);
@@ -1368,14 +1375,16 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
1368 * returns the tree buffer or NULL. 1375 * returns the tree buffer or NULL.
1369 */ 1376 */
1370struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, 1377struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
1371 struct btrfs_root *root, u64 hint) 1378 struct btrfs_root *root, u64 hint,
1379 u64 empty_size)
1372{ 1380{
1373 struct btrfs_key ins; 1381 struct btrfs_key ins;
1374 int ret; 1382 int ret;
1375 struct buffer_head *buf; 1383 struct buffer_head *buf;
1376 1384
1377 ret = btrfs_alloc_extent(trans, root, root->root_key.objectid, 1385 ret = btrfs_alloc_extent(trans, root, root->root_key.objectid,
1378 1, hint, (unsigned long)-1, &ins, 0); 1386 1, empty_size, hint,
1387 (unsigned long)-1, &ins, 0);
1379 if (ret) { 1388 if (ret) {
1380 BUG_ON(ret > 0); 1389 BUG_ON(ret > 0);
1381 return ERR_PTR(ret); 1390 return ERR_PTR(ret);
@@ -1385,6 +1394,7 @@ struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
1385 btrfs_free_extent(trans, root, ins.objectid, 1, 0); 1394 btrfs_free_extent(trans, root, ins.objectid, 1, 0);
1386 return ERR_PTR(-ENOMEM); 1395 return ERR_PTR(-ENOMEM);
1387 } 1396 }
1397 WARN_ON(buffer_dirty(buf));
1388 set_buffer_uptodate(buf); 1398 set_buffer_uptodate(buf);
1389 set_buffer_checked(buf); 1399 set_buffer_checked(buf);
1390 set_radix_bit(&trans->transaction->dirty_pages, buf->b_page->index); 1400 set_radix_bit(&trans->transaction->dirty_pages, buf->b_page->index);
@@ -1591,13 +1601,15 @@ int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root
1591 struct btrfs_key key; 1601 struct btrfs_key key;
1592 struct btrfs_disk_key *found_key; 1602 struct btrfs_disk_key *found_key;
1593 struct btrfs_node *node; 1603 struct btrfs_node *node;
1604
1594 btrfs_disk_key_to_cpu(&key, &root_item->drop_progress); 1605 btrfs_disk_key_to_cpu(&key, &root_item->drop_progress);
1606 level = root_item->drop_level;
1607 path->lowest_level = level;
1595 wret = btrfs_search_slot(NULL, root, &key, path, 0, 0); 1608 wret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
1596 if (ret < 0) { 1609 if (wret < 0) {
1597 ret = wret; 1610 ret = wret;
1598 goto out; 1611 goto out;
1599 } 1612 }
1600 level = root_item->drop_level;
1601 node = btrfs_buffer_node(path->nodes[level]); 1613 node = btrfs_buffer_node(path->nodes[level]);
1602 found_key = &node->ptrs[path->slots[level]].key; 1614 found_key = &node->ptrs[path->slots[level]].key;
1603 WARN_ON(memcmp(found_key, &root_item->drop_progress, 1615 WARN_ON(memcmp(found_key, &root_item->drop_progress,
@@ -1617,8 +1629,6 @@ int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root
1617 ret = wret; 1629 ret = wret;
1618 num_walks++; 1630 num_walks++;
1619 if (num_walks > 10) { 1631 if (num_walks > 10) {
1620 struct btrfs_key key;
1621 btrfs_disk_key_to_cpu(&key, &root_item->drop_progress);
1622 ret = -EAGAIN; 1632 ret = -EAGAIN;
1623 get_bh(root->node); 1633 get_bh(root->node);
1624 break; 1634 break;
@@ -1627,6 +1637,7 @@ int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root
1627 for (i = 0; i <= orig_level; i++) { 1637 for (i = 0; i <= orig_level; i++) {
1628 if (path->nodes[i]) { 1638 if (path->nodes[i]) {
1629 btrfs_block_release(root, path->nodes[i]); 1639 btrfs_block_release(root, path->nodes[i]);
1640 path->nodes[i] = 0;
1630 } 1641 }
1631 } 1642 }
1632out: 1643out: