diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /fs/btrfs/disk-io.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r-- | fs/btrfs/disk-io.c | 84 |
1 files changed, 51 insertions, 33 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 02b6afbd7450..feca04197d02 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/kthread.h> | 27 | #include <linux/kthread.h> |
28 | #include <linux/freezer.h> | 28 | #include <linux/freezer.h> |
29 | #include <linux/crc32c.h> | 29 | #include <linux/crc32c.h> |
30 | #include <linux/slab.h> | ||
30 | #include "compat.h" | 31 | #include "compat.h" |
31 | #include "ctree.h" | 32 | #include "ctree.h" |
32 | #include "disk-io.h" | 33 | #include "disk-io.h" |
@@ -43,8 +44,6 @@ static struct extent_io_ops btree_extent_io_ops; | |||
43 | static void end_workqueue_fn(struct btrfs_work *work); | 44 | static void end_workqueue_fn(struct btrfs_work *work); |
44 | static void free_fs_root(struct btrfs_root *root); | 45 | static void free_fs_root(struct btrfs_root *root); |
45 | 46 | ||
46 | static atomic_t btrfs_bdi_num = ATOMIC_INIT(0); | ||
47 | |||
48 | /* | 47 | /* |
49 | * end_io_wq structs are used to do processing in task context when an IO is | 48 | * end_io_wq structs are used to do processing in task context when an IO is |
50 | * complete. This is used during reads to verify checksums, and it is used | 49 | * complete. This is used during reads to verify checksums, and it is used |
@@ -263,13 +262,15 @@ static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf, | |||
263 | static int verify_parent_transid(struct extent_io_tree *io_tree, | 262 | static int verify_parent_transid(struct extent_io_tree *io_tree, |
264 | struct extent_buffer *eb, u64 parent_transid) | 263 | struct extent_buffer *eb, u64 parent_transid) |
265 | { | 264 | { |
265 | struct extent_state *cached_state = NULL; | ||
266 | int ret; | 266 | int ret; |
267 | 267 | ||
268 | if (!parent_transid || btrfs_header_generation(eb) == parent_transid) | 268 | if (!parent_transid || btrfs_header_generation(eb) == parent_transid) |
269 | return 0; | 269 | return 0; |
270 | 270 | ||
271 | lock_extent(io_tree, eb->start, eb->start + eb->len - 1, GFP_NOFS); | 271 | lock_extent_bits(io_tree, eb->start, eb->start + eb->len - 1, |
272 | if (extent_buffer_uptodate(io_tree, eb) && | 272 | 0, &cached_state, GFP_NOFS); |
273 | if (extent_buffer_uptodate(io_tree, eb, cached_state) && | ||
273 | btrfs_header_generation(eb) == parent_transid) { | 274 | btrfs_header_generation(eb) == parent_transid) { |
274 | ret = 0; | 275 | ret = 0; |
275 | goto out; | 276 | goto out; |
@@ -282,10 +283,10 @@ static int verify_parent_transid(struct extent_io_tree *io_tree, | |||
282 | (unsigned long long)btrfs_header_generation(eb)); | 283 | (unsigned long long)btrfs_header_generation(eb)); |
283 | } | 284 | } |
284 | ret = 1; | 285 | ret = 1; |
285 | clear_extent_buffer_uptodate(io_tree, eb); | 286 | clear_extent_buffer_uptodate(io_tree, eb, &cached_state); |
286 | out: | 287 | out: |
287 | unlock_extent(io_tree, eb->start, eb->start + eb->len - 1, | 288 | unlock_extent_cached(io_tree, eb->start, eb->start + eb->len - 1, |
288 | GFP_NOFS); | 289 | &cached_state, GFP_NOFS); |
289 | return ret; | 290 | return ret; |
290 | } | 291 | } |
291 | 292 | ||
@@ -892,6 +893,8 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, | |||
892 | root->stripesize = stripesize; | 893 | root->stripesize = stripesize; |
893 | root->ref_cows = 0; | 894 | root->ref_cows = 0; |
894 | root->track_dirty = 0; | 895 | root->track_dirty = 0; |
896 | root->in_radix = 0; | ||
897 | root->clean_orphans = 0; | ||
895 | 898 | ||
896 | root->fs_info = fs_info; | 899 | root->fs_info = fs_info; |
897 | root->objectid = objectid; | 900 | root->objectid = objectid; |
@@ -899,7 +902,7 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, | |||
899 | root->highest_objectid = 0; | 902 | root->highest_objectid = 0; |
900 | root->name = NULL; | 903 | root->name = NULL; |
901 | root->in_sysfs = 0; | 904 | root->in_sysfs = 0; |
902 | root->inode_tree.rb_node = NULL; | 905 | root->inode_tree = RB_ROOT; |
903 | 906 | ||
904 | INIT_LIST_HEAD(&root->dirty_list); | 907 | INIT_LIST_HEAD(&root->dirty_list); |
905 | INIT_LIST_HEAD(&root->orphan_list); | 908 | INIT_LIST_HEAD(&root->orphan_list); |
@@ -928,7 +931,6 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, | |||
928 | root->defrag_trans_start = fs_info->generation; | 931 | root->defrag_trans_start = fs_info->generation; |
929 | init_completion(&root->kobj_unregister); | 932 | init_completion(&root->kobj_unregister); |
930 | root->defrag_running = 0; | 933 | root->defrag_running = 0; |
931 | root->defrag_level = 0; | ||
932 | root->root_key.objectid = objectid; | 934 | root->root_key.objectid = objectid; |
933 | root->anon_super.s_root = NULL; | 935 | root->anon_super.s_root = NULL; |
934 | root->anon_super.s_dev = 0; | 936 | root->anon_super.s_dev = 0; |
@@ -980,12 +982,12 @@ int btrfs_free_log_root_tree(struct btrfs_trans_handle *trans, | |||
980 | 982 | ||
981 | while (1) { | 983 | while (1) { |
982 | ret = find_first_extent_bit(&log_root_tree->dirty_log_pages, | 984 | ret = find_first_extent_bit(&log_root_tree->dirty_log_pages, |
983 | 0, &start, &end, EXTENT_DIRTY); | 985 | 0, &start, &end, EXTENT_DIRTY | EXTENT_NEW); |
984 | if (ret) | 986 | if (ret) |
985 | break; | 987 | break; |
986 | 988 | ||
987 | clear_extent_dirty(&log_root_tree->dirty_log_pages, | 989 | clear_extent_bits(&log_root_tree->dirty_log_pages, start, end, |
988 | start, end, GFP_NOFS); | 990 | EXTENT_DIRTY | EXTENT_NEW, GFP_NOFS); |
989 | } | 991 | } |
990 | eb = fs_info->log_root_tree->node; | 992 | eb = fs_info->log_root_tree->node; |
991 | 993 | ||
@@ -1210,8 +1212,10 @@ again: | |||
1210 | ret = radix_tree_insert(&fs_info->fs_roots_radix, | 1212 | ret = radix_tree_insert(&fs_info->fs_roots_radix, |
1211 | (unsigned long)root->root_key.objectid, | 1213 | (unsigned long)root->root_key.objectid, |
1212 | root); | 1214 | root); |
1213 | if (ret == 0) | 1215 | if (ret == 0) { |
1214 | root->in_radix = 1; | 1216 | root->in_radix = 1; |
1217 | root->clean_orphans = 1; | ||
1218 | } | ||
1215 | spin_unlock(&fs_info->fs_roots_radix_lock); | 1219 | spin_unlock(&fs_info->fs_roots_radix_lock); |
1216 | radix_tree_preload_end(); | 1220 | radix_tree_preload_end(); |
1217 | if (ret) { | 1221 | if (ret) { |
@@ -1225,10 +1229,6 @@ again: | |||
1225 | ret = btrfs_find_dead_roots(fs_info->tree_root, | 1229 | ret = btrfs_find_dead_roots(fs_info->tree_root, |
1226 | root->root_key.objectid); | 1230 | root->root_key.objectid); |
1227 | WARN_ON(ret); | 1231 | WARN_ON(ret); |
1228 | |||
1229 | if (!(fs_info->sb->s_flags & MS_RDONLY)) | ||
1230 | btrfs_orphan_cleanup(root); | ||
1231 | |||
1232 | return root; | 1232 | return root; |
1233 | fail: | 1233 | fail: |
1234 | free_fs_root(root); | 1234 | free_fs_root(root); |
@@ -1373,19 +1373,11 @@ static int setup_bdi(struct btrfs_fs_info *info, struct backing_dev_info *bdi) | |||
1373 | { | 1373 | { |
1374 | int err; | 1374 | int err; |
1375 | 1375 | ||
1376 | bdi->name = "btrfs"; | ||
1377 | bdi->capabilities = BDI_CAP_MAP_COPY; | 1376 | bdi->capabilities = BDI_CAP_MAP_COPY; |
1378 | err = bdi_init(bdi); | 1377 | err = bdi_setup_and_register(bdi, "btrfs", BDI_CAP_MAP_COPY); |
1379 | if (err) | 1378 | if (err) |
1380 | return err; | 1379 | return err; |
1381 | 1380 | ||
1382 | err = bdi_register(bdi, NULL, "btrfs-%d", | ||
1383 | atomic_inc_return(&btrfs_bdi_num)); | ||
1384 | if (err) { | ||
1385 | bdi_destroy(bdi); | ||
1386 | return err; | ||
1387 | } | ||
1388 | |||
1389 | bdi->ra_pages = default_backing_dev_info.ra_pages; | 1381 | bdi->ra_pages = default_backing_dev_info.ra_pages; |
1390 | bdi->unplug_io_fn = btrfs_unplug_io_fn; | 1382 | bdi->unplug_io_fn = btrfs_unplug_io_fn; |
1391 | bdi->unplug_io_data = info; | 1383 | bdi->unplug_io_data = info; |
@@ -1477,6 +1469,7 @@ static int cleaner_kthread(void *arg) | |||
1477 | 1469 | ||
1478 | if (!(root->fs_info->sb->s_flags & MS_RDONLY) && | 1470 | if (!(root->fs_info->sb->s_flags & MS_RDONLY) && |
1479 | mutex_trylock(&root->fs_info->cleaner_mutex)) { | 1471 | mutex_trylock(&root->fs_info->cleaner_mutex)) { |
1472 | btrfs_run_delayed_iputs(root); | ||
1480 | btrfs_clean_old_snapshots(root); | 1473 | btrfs_clean_old_snapshots(root); |
1481 | mutex_unlock(&root->fs_info->cleaner_mutex); | 1474 | mutex_unlock(&root->fs_info->cleaner_mutex); |
1482 | } | 1475 | } |
@@ -1606,6 +1599,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1606 | INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_ATOMIC); | 1599 | INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_ATOMIC); |
1607 | INIT_LIST_HEAD(&fs_info->trans_list); | 1600 | INIT_LIST_HEAD(&fs_info->trans_list); |
1608 | INIT_LIST_HEAD(&fs_info->dead_roots); | 1601 | INIT_LIST_HEAD(&fs_info->dead_roots); |
1602 | INIT_LIST_HEAD(&fs_info->delayed_iputs); | ||
1609 | INIT_LIST_HEAD(&fs_info->hashers); | 1603 | INIT_LIST_HEAD(&fs_info->hashers); |
1610 | INIT_LIST_HEAD(&fs_info->delalloc_inodes); | 1604 | INIT_LIST_HEAD(&fs_info->delalloc_inodes); |
1611 | INIT_LIST_HEAD(&fs_info->ordered_operations); | 1605 | INIT_LIST_HEAD(&fs_info->ordered_operations); |
@@ -1614,6 +1608,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1614 | spin_lock_init(&fs_info->new_trans_lock); | 1608 | spin_lock_init(&fs_info->new_trans_lock); |
1615 | spin_lock_init(&fs_info->ref_cache_lock); | 1609 | spin_lock_init(&fs_info->ref_cache_lock); |
1616 | spin_lock_init(&fs_info->fs_roots_radix_lock); | 1610 | spin_lock_init(&fs_info->fs_roots_radix_lock); |
1611 | spin_lock_init(&fs_info->delayed_iput_lock); | ||
1617 | 1612 | ||
1618 | init_completion(&fs_info->kobj_unregister); | 1613 | init_completion(&fs_info->kobj_unregister); |
1619 | fs_info->tree_root = tree_root; | 1614 | fs_info->tree_root = tree_root; |
@@ -1630,7 +1625,6 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1630 | atomic_set(&fs_info->async_submit_draining, 0); | 1625 | atomic_set(&fs_info->async_submit_draining, 0); |
1631 | atomic_set(&fs_info->nr_async_bios, 0); | 1626 | atomic_set(&fs_info->nr_async_bios, 0); |
1632 | fs_info->sb = sb; | 1627 | fs_info->sb = sb; |
1633 | fs_info->max_extent = (u64)-1; | ||
1634 | fs_info->max_inline = 8192 * 1024; | 1628 | fs_info->max_inline = 8192 * 1024; |
1635 | fs_info->metadata_ratio = 0; | 1629 | fs_info->metadata_ratio = 0; |
1636 | 1630 | ||
@@ -1671,7 +1665,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1671 | insert_inode_hash(fs_info->btree_inode); | 1665 | insert_inode_hash(fs_info->btree_inode); |
1672 | 1666 | ||
1673 | spin_lock_init(&fs_info->block_group_cache_lock); | 1667 | spin_lock_init(&fs_info->block_group_cache_lock); |
1674 | fs_info->block_group_cache_tree.rb_node = NULL; | 1668 | fs_info->block_group_cache_tree = RB_ROOT; |
1675 | 1669 | ||
1676 | extent_io_tree_init(&fs_info->freed_extents[0], | 1670 | extent_io_tree_init(&fs_info->freed_extents[0], |
1677 | fs_info->btree_inode->i_mapping, GFP_NOFS); | 1671 | fs_info->btree_inode->i_mapping, GFP_NOFS); |
@@ -1689,6 +1683,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1689 | mutex_init(&fs_info->cleaner_mutex); | 1683 | mutex_init(&fs_info->cleaner_mutex); |
1690 | mutex_init(&fs_info->volume_mutex); | 1684 | mutex_init(&fs_info->volume_mutex); |
1691 | init_rwsem(&fs_info->extent_commit_sem); | 1685 | init_rwsem(&fs_info->extent_commit_sem); |
1686 | init_rwsem(&fs_info->cleanup_work_sem); | ||
1692 | init_rwsem(&fs_info->subvol_sem); | 1687 | init_rwsem(&fs_info->subvol_sem); |
1693 | 1688 | ||
1694 | btrfs_init_free_cluster(&fs_info->meta_alloc_cluster); | 1689 | btrfs_init_free_cluster(&fs_info->meta_alloc_cluster); |
@@ -1917,7 +1912,11 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1917 | 1912 | ||
1918 | csum_root->track_dirty = 1; | 1913 | csum_root->track_dirty = 1; |
1919 | 1914 | ||
1920 | btrfs_read_block_groups(extent_root); | 1915 | ret = btrfs_read_block_groups(extent_root); |
1916 | if (ret) { | ||
1917 | printk(KERN_ERR "Failed to read block groups: %d\n", ret); | ||
1918 | goto fail_block_groups; | ||
1919 | } | ||
1921 | 1920 | ||
1922 | fs_info->generation = generation; | 1921 | fs_info->generation = generation; |
1923 | fs_info->last_trans_committed = generation; | 1922 | fs_info->last_trans_committed = generation; |
@@ -1927,7 +1926,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1927 | fs_info->cleaner_kthread = kthread_run(cleaner_kthread, tree_root, | 1926 | fs_info->cleaner_kthread = kthread_run(cleaner_kthread, tree_root, |
1928 | "btrfs-cleaner"); | 1927 | "btrfs-cleaner"); |
1929 | if (IS_ERR(fs_info->cleaner_kthread)) | 1928 | if (IS_ERR(fs_info->cleaner_kthread)) |
1930 | goto fail_csum_root; | 1929 | goto fail_block_groups; |
1931 | 1930 | ||
1932 | fs_info->transaction_kthread = kthread_run(transaction_kthread, | 1931 | fs_info->transaction_kthread = kthread_run(transaction_kthread, |
1933 | tree_root, | 1932 | tree_root, |
@@ -1979,7 +1978,12 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1979 | 1978 | ||
1980 | if (!(sb->s_flags & MS_RDONLY)) { | 1979 | if (!(sb->s_flags & MS_RDONLY)) { |
1981 | ret = btrfs_recover_relocation(tree_root); | 1980 | ret = btrfs_recover_relocation(tree_root); |
1982 | BUG_ON(ret); | 1981 | if (ret < 0) { |
1982 | printk(KERN_WARNING | ||
1983 | "btrfs: failed to recover relocation\n"); | ||
1984 | err = -EINVAL; | ||
1985 | goto fail_trans_kthread; | ||
1986 | } | ||
1983 | } | 1987 | } |
1984 | 1988 | ||
1985 | location.objectid = BTRFS_FS_TREE_OBJECTID; | 1989 | location.objectid = BTRFS_FS_TREE_OBJECTID; |
@@ -1990,6 +1994,12 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1990 | if (!fs_info->fs_root) | 1994 | if (!fs_info->fs_root) |
1991 | goto fail_trans_kthread; | 1995 | goto fail_trans_kthread; |
1992 | 1996 | ||
1997 | if (!(sb->s_flags & MS_RDONLY)) { | ||
1998 | down_read(&fs_info->cleanup_work_sem); | ||
1999 | btrfs_orphan_cleanup(fs_info->fs_root); | ||
2000 | up_read(&fs_info->cleanup_work_sem); | ||
2001 | } | ||
2002 | |||
1993 | return tree_root; | 2003 | return tree_root; |
1994 | 2004 | ||
1995 | fail_trans_kthread: | 2005 | fail_trans_kthread: |
@@ -2004,7 +2014,8 @@ fail_cleaner: | |||
2004 | filemap_write_and_wait(fs_info->btree_inode->i_mapping); | 2014 | filemap_write_and_wait(fs_info->btree_inode->i_mapping); |
2005 | invalidate_inode_pages2(fs_info->btree_inode->i_mapping); | 2015 | invalidate_inode_pages2(fs_info->btree_inode->i_mapping); |
2006 | 2016 | ||
2007 | fail_csum_root: | 2017 | fail_block_groups: |
2018 | btrfs_free_block_groups(fs_info); | ||
2008 | free_extent_buffer(csum_root->node); | 2019 | free_extent_buffer(csum_root->node); |
2009 | free_extent_buffer(csum_root->commit_root); | 2020 | free_extent_buffer(csum_root->commit_root); |
2010 | fail_dev_root: | 2021 | fail_dev_root: |
@@ -2386,8 +2397,14 @@ int btrfs_commit_super(struct btrfs_root *root) | |||
2386 | int ret; | 2397 | int ret; |
2387 | 2398 | ||
2388 | mutex_lock(&root->fs_info->cleaner_mutex); | 2399 | mutex_lock(&root->fs_info->cleaner_mutex); |
2400 | btrfs_run_delayed_iputs(root); | ||
2389 | btrfs_clean_old_snapshots(root); | 2401 | btrfs_clean_old_snapshots(root); |
2390 | mutex_unlock(&root->fs_info->cleaner_mutex); | 2402 | mutex_unlock(&root->fs_info->cleaner_mutex); |
2403 | |||
2404 | /* wait until ongoing cleanup work done */ | ||
2405 | down_write(&root->fs_info->cleanup_work_sem); | ||
2406 | up_write(&root->fs_info->cleanup_work_sem); | ||
2407 | |||
2391 | trans = btrfs_start_transaction(root, 1); | 2408 | trans = btrfs_start_transaction(root, 1); |
2392 | ret = btrfs_commit_transaction(trans, root); | 2409 | ret = btrfs_commit_transaction(trans, root); |
2393 | BUG_ON(ret); | 2410 | BUG_ON(ret); |
@@ -2477,7 +2494,8 @@ int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid) | |||
2477 | int ret; | 2494 | int ret; |
2478 | struct inode *btree_inode = buf->first_page->mapping->host; | 2495 | struct inode *btree_inode = buf->first_page->mapping->host; |
2479 | 2496 | ||
2480 | ret = extent_buffer_uptodate(&BTRFS_I(btree_inode)->io_tree, buf); | 2497 | ret = extent_buffer_uptodate(&BTRFS_I(btree_inode)->io_tree, buf, |
2498 | NULL); | ||
2481 | if (!ret) | 2499 | if (!ret) |
2482 | return ret; | 2500 | return ret; |
2483 | 2501 | ||