diff options
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/ctree.c | 39 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 2 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 53 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 2 | ||||
-rw-r--r-- | fs/btrfs/ioctl.c | 4 | ||||
-rw-r--r-- | fs/btrfs/super.c | 16 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 1 |
7 files changed, 93 insertions, 24 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index a99f1c2a710d..fedf8b9f03a2 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -1469,6 +1469,7 @@ read_block_for_search(struct btrfs_trans_handle *trans, | |||
1469 | u32 blocksize; | 1469 | u32 blocksize; |
1470 | struct extent_buffer *b = *eb_ret; | 1470 | struct extent_buffer *b = *eb_ret; |
1471 | struct extent_buffer *tmp; | 1471 | struct extent_buffer *tmp; |
1472 | int ret; | ||
1472 | 1473 | ||
1473 | blocknr = btrfs_node_blockptr(b, slot); | 1474 | blocknr = btrfs_node_blockptr(b, slot); |
1474 | gen = btrfs_node_ptr_generation(b, slot); | 1475 | gen = btrfs_node_ptr_generation(b, slot); |
@@ -1476,6 +1477,10 @@ read_block_for_search(struct btrfs_trans_handle *trans, | |||
1476 | 1477 | ||
1477 | tmp = btrfs_find_tree_block(root, blocknr, blocksize); | 1478 | tmp = btrfs_find_tree_block(root, blocknr, blocksize); |
1478 | if (tmp && btrfs_buffer_uptodate(tmp, gen)) { | 1479 | if (tmp && btrfs_buffer_uptodate(tmp, gen)) { |
1480 | /* | ||
1481 | * we found an up to date block without sleeping, return | ||
1482 | * right away | ||
1483 | */ | ||
1479 | *eb_ret = tmp; | 1484 | *eb_ret = tmp; |
1480 | return 0; | 1485 | return 0; |
1481 | } | 1486 | } |
@@ -1483,7 +1488,9 @@ read_block_for_search(struct btrfs_trans_handle *trans, | |||
1483 | /* | 1488 | /* |
1484 | * reduce lock contention at high levels | 1489 | * reduce lock contention at high levels |
1485 | * of the btree by dropping locks before | 1490 | * of the btree by dropping locks before |
1486 | * we read. | 1491 | * we read. Don't release the lock on the current |
1492 | * level because we need to walk this node to figure | ||
1493 | * out which blocks to read. | ||
1487 | */ | 1494 | */ |
1488 | btrfs_unlock_up_safe(p, level + 1); | 1495 | btrfs_unlock_up_safe(p, level + 1); |
1489 | btrfs_set_path_blocking(p); | 1496 | btrfs_set_path_blocking(p); |
@@ -1494,10 +1501,21 @@ read_block_for_search(struct btrfs_trans_handle *trans, | |||
1494 | reada_for_search(root, p, level, slot, key->objectid); | 1501 | reada_for_search(root, p, level, slot, key->objectid); |
1495 | 1502 | ||
1496 | btrfs_release_path(NULL, p); | 1503 | btrfs_release_path(NULL, p); |
1504 | |||
1505 | ret = -EAGAIN; | ||
1497 | tmp = read_tree_block(root, blocknr, blocksize, gen); | 1506 | tmp = read_tree_block(root, blocknr, blocksize, gen); |
1498 | if (tmp) | 1507 | if (tmp) { |
1508 | /* | ||
1509 | * If the read above didn't mark this buffer up to date, | ||
1510 | * it will never end up being up to date. Set ret to EIO now | ||
1511 | * and give up so that our caller doesn't loop forever | ||
1512 | * on our EAGAINs. | ||
1513 | */ | ||
1514 | if (!btrfs_buffer_uptodate(tmp, 0)) | ||
1515 | ret = -EIO; | ||
1499 | free_extent_buffer(tmp); | 1516 | free_extent_buffer(tmp); |
1500 | return -EAGAIN; | 1517 | } |
1518 | return ret; | ||
1501 | } | 1519 | } |
1502 | 1520 | ||
1503 | /* | 1521 | /* |
@@ -1696,6 +1714,9 @@ cow_done: | |||
1696 | if (ret == -EAGAIN) | 1714 | if (ret == -EAGAIN) |
1697 | goto again; | 1715 | goto again; |
1698 | 1716 | ||
1717 | if (ret == -EIO) | ||
1718 | goto done; | ||
1719 | |||
1699 | if (!p->skip_locking) { | 1720 | if (!p->skip_locking) { |
1700 | int lret; | 1721 | int lret; |
1701 | 1722 | ||
@@ -1738,6 +1759,8 @@ done: | |||
1738 | */ | 1759 | */ |
1739 | if (!p->leave_spinning) | 1760 | if (!p->leave_spinning) |
1740 | btrfs_set_path_blocking(p); | 1761 | btrfs_set_path_blocking(p); |
1762 | if (ret < 0) | ||
1763 | btrfs_release_path(root, p); | ||
1741 | return ret; | 1764 | return ret; |
1742 | } | 1765 | } |
1743 | 1766 | ||
@@ -4212,6 +4235,11 @@ again: | |||
4212 | if (ret == -EAGAIN) | 4235 | if (ret == -EAGAIN) |
4213 | goto again; | 4236 | goto again; |
4214 | 4237 | ||
4238 | if (ret < 0) { | ||
4239 | btrfs_release_path(root, path); | ||
4240 | goto done; | ||
4241 | } | ||
4242 | |||
4215 | if (!path->skip_locking) { | 4243 | if (!path->skip_locking) { |
4216 | ret = btrfs_try_spin_lock(next); | 4244 | ret = btrfs_try_spin_lock(next); |
4217 | if (!ret) { | 4245 | if (!ret) { |
@@ -4246,6 +4274,11 @@ again: | |||
4246 | if (ret == -EAGAIN) | 4274 | if (ret == -EAGAIN) |
4247 | goto again; | 4275 | goto again; |
4248 | 4276 | ||
4277 | if (ret < 0) { | ||
4278 | btrfs_release_path(root, path); | ||
4279 | goto done; | ||
4280 | } | ||
4281 | |||
4249 | if (!path->skip_locking) { | 4282 | if (!path->skip_locking) { |
4250 | btrfs_assert_tree_locked(path->nodes[level]); | 4283 | btrfs_assert_tree_locked(path->nodes[level]); |
4251 | ret = btrfs_try_spin_lock(next); | 4284 | ret = btrfs_try_spin_lock(next); |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 0ff16d3331da..4b0ea0b80c23 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -848,8 +848,6 @@ struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr, | |||
848 | 848 | ||
849 | if (ret == 0) | 849 | if (ret == 0) |
850 | set_bit(EXTENT_BUFFER_UPTODATE, &buf->bflags); | 850 | set_bit(EXTENT_BUFFER_UPTODATE, &buf->bflags); |
851 | else | ||
852 | WARN_ON(1); | ||
853 | return buf; | 851 | return buf; |
854 | 852 | ||
855 | } | 853 | } |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index e4966444811b..35af93355063 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -312,7 +312,7 @@ btrfs_lookup_first_block_group(struct btrfs_fs_info *info, u64 bytenr) | |||
312 | } | 312 | } |
313 | 313 | ||
314 | /* | 314 | /* |
315 | * return the block group that contains teh given bytenr | 315 | * return the block group that contains the given bytenr |
316 | */ | 316 | */ |
317 | struct btrfs_block_group_cache *btrfs_lookup_block_group( | 317 | struct btrfs_block_group_cache *btrfs_lookup_block_group( |
318 | struct btrfs_fs_info *info, | 318 | struct btrfs_fs_info *info, |
@@ -2622,7 +2622,18 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans, | |||
2622 | search_start); | 2622 | search_start); |
2623 | if (block_group && block_group_bits(block_group, data)) { | 2623 | if (block_group && block_group_bits(block_group, data)) { |
2624 | down_read(&space_info->groups_sem); | 2624 | down_read(&space_info->groups_sem); |
2625 | goto have_block_group; | 2625 | if (list_empty(&block_group->list) || |
2626 | block_group->ro) { | ||
2627 | /* | ||
2628 | * someone is removing this block group, | ||
2629 | * we can't jump into the have_block_group | ||
2630 | * target because our list pointers are not | ||
2631 | * valid | ||
2632 | */ | ||
2633 | btrfs_put_block_group(block_group); | ||
2634 | up_read(&space_info->groups_sem); | ||
2635 | } else | ||
2636 | goto have_block_group; | ||
2626 | } else if (block_group) { | 2637 | } else if (block_group) { |
2627 | btrfs_put_block_group(block_group); | 2638 | btrfs_put_block_group(block_group); |
2628 | } | 2639 | } |
@@ -2656,6 +2667,13 @@ have_block_group: | |||
2656 | * people trying to start a new cluster | 2667 | * people trying to start a new cluster |
2657 | */ | 2668 | */ |
2658 | spin_lock(&last_ptr->refill_lock); | 2669 | spin_lock(&last_ptr->refill_lock); |
2670 | if (last_ptr->block_group && | ||
2671 | (last_ptr->block_group->ro || | ||
2672 | !block_group_bits(last_ptr->block_group, data))) { | ||
2673 | offset = 0; | ||
2674 | goto refill_cluster; | ||
2675 | } | ||
2676 | |||
2659 | offset = btrfs_alloc_from_cluster(block_group, last_ptr, | 2677 | offset = btrfs_alloc_from_cluster(block_group, last_ptr, |
2660 | num_bytes, search_start); | 2678 | num_bytes, search_start); |
2661 | if (offset) { | 2679 | if (offset) { |
@@ -2681,10 +2699,17 @@ have_block_group: | |||
2681 | 2699 | ||
2682 | last_ptr_loop = 1; | 2700 | last_ptr_loop = 1; |
2683 | search_start = block_group->key.objectid; | 2701 | search_start = block_group->key.objectid; |
2702 | /* | ||
2703 | * we know this block group is properly | ||
2704 | * in the list because | ||
2705 | * btrfs_remove_block_group, drops the | ||
2706 | * cluster before it removes the block | ||
2707 | * group from the list | ||
2708 | */ | ||
2684 | goto have_block_group; | 2709 | goto have_block_group; |
2685 | } | 2710 | } |
2686 | spin_unlock(&last_ptr->lock); | 2711 | spin_unlock(&last_ptr->lock); |
2687 | 2712 | refill_cluster: | |
2688 | /* | 2713 | /* |
2689 | * this cluster didn't work out, free it and | 2714 | * this cluster didn't work out, free it and |
2690 | * start over | 2715 | * start over |
@@ -5968,6 +5993,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, | |||
5968 | { | 5993 | { |
5969 | struct btrfs_path *path; | 5994 | struct btrfs_path *path; |
5970 | struct btrfs_block_group_cache *block_group; | 5995 | struct btrfs_block_group_cache *block_group; |
5996 | struct btrfs_free_cluster *cluster; | ||
5971 | struct btrfs_key key; | 5997 | struct btrfs_key key; |
5972 | int ret; | 5998 | int ret; |
5973 | 5999 | ||
@@ -5979,6 +6005,21 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, | |||
5979 | 6005 | ||
5980 | memcpy(&key, &block_group->key, sizeof(key)); | 6006 | memcpy(&key, &block_group->key, sizeof(key)); |
5981 | 6007 | ||
6008 | /* make sure this block group isn't part of an allocation cluster */ | ||
6009 | cluster = &root->fs_info->data_alloc_cluster; | ||
6010 | spin_lock(&cluster->refill_lock); | ||
6011 | btrfs_return_cluster_to_free_space(block_group, cluster); | ||
6012 | spin_unlock(&cluster->refill_lock); | ||
6013 | |||
6014 | /* | ||
6015 | * make sure this block group isn't part of a metadata | ||
6016 | * allocation cluster | ||
6017 | */ | ||
6018 | cluster = &root->fs_info->meta_alloc_cluster; | ||
6019 | spin_lock(&cluster->refill_lock); | ||
6020 | btrfs_return_cluster_to_free_space(block_group, cluster); | ||
6021 | spin_unlock(&cluster->refill_lock); | ||
6022 | |||
5982 | path = btrfs_alloc_path(); | 6023 | path = btrfs_alloc_path(); |
5983 | BUG_ON(!path); | 6024 | BUG_ON(!path); |
5984 | 6025 | ||
@@ -5988,7 +6029,11 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, | |||
5988 | spin_unlock(&root->fs_info->block_group_cache_lock); | 6029 | spin_unlock(&root->fs_info->block_group_cache_lock); |
5989 | btrfs_remove_free_space_cache(block_group); | 6030 | btrfs_remove_free_space_cache(block_group); |
5990 | down_write(&block_group->space_info->groups_sem); | 6031 | down_write(&block_group->space_info->groups_sem); |
5991 | list_del(&block_group->list); | 6032 | /* |
6033 | * we must use list_del_init so people can check to see if they | ||
6034 | * are still on the list after taking the semaphore | ||
6035 | */ | ||
6036 | list_del_init(&block_group->list); | ||
5992 | up_write(&block_group->space_info->groups_sem); | 6037 | up_write(&block_group->space_info->groups_sem); |
5993 | 6038 | ||
5994 | spin_lock(&block_group->space_info->lock); | 6039 | spin_lock(&block_group->space_info->lock); |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 90c23eb28829..1c8b0190d031 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -3122,6 +3122,7 @@ static noinline void init_btrfs_i(struct inode *inode) | |||
3122 | bi->flags = 0; | 3122 | bi->flags = 0; |
3123 | bi->index_cnt = (u64)-1; | 3123 | bi->index_cnt = (u64)-1; |
3124 | bi->last_unlink_trans = 0; | 3124 | bi->last_unlink_trans = 0; |
3125 | bi->ordered_data_close = 0; | ||
3125 | extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS); | 3126 | extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS); |
3126 | extent_io_tree_init(&BTRFS_I(inode)->io_tree, | 3127 | extent_io_tree_init(&BTRFS_I(inode)->io_tree, |
3127 | inode->i_mapping, GFP_NOFS); | 3128 | inode->i_mapping, GFP_NOFS); |
@@ -4295,7 +4296,6 @@ out: | |||
4295 | } | 4296 | } |
4296 | if (err) { | 4297 | if (err) { |
4297 | free_extent_map(em); | 4298 | free_extent_map(em); |
4298 | WARN_ON(1); | ||
4299 | return ERR_PTR(err); | 4299 | return ERR_PTR(err); |
4300 | } | 4300 | } |
4301 | return em; | 4301 | return em; |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 5e94ea6e1cbe..2624b53ea783 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -437,10 +437,6 @@ out_unlock: | |||
437 | return 0; | 437 | return 0; |
438 | } | 438 | } |
439 | 439 | ||
440 | /* | ||
441 | * Called inside transaction, so use GFP_NOFS | ||
442 | */ | ||
443 | |||
444 | static int btrfs_ioctl_resize(struct btrfs_root *root, void __user *arg) | 440 | static int btrfs_ioctl_resize(struct btrfs_root *root, void __user *arg) |
445 | { | 441 | { |
446 | u64 new_size; | 442 | u64 new_size; |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 3536bdb2d7cb..2ff7cd2db25f 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -436,9 +436,9 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
436 | if (btrfs_test_opt(root, SSD)) | 436 | if (btrfs_test_opt(root, SSD)) |
437 | seq_puts(seq, ",ssd"); | 437 | seq_puts(seq, ",ssd"); |
438 | if (btrfs_test_opt(root, NOTREELOG)) | 438 | if (btrfs_test_opt(root, NOTREELOG)) |
439 | seq_puts(seq, ",no-treelog"); | 439 | seq_puts(seq, ",notreelog"); |
440 | if (btrfs_test_opt(root, FLUSHONCOMMIT)) | 440 | if (btrfs_test_opt(root, FLUSHONCOMMIT)) |
441 | seq_puts(seq, ",flush-on-commit"); | 441 | seq_puts(seq, ",flushoncommit"); |
442 | if (!(root->fs_info->sb->s_flags & MS_POSIXACL)) | 442 | if (!(root->fs_info->sb->s_flags & MS_POSIXACL)) |
443 | seq_puts(seq, ",noacl"); | 443 | seq_puts(seq, ",noacl"); |
444 | return 0; | 444 | return 0; |
@@ -502,8 +502,7 @@ static int btrfs_get_sb(struct file_system_type *fs_type, int flags, | |||
502 | 502 | ||
503 | if (s->s_root) { | 503 | if (s->s_root) { |
504 | if ((flags ^ s->s_flags) & MS_RDONLY) { | 504 | if ((flags ^ s->s_flags) & MS_RDONLY) { |
505 | up_write(&s->s_umount); | 505 | deactivate_locked_super(s); |
506 | deactivate_super(s); | ||
507 | error = -EBUSY; | 506 | error = -EBUSY; |
508 | goto error_close_devices; | 507 | goto error_close_devices; |
509 | } | 508 | } |
@@ -517,8 +516,7 @@ static int btrfs_get_sb(struct file_system_type *fs_type, int flags, | |||
517 | error = btrfs_fill_super(s, fs_devices, data, | 516 | error = btrfs_fill_super(s, fs_devices, data, |
518 | flags & MS_SILENT ? 1 : 0); | 517 | flags & MS_SILENT ? 1 : 0); |
519 | if (error) { | 518 | if (error) { |
520 | up_write(&s->s_umount); | 519 | deactivate_locked_super(s); |
521 | deactivate_super(s); | ||
522 | goto error_free_subvol_name; | 520 | goto error_free_subvol_name; |
523 | } | 521 | } |
524 | 522 | ||
@@ -535,15 +533,13 @@ static int btrfs_get_sb(struct file_system_type *fs_type, int flags, | |||
535 | mutex_unlock(&s->s_root->d_inode->i_mutex); | 533 | mutex_unlock(&s->s_root->d_inode->i_mutex); |
536 | 534 | ||
537 | if (IS_ERR(root)) { | 535 | if (IS_ERR(root)) { |
538 | up_write(&s->s_umount); | 536 | deactivate_locked_super(s); |
539 | deactivate_super(s); | ||
540 | error = PTR_ERR(root); | 537 | error = PTR_ERR(root); |
541 | goto error_free_subvol_name; | 538 | goto error_free_subvol_name; |
542 | } | 539 | } |
543 | if (!root->d_inode) { | 540 | if (!root->d_inode) { |
544 | dput(root); | 541 | dput(root); |
545 | up_write(&s->s_umount); | 542 | deactivate_locked_super(s); |
546 | deactivate_super(s); | ||
547 | error = -ENXIO; | 543 | error = -ENXIO; |
548 | goto error_free_subvol_name; | 544 | goto error_free_subvol_name; |
549 | } | 545 | } |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 5f01dad4b696..a6d35b0054ca 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -1440,6 +1440,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) | |||
1440 | device->io_align = root->sectorsize; | 1440 | device->io_align = root->sectorsize; |
1441 | device->sector_size = root->sectorsize; | 1441 | device->sector_size = root->sectorsize; |
1442 | device->total_bytes = i_size_read(bdev->bd_inode); | 1442 | device->total_bytes = i_size_read(bdev->bd_inode); |
1443 | device->disk_total_bytes = device->total_bytes; | ||
1443 | device->dev_root = root->fs_info->dev_root; | 1444 | device->dev_root = root->fs_info->dev_root; |
1444 | device->bdev = bdev; | 1445 | device->bdev = bdev; |
1445 | device->in_fs_metadata = 1; | 1446 | device->in_fs_metadata = 1; |