diff options
Diffstat (limited to 'fs/btrfs')
| -rw-r--r-- | fs/btrfs/async-thread.c | 2 | ||||
| -rw-r--r-- | fs/btrfs/backref.c | 33 | ||||
| -rw-r--r-- | fs/btrfs/ctree.c | 94 | ||||
| -rw-r--r-- | fs/btrfs/ctree.h | 13 | ||||
| -rw-r--r-- | fs/btrfs/disk-io.c | 23 | ||||
| -rw-r--r-- | fs/btrfs/extent-tree.c | 35 | ||||
| -rw-r--r-- | fs/btrfs/extent_io.c | 8 | ||||
| -rw-r--r-- | fs/btrfs/extent_io.h | 1 | ||||
| -rw-r--r-- | fs/btrfs/file.c | 21 | ||||
| -rw-r--r-- | fs/btrfs/inode-map.c | 14 | ||||
| -rw-r--r-- | fs/btrfs/inode.c | 36 | ||||
| -rw-r--r-- | fs/btrfs/ioctl.c | 35 | ||||
| -rw-r--r-- | fs/btrfs/relocation.c | 21 | ||||
| -rw-r--r-- | fs/btrfs/scrub.c | 108 | ||||
| -rw-r--r-- | fs/btrfs/send.c | 117 | ||||
| -rw-r--r-- | fs/btrfs/super.c | 22 | ||||
| -rw-r--r-- | fs/btrfs/transaction.c | 48 | ||||
| -rw-r--r-- | fs/btrfs/transaction.h | 3 | ||||
| -rw-r--r-- | fs/btrfs/volumes.c | 35 |
19 files changed, 379 insertions, 290 deletions
diff --git a/fs/btrfs/async-thread.c b/fs/btrfs/async-thread.c index ecb5832c0967..5a201d81049c 100644 --- a/fs/btrfs/async-thread.c +++ b/fs/btrfs/async-thread.c | |||
| @@ -323,6 +323,8 @@ void btrfs_destroy_workqueue(struct btrfs_workqueue *wq) | |||
| 323 | 323 | ||
| 324 | void btrfs_workqueue_set_max(struct btrfs_workqueue *wq, int max) | 324 | void btrfs_workqueue_set_max(struct btrfs_workqueue *wq, int max) |
| 325 | { | 325 | { |
| 326 | if (!wq) | ||
| 327 | return; | ||
| 326 | wq->normal->max_active = max; | 328 | wq->normal->max_active = max; |
| 327 | if (wq->high) | 329 | if (wq->high) |
| 328 | wq->high->max_active = max; | 330 | wq->high->max_active = max; |
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index aad7201ad11b..10db21fa0926 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c | |||
| @@ -330,7 +330,10 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info, | |||
| 330 | goto out; | 330 | goto out; |
| 331 | } | 331 | } |
| 332 | 332 | ||
| 333 | root_level = btrfs_old_root_level(root, time_seq); | 333 | if (path->search_commit_root) |
| 334 | root_level = btrfs_header_level(root->commit_root); | ||
| 335 | else | ||
| 336 | root_level = btrfs_old_root_level(root, time_seq); | ||
| 334 | 337 | ||
| 335 | if (root_level + 1 == level) { | 338 | if (root_level + 1 == level) { |
| 336 | srcu_read_unlock(&fs_info->subvol_srcu, index); | 339 | srcu_read_unlock(&fs_info->subvol_srcu, index); |
| @@ -1099,9 +1102,9 @@ static int btrfs_find_all_leafs(struct btrfs_trans_handle *trans, | |||
| 1099 | * | 1102 | * |
| 1100 | * returns 0 on success, < 0 on error. | 1103 | * returns 0 on success, < 0 on error. |
| 1101 | */ | 1104 | */ |
| 1102 | int btrfs_find_all_roots(struct btrfs_trans_handle *trans, | 1105 | static int __btrfs_find_all_roots(struct btrfs_trans_handle *trans, |
| 1103 | struct btrfs_fs_info *fs_info, u64 bytenr, | 1106 | struct btrfs_fs_info *fs_info, u64 bytenr, |
| 1104 | u64 time_seq, struct ulist **roots) | 1107 | u64 time_seq, struct ulist **roots) |
| 1105 | { | 1108 | { |
| 1106 | struct ulist *tmp; | 1109 | struct ulist *tmp; |
| 1107 | struct ulist_node *node = NULL; | 1110 | struct ulist_node *node = NULL; |
| @@ -1137,6 +1140,20 @@ int btrfs_find_all_roots(struct btrfs_trans_handle *trans, | |||
| 1137 | return 0; | 1140 | return 0; |
| 1138 | } | 1141 | } |
| 1139 | 1142 | ||
| 1143 | int btrfs_find_all_roots(struct btrfs_trans_handle *trans, | ||
| 1144 | struct btrfs_fs_info *fs_info, u64 bytenr, | ||
| 1145 | u64 time_seq, struct ulist **roots) | ||
| 1146 | { | ||
| 1147 | int ret; | ||
| 1148 | |||
| 1149 | if (!trans) | ||
| 1150 | down_read(&fs_info->commit_root_sem); | ||
| 1151 | ret = __btrfs_find_all_roots(trans, fs_info, bytenr, time_seq, roots); | ||
| 1152 | if (!trans) | ||
| 1153 | up_read(&fs_info->commit_root_sem); | ||
| 1154 | return ret; | ||
| 1155 | } | ||
| 1156 | |||
| 1140 | /* | 1157 | /* |
| 1141 | * this makes the path point to (inum INODE_ITEM ioff) | 1158 | * this makes the path point to (inum INODE_ITEM ioff) |
| 1142 | */ | 1159 | */ |
| @@ -1516,6 +1533,8 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info, | |||
| 1516 | if (IS_ERR(trans)) | 1533 | if (IS_ERR(trans)) |
| 1517 | return PTR_ERR(trans); | 1534 | return PTR_ERR(trans); |
| 1518 | btrfs_get_tree_mod_seq(fs_info, &tree_mod_seq_elem); | 1535 | btrfs_get_tree_mod_seq(fs_info, &tree_mod_seq_elem); |
| 1536 | } else { | ||
| 1537 | down_read(&fs_info->commit_root_sem); | ||
| 1519 | } | 1538 | } |
| 1520 | 1539 | ||
| 1521 | ret = btrfs_find_all_leafs(trans, fs_info, extent_item_objectid, | 1540 | ret = btrfs_find_all_leafs(trans, fs_info, extent_item_objectid, |
| @@ -1526,8 +1545,8 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info, | |||
| 1526 | 1545 | ||
| 1527 | ULIST_ITER_INIT(&ref_uiter); | 1546 | ULIST_ITER_INIT(&ref_uiter); |
| 1528 | while (!ret && (ref_node = ulist_next(refs, &ref_uiter))) { | 1547 | while (!ret && (ref_node = ulist_next(refs, &ref_uiter))) { |
| 1529 | ret = btrfs_find_all_roots(trans, fs_info, ref_node->val, | 1548 | ret = __btrfs_find_all_roots(trans, fs_info, ref_node->val, |
| 1530 | tree_mod_seq_elem.seq, &roots); | 1549 | tree_mod_seq_elem.seq, &roots); |
| 1531 | if (ret) | 1550 | if (ret) |
| 1532 | break; | 1551 | break; |
| 1533 | ULIST_ITER_INIT(&root_uiter); | 1552 | ULIST_ITER_INIT(&root_uiter); |
| @@ -1549,6 +1568,8 @@ out: | |||
| 1549 | if (!search_commit_root) { | 1568 | if (!search_commit_root) { |
| 1550 | btrfs_put_tree_mod_seq(fs_info, &tree_mod_seq_elem); | 1569 | btrfs_put_tree_mod_seq(fs_info, &tree_mod_seq_elem); |
| 1551 | btrfs_end_transaction(trans, fs_info->extent_root); | 1570 | btrfs_end_transaction(trans, fs_info->extent_root); |
| 1571 | } else { | ||
| 1572 | up_read(&fs_info->commit_root_sem); | ||
| 1552 | } | 1573 | } |
| 1553 | 1574 | ||
| 1554 | return ret; | 1575 | return ret; |
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 88d1b1eedc9c..1bcfcdb23cf4 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
| @@ -2769,9 +2769,13 @@ again: | |||
| 2769 | * the commit roots are read only | 2769 | * the commit roots are read only |
| 2770 | * so we always do read locks | 2770 | * so we always do read locks |
| 2771 | */ | 2771 | */ |
| 2772 | if (p->need_commit_sem) | ||
| 2773 | down_read(&root->fs_info->commit_root_sem); | ||
| 2772 | b = root->commit_root; | 2774 | b = root->commit_root; |
| 2773 | extent_buffer_get(b); | 2775 | extent_buffer_get(b); |
| 2774 | level = btrfs_header_level(b); | 2776 | level = btrfs_header_level(b); |
| 2777 | if (p->need_commit_sem) | ||
| 2778 | up_read(&root->fs_info->commit_root_sem); | ||
| 2775 | if (!p->skip_locking) | 2779 | if (!p->skip_locking) |
| 2776 | btrfs_tree_read_lock(b); | 2780 | btrfs_tree_read_lock(b); |
| 2777 | } else { | 2781 | } else { |
| @@ -5360,7 +5364,6 @@ int btrfs_compare_trees(struct btrfs_root *left_root, | |||
| 5360 | { | 5364 | { |
| 5361 | int ret; | 5365 | int ret; |
| 5362 | int cmp; | 5366 | int cmp; |
| 5363 | struct btrfs_trans_handle *trans = NULL; | ||
| 5364 | struct btrfs_path *left_path = NULL; | 5367 | struct btrfs_path *left_path = NULL; |
| 5365 | struct btrfs_path *right_path = NULL; | 5368 | struct btrfs_path *right_path = NULL; |
| 5366 | struct btrfs_key left_key; | 5369 | struct btrfs_key left_key; |
| @@ -5378,9 +5381,6 @@ int btrfs_compare_trees(struct btrfs_root *left_root, | |||
| 5378 | u64 right_blockptr; | 5381 | u64 right_blockptr; |
| 5379 | u64 left_gen; | 5382 | u64 left_gen; |
| 5380 | u64 right_gen; | 5383 | u64 right_gen; |
| 5381 | u64 left_start_ctransid; | ||
| 5382 | u64 right_start_ctransid; | ||
| 5383 | u64 ctransid; | ||
| 5384 | 5384 | ||
| 5385 | left_path = btrfs_alloc_path(); | 5385 | left_path = btrfs_alloc_path(); |
| 5386 | if (!left_path) { | 5386 | if (!left_path) { |
| @@ -5404,21 +5404,6 @@ int btrfs_compare_trees(struct btrfs_root *left_root, | |||
| 5404 | right_path->search_commit_root = 1; | 5404 | right_path->search_commit_root = 1; |
| 5405 | right_path->skip_locking = 1; | 5405 | right_path->skip_locking = 1; |
| 5406 | 5406 | ||
| 5407 | spin_lock(&left_root->root_item_lock); | ||
| 5408 | left_start_ctransid = btrfs_root_ctransid(&left_root->root_item); | ||
| 5409 | spin_unlock(&left_root->root_item_lock); | ||
| 5410 | |||
| 5411 | spin_lock(&right_root->root_item_lock); | ||
| 5412 | right_start_ctransid = btrfs_root_ctransid(&right_root->root_item); | ||
| 5413 | spin_unlock(&right_root->root_item_lock); | ||
| 5414 | |||
| 5415 | trans = btrfs_join_transaction(left_root); | ||
| 5416 | if (IS_ERR(trans)) { | ||
| 5417 | ret = PTR_ERR(trans); | ||
| 5418 | trans = NULL; | ||
| 5419 | goto out; | ||
| 5420 | } | ||
| 5421 | |||
| 5422 | /* | 5407 | /* |
| 5423 | * Strategy: Go to the first items of both trees. Then do | 5408 | * Strategy: Go to the first items of both trees. Then do |
| 5424 | * | 5409 | * |
| @@ -5455,6 +5440,7 @@ int btrfs_compare_trees(struct btrfs_root *left_root, | |||
| 5455 | * the right if possible or go up and right. | 5440 | * the right if possible or go up and right. |
| 5456 | */ | 5441 | */ |
| 5457 | 5442 | ||
| 5443 | down_read(&left_root->fs_info->commit_root_sem); | ||
| 5458 | left_level = btrfs_header_level(left_root->commit_root); | 5444 | left_level = btrfs_header_level(left_root->commit_root); |
| 5459 | left_root_level = left_level; | 5445 | left_root_level = left_level; |
| 5460 | left_path->nodes[left_level] = left_root->commit_root; | 5446 | left_path->nodes[left_level] = left_root->commit_root; |
| @@ -5464,6 +5450,7 @@ int btrfs_compare_trees(struct btrfs_root *left_root, | |||
| 5464 | right_root_level = right_level; | 5450 | right_root_level = right_level; |
| 5465 | right_path->nodes[right_level] = right_root->commit_root; | 5451 | right_path->nodes[right_level] = right_root->commit_root; |
| 5466 | extent_buffer_get(right_path->nodes[right_level]); | 5452 | extent_buffer_get(right_path->nodes[right_level]); |
| 5453 | up_read(&left_root->fs_info->commit_root_sem); | ||
| 5467 | 5454 | ||
| 5468 | if (left_level == 0) | 5455 | if (left_level == 0) |
| 5469 | btrfs_item_key_to_cpu(left_path->nodes[left_level], | 5456 | btrfs_item_key_to_cpu(left_path->nodes[left_level], |
| @@ -5482,67 +5469,6 @@ int btrfs_compare_trees(struct btrfs_root *left_root, | |||
| 5482 | advance_left = advance_right = 0; | 5469 | advance_left = advance_right = 0; |
| 5483 | 5470 | ||
| 5484 | while (1) { | 5471 | while (1) { |
| 5485 | /* | ||
| 5486 | * We need to make sure the transaction does not get committed | ||
| 5487 | * while we do anything on commit roots. This means, we need to | ||
| 5488 | * join and leave transactions for every item that we process. | ||
| 5489 | */ | ||
| 5490 | if (trans && btrfs_should_end_transaction(trans, left_root)) { | ||
| 5491 | btrfs_release_path(left_path); | ||
| 5492 | btrfs_release_path(right_path); | ||
| 5493 | |||
| 5494 | ret = btrfs_end_transaction(trans, left_root); | ||
| 5495 | trans = NULL; | ||
| 5496 | if (ret < 0) | ||
| 5497 | goto out; | ||
| 5498 | } | ||
| 5499 | /* now rejoin the transaction */ | ||
| 5500 | if (!trans) { | ||
| 5501 | trans = btrfs_join_transaction(left_root); | ||
| 5502 | if (IS_ERR(trans)) { | ||
| 5503 | ret = PTR_ERR(trans); | ||
| 5504 | trans = NULL; | ||
| 5505 | goto out; | ||
| 5506 | } | ||
| 5507 | |||
| 5508 | spin_lock(&left_root->root_item_lock); | ||
| 5509 | ctransid = btrfs_root_ctransid(&left_root->root_item); | ||
| 5510 | spin_unlock(&left_root->root_item_lock); | ||
| 5511 | if (ctransid != left_start_ctransid) | ||
| 5512 | left_start_ctransid = 0; | ||
| 5513 | |||
| 5514 | spin_lock(&right_root->root_item_lock); | ||
| 5515 | ctransid = btrfs_root_ctransid(&right_root->root_item); | ||
| 5516 | spin_unlock(&right_root->root_item_lock); | ||
| 5517 | if (ctransid != right_start_ctransid) | ||
| 5518 | right_start_ctransid = 0; | ||
| 5519 | |||
| 5520 | if (!left_start_ctransid || !right_start_ctransid) { | ||
| 5521 | WARN(1, KERN_WARNING | ||
| 5522 | "BTRFS: btrfs_compare_tree detected " | ||
| 5523 | "a change in one of the trees while " | ||
| 5524 | "iterating. This is probably a " | ||
| 5525 | "bug.\n"); | ||
| 5526 | ret = -EIO; | ||
| 5527 | goto out; | ||
| 5528 | } | ||
| 5529 | |||
| 5530 | /* | ||
| 5531 | * the commit root may have changed, so start again | ||
| 5532 | * where we stopped | ||
| 5533 | */ | ||
| 5534 | left_path->lowest_level = left_level; | ||
| 5535 | right_path->lowest_level = right_level; | ||
| 5536 | ret = btrfs_search_slot(NULL, left_root, | ||
| 5537 | &left_key, left_path, 0, 0); | ||
| 5538 | if (ret < 0) | ||
| 5539 | goto out; | ||
| 5540 | ret = btrfs_search_slot(NULL, right_root, | ||
| 5541 | &right_key, right_path, 0, 0); | ||
| 5542 | if (ret < 0) | ||
| 5543 | goto out; | ||
| 5544 | } | ||
| 5545 | |||
| 5546 | if (advance_left && !left_end_reached) { | 5472 | if (advance_left && !left_end_reached) { |
| 5547 | ret = tree_advance(left_root, left_path, &left_level, | 5473 | ret = tree_advance(left_root, left_path, &left_level, |
| 5548 | left_root_level, | 5474 | left_root_level, |
| @@ -5672,14 +5598,6 @@ out: | |||
| 5672 | btrfs_free_path(left_path); | 5598 | btrfs_free_path(left_path); |
| 5673 | btrfs_free_path(right_path); | 5599 | btrfs_free_path(right_path); |
| 5674 | kfree(tmp_buf); | 5600 | kfree(tmp_buf); |
| 5675 | |||
| 5676 | if (trans) { | ||
| 5677 | if (!ret) | ||
| 5678 | ret = btrfs_end_transaction(trans, left_root); | ||
| 5679 | else | ||
| 5680 | btrfs_end_transaction(trans, left_root); | ||
| 5681 | } | ||
| 5682 | |||
| 5683 | return ret; | 5601 | return ret; |
| 5684 | } | 5602 | } |
| 5685 | 5603 | ||
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index bc96c03dd259..4c48df572bd6 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -609,6 +609,7 @@ struct btrfs_path { | |||
| 609 | unsigned int skip_locking:1; | 609 | unsigned int skip_locking:1; |
| 610 | unsigned int leave_spinning:1; | 610 | unsigned int leave_spinning:1; |
| 611 | unsigned int search_commit_root:1; | 611 | unsigned int search_commit_root:1; |
| 612 | unsigned int need_commit_sem:1; | ||
| 612 | }; | 613 | }; |
| 613 | 614 | ||
| 614 | /* | 615 | /* |
| @@ -986,7 +987,8 @@ struct btrfs_dev_replace_item { | |||
| 986 | #define BTRFS_BLOCK_GROUP_RAID10 (1ULL << 6) | 987 | #define BTRFS_BLOCK_GROUP_RAID10 (1ULL << 6) |
| 987 | #define BTRFS_BLOCK_GROUP_RAID5 (1ULL << 7) | 988 | #define BTRFS_BLOCK_GROUP_RAID5 (1ULL << 7) |
| 988 | #define BTRFS_BLOCK_GROUP_RAID6 (1ULL << 8) | 989 | #define BTRFS_BLOCK_GROUP_RAID6 (1ULL << 8) |
| 989 | #define BTRFS_BLOCK_GROUP_RESERVED BTRFS_AVAIL_ALLOC_BIT_SINGLE | 990 | #define BTRFS_BLOCK_GROUP_RESERVED (BTRFS_AVAIL_ALLOC_BIT_SINGLE | \ |
| 991 | BTRFS_SPACE_INFO_GLOBAL_RSV) | ||
| 990 | 992 | ||
| 991 | enum btrfs_raid_types { | 993 | enum btrfs_raid_types { |
| 992 | BTRFS_RAID_RAID10, | 994 | BTRFS_RAID_RAID10, |
| @@ -1018,6 +1020,12 @@ enum btrfs_raid_types { | |||
| 1018 | */ | 1020 | */ |
| 1019 | #define BTRFS_AVAIL_ALLOC_BIT_SINGLE (1ULL << 48) | 1021 | #define BTRFS_AVAIL_ALLOC_BIT_SINGLE (1ULL << 48) |
| 1020 | 1022 | ||
| 1023 | /* | ||
| 1024 | * A fake block group type that is used to communicate global block reserve | ||
| 1025 | * size to userspace via the SPACE_INFO ioctl. | ||
| 1026 | */ | ||
| 1027 | #define BTRFS_SPACE_INFO_GLOBAL_RSV (1ULL << 49) | ||
| 1028 | |||
| 1021 | #define BTRFS_EXTENDED_PROFILE_MASK (BTRFS_BLOCK_GROUP_PROFILE_MASK | \ | 1029 | #define BTRFS_EXTENDED_PROFILE_MASK (BTRFS_BLOCK_GROUP_PROFILE_MASK | \ |
| 1022 | BTRFS_AVAIL_ALLOC_BIT_SINGLE) | 1030 | BTRFS_AVAIL_ALLOC_BIT_SINGLE) |
| 1023 | 1031 | ||
| @@ -1440,7 +1448,7 @@ struct btrfs_fs_info { | |||
| 1440 | */ | 1448 | */ |
| 1441 | struct mutex ordered_extent_flush_mutex; | 1449 | struct mutex ordered_extent_flush_mutex; |
| 1442 | 1450 | ||
| 1443 | struct rw_semaphore extent_commit_sem; | 1451 | struct rw_semaphore commit_root_sem; |
| 1444 | 1452 | ||
| 1445 | struct rw_semaphore cleanup_work_sem; | 1453 | struct rw_semaphore cleanup_work_sem; |
| 1446 | 1454 | ||
| @@ -1711,7 +1719,6 @@ struct btrfs_root { | |||
| 1711 | struct btrfs_block_rsv *block_rsv; | 1719 | struct btrfs_block_rsv *block_rsv; |
| 1712 | 1720 | ||
| 1713 | /* free ino cache stuff */ | 1721 | /* free ino cache stuff */ |
| 1714 | struct mutex fs_commit_mutex; | ||
| 1715 | struct btrfs_free_space_ctl *free_ino_ctl; | 1722 | struct btrfs_free_space_ctl *free_ino_ctl; |
| 1716 | enum btrfs_caching_type cached; | 1723 | enum btrfs_caching_type cached; |
| 1717 | spinlock_t cache_lock; | 1724 | spinlock_t cache_lock; |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index bd0f752b797b..029d46c2e170 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
| @@ -329,6 +329,8 @@ static int verify_parent_transid(struct extent_io_tree *io_tree, | |||
| 329 | { | 329 | { |
| 330 | struct extent_state *cached_state = NULL; | 330 | struct extent_state *cached_state = NULL; |
| 331 | int ret; | 331 | int ret; |
| 332 | bool need_lock = (current->journal_info == | ||
| 333 | (void *)BTRFS_SEND_TRANS_STUB); | ||
| 332 | 334 | ||
| 333 | if (!parent_transid || btrfs_header_generation(eb) == parent_transid) | 335 | if (!parent_transid || btrfs_header_generation(eb) == parent_transid) |
| 334 | return 0; | 336 | return 0; |
| @@ -336,6 +338,11 @@ static int verify_parent_transid(struct extent_io_tree *io_tree, | |||
| 336 | if (atomic) | 338 | if (atomic) |
| 337 | return -EAGAIN; | 339 | return -EAGAIN; |
| 338 | 340 | ||
| 341 | if (need_lock) { | ||
| 342 | btrfs_tree_read_lock(eb); | ||
| 343 | btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK); | ||
| 344 | } | ||
| 345 | |||
| 339 | lock_extent_bits(io_tree, eb->start, eb->start + eb->len - 1, | 346 | lock_extent_bits(io_tree, eb->start, eb->start + eb->len - 1, |
| 340 | 0, &cached_state); | 347 | 0, &cached_state); |
| 341 | if (extent_buffer_uptodate(eb) && | 348 | if (extent_buffer_uptodate(eb) && |
| @@ -347,10 +354,21 @@ static int verify_parent_transid(struct extent_io_tree *io_tree, | |||
| 347 | "found %llu\n", | 354 | "found %llu\n", |
| 348 | eb->start, parent_transid, btrfs_header_generation(eb)); | 355 | eb->start, parent_transid, btrfs_header_generation(eb)); |
| 349 | ret = 1; | 356 | ret = 1; |
| 350 | clear_extent_buffer_uptodate(eb); | 357 | |
| 358 | /* | ||
| 359 | * Things reading via commit roots that don't have normal protection, | ||
| 360 | * like send, can have a really old block in cache that may point at a | ||
| 361 | * block that has been free'd and re-allocated. So don't clear uptodate | ||
| 362 | * if we find an eb that is under IO (dirty/writeback) because we could | ||
| 363 | * end up reading in the stale data and then writing it back out and | ||
| 364 | * making everybody very sad. | ||
| 365 | */ | ||
| 366 | if (!extent_buffer_under_io(eb)) | ||
| 367 | clear_extent_buffer_uptodate(eb); | ||
| 351 | out: | 368 | out: |
| 352 | unlock_extent_cached(io_tree, eb->start, eb->start + eb->len - 1, | 369 | unlock_extent_cached(io_tree, eb->start, eb->start + eb->len - 1, |
| 353 | &cached_state, GFP_NOFS); | 370 | &cached_state, GFP_NOFS); |
| 371 | btrfs_tree_read_unlock_blocking(eb); | ||
| 354 | return ret; | 372 | return ret; |
| 355 | } | 373 | } |
| 356 | 374 | ||
| @@ -1546,7 +1564,6 @@ int btrfs_init_fs_root(struct btrfs_root *root) | |||
| 1546 | root->subv_writers = writers; | 1564 | root->subv_writers = writers; |
| 1547 | 1565 | ||
| 1548 | btrfs_init_free_ino_ctl(root); | 1566 | btrfs_init_free_ino_ctl(root); |
| 1549 | mutex_init(&root->fs_commit_mutex); | ||
| 1550 | spin_lock_init(&root->cache_lock); | 1567 | spin_lock_init(&root->cache_lock); |
| 1551 | init_waitqueue_head(&root->cache_wait); | 1568 | init_waitqueue_head(&root->cache_wait); |
| 1552 | 1569 | ||
| @@ -2324,7 +2341,7 @@ int open_ctree(struct super_block *sb, | |||
| 2324 | mutex_init(&fs_info->transaction_kthread_mutex); | 2341 | mutex_init(&fs_info->transaction_kthread_mutex); |
| 2325 | mutex_init(&fs_info->cleaner_mutex); | 2342 | mutex_init(&fs_info->cleaner_mutex); |
| 2326 | mutex_init(&fs_info->volume_mutex); | 2343 | mutex_init(&fs_info->volume_mutex); |
| 2327 | init_rwsem(&fs_info->extent_commit_sem); | 2344 | init_rwsem(&fs_info->commit_root_sem); |
| 2328 | init_rwsem(&fs_info->cleanup_work_sem); | 2345 | init_rwsem(&fs_info->cleanup_work_sem); |
| 2329 | init_rwsem(&fs_info->subvol_sem); | 2346 | init_rwsem(&fs_info->subvol_sem); |
| 2330 | sema_init(&fs_info->uuid_tree_rescan_sem, 1); | 2347 | sema_init(&fs_info->uuid_tree_rescan_sem, 1); |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index c6b6a6e3e735..1306487c82cf 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -419,7 +419,7 @@ static noinline void caching_thread(struct btrfs_work *work) | |||
| 419 | again: | 419 | again: |
| 420 | mutex_lock(&caching_ctl->mutex); | 420 | mutex_lock(&caching_ctl->mutex); |
| 421 | /* need to make sure the commit_root doesn't disappear */ | 421 | /* need to make sure the commit_root doesn't disappear */ |
| 422 | down_read(&fs_info->extent_commit_sem); | 422 | down_read(&fs_info->commit_root_sem); |
| 423 | 423 | ||
| 424 | next: | 424 | next: |
| 425 | ret = btrfs_search_slot(NULL, extent_root, &key, path, 0, 0); | 425 | ret = btrfs_search_slot(NULL, extent_root, &key, path, 0, 0); |
| @@ -443,10 +443,10 @@ next: | |||
| 443 | break; | 443 | break; |
| 444 | 444 | ||
| 445 | if (need_resched() || | 445 | if (need_resched() || |
| 446 | rwsem_is_contended(&fs_info->extent_commit_sem)) { | 446 | rwsem_is_contended(&fs_info->commit_root_sem)) { |
| 447 | caching_ctl->progress = last; | 447 | caching_ctl->progress = last; |
| 448 | btrfs_release_path(path); | 448 | btrfs_release_path(path); |
| 449 | up_read(&fs_info->extent_commit_sem); | 449 | up_read(&fs_info->commit_root_sem); |
| 450 | mutex_unlock(&caching_ctl->mutex); | 450 | mutex_unlock(&caching_ctl->mutex); |
| 451 | cond_resched(); | 451 | cond_resched(); |
| 452 | goto again; | 452 | goto again; |
| @@ -513,7 +513,7 @@ next: | |||
| 513 | 513 | ||
| 514 | err: | 514 | err: |
| 515 | btrfs_free_path(path); | 515 | btrfs_free_path(path); |
| 516 | up_read(&fs_info->extent_commit_sem); | 516 | up_read(&fs_info->commit_root_sem); |
| 517 | 517 | ||
| 518 | free_excluded_extents(extent_root, block_group); | 518 | free_excluded_extents(extent_root, block_group); |
| 519 | 519 | ||
| @@ -633,10 +633,10 @@ static int cache_block_group(struct btrfs_block_group_cache *cache, | |||
| 633 | return 0; | 633 | return 0; |
| 634 | } | 634 | } |
| 635 | 635 | ||
| 636 | down_write(&fs_info->extent_commit_sem); | 636 | down_write(&fs_info->commit_root_sem); |
| 637 | atomic_inc(&caching_ctl->count); | 637 | atomic_inc(&caching_ctl->count); |
| 638 | list_add_tail(&caching_ctl->list, &fs_info->caching_block_groups); | 638 | list_add_tail(&caching_ctl->list, &fs_info->caching_block_groups); |
| 639 | up_write(&fs_info->extent_commit_sem); | 639 | up_write(&fs_info->commit_root_sem); |
| 640 | 640 | ||
| 641 | btrfs_get_block_group(cache); | 641 | btrfs_get_block_group(cache); |
| 642 | 642 | ||
| @@ -2444,7 +2444,8 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, | |||
| 2444 | spin_unlock(&locked_ref->lock); | 2444 | spin_unlock(&locked_ref->lock); |
| 2445 | spin_lock(&delayed_refs->lock); | 2445 | spin_lock(&delayed_refs->lock); |
| 2446 | spin_lock(&locked_ref->lock); | 2446 | spin_lock(&locked_ref->lock); |
| 2447 | if (rb_first(&locked_ref->ref_root)) { | 2447 | if (rb_first(&locked_ref->ref_root) || |
| 2448 | locked_ref->extent_op) { | ||
| 2448 | spin_unlock(&locked_ref->lock); | 2449 | spin_unlock(&locked_ref->lock); |
| 2449 | spin_unlock(&delayed_refs->lock); | 2450 | spin_unlock(&delayed_refs->lock); |
| 2450 | continue; | 2451 | continue; |
| @@ -5470,7 +5471,7 @@ void btrfs_prepare_extent_commit(struct btrfs_trans_handle *trans, | |||
| 5470 | struct btrfs_block_group_cache *cache; | 5471 | struct btrfs_block_group_cache *cache; |
| 5471 | struct btrfs_space_info *space_info; | 5472 | struct btrfs_space_info *space_info; |
| 5472 | 5473 | ||
| 5473 | down_write(&fs_info->extent_commit_sem); | 5474 | down_write(&fs_info->commit_root_sem); |
| 5474 | 5475 | ||
| 5475 | list_for_each_entry_safe(caching_ctl, next, | 5476 | list_for_each_entry_safe(caching_ctl, next, |
| 5476 | &fs_info->caching_block_groups, list) { | 5477 | &fs_info->caching_block_groups, list) { |
| @@ -5489,7 +5490,7 @@ void btrfs_prepare_extent_commit(struct btrfs_trans_handle *trans, | |||
| 5489 | else | 5490 | else |
| 5490 | fs_info->pinned_extents = &fs_info->freed_extents[0]; | 5491 | fs_info->pinned_extents = &fs_info->freed_extents[0]; |
| 5491 | 5492 | ||
| 5492 | up_write(&fs_info->extent_commit_sem); | 5493 | up_write(&fs_info->commit_root_sem); |
| 5493 | 5494 | ||
| 5494 | list_for_each_entry_rcu(space_info, &fs_info->space_info, list) | 5495 | list_for_each_entry_rcu(space_info, &fs_info->space_info, list) |
| 5495 | percpu_counter_set(&space_info->total_bytes_pinned, 0); | 5496 | percpu_counter_set(&space_info->total_bytes_pinned, 0); |
| @@ -5744,6 +5745,8 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans, | |||
| 5744 | "unable to find ref byte nr %llu parent %llu root %llu owner %llu offset %llu", | 5745 | "unable to find ref byte nr %llu parent %llu root %llu owner %llu offset %llu", |
| 5745 | bytenr, parent, root_objectid, owner_objectid, | 5746 | bytenr, parent, root_objectid, owner_objectid, |
| 5746 | owner_offset); | 5747 | owner_offset); |
| 5748 | btrfs_abort_transaction(trans, extent_root, ret); | ||
| 5749 | goto out; | ||
| 5747 | } else { | 5750 | } else { |
| 5748 | btrfs_abort_transaction(trans, extent_root, ret); | 5751 | btrfs_abort_transaction(trans, extent_root, ret); |
| 5749 | goto out; | 5752 | goto out; |
| @@ -8255,14 +8258,14 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info) | |||
| 8255 | struct btrfs_caching_control *caching_ctl; | 8258 | struct btrfs_caching_control *caching_ctl; |
| 8256 | struct rb_node *n; | 8259 | struct rb_node *n; |
| 8257 | 8260 | ||
| 8258 | down_write(&info->extent_commit_sem); | 8261 | down_write(&info->commit_root_sem); |
| 8259 | while (!list_empty(&info->caching_block_groups)) { | 8262 | while (!list_empty(&info->caching_block_groups)) { |
| 8260 | caching_ctl = list_entry(info->caching_block_groups.next, | 8263 | caching_ctl = list_entry(info->caching_block_groups.next, |
| 8261 | struct btrfs_caching_control, list); | 8264 | struct btrfs_caching_control, list); |
| 8262 | list_del(&caching_ctl->list); | 8265 | list_del(&caching_ctl->list); |
| 8263 | put_caching_control(caching_ctl); | 8266 | put_caching_control(caching_ctl); |
| 8264 | } | 8267 | } |
| 8265 | up_write(&info->extent_commit_sem); | 8268 | up_write(&info->commit_root_sem); |
| 8266 | 8269 | ||
| 8267 | spin_lock(&info->block_group_cache_lock); | 8270 | spin_lock(&info->block_group_cache_lock); |
| 8268 | while ((n = rb_last(&info->block_group_cache_tree)) != NULL) { | 8271 | while ((n = rb_last(&info->block_group_cache_tree)) != NULL) { |
| @@ -8336,9 +8339,15 @@ static void __link_block_group(struct btrfs_space_info *space_info, | |||
| 8336 | struct btrfs_block_group_cache *cache) | 8339 | struct btrfs_block_group_cache *cache) |
| 8337 | { | 8340 | { |
| 8338 | int index = get_block_group_index(cache); | 8341 | int index = get_block_group_index(cache); |
| 8342 | bool first = false; | ||
| 8339 | 8343 | ||
| 8340 | down_write(&space_info->groups_sem); | 8344 | down_write(&space_info->groups_sem); |
| 8341 | if (list_empty(&space_info->block_groups[index])) { | 8345 | if (list_empty(&space_info->block_groups[index])) |
| 8346 | first = true; | ||
| 8347 | list_add_tail(&cache->list, &space_info->block_groups[index]); | ||
| 8348 | up_write(&space_info->groups_sem); | ||
| 8349 | |||
| 8350 | if (first) { | ||
| 8342 | struct kobject *kobj = &space_info->block_group_kobjs[index]; | 8351 | struct kobject *kobj = &space_info->block_group_kobjs[index]; |
| 8343 | int ret; | 8352 | int ret; |
| 8344 | 8353 | ||
| @@ -8350,8 +8359,6 @@ static void __link_block_group(struct btrfs_space_info *space_info, | |||
| 8350 | kobject_put(&space_info->kobj); | 8359 | kobject_put(&space_info->kobj); |
| 8351 | } | 8360 | } |
| 8352 | } | 8361 | } |
| 8353 | list_add_tail(&cache->list, &space_info->block_groups[index]); | ||
| 8354 | up_write(&space_info->groups_sem); | ||
| 8355 | } | 8362 | } |
| 8356 | 8363 | ||
| 8357 | static struct btrfs_block_group_cache * | 8364 | static struct btrfs_block_group_cache * |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index ae69a00387e7..3955e475ceec 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
| @@ -749,6 +749,7 @@ again: | |||
| 749 | * our range starts | 749 | * our range starts |
| 750 | */ | 750 | */ |
| 751 | node = tree_search(tree, start); | 751 | node = tree_search(tree, start); |
| 752 | process_node: | ||
| 752 | if (!node) | 753 | if (!node) |
| 753 | break; | 754 | break; |
| 754 | 755 | ||
| @@ -769,7 +770,10 @@ again: | |||
| 769 | if (start > end) | 770 | if (start > end) |
| 770 | break; | 771 | break; |
| 771 | 772 | ||
| 772 | cond_resched_lock(&tree->lock); | 773 | if (!cond_resched_lock(&tree->lock)) { |
| 774 | node = rb_next(node); | ||
| 775 | goto process_node; | ||
| 776 | } | ||
| 773 | } | 777 | } |
| 774 | out: | 778 | out: |
| 775 | spin_unlock(&tree->lock); | 779 | spin_unlock(&tree->lock); |
| @@ -4306,7 +4310,7 @@ static void __free_extent_buffer(struct extent_buffer *eb) | |||
| 4306 | kmem_cache_free(extent_buffer_cache, eb); | 4310 | kmem_cache_free(extent_buffer_cache, eb); |
| 4307 | } | 4311 | } |
| 4308 | 4312 | ||
| 4309 | static int extent_buffer_under_io(struct extent_buffer *eb) | 4313 | int extent_buffer_under_io(struct extent_buffer *eb) |
| 4310 | { | 4314 | { |
| 4311 | return (atomic_read(&eb->io_pages) || | 4315 | return (atomic_read(&eb->io_pages) || |
| 4312 | test_bit(EXTENT_BUFFER_WRITEBACK, &eb->bflags) || | 4316 | test_bit(EXTENT_BUFFER_WRITEBACK, &eb->bflags) || |
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index 58b27e5ab521..c488b45237bf 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h | |||
| @@ -320,6 +320,7 @@ int set_extent_buffer_dirty(struct extent_buffer *eb); | |||
| 320 | int set_extent_buffer_uptodate(struct extent_buffer *eb); | 320 | int set_extent_buffer_uptodate(struct extent_buffer *eb); |
| 321 | int clear_extent_buffer_uptodate(struct extent_buffer *eb); | 321 | int clear_extent_buffer_uptodate(struct extent_buffer *eb); |
| 322 | int extent_buffer_uptodate(struct extent_buffer *eb); | 322 | int extent_buffer_uptodate(struct extent_buffer *eb); |
| 323 | int extent_buffer_under_io(struct extent_buffer *eb); | ||
| 323 | int map_private_extent_buffer(struct extent_buffer *eb, unsigned long offset, | 324 | int map_private_extent_buffer(struct extent_buffer *eb, unsigned long offset, |
| 324 | unsigned long min_len, char **map, | 325 | unsigned long min_len, char **map, |
| 325 | unsigned long *map_start, | 326 | unsigned long *map_start, |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index c660527af838..eb742c07e7a4 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
| @@ -425,13 +425,8 @@ static noinline int btrfs_copy_from_user(loff_t pos, int num_pages, | |||
| 425 | struct page *page = prepared_pages[pg]; | 425 | struct page *page = prepared_pages[pg]; |
| 426 | /* | 426 | /* |
| 427 | * Copy data from userspace to the current page | 427 | * Copy data from userspace to the current page |
| 428 | * | ||
| 429 | * Disable pagefault to avoid recursive lock since | ||
| 430 | * the pages are already locked | ||
| 431 | */ | 428 | */ |
| 432 | pagefault_disable(); | ||
| 433 | copied = iov_iter_copy_from_user_atomic(page, i, offset, count); | 429 | copied = iov_iter_copy_from_user_atomic(page, i, offset, count); |
| 434 | pagefault_enable(); | ||
| 435 | 430 | ||
| 436 | /* Flush processor's dcache for this page */ | 431 | /* Flush processor's dcache for this page */ |
| 437 | flush_dcache_page(page); | 432 | flush_dcache_page(page); |
| @@ -1665,7 +1660,7 @@ again: | |||
| 1665 | static ssize_t __btrfs_direct_write(struct kiocb *iocb, | 1660 | static ssize_t __btrfs_direct_write(struct kiocb *iocb, |
| 1666 | const struct iovec *iov, | 1661 | const struct iovec *iov, |
| 1667 | unsigned long nr_segs, loff_t pos, | 1662 | unsigned long nr_segs, loff_t pos, |
| 1668 | loff_t *ppos, size_t count, size_t ocount) | 1663 | size_t count, size_t ocount) |
| 1669 | { | 1664 | { |
| 1670 | struct file *file = iocb->ki_filp; | 1665 | struct file *file = iocb->ki_filp; |
| 1671 | struct iov_iter i; | 1666 | struct iov_iter i; |
| @@ -1674,7 +1669,7 @@ static ssize_t __btrfs_direct_write(struct kiocb *iocb, | |||
| 1674 | loff_t endbyte; | 1669 | loff_t endbyte; |
| 1675 | int err; | 1670 | int err; |
| 1676 | 1671 | ||
| 1677 | written = generic_file_direct_write(iocb, iov, &nr_segs, pos, ppos, | 1672 | written = generic_file_direct_write(iocb, iov, &nr_segs, pos, |
| 1678 | count, ocount); | 1673 | count, ocount); |
| 1679 | 1674 | ||
| 1680 | if (written < 0 || written == count) | 1675 | if (written < 0 || written == count) |
| @@ -1693,7 +1688,7 @@ static ssize_t __btrfs_direct_write(struct kiocb *iocb, | |||
| 1693 | if (err) | 1688 | if (err) |
| 1694 | goto out; | 1689 | goto out; |
| 1695 | written += written_buffered; | 1690 | written += written_buffered; |
| 1696 | *ppos = pos + written_buffered; | 1691 | iocb->ki_pos = pos + written_buffered; |
| 1697 | invalidate_mapping_pages(file->f_mapping, pos >> PAGE_CACHE_SHIFT, | 1692 | invalidate_mapping_pages(file->f_mapping, pos >> PAGE_CACHE_SHIFT, |
| 1698 | endbyte >> PAGE_CACHE_SHIFT); | 1693 | endbyte >> PAGE_CACHE_SHIFT); |
| 1699 | out: | 1694 | out: |
| @@ -1725,8 +1720,8 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
| 1725 | struct file *file = iocb->ki_filp; | 1720 | struct file *file = iocb->ki_filp; |
| 1726 | struct inode *inode = file_inode(file); | 1721 | struct inode *inode = file_inode(file); |
| 1727 | struct btrfs_root *root = BTRFS_I(inode)->root; | 1722 | struct btrfs_root *root = BTRFS_I(inode)->root; |
| 1728 | loff_t *ppos = &iocb->ki_pos; | ||
| 1729 | u64 start_pos; | 1723 | u64 start_pos; |
| 1724 | u64 end_pos; | ||
| 1730 | ssize_t num_written = 0; | 1725 | ssize_t num_written = 0; |
| 1731 | ssize_t err = 0; | 1726 | ssize_t err = 0; |
| 1732 | size_t count, ocount; | 1727 | size_t count, ocount; |
| @@ -1781,7 +1776,9 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
| 1781 | 1776 | ||
| 1782 | start_pos = round_down(pos, root->sectorsize); | 1777 | start_pos = round_down(pos, root->sectorsize); |
| 1783 | if (start_pos > i_size_read(inode)) { | 1778 | if (start_pos > i_size_read(inode)) { |
| 1784 | err = btrfs_cont_expand(inode, i_size_read(inode), start_pos); | 1779 | /* Expand hole size to cover write data, preventing empty gap */ |
| 1780 | end_pos = round_up(pos + iov->iov_len, root->sectorsize); | ||
| 1781 | err = btrfs_cont_expand(inode, i_size_read(inode), end_pos); | ||
| 1785 | if (err) { | 1782 | if (err) { |
| 1786 | mutex_unlock(&inode->i_mutex); | 1783 | mutex_unlock(&inode->i_mutex); |
| 1787 | goto out; | 1784 | goto out; |
| @@ -1793,7 +1790,7 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
| 1793 | 1790 | ||
| 1794 | if (unlikely(file->f_flags & O_DIRECT)) { | 1791 | if (unlikely(file->f_flags & O_DIRECT)) { |
| 1795 | num_written = __btrfs_direct_write(iocb, iov, nr_segs, | 1792 | num_written = __btrfs_direct_write(iocb, iov, nr_segs, |
| 1796 | pos, ppos, count, ocount); | 1793 | pos, count, ocount); |
| 1797 | } else { | 1794 | } else { |
| 1798 | struct iov_iter i; | 1795 | struct iov_iter i; |
| 1799 | 1796 | ||
| @@ -1801,7 +1798,7 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
| 1801 | 1798 | ||
| 1802 | num_written = __btrfs_buffered_write(file, &i, pos); | 1799 | num_written = __btrfs_buffered_write(file, &i, pos); |
| 1803 | if (num_written > 0) | 1800 | if (num_written > 0) |
| 1804 | *ppos = pos + num_written; | 1801 | iocb->ki_pos = pos + num_written; |
| 1805 | } | 1802 | } |
| 1806 | 1803 | ||
| 1807 | mutex_unlock(&inode->i_mutex); | 1804 | mutex_unlock(&inode->i_mutex); |
diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c index ab485e57b6fe..cc8ca193d830 100644 --- a/fs/btrfs/inode-map.c +++ b/fs/btrfs/inode-map.c | |||
| @@ -55,7 +55,7 @@ static int caching_kthread(void *data) | |||
| 55 | key.type = BTRFS_INODE_ITEM_KEY; | 55 | key.type = BTRFS_INODE_ITEM_KEY; |
| 56 | again: | 56 | again: |
| 57 | /* need to make sure the commit_root doesn't disappear */ | 57 | /* need to make sure the commit_root doesn't disappear */ |
| 58 | mutex_lock(&root->fs_commit_mutex); | 58 | down_read(&fs_info->commit_root_sem); |
| 59 | 59 | ||
| 60 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 60 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
| 61 | if (ret < 0) | 61 | if (ret < 0) |
| @@ -88,7 +88,7 @@ again: | |||
| 88 | btrfs_item_key_to_cpu(leaf, &key, 0); | 88 | btrfs_item_key_to_cpu(leaf, &key, 0); |
| 89 | btrfs_release_path(path); | 89 | btrfs_release_path(path); |
| 90 | root->cache_progress = last; | 90 | root->cache_progress = last; |
| 91 | mutex_unlock(&root->fs_commit_mutex); | 91 | up_read(&fs_info->commit_root_sem); |
| 92 | schedule_timeout(1); | 92 | schedule_timeout(1); |
| 93 | goto again; | 93 | goto again; |
| 94 | } else | 94 | } else |
| @@ -127,7 +127,7 @@ next: | |||
| 127 | btrfs_unpin_free_ino(root); | 127 | btrfs_unpin_free_ino(root); |
| 128 | out: | 128 | out: |
| 129 | wake_up(&root->cache_wait); | 129 | wake_up(&root->cache_wait); |
| 130 | mutex_unlock(&root->fs_commit_mutex); | 130 | up_read(&fs_info->commit_root_sem); |
| 131 | 131 | ||
| 132 | btrfs_free_path(path); | 132 | btrfs_free_path(path); |
| 133 | 133 | ||
| @@ -223,11 +223,11 @@ again: | |||
| 223 | * or the caching work is done. | 223 | * or the caching work is done. |
| 224 | */ | 224 | */ |
| 225 | 225 | ||
| 226 | mutex_lock(&root->fs_commit_mutex); | 226 | down_write(&root->fs_info->commit_root_sem); |
| 227 | spin_lock(&root->cache_lock); | 227 | spin_lock(&root->cache_lock); |
| 228 | if (root->cached == BTRFS_CACHE_FINISHED) { | 228 | if (root->cached == BTRFS_CACHE_FINISHED) { |
| 229 | spin_unlock(&root->cache_lock); | 229 | spin_unlock(&root->cache_lock); |
| 230 | mutex_unlock(&root->fs_commit_mutex); | 230 | up_write(&root->fs_info->commit_root_sem); |
| 231 | goto again; | 231 | goto again; |
| 232 | } | 232 | } |
| 233 | spin_unlock(&root->cache_lock); | 233 | spin_unlock(&root->cache_lock); |
| @@ -240,7 +240,7 @@ again: | |||
| 240 | else | 240 | else |
| 241 | __btrfs_add_free_space(pinned, objectid, 1); | 241 | __btrfs_add_free_space(pinned, objectid, 1); |
| 242 | 242 | ||
| 243 | mutex_unlock(&root->fs_commit_mutex); | 243 | up_write(&root->fs_info->commit_root_sem); |
| 244 | } | 244 | } |
| 245 | } | 245 | } |
| 246 | 246 | ||
| @@ -250,7 +250,7 @@ again: | |||
| 250 | * and others will just be dropped, because the commit root we were | 250 | * and others will just be dropped, because the commit root we were |
| 251 | * searching has changed. | 251 | * searching has changed. |
| 252 | * | 252 | * |
| 253 | * Must be called with root->fs_commit_mutex held | 253 | * Must be called with root->fs_info->commit_root_sem held |
| 254 | */ | 254 | */ |
| 255 | void btrfs_unpin_free_ino(struct btrfs_root *root) | 255 | void btrfs_unpin_free_ino(struct btrfs_root *root) |
| 256 | { | 256 | { |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 06e9a4152b14..5f805bc944fa 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -394,6 +394,14 @@ static noinline int compress_file_range(struct inode *inode, | |||
| 394 | (start > 0 || end + 1 < BTRFS_I(inode)->disk_i_size)) | 394 | (start > 0 || end + 1 < BTRFS_I(inode)->disk_i_size)) |
| 395 | btrfs_add_inode_defrag(NULL, inode); | 395 | btrfs_add_inode_defrag(NULL, inode); |
| 396 | 396 | ||
| 397 | /* | ||
| 398 | * skip compression for a small file range(<=blocksize) that | ||
| 399 | * isn't an inline extent, since it dosen't save disk space at all. | ||
| 400 | */ | ||
| 401 | if ((end - start + 1) <= blocksize && | ||
| 402 | (start > 0 || end + 1 < BTRFS_I(inode)->disk_i_size)) | ||
| 403 | goto cleanup_and_bail_uncompressed; | ||
| 404 | |||
| 397 | actual_end = min_t(u64, isize, end + 1); | 405 | actual_end = min_t(u64, isize, end + 1); |
| 398 | again: | 406 | again: |
| 399 | will_compress = 0; | 407 | will_compress = 0; |
| @@ -1271,6 +1279,15 @@ next_slot: | |||
| 1271 | disk_bytenr += cur_offset - found_key.offset; | 1279 | disk_bytenr += cur_offset - found_key.offset; |
| 1272 | num_bytes = min(end + 1, extent_end) - cur_offset; | 1280 | num_bytes = min(end + 1, extent_end) - cur_offset; |
| 1273 | /* | 1281 | /* |
| 1282 | * if there are pending snapshots for this root, | ||
| 1283 | * we fall into common COW way. | ||
| 1284 | */ | ||
| 1285 | if (!nolock) { | ||
| 1286 | err = btrfs_start_nocow_write(root); | ||
| 1287 | if (!err) | ||
| 1288 | goto out_check; | ||
| 1289 | } | ||
| 1290 | /* | ||
| 1274 | * force cow if csum exists in the range. | 1291 | * force cow if csum exists in the range. |
| 1275 | * this ensure that csum for a given extent are | 1292 | * this ensure that csum for a given extent are |
| 1276 | * either valid or do not exist. | 1293 | * either valid or do not exist. |
| @@ -1289,6 +1306,8 @@ next_slot: | |||
| 1289 | out_check: | 1306 | out_check: |
| 1290 | if (extent_end <= start) { | 1307 | if (extent_end <= start) { |
| 1291 | path->slots[0]++; | 1308 | path->slots[0]++; |
| 1309 | if (!nolock && nocow) | ||
| 1310 | btrfs_end_nocow_write(root); | ||
| 1292 | goto next_slot; | 1311 | goto next_slot; |
| 1293 | } | 1312 | } |
| 1294 | if (!nocow) { | 1313 | if (!nocow) { |
| @@ -1306,8 +1325,11 @@ out_check: | |||
| 1306 | ret = cow_file_range(inode, locked_page, | 1325 | ret = cow_file_range(inode, locked_page, |
| 1307 | cow_start, found_key.offset - 1, | 1326 | cow_start, found_key.offset - 1, |
| 1308 | page_started, nr_written, 1); | 1327 | page_started, nr_written, 1); |
| 1309 | if (ret) | 1328 | if (ret) { |
| 1329 | if (!nolock && nocow) | ||
| 1330 | btrfs_end_nocow_write(root); | ||
| 1310 | goto error; | 1331 | goto error; |
| 1332 | } | ||
| 1311 | cow_start = (u64)-1; | 1333 | cow_start = (u64)-1; |
| 1312 | } | 1334 | } |
| 1313 | 1335 | ||
| @@ -1354,8 +1376,11 @@ out_check: | |||
| 1354 | BTRFS_DATA_RELOC_TREE_OBJECTID) { | 1376 | BTRFS_DATA_RELOC_TREE_OBJECTID) { |
| 1355 | ret = btrfs_reloc_clone_csums(inode, cur_offset, | 1377 | ret = btrfs_reloc_clone_csums(inode, cur_offset, |
| 1356 | num_bytes); | 1378 | num_bytes); |
| 1357 | if (ret) | 1379 | if (ret) { |
| 1380 | if (!nolock && nocow) | ||
| 1381 | btrfs_end_nocow_write(root); | ||
| 1358 | goto error; | 1382 | goto error; |
| 1383 | } | ||
| 1359 | } | 1384 | } |
| 1360 | 1385 | ||
| 1361 | extent_clear_unlock_delalloc(inode, cur_offset, | 1386 | extent_clear_unlock_delalloc(inode, cur_offset, |
| @@ -1363,6 +1388,8 @@ out_check: | |||
| 1363 | locked_page, EXTENT_LOCKED | | 1388 | locked_page, EXTENT_LOCKED | |
| 1364 | EXTENT_DELALLOC, PAGE_UNLOCK | | 1389 | EXTENT_DELALLOC, PAGE_UNLOCK | |
| 1365 | PAGE_SET_PRIVATE2); | 1390 | PAGE_SET_PRIVATE2); |
| 1391 | if (!nolock && nocow) | ||
| 1392 | btrfs_end_nocow_write(root); | ||
| 1366 | cur_offset = extent_end; | 1393 | cur_offset = extent_end; |
| 1367 | if (cur_offset > end) | 1394 | if (cur_offset > end) |
| 1368 | break; | 1395 | break; |
| @@ -8476,19 +8503,20 @@ static int __start_delalloc_inodes(struct btrfs_root *root, int delay_iput, | |||
| 8476 | else | 8503 | else |
| 8477 | iput(inode); | 8504 | iput(inode); |
| 8478 | ret = -ENOMEM; | 8505 | ret = -ENOMEM; |
| 8479 | break; | 8506 | goto out; |
| 8480 | } | 8507 | } |
| 8481 | list_add_tail(&work->list, &works); | 8508 | list_add_tail(&work->list, &works); |
| 8482 | btrfs_queue_work(root->fs_info->flush_workers, | 8509 | btrfs_queue_work(root->fs_info->flush_workers, |
| 8483 | &work->work); | 8510 | &work->work); |
| 8484 | ret++; | 8511 | ret++; |
| 8485 | if (nr != -1 && ret >= nr) | 8512 | if (nr != -1 && ret >= nr) |
| 8486 | break; | 8513 | goto out; |
| 8487 | cond_resched(); | 8514 | cond_resched(); |
| 8488 | spin_lock(&root->delalloc_lock); | 8515 | spin_lock(&root->delalloc_lock); |
| 8489 | } | 8516 | } |
| 8490 | spin_unlock(&root->delalloc_lock); | 8517 | spin_unlock(&root->delalloc_lock); |
| 8491 | 8518 | ||
| 8519 | out: | ||
| 8492 | list_for_each_entry_safe(work, next, &works, list) { | 8520 | list_for_each_entry_safe(work, next, &works, list) { |
| 8493 | list_del_init(&work->list); | 8521 | list_del_init(&work->list); |
| 8494 | btrfs_wait_and_free_delalloc_work(work); | 8522 | btrfs_wait_and_free_delalloc_work(work); |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 0401397b5c92..e79ff6b90cb7 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
| @@ -1472,6 +1472,7 @@ static noinline int btrfs_ioctl_resize(struct file *file, | |||
| 1472 | struct btrfs_trans_handle *trans; | 1472 | struct btrfs_trans_handle *trans; |
| 1473 | struct btrfs_device *device = NULL; | 1473 | struct btrfs_device *device = NULL; |
| 1474 | char *sizestr; | 1474 | char *sizestr; |
| 1475 | char *retptr; | ||
| 1475 | char *devstr = NULL; | 1476 | char *devstr = NULL; |
| 1476 | int ret = 0; | 1477 | int ret = 0; |
| 1477 | int mod = 0; | 1478 | int mod = 0; |
| @@ -1539,8 +1540,8 @@ static noinline int btrfs_ioctl_resize(struct file *file, | |||
| 1539 | mod = 1; | 1540 | mod = 1; |
| 1540 | sizestr++; | 1541 | sizestr++; |
| 1541 | } | 1542 | } |
| 1542 | new_size = memparse(sizestr, NULL); | 1543 | new_size = memparse(sizestr, &retptr); |
| 1543 | if (new_size == 0) { | 1544 | if (*retptr != '\0' || new_size == 0) { |
| 1544 | ret = -EINVAL; | 1545 | ret = -EINVAL; |
| 1545 | goto out_free; | 1546 | goto out_free; |
| 1546 | } | 1547 | } |
| @@ -3140,8 +3141,9 @@ process_slot: | |||
| 3140 | new_key.offset + datal, | 3141 | new_key.offset + datal, |
| 3141 | 1); | 3142 | 1); |
| 3142 | if (ret) { | 3143 | if (ret) { |
| 3143 | btrfs_abort_transaction(trans, root, | 3144 | if (ret != -EINVAL) |
| 3144 | ret); | 3145 | btrfs_abort_transaction(trans, |
| 3146 | root, ret); | ||
| 3145 | btrfs_end_transaction(trans, root); | 3147 | btrfs_end_transaction(trans, root); |
| 3146 | goto out; | 3148 | goto out; |
| 3147 | } | 3149 | } |
| @@ -3538,6 +3540,11 @@ static long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg) | |||
| 3538 | up_read(&info->groups_sem); | 3540 | up_read(&info->groups_sem); |
| 3539 | } | 3541 | } |
| 3540 | 3542 | ||
| 3543 | /* | ||
| 3544 | * Global block reserve, exported as a space_info | ||
| 3545 | */ | ||
| 3546 | slot_count++; | ||
| 3547 | |||
| 3541 | /* space_slots == 0 means they are asking for a count */ | 3548 | /* space_slots == 0 means they are asking for a count */ |
| 3542 | if (space_args.space_slots == 0) { | 3549 | if (space_args.space_slots == 0) { |
| 3543 | space_args.total_spaces = slot_count; | 3550 | space_args.total_spaces = slot_count; |
| @@ -3596,6 +3603,21 @@ static long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg) | |||
| 3596 | up_read(&info->groups_sem); | 3603 | up_read(&info->groups_sem); |
| 3597 | } | 3604 | } |
| 3598 | 3605 | ||
| 3606 | /* | ||
| 3607 | * Add global block reserve | ||
| 3608 | */ | ||
| 3609 | if (slot_count) { | ||
| 3610 | struct btrfs_block_rsv *block_rsv = &root->fs_info->global_block_rsv; | ||
| 3611 | |||
| 3612 | spin_lock(&block_rsv->lock); | ||
| 3613 | space.total_bytes = block_rsv->size; | ||
| 3614 | space.used_bytes = block_rsv->size - block_rsv->reserved; | ||
| 3615 | spin_unlock(&block_rsv->lock); | ||
| 3616 | space.flags = BTRFS_SPACE_INFO_GLOBAL_RSV; | ||
| 3617 | memcpy(dest, &space, sizeof(space)); | ||
| 3618 | space_args.total_spaces++; | ||
| 3619 | } | ||
| 3620 | |||
| 3599 | user_dest = (struct btrfs_ioctl_space_info __user *) | 3621 | user_dest = (struct btrfs_ioctl_space_info __user *) |
| 3600 | (arg + sizeof(struct btrfs_ioctl_space_args)); | 3622 | (arg + sizeof(struct btrfs_ioctl_space_args)); |
| 3601 | 3623 | ||
| @@ -4531,9 +4553,8 @@ static long btrfs_ioctl_set_received_subvol_32(struct file *file, | |||
| 4531 | } | 4553 | } |
| 4532 | 4554 | ||
| 4533 | args64 = kmalloc(sizeof(*args64), GFP_NOFS); | 4555 | args64 = kmalloc(sizeof(*args64), GFP_NOFS); |
| 4534 | if (IS_ERR(args64)) { | 4556 | if (!args64) { |
| 4535 | ret = PTR_ERR(args64); | 4557 | ret = -ENOMEM; |
| 4536 | args64 = NULL; | ||
| 4537 | goto out; | 4558 | goto out; |
| 4538 | } | 4559 | } |
| 4539 | 4560 | ||
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index def428a25b2a..7f92ab1daa87 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
| @@ -2317,7 +2317,6 @@ void free_reloc_roots(struct list_head *list) | |||
| 2317 | static noinline_for_stack | 2317 | static noinline_for_stack |
| 2318 | int merge_reloc_roots(struct reloc_control *rc) | 2318 | int merge_reloc_roots(struct reloc_control *rc) |
| 2319 | { | 2319 | { |
| 2320 | struct btrfs_trans_handle *trans; | ||
| 2321 | struct btrfs_root *root; | 2320 | struct btrfs_root *root; |
| 2322 | struct btrfs_root *reloc_root; | 2321 | struct btrfs_root *reloc_root; |
| 2323 | u64 last_snap; | 2322 | u64 last_snap; |
| @@ -2375,26 +2374,6 @@ again: | |||
| 2375 | list_add_tail(&reloc_root->root_list, | 2374 | list_add_tail(&reloc_root->root_list, |
| 2376 | &reloc_roots); | 2375 | &reloc_roots); |
| 2377 | goto out; | 2376 | goto out; |
| 2378 | } else if (!ret) { | ||
| 2379 | /* | ||
| 2380 | * recover the last snapshot tranid to avoid | ||
| 2381 | * the space balance break NOCOW. | ||
| 2382 | */ | ||
| 2383 | root = read_fs_root(rc->extent_root->fs_info, | ||
| 2384 | objectid); | ||
| 2385 | if (IS_ERR(root)) | ||
| 2386 | continue; | ||
| 2387 | |||
| 2388 | trans = btrfs_join_transaction(root); | ||
| 2389 | BUG_ON(IS_ERR(trans)); | ||
| 2390 | |||
| 2391 | /* Check if the fs/file tree was snapshoted or not. */ | ||
| 2392 | if (btrfs_root_last_snapshot(&root->root_item) == | ||
| 2393 | otransid - 1) | ||
| 2394 | btrfs_set_root_last_snapshot(&root->root_item, | ||
| 2395 | last_snap); | ||
| 2396 | |||
| 2397 | btrfs_end_transaction(trans, root); | ||
| 2398 | } | 2377 | } |
| 2399 | } | 2378 | } |
| 2400 | 2379 | ||
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index 93e6d7172844..0be77993378e 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c | |||
| @@ -2235,6 +2235,47 @@ behind_scrub_pages: | |||
| 2235 | return 0; | 2235 | return 0; |
| 2236 | } | 2236 | } |
| 2237 | 2237 | ||
| 2238 | /* | ||
| 2239 | * Given a physical address, this will calculate it's | ||
| 2240 | * logical offset. if this is a parity stripe, it will return | ||
| 2241 | * the most left data stripe's logical offset. | ||
| 2242 | * | ||
| 2243 | * return 0 if it is a data stripe, 1 means parity stripe. | ||
| 2244 | */ | ||
| 2245 | static int get_raid56_logic_offset(u64 physical, int num, | ||
| 2246 | struct map_lookup *map, u64 *offset) | ||
| 2247 | { | ||
| 2248 | int i; | ||
| 2249 | int j = 0; | ||
| 2250 | u64 stripe_nr; | ||
| 2251 | u64 last_offset; | ||
| 2252 | int stripe_index; | ||
| 2253 | int rot; | ||
| 2254 | |||
| 2255 | last_offset = (physical - map->stripes[num].physical) * | ||
| 2256 | nr_data_stripes(map); | ||
| 2257 | *offset = last_offset; | ||
| 2258 | for (i = 0; i < nr_data_stripes(map); i++) { | ||
| 2259 | *offset = last_offset + i * map->stripe_len; | ||
| 2260 | |||
| 2261 | stripe_nr = *offset; | ||
| 2262 | do_div(stripe_nr, map->stripe_len); | ||
| 2263 | do_div(stripe_nr, nr_data_stripes(map)); | ||
| 2264 | |||
| 2265 | /* Work out the disk rotation on this stripe-set */ | ||
| 2266 | rot = do_div(stripe_nr, map->num_stripes); | ||
| 2267 | /* calculate which stripe this data locates */ | ||
| 2268 | rot += i; | ||
| 2269 | stripe_index = rot % map->num_stripes; | ||
| 2270 | if (stripe_index == num) | ||
| 2271 | return 0; | ||
| 2272 | if (stripe_index < num) | ||
| 2273 | j++; | ||
| 2274 | } | ||
| 2275 | *offset = last_offset + j * map->stripe_len; | ||
| 2276 | return 1; | ||
| 2277 | } | ||
| 2278 | |||
| 2238 | static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, | 2279 | static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, |
| 2239 | struct map_lookup *map, | 2280 | struct map_lookup *map, |
| 2240 | struct btrfs_device *scrub_dev, | 2281 | struct btrfs_device *scrub_dev, |
| @@ -2256,6 +2297,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, | |||
| 2256 | u64 physical; | 2297 | u64 physical; |
| 2257 | u64 logical; | 2298 | u64 logical; |
| 2258 | u64 logic_end; | 2299 | u64 logic_end; |
| 2300 | u64 physical_end; | ||
| 2259 | u64 generation; | 2301 | u64 generation; |
| 2260 | int mirror_num; | 2302 | int mirror_num; |
| 2261 | struct reada_control *reada1; | 2303 | struct reada_control *reada1; |
| @@ -2269,16 +2311,10 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, | |||
| 2269 | u64 extent_len; | 2311 | u64 extent_len; |
| 2270 | struct btrfs_device *extent_dev; | 2312 | struct btrfs_device *extent_dev; |
| 2271 | int extent_mirror_num; | 2313 | int extent_mirror_num; |
| 2272 | int stop_loop; | 2314 | int stop_loop = 0; |
| 2273 | |||
| 2274 | if (map->type & (BTRFS_BLOCK_GROUP_RAID5 | | ||
| 2275 | BTRFS_BLOCK_GROUP_RAID6)) { | ||
| 2276 | if (num >= nr_data_stripes(map)) { | ||
| 2277 | return 0; | ||
| 2278 | } | ||
| 2279 | } | ||
| 2280 | 2315 | ||
| 2281 | nstripes = length; | 2316 | nstripes = length; |
| 2317 | physical = map->stripes[num].physical; | ||
| 2282 | offset = 0; | 2318 | offset = 0; |
| 2283 | do_div(nstripes, map->stripe_len); | 2319 | do_div(nstripes, map->stripe_len); |
| 2284 | if (map->type & BTRFS_BLOCK_GROUP_RAID0) { | 2320 | if (map->type & BTRFS_BLOCK_GROUP_RAID0) { |
| @@ -2296,6 +2332,11 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, | |||
| 2296 | } else if (map->type & BTRFS_BLOCK_GROUP_DUP) { | 2332 | } else if (map->type & BTRFS_BLOCK_GROUP_DUP) { |
| 2297 | increment = map->stripe_len; | 2333 | increment = map->stripe_len; |
| 2298 | mirror_num = num % map->num_stripes + 1; | 2334 | mirror_num = num % map->num_stripes + 1; |
| 2335 | } else if (map->type & (BTRFS_BLOCK_GROUP_RAID5 | | ||
| 2336 | BTRFS_BLOCK_GROUP_RAID6)) { | ||
| 2337 | get_raid56_logic_offset(physical, num, map, &offset); | ||
| 2338 | increment = map->stripe_len * nr_data_stripes(map); | ||
| 2339 | mirror_num = 1; | ||
| 2299 | } else { | 2340 | } else { |
| 2300 | increment = map->stripe_len; | 2341 | increment = map->stripe_len; |
| 2301 | mirror_num = 1; | 2342 | mirror_num = 1; |
| @@ -2319,7 +2360,15 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, | |||
| 2319 | * to not hold off transaction commits | 2360 | * to not hold off transaction commits |
| 2320 | */ | 2361 | */ |
| 2321 | logical = base + offset; | 2362 | logical = base + offset; |
| 2322 | 2363 | physical_end = physical + nstripes * map->stripe_len; | |
| 2364 | if (map->type & (BTRFS_BLOCK_GROUP_RAID5 | | ||
| 2365 | BTRFS_BLOCK_GROUP_RAID6)) { | ||
| 2366 | get_raid56_logic_offset(physical_end, num, | ||
| 2367 | map, &logic_end); | ||
| 2368 | logic_end += base; | ||
| 2369 | } else { | ||
| 2370 | logic_end = logical + increment * nstripes; | ||
| 2371 | } | ||
| 2323 | wait_event(sctx->list_wait, | 2372 | wait_event(sctx->list_wait, |
| 2324 | atomic_read(&sctx->bios_in_flight) == 0); | 2373 | atomic_read(&sctx->bios_in_flight) == 0); |
| 2325 | scrub_blocked_if_needed(fs_info); | 2374 | scrub_blocked_if_needed(fs_info); |
| @@ -2328,7 +2377,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, | |||
| 2328 | key_start.objectid = logical; | 2377 | key_start.objectid = logical; |
| 2329 | key_start.type = BTRFS_EXTENT_ITEM_KEY; | 2378 | key_start.type = BTRFS_EXTENT_ITEM_KEY; |
| 2330 | key_start.offset = (u64)0; | 2379 | key_start.offset = (u64)0; |
| 2331 | key_end.objectid = base + offset + nstripes * increment; | 2380 | key_end.objectid = logic_end; |
| 2332 | key_end.type = BTRFS_METADATA_ITEM_KEY; | 2381 | key_end.type = BTRFS_METADATA_ITEM_KEY; |
| 2333 | key_end.offset = (u64)-1; | 2382 | key_end.offset = (u64)-1; |
| 2334 | reada1 = btrfs_reada_add(root, &key_start, &key_end); | 2383 | reada1 = btrfs_reada_add(root, &key_start, &key_end); |
| @@ -2338,7 +2387,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, | |||
| 2338 | key_start.offset = logical; | 2387 | key_start.offset = logical; |
| 2339 | key_end.objectid = BTRFS_EXTENT_CSUM_OBJECTID; | 2388 | key_end.objectid = BTRFS_EXTENT_CSUM_OBJECTID; |
| 2340 | key_end.type = BTRFS_EXTENT_CSUM_KEY; | 2389 | key_end.type = BTRFS_EXTENT_CSUM_KEY; |
| 2341 | key_end.offset = base + offset + nstripes * increment; | 2390 | key_end.offset = logic_end; |
| 2342 | reada2 = btrfs_reada_add(csum_root, &key_start, &key_end); | 2391 | reada2 = btrfs_reada_add(csum_root, &key_start, &key_end); |
| 2343 | 2392 | ||
| 2344 | if (!IS_ERR(reada1)) | 2393 | if (!IS_ERR(reada1)) |
| @@ -2356,11 +2405,17 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, | |||
| 2356 | /* | 2405 | /* |
| 2357 | * now find all extents for each stripe and scrub them | 2406 | * now find all extents for each stripe and scrub them |
| 2358 | */ | 2407 | */ |
| 2359 | logical = base + offset; | ||
| 2360 | physical = map->stripes[num].physical; | ||
| 2361 | logic_end = logical + increment * nstripes; | ||
| 2362 | ret = 0; | 2408 | ret = 0; |
| 2363 | while (logical < logic_end) { | 2409 | while (physical < physical_end) { |
| 2410 | /* for raid56, we skip parity stripe */ | ||
| 2411 | if (map->type & (BTRFS_BLOCK_GROUP_RAID5 | | ||
| 2412 | BTRFS_BLOCK_GROUP_RAID6)) { | ||
| 2413 | ret = get_raid56_logic_offset(physical, num, | ||
| 2414 | map, &logical); | ||
| 2415 | logical += base; | ||
| 2416 | if (ret) | ||
| 2417 | goto skip; | ||
| 2418 | } | ||
| 2364 | /* | 2419 | /* |
| 2365 | * canceled? | 2420 | * canceled? |
| 2366 | */ | 2421 | */ |
| @@ -2504,15 +2559,29 @@ again: | |||
| 2504 | scrub_free_csums(sctx); | 2559 | scrub_free_csums(sctx); |
| 2505 | if (extent_logical + extent_len < | 2560 | if (extent_logical + extent_len < |
| 2506 | key.objectid + bytes) { | 2561 | key.objectid + bytes) { |
| 2507 | logical += increment; | 2562 | if (map->type & (BTRFS_BLOCK_GROUP_RAID5 | |
| 2508 | physical += map->stripe_len; | 2563 | BTRFS_BLOCK_GROUP_RAID6)) { |
| 2509 | 2564 | /* | |
| 2565 | * loop until we find next data stripe | ||
| 2566 | * or we have finished all stripes. | ||
| 2567 | */ | ||
| 2568 | do { | ||
| 2569 | physical += map->stripe_len; | ||
| 2570 | ret = get_raid56_logic_offset( | ||
| 2571 | physical, num, | ||
| 2572 | map, &logical); | ||
| 2573 | logical += base; | ||
| 2574 | } while (physical < physical_end && ret); | ||
| 2575 | } else { | ||
| 2576 | physical += map->stripe_len; | ||
| 2577 | logical += increment; | ||
| 2578 | } | ||
| 2510 | if (logical < key.objectid + bytes) { | 2579 | if (logical < key.objectid + bytes) { |
| 2511 | cond_resched(); | 2580 | cond_resched(); |
| 2512 | goto again; | 2581 | goto again; |
| 2513 | } | 2582 | } |
| 2514 | 2583 | ||
| 2515 | if (logical >= logic_end) { | 2584 | if (physical >= physical_end) { |
| 2516 | stop_loop = 1; | 2585 | stop_loop = 1; |
| 2517 | break; | 2586 | break; |
| 2518 | } | 2587 | } |
| @@ -2521,6 +2590,7 @@ next: | |||
| 2521 | path->slots[0]++; | 2590 | path->slots[0]++; |
| 2522 | } | 2591 | } |
| 2523 | btrfs_release_path(path); | 2592 | btrfs_release_path(path); |
| 2593 | skip: | ||
| 2524 | logical += increment; | 2594 | logical += increment; |
| 2525 | physical += map->stripe_len; | 2595 | physical += map->stripe_len; |
| 2526 | spin_lock(&sctx->stat_lock); | 2596 | spin_lock(&sctx->stat_lock); |
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index 9b6da9d55f9a..1ac3ca98c429 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c | |||
| @@ -493,6 +493,7 @@ static struct btrfs_path *alloc_path_for_send(void) | |||
| 493 | return NULL; | 493 | return NULL; |
| 494 | path->search_commit_root = 1; | 494 | path->search_commit_root = 1; |
| 495 | path->skip_locking = 1; | 495 | path->skip_locking = 1; |
| 496 | path->need_commit_sem = 1; | ||
| 496 | return path; | 497 | return path; |
| 497 | } | 498 | } |
| 498 | 499 | ||
| @@ -771,29 +772,22 @@ out: | |||
| 771 | /* | 772 | /* |
| 772 | * Helper function to retrieve some fields from an inode item. | 773 | * Helper function to retrieve some fields from an inode item. |
| 773 | */ | 774 | */ |
| 774 | static int get_inode_info(struct btrfs_root *root, | 775 | static int __get_inode_info(struct btrfs_root *root, struct btrfs_path *path, |
| 775 | u64 ino, u64 *size, u64 *gen, | 776 | u64 ino, u64 *size, u64 *gen, u64 *mode, u64 *uid, |
| 776 | u64 *mode, u64 *uid, u64 *gid, | 777 | u64 *gid, u64 *rdev) |
| 777 | u64 *rdev) | ||
| 778 | { | 778 | { |
| 779 | int ret; | 779 | int ret; |
| 780 | struct btrfs_inode_item *ii; | 780 | struct btrfs_inode_item *ii; |
| 781 | struct btrfs_key key; | 781 | struct btrfs_key key; |
| 782 | struct btrfs_path *path; | ||
| 783 | |||
| 784 | path = alloc_path_for_send(); | ||
| 785 | if (!path) | ||
| 786 | return -ENOMEM; | ||
| 787 | 782 | ||
| 788 | key.objectid = ino; | 783 | key.objectid = ino; |
| 789 | key.type = BTRFS_INODE_ITEM_KEY; | 784 | key.type = BTRFS_INODE_ITEM_KEY; |
| 790 | key.offset = 0; | 785 | key.offset = 0; |
| 791 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 786 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
| 792 | if (ret < 0) | ||
| 793 | goto out; | ||
| 794 | if (ret) { | 787 | if (ret) { |
| 795 | ret = -ENOENT; | 788 | if (ret > 0) |
| 796 | goto out; | 789 | ret = -ENOENT; |
| 790 | return ret; | ||
| 797 | } | 791 | } |
| 798 | 792 | ||
| 799 | ii = btrfs_item_ptr(path->nodes[0], path->slots[0], | 793 | ii = btrfs_item_ptr(path->nodes[0], path->slots[0], |
| @@ -811,7 +805,22 @@ static int get_inode_info(struct btrfs_root *root, | |||
| 811 | if (rdev) | 805 | if (rdev) |
| 812 | *rdev = btrfs_inode_rdev(path->nodes[0], ii); | 806 | *rdev = btrfs_inode_rdev(path->nodes[0], ii); |
| 813 | 807 | ||
| 814 | out: | 808 | return ret; |
| 809 | } | ||
| 810 | |||
| 811 | static int get_inode_info(struct btrfs_root *root, | ||
| 812 | u64 ino, u64 *size, u64 *gen, | ||
| 813 | u64 *mode, u64 *uid, u64 *gid, | ||
| 814 | u64 *rdev) | ||
| 815 | { | ||
| 816 | struct btrfs_path *path; | ||
| 817 | int ret; | ||
| 818 | |||
| 819 | path = alloc_path_for_send(); | ||
| 820 | if (!path) | ||
| 821 | return -ENOMEM; | ||
| 822 | ret = __get_inode_info(root, path, ino, size, gen, mode, uid, gid, | ||
| 823 | rdev); | ||
| 815 | btrfs_free_path(path); | 824 | btrfs_free_path(path); |
| 816 | return ret; | 825 | return ret; |
| 817 | } | 826 | } |
| @@ -1085,6 +1094,7 @@ out: | |||
| 1085 | struct backref_ctx { | 1094 | struct backref_ctx { |
| 1086 | struct send_ctx *sctx; | 1095 | struct send_ctx *sctx; |
| 1087 | 1096 | ||
| 1097 | struct btrfs_path *path; | ||
| 1088 | /* number of total found references */ | 1098 | /* number of total found references */ |
| 1089 | u64 found; | 1099 | u64 found; |
| 1090 | 1100 | ||
| @@ -1155,8 +1165,9 @@ static int __iterate_backrefs(u64 ino, u64 offset, u64 root, void *ctx_) | |||
| 1155 | * There are inodes that have extents that lie behind its i_size. Don't | 1165 | * There are inodes that have extents that lie behind its i_size. Don't |
| 1156 | * accept clones from these extents. | 1166 | * accept clones from these extents. |
| 1157 | */ | 1167 | */ |
| 1158 | ret = get_inode_info(found->root, ino, &i_size, NULL, NULL, NULL, NULL, | 1168 | ret = __get_inode_info(found->root, bctx->path, ino, &i_size, NULL, NULL, |
| 1159 | NULL); | 1169 | NULL, NULL, NULL); |
| 1170 | btrfs_release_path(bctx->path); | ||
| 1160 | if (ret < 0) | 1171 | if (ret < 0) |
| 1161 | return ret; | 1172 | return ret; |
| 1162 | 1173 | ||
| @@ -1235,12 +1246,17 @@ static int find_extent_clone(struct send_ctx *sctx, | |||
| 1235 | if (!tmp_path) | 1246 | if (!tmp_path) |
| 1236 | return -ENOMEM; | 1247 | return -ENOMEM; |
| 1237 | 1248 | ||
| 1249 | /* We only use this path under the commit sem */ | ||
| 1250 | tmp_path->need_commit_sem = 0; | ||
| 1251 | |||
| 1238 | backref_ctx = kmalloc(sizeof(*backref_ctx), GFP_NOFS); | 1252 | backref_ctx = kmalloc(sizeof(*backref_ctx), GFP_NOFS); |
| 1239 | if (!backref_ctx) { | 1253 | if (!backref_ctx) { |
| 1240 | ret = -ENOMEM; | 1254 | ret = -ENOMEM; |
| 1241 | goto out; | 1255 | goto out; |
| 1242 | } | 1256 | } |
| 1243 | 1257 | ||
| 1258 | backref_ctx->path = tmp_path; | ||
| 1259 | |||
| 1244 | if (data_offset >= ino_size) { | 1260 | if (data_offset >= ino_size) { |
| 1245 | /* | 1261 | /* |
| 1246 | * There may be extents that lie behind the file's size. | 1262 | * There may be extents that lie behind the file's size. |
| @@ -1268,8 +1284,10 @@ static int find_extent_clone(struct send_ctx *sctx, | |||
| 1268 | } | 1284 | } |
| 1269 | logical = disk_byte + btrfs_file_extent_offset(eb, fi); | 1285 | logical = disk_byte + btrfs_file_extent_offset(eb, fi); |
| 1270 | 1286 | ||
| 1287 | down_read(&sctx->send_root->fs_info->commit_root_sem); | ||
| 1271 | ret = extent_from_logical(sctx->send_root->fs_info, disk_byte, tmp_path, | 1288 | ret = extent_from_logical(sctx->send_root->fs_info, disk_byte, tmp_path, |
| 1272 | &found_key, &flags); | 1289 | &found_key, &flags); |
| 1290 | up_read(&sctx->send_root->fs_info->commit_root_sem); | ||
| 1273 | btrfs_release_path(tmp_path); | 1291 | btrfs_release_path(tmp_path); |
| 1274 | 1292 | ||
| 1275 | if (ret < 0) | 1293 | if (ret < 0) |
| @@ -4418,6 +4436,9 @@ static int send_hole(struct send_ctx *sctx, u64 end) | |||
| 4418 | p = fs_path_alloc(); | 4436 | p = fs_path_alloc(); |
| 4419 | if (!p) | 4437 | if (!p) |
| 4420 | return -ENOMEM; | 4438 | return -ENOMEM; |
| 4439 | ret = get_cur_path(sctx, sctx->cur_ino, sctx->cur_inode_gen, p); | ||
| 4440 | if (ret < 0) | ||
| 4441 | goto tlv_put_failure; | ||
| 4421 | memset(sctx->read_buf, 0, BTRFS_SEND_READ_SIZE); | 4442 | memset(sctx->read_buf, 0, BTRFS_SEND_READ_SIZE); |
| 4422 | while (offset < end) { | 4443 | while (offset < end) { |
| 4423 | len = min_t(u64, end - offset, BTRFS_SEND_READ_SIZE); | 4444 | len = min_t(u64, end - offset, BTRFS_SEND_READ_SIZE); |
| @@ -4425,9 +4446,6 @@ static int send_hole(struct send_ctx *sctx, u64 end) | |||
| 4425 | ret = begin_cmd(sctx, BTRFS_SEND_C_WRITE); | 4446 | ret = begin_cmd(sctx, BTRFS_SEND_C_WRITE); |
| 4426 | if (ret < 0) | 4447 | if (ret < 0) |
| 4427 | break; | 4448 | break; |
| 4428 | ret = get_cur_path(sctx, sctx->cur_ino, sctx->cur_inode_gen, p); | ||
| 4429 | if (ret < 0) | ||
| 4430 | break; | ||
| 4431 | TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, p); | 4449 | TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, p); |
| 4432 | TLV_PUT_U64(sctx, BTRFS_SEND_A_FILE_OFFSET, offset); | 4450 | TLV_PUT_U64(sctx, BTRFS_SEND_A_FILE_OFFSET, offset); |
| 4433 | TLV_PUT(sctx, BTRFS_SEND_A_DATA, sctx->read_buf, len); | 4451 | TLV_PUT(sctx, BTRFS_SEND_A_DATA, sctx->read_buf, len); |
| @@ -4968,7 +4986,9 @@ static int finish_inode_if_needed(struct send_ctx *sctx, int at_end) | |||
| 4968 | 4986 | ||
| 4969 | if (S_ISREG(sctx->cur_inode_mode)) { | 4987 | if (S_ISREG(sctx->cur_inode_mode)) { |
| 4970 | if (need_send_hole(sctx)) { | 4988 | if (need_send_hole(sctx)) { |
| 4971 | if (sctx->cur_inode_last_extent == (u64)-1) { | 4989 | if (sctx->cur_inode_last_extent == (u64)-1 || |
| 4990 | sctx->cur_inode_last_extent < | ||
| 4991 | sctx->cur_inode_size) { | ||
| 4972 | ret = get_last_extent(sctx, (u64)-1); | 4992 | ret = get_last_extent(sctx, (u64)-1); |
| 4973 | if (ret) | 4993 | if (ret) |
| 4974 | goto out; | 4994 | goto out; |
| @@ -5367,57 +5387,21 @@ out: | |||
| 5367 | static int full_send_tree(struct send_ctx *sctx) | 5387 | static int full_send_tree(struct send_ctx *sctx) |
| 5368 | { | 5388 | { |
| 5369 | int ret; | 5389 | int ret; |
| 5370 | struct btrfs_trans_handle *trans = NULL; | ||
| 5371 | struct btrfs_root *send_root = sctx->send_root; | 5390 | struct btrfs_root *send_root = sctx->send_root; |
| 5372 | struct btrfs_key key; | 5391 | struct btrfs_key key; |
| 5373 | struct btrfs_key found_key; | 5392 | struct btrfs_key found_key; |
| 5374 | struct btrfs_path *path; | 5393 | struct btrfs_path *path; |
| 5375 | struct extent_buffer *eb; | 5394 | struct extent_buffer *eb; |
| 5376 | int slot; | 5395 | int slot; |
| 5377 | u64 start_ctransid; | ||
| 5378 | u64 ctransid; | ||
| 5379 | 5396 | ||
| 5380 | path = alloc_path_for_send(); | 5397 | path = alloc_path_for_send(); |
| 5381 | if (!path) | 5398 | if (!path) |
| 5382 | return -ENOMEM; | 5399 | return -ENOMEM; |
| 5383 | 5400 | ||
| 5384 | spin_lock(&send_root->root_item_lock); | ||
| 5385 | start_ctransid = btrfs_root_ctransid(&send_root->root_item); | ||
| 5386 | spin_unlock(&send_root->root_item_lock); | ||
| 5387 | |||
| 5388 | key.objectid = BTRFS_FIRST_FREE_OBJECTID; | 5401 | key.objectid = BTRFS_FIRST_FREE_OBJECTID; |
| 5389 | key.type = BTRFS_INODE_ITEM_KEY; | 5402 | key.type = BTRFS_INODE_ITEM_KEY; |
| 5390 | key.offset = 0; | 5403 | key.offset = 0; |
| 5391 | 5404 | ||
| 5392 | join_trans: | ||
| 5393 | /* | ||
| 5394 | * We need to make sure the transaction does not get committed | ||
| 5395 | * while we do anything on commit roots. Join a transaction to prevent | ||
| 5396 | * this. | ||
| 5397 | */ | ||
| 5398 | trans = btrfs_join_transaction(send_root); | ||
| 5399 | if (IS_ERR(trans)) { | ||
| 5400 | ret = PTR_ERR(trans); | ||
| 5401 | trans = NULL; | ||
| 5402 | goto out; | ||
| 5403 | } | ||
| 5404 | |||
| 5405 | /* | ||
| 5406 | * Make sure the tree has not changed after re-joining. We detect this | ||
| 5407 | * by comparing start_ctransid and ctransid. They should always match. | ||
| 5408 | */ | ||
| 5409 | spin_lock(&send_root->root_item_lock); | ||
| 5410 | ctransid = btrfs_root_ctransid(&send_root->root_item); | ||
| 5411 | spin_unlock(&send_root->root_item_lock); | ||
| 5412 | |||
| 5413 | if (ctransid != start_ctransid) { | ||
| 5414 | WARN(1, KERN_WARNING "BTRFS: the root that you're trying to " | ||
| 5415 | "send was modified in between. This is " | ||
| 5416 | "probably a bug.\n"); | ||
| 5417 | ret = -EIO; | ||
| 5418 | goto out; | ||
| 5419 | } | ||
| 5420 | |||
| 5421 | ret = btrfs_search_slot_for_read(send_root, &key, path, 1, 0); | 5405 | ret = btrfs_search_slot_for_read(send_root, &key, path, 1, 0); |
| 5422 | if (ret < 0) | 5406 | if (ret < 0) |
| 5423 | goto out; | 5407 | goto out; |
| @@ -5425,19 +5409,6 @@ join_trans: | |||
| 5425 | goto out_finish; | 5409 | goto out_finish; |
| 5426 | 5410 | ||
| 5427 | while (1) { | 5411 | while (1) { |
| 5428 | /* | ||
| 5429 | * When someone want to commit while we iterate, end the | ||
| 5430 | * joined transaction and rejoin. | ||
| 5431 | */ | ||
| 5432 | if (btrfs_should_end_transaction(trans, send_root)) { | ||
| 5433 | ret = btrfs_end_transaction(trans, send_root); | ||
| 5434 | trans = NULL; | ||
| 5435 | if (ret < 0) | ||
| 5436 | goto out; | ||
| 5437 | btrfs_release_path(path); | ||
| 5438 | goto join_trans; | ||
| 5439 | } | ||
| 5440 | |||
| 5441 | eb = path->nodes[0]; | 5412 | eb = path->nodes[0]; |
| 5442 | slot = path->slots[0]; | 5413 | slot = path->slots[0]; |
| 5443 | btrfs_item_key_to_cpu(eb, &found_key, slot); | 5414 | btrfs_item_key_to_cpu(eb, &found_key, slot); |
| @@ -5465,12 +5436,6 @@ out_finish: | |||
| 5465 | 5436 | ||
| 5466 | out: | 5437 | out: |
| 5467 | btrfs_free_path(path); | 5438 | btrfs_free_path(path); |
| 5468 | if (trans) { | ||
| 5469 | if (!ret) | ||
| 5470 | ret = btrfs_end_transaction(trans, send_root); | ||
| 5471 | else | ||
| 5472 | btrfs_end_transaction(trans, send_root); | ||
| 5473 | } | ||
| 5474 | return ret; | 5439 | return ret; |
| 5475 | } | 5440 | } |
| 5476 | 5441 | ||
| @@ -5718,7 +5683,9 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_) | |||
| 5718 | NULL); | 5683 | NULL); |
| 5719 | sort_clone_roots = 1; | 5684 | sort_clone_roots = 1; |
| 5720 | 5685 | ||
| 5686 | current->journal_info = (void *)BTRFS_SEND_TRANS_STUB; | ||
| 5721 | ret = send_subvol(sctx); | 5687 | ret = send_subvol(sctx); |
| 5688 | current->journal_info = NULL; | ||
| 5722 | if (ret < 0) | 5689 | if (ret < 0) |
| 5723 | goto out; | 5690 | goto out; |
| 5724 | 5691 | ||
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 9dbf42395153..5011aadacab8 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
| @@ -66,6 +66,8 @@ | |||
| 66 | static const struct super_operations btrfs_super_ops; | 66 | static const struct super_operations btrfs_super_ops; |
| 67 | static struct file_system_type btrfs_fs_type; | 67 | static struct file_system_type btrfs_fs_type; |
| 68 | 68 | ||
| 69 | static int btrfs_remount(struct super_block *sb, int *flags, char *data); | ||
| 70 | |||
| 69 | static const char *btrfs_decode_error(int errno) | 71 | static const char *btrfs_decode_error(int errno) |
| 70 | { | 72 | { |
| 71 | char *errstr = "unknown"; | 73 | char *errstr = "unknown"; |
| @@ -1185,6 +1187,26 @@ static struct dentry *mount_subvol(const char *subvol_name, int flags, | |||
| 1185 | mnt = vfs_kern_mount(&btrfs_fs_type, flags, device_name, | 1187 | mnt = vfs_kern_mount(&btrfs_fs_type, flags, device_name, |
| 1186 | newargs); | 1188 | newargs); |
| 1187 | kfree(newargs); | 1189 | kfree(newargs); |
| 1190 | |||
| 1191 | if (PTR_RET(mnt) == -EBUSY) { | ||
| 1192 | if (flags & MS_RDONLY) { | ||
| 1193 | mnt = vfs_kern_mount(&btrfs_fs_type, flags & ~MS_RDONLY, device_name, | ||
| 1194 | newargs); | ||
| 1195 | } else { | ||
| 1196 | int r; | ||
| 1197 | mnt = vfs_kern_mount(&btrfs_fs_type, flags | MS_RDONLY, device_name, | ||
| 1198 | newargs); | ||
| 1199 | if (IS_ERR(mnt)) | ||
| 1200 | return ERR_CAST(mnt); | ||
| 1201 | |||
| 1202 | r = btrfs_remount(mnt->mnt_sb, &flags, NULL); | ||
| 1203 | if (r < 0) { | ||
| 1204 | /* FIXME: release vfsmount mnt ??*/ | ||
| 1205 | return ERR_PTR(r); | ||
| 1206 | } | ||
| 1207 | } | ||
| 1208 | } | ||
| 1209 | |||
| 1188 | if (IS_ERR(mnt)) | 1210 | if (IS_ERR(mnt)) |
| 1189 | return ERR_CAST(mnt); | 1211 | return ERR_CAST(mnt); |
| 1190 | 1212 | ||
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index a04707f740d6..7579f6d0b854 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
| @@ -75,10 +75,21 @@ void btrfs_put_transaction(struct btrfs_transaction *transaction) | |||
| 75 | } | 75 | } |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | static noinline void switch_commit_root(struct btrfs_root *root) | 78 | static noinline void switch_commit_roots(struct btrfs_transaction *trans, |
| 79 | struct btrfs_fs_info *fs_info) | ||
| 79 | { | 80 | { |
| 80 | free_extent_buffer(root->commit_root); | 81 | struct btrfs_root *root, *tmp; |
| 81 | root->commit_root = btrfs_root_node(root); | 82 | |
| 83 | down_write(&fs_info->commit_root_sem); | ||
| 84 | list_for_each_entry_safe(root, tmp, &trans->switch_commits, | ||
| 85 | dirty_list) { | ||
| 86 | list_del_init(&root->dirty_list); | ||
| 87 | free_extent_buffer(root->commit_root); | ||
| 88 | root->commit_root = btrfs_root_node(root); | ||
| 89 | if (is_fstree(root->objectid)) | ||
| 90 | btrfs_unpin_free_ino(root); | ||
| 91 | } | ||
| 92 | up_write(&fs_info->commit_root_sem); | ||
| 82 | } | 93 | } |
| 83 | 94 | ||
| 84 | static inline void extwriter_counter_inc(struct btrfs_transaction *trans, | 95 | static inline void extwriter_counter_inc(struct btrfs_transaction *trans, |
| @@ -208,6 +219,7 @@ loop: | |||
| 208 | INIT_LIST_HEAD(&cur_trans->pending_snapshots); | 219 | INIT_LIST_HEAD(&cur_trans->pending_snapshots); |
| 209 | INIT_LIST_HEAD(&cur_trans->ordered_operations); | 220 | INIT_LIST_HEAD(&cur_trans->ordered_operations); |
| 210 | INIT_LIST_HEAD(&cur_trans->pending_chunks); | 221 | INIT_LIST_HEAD(&cur_trans->pending_chunks); |
| 222 | INIT_LIST_HEAD(&cur_trans->switch_commits); | ||
| 211 | list_add_tail(&cur_trans->list, &fs_info->trans_list); | 223 | list_add_tail(&cur_trans->list, &fs_info->trans_list); |
| 212 | extent_io_tree_init(&cur_trans->dirty_pages, | 224 | extent_io_tree_init(&cur_trans->dirty_pages, |
| 213 | fs_info->btree_inode->i_mapping); | 225 | fs_info->btree_inode->i_mapping); |
| @@ -375,7 +387,8 @@ start_transaction(struct btrfs_root *root, u64 num_items, unsigned int type, | |||
| 375 | if (test_bit(BTRFS_FS_STATE_ERROR, &root->fs_info->fs_state)) | 387 | if (test_bit(BTRFS_FS_STATE_ERROR, &root->fs_info->fs_state)) |
| 376 | return ERR_PTR(-EROFS); | 388 | return ERR_PTR(-EROFS); |
| 377 | 389 | ||
| 378 | if (current->journal_info) { | 390 | if (current->journal_info && |
| 391 | current->journal_info != (void *)BTRFS_SEND_TRANS_STUB) { | ||
| 379 | WARN_ON(type & TRANS_EXTWRITERS); | 392 | WARN_ON(type & TRANS_EXTWRITERS); |
| 380 | h = current->journal_info; | 393 | h = current->journal_info; |
| 381 | h->use_count++; | 394 | h->use_count++; |
| @@ -919,9 +932,6 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans, | |||
| 919 | return ret; | 932 | return ret; |
| 920 | } | 933 | } |
| 921 | 934 | ||
| 922 | if (root != root->fs_info->extent_root) | ||
| 923 | switch_commit_root(root); | ||
| 924 | |||
| 925 | return 0; | 935 | return 0; |
| 926 | } | 936 | } |
| 927 | 937 | ||
| @@ -977,15 +987,16 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans, | |||
| 977 | list_del_init(next); | 987 | list_del_init(next); |
| 978 | root = list_entry(next, struct btrfs_root, dirty_list); | 988 | root = list_entry(next, struct btrfs_root, dirty_list); |
| 979 | 989 | ||
| 990 | if (root != fs_info->extent_root) | ||
| 991 | list_add_tail(&root->dirty_list, | ||
| 992 | &trans->transaction->switch_commits); | ||
| 980 | ret = update_cowonly_root(trans, root); | 993 | ret = update_cowonly_root(trans, root); |
| 981 | if (ret) | 994 | if (ret) |
| 982 | return ret; | 995 | return ret; |
| 983 | } | 996 | } |
| 984 | 997 | ||
| 985 | down_write(&fs_info->extent_commit_sem); | 998 | list_add_tail(&fs_info->extent_root->dirty_list, |
| 986 | switch_commit_root(fs_info->extent_root); | 999 | &trans->transaction->switch_commits); |
| 987 | up_write(&fs_info->extent_commit_sem); | ||
| 988 | |||
| 989 | btrfs_after_dev_replace_commit(fs_info); | 1000 | btrfs_after_dev_replace_commit(fs_info); |
| 990 | 1001 | ||
| 991 | return 0; | 1002 | return 0; |
| @@ -1042,11 +1053,8 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans, | |||
| 1042 | smp_wmb(); | 1053 | smp_wmb(); |
| 1043 | 1054 | ||
| 1044 | if (root->commit_root != root->node) { | 1055 | if (root->commit_root != root->node) { |
| 1045 | mutex_lock(&root->fs_commit_mutex); | 1056 | list_add_tail(&root->dirty_list, |
| 1046 | switch_commit_root(root); | 1057 | &trans->transaction->switch_commits); |
| 1047 | btrfs_unpin_free_ino(root); | ||
| 1048 | mutex_unlock(&root->fs_commit_mutex); | ||
| 1049 | |||
| 1050 | btrfs_set_root_node(&root->root_item, | 1058 | btrfs_set_root_node(&root->root_item, |
| 1051 | root->node); | 1059 | root->node); |
| 1052 | } | 1060 | } |
| @@ -1857,11 +1865,15 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
| 1857 | 1865 | ||
| 1858 | btrfs_set_root_node(&root->fs_info->tree_root->root_item, | 1866 | btrfs_set_root_node(&root->fs_info->tree_root->root_item, |
| 1859 | root->fs_info->tree_root->node); | 1867 | root->fs_info->tree_root->node); |
| 1860 | switch_commit_root(root->fs_info->tree_root); | 1868 | list_add_tail(&root->fs_info->tree_root->dirty_list, |
| 1869 | &cur_trans->switch_commits); | ||
| 1861 | 1870 | ||
| 1862 | btrfs_set_root_node(&root->fs_info->chunk_root->root_item, | 1871 | btrfs_set_root_node(&root->fs_info->chunk_root->root_item, |
| 1863 | root->fs_info->chunk_root->node); | 1872 | root->fs_info->chunk_root->node); |
| 1864 | switch_commit_root(root->fs_info->chunk_root); | 1873 | list_add_tail(&root->fs_info->chunk_root->dirty_list, |
| 1874 | &cur_trans->switch_commits); | ||
| 1875 | |||
| 1876 | switch_commit_roots(cur_trans, root->fs_info); | ||
| 1865 | 1877 | ||
| 1866 | assert_qgroups_uptodate(trans); | 1878 | assert_qgroups_uptodate(trans); |
| 1867 | update_super_roots(root); | 1879 | update_super_roots(root); |
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h index 6ac037e9f9f0..b57b924e8e03 100644 --- a/fs/btrfs/transaction.h +++ b/fs/btrfs/transaction.h | |||
| @@ -57,6 +57,7 @@ struct btrfs_transaction { | |||
| 57 | struct list_head pending_snapshots; | 57 | struct list_head pending_snapshots; |
| 58 | struct list_head ordered_operations; | 58 | struct list_head ordered_operations; |
| 59 | struct list_head pending_chunks; | 59 | struct list_head pending_chunks; |
| 60 | struct list_head switch_commits; | ||
| 60 | struct btrfs_delayed_ref_root delayed_refs; | 61 | struct btrfs_delayed_ref_root delayed_refs; |
| 61 | int aborted; | 62 | int aborted; |
| 62 | }; | 63 | }; |
| @@ -78,6 +79,8 @@ struct btrfs_transaction { | |||
| 78 | #define TRANS_EXTWRITERS (__TRANS_USERSPACE | __TRANS_START | \ | 79 | #define TRANS_EXTWRITERS (__TRANS_USERSPACE | __TRANS_START | \ |
| 79 | __TRANS_ATTACH) | 80 | __TRANS_ATTACH) |
| 80 | 81 | ||
| 82 | #define BTRFS_SEND_TRANS_STUB 1 | ||
| 83 | |||
| 81 | struct btrfs_trans_handle { | 84 | struct btrfs_trans_handle { |
| 82 | u64 transid; | 85 | u64 transid; |
| 83 | u64 bytes_reserved; | 86 | u64 bytes_reserved; |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index d241130a32fd..49d7fab73360 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
| @@ -448,6 +448,14 @@ static void pending_bios_fn(struct btrfs_work *work) | |||
| 448 | run_scheduled_bios(device); | 448 | run_scheduled_bios(device); |
| 449 | } | 449 | } |
| 450 | 450 | ||
| 451 | /* | ||
| 452 | * Add new device to list of registered devices | ||
| 453 | * | ||
| 454 | * Returns: | ||
| 455 | * 1 - first time device is seen | ||
| 456 | * 0 - device already known | ||
| 457 | * < 0 - error | ||
| 458 | */ | ||
| 451 | static noinline int device_list_add(const char *path, | 459 | static noinline int device_list_add(const char *path, |
| 452 | struct btrfs_super_block *disk_super, | 460 | struct btrfs_super_block *disk_super, |
| 453 | u64 devid, struct btrfs_fs_devices **fs_devices_ret) | 461 | u64 devid, struct btrfs_fs_devices **fs_devices_ret) |
| @@ -455,6 +463,7 @@ static noinline int device_list_add(const char *path, | |||
| 455 | struct btrfs_device *device; | 463 | struct btrfs_device *device; |
| 456 | struct btrfs_fs_devices *fs_devices; | 464 | struct btrfs_fs_devices *fs_devices; |
| 457 | struct rcu_string *name; | 465 | struct rcu_string *name; |
| 466 | int ret = 0; | ||
| 458 | u64 found_transid = btrfs_super_generation(disk_super); | 467 | u64 found_transid = btrfs_super_generation(disk_super); |
| 459 | 468 | ||
| 460 | fs_devices = find_fsid(disk_super->fsid); | 469 | fs_devices = find_fsid(disk_super->fsid); |
| @@ -495,6 +504,7 @@ static noinline int device_list_add(const char *path, | |||
| 495 | fs_devices->num_devices++; | 504 | fs_devices->num_devices++; |
| 496 | mutex_unlock(&fs_devices->device_list_mutex); | 505 | mutex_unlock(&fs_devices->device_list_mutex); |
| 497 | 506 | ||
| 507 | ret = 1; | ||
| 498 | device->fs_devices = fs_devices; | 508 | device->fs_devices = fs_devices; |
| 499 | } else if (!device->name || strcmp(device->name->str, path)) { | 509 | } else if (!device->name || strcmp(device->name->str, path)) { |
| 500 | name = rcu_string_strdup(path, GFP_NOFS); | 510 | name = rcu_string_strdup(path, GFP_NOFS); |
| @@ -513,7 +523,8 @@ static noinline int device_list_add(const char *path, | |||
| 513 | fs_devices->latest_trans = found_transid; | 523 | fs_devices->latest_trans = found_transid; |
| 514 | } | 524 | } |
| 515 | *fs_devices_ret = fs_devices; | 525 | *fs_devices_ret = fs_devices; |
| 516 | return 0; | 526 | |
| 527 | return ret; | ||
| 517 | } | 528 | } |
| 518 | 529 | ||
| 519 | static struct btrfs_fs_devices *clone_fs_devices(struct btrfs_fs_devices *orig) | 530 | static struct btrfs_fs_devices *clone_fs_devices(struct btrfs_fs_devices *orig) |
| @@ -910,17 +921,19 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder, | |||
| 910 | transid = btrfs_super_generation(disk_super); | 921 | transid = btrfs_super_generation(disk_super); |
| 911 | total_devices = btrfs_super_num_devices(disk_super); | 922 | total_devices = btrfs_super_num_devices(disk_super); |
| 912 | 923 | ||
| 913 | if (disk_super->label[0]) { | ||
| 914 | if (disk_super->label[BTRFS_LABEL_SIZE - 1]) | ||
| 915 | disk_super->label[BTRFS_LABEL_SIZE - 1] = '\0'; | ||
| 916 | printk(KERN_INFO "BTRFS: device label %s ", disk_super->label); | ||
| 917 | } else { | ||
| 918 | printk(KERN_INFO "BTRFS: device fsid %pU ", disk_super->fsid); | ||
| 919 | } | ||
| 920 | |||
| 921 | printk(KERN_CONT "devid %llu transid %llu %s\n", devid, transid, path); | ||
| 922 | |||
| 923 | ret = device_list_add(path, disk_super, devid, fs_devices_ret); | 924 | ret = device_list_add(path, disk_super, devid, fs_devices_ret); |
| 925 | if (ret > 0) { | ||
| 926 | if (disk_super->label[0]) { | ||
| 927 | if (disk_super->label[BTRFS_LABEL_SIZE - 1]) | ||
| 928 | disk_super->label[BTRFS_LABEL_SIZE - 1] = '\0'; | ||
| 929 | printk(KERN_INFO "BTRFS: device label %s ", disk_super->label); | ||
| 930 | } else { | ||
| 931 | printk(KERN_INFO "BTRFS: device fsid %pU ", disk_super->fsid); | ||
| 932 | } | ||
| 933 | |||
| 934 | printk(KERN_CONT "devid %llu transid %llu %s\n", devid, transid, path); | ||
| 935 | ret = 0; | ||
| 936 | } | ||
| 924 | if (!ret && fs_devices_ret) | 937 | if (!ret && fs_devices_ret) |
| 925 | (*fs_devices_ret)->total_devices = total_devices; | 938 | (*fs_devices_ret)->total_devices = total_devices; |
| 926 | 939 | ||
