diff options
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r-- | fs/btrfs/disk-io.c | 134 |
1 files changed, 127 insertions, 7 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 1a4a2a975926..05f4fb6e0607 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -1225,6 +1225,82 @@ static struct btrfs_root *btrfs_alloc_root(struct btrfs_fs_info *fs_info) | |||
1225 | return root; | 1225 | return root; |
1226 | } | 1226 | } |
1227 | 1227 | ||
1228 | struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans, | ||
1229 | struct btrfs_fs_info *fs_info, | ||
1230 | u64 objectid) | ||
1231 | { | ||
1232 | struct extent_buffer *leaf; | ||
1233 | struct btrfs_root *tree_root = fs_info->tree_root; | ||
1234 | struct btrfs_root *root; | ||
1235 | struct btrfs_key key; | ||
1236 | int ret = 0; | ||
1237 | u64 bytenr; | ||
1238 | |||
1239 | root = btrfs_alloc_root(fs_info); | ||
1240 | if (!root) | ||
1241 | return ERR_PTR(-ENOMEM); | ||
1242 | |||
1243 | __setup_root(tree_root->nodesize, tree_root->leafsize, | ||
1244 | tree_root->sectorsize, tree_root->stripesize, | ||
1245 | root, fs_info, objectid); | ||
1246 | root->root_key.objectid = objectid; | ||
1247 | root->root_key.type = BTRFS_ROOT_ITEM_KEY; | ||
1248 | root->root_key.offset = 0; | ||
1249 | |||
1250 | leaf = btrfs_alloc_free_block(trans, root, root->leafsize, | ||
1251 | 0, objectid, NULL, 0, 0, 0); | ||
1252 | if (IS_ERR(leaf)) { | ||
1253 | ret = PTR_ERR(leaf); | ||
1254 | goto fail; | ||
1255 | } | ||
1256 | |||
1257 | bytenr = leaf->start; | ||
1258 | memset_extent_buffer(leaf, 0, 0, sizeof(struct btrfs_header)); | ||
1259 | btrfs_set_header_bytenr(leaf, leaf->start); | ||
1260 | btrfs_set_header_generation(leaf, trans->transid); | ||
1261 | btrfs_set_header_backref_rev(leaf, BTRFS_MIXED_BACKREF_REV); | ||
1262 | btrfs_set_header_owner(leaf, objectid); | ||
1263 | root->node = leaf; | ||
1264 | |||
1265 | write_extent_buffer(leaf, fs_info->fsid, | ||
1266 | (unsigned long)btrfs_header_fsid(leaf), | ||
1267 | BTRFS_FSID_SIZE); | ||
1268 | write_extent_buffer(leaf, fs_info->chunk_tree_uuid, | ||
1269 | (unsigned long)btrfs_header_chunk_tree_uuid(leaf), | ||
1270 | BTRFS_UUID_SIZE); | ||
1271 | btrfs_mark_buffer_dirty(leaf); | ||
1272 | |||
1273 | root->commit_root = btrfs_root_node(root); | ||
1274 | root->track_dirty = 1; | ||
1275 | |||
1276 | |||
1277 | root->root_item.flags = 0; | ||
1278 | root->root_item.byte_limit = 0; | ||
1279 | btrfs_set_root_bytenr(&root->root_item, leaf->start); | ||
1280 | btrfs_set_root_generation(&root->root_item, trans->transid); | ||
1281 | btrfs_set_root_level(&root->root_item, 0); | ||
1282 | btrfs_set_root_refs(&root->root_item, 1); | ||
1283 | btrfs_set_root_used(&root->root_item, leaf->len); | ||
1284 | btrfs_set_root_last_snapshot(&root->root_item, 0); | ||
1285 | btrfs_set_root_dirid(&root->root_item, 0); | ||
1286 | root->root_item.drop_level = 0; | ||
1287 | |||
1288 | key.objectid = objectid; | ||
1289 | key.type = BTRFS_ROOT_ITEM_KEY; | ||
1290 | key.offset = 0; | ||
1291 | ret = btrfs_insert_root(trans, tree_root, &key, &root->root_item); | ||
1292 | if (ret) | ||
1293 | goto fail; | ||
1294 | |||
1295 | btrfs_tree_unlock(leaf); | ||
1296 | |||
1297 | fail: | ||
1298 | if (ret) | ||
1299 | return ERR_PTR(ret); | ||
1300 | |||
1301 | return root; | ||
1302 | } | ||
1303 | |||
1228 | static struct btrfs_root *alloc_log_tree(struct btrfs_trans_handle *trans, | 1304 | static struct btrfs_root *alloc_log_tree(struct btrfs_trans_handle *trans, |
1229 | struct btrfs_fs_info *fs_info) | 1305 | struct btrfs_fs_info *fs_info) |
1230 | { | 1306 | { |
@@ -1396,6 +1472,9 @@ struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info, | |||
1396 | return fs_info->dev_root; | 1472 | return fs_info->dev_root; |
1397 | if (location->objectid == BTRFS_CSUM_TREE_OBJECTID) | 1473 | if (location->objectid == BTRFS_CSUM_TREE_OBJECTID) |
1398 | return fs_info->csum_root; | 1474 | return fs_info->csum_root; |
1475 | if (location->objectid == BTRFS_QUOTA_TREE_OBJECTID) | ||
1476 | return fs_info->quota_root ? fs_info->quota_root : | ||
1477 | ERR_PTR(-ENOENT); | ||
1399 | again: | 1478 | again: |
1400 | spin_lock(&fs_info->fs_roots_radix_lock); | 1479 | spin_lock(&fs_info->fs_roots_radix_lock); |
1401 | root = radix_tree_lookup(&fs_info->fs_roots_radix, | 1480 | root = radix_tree_lookup(&fs_info->fs_roots_radix, |
@@ -1823,6 +1902,10 @@ static void free_root_pointers(struct btrfs_fs_info *info, int chunk_root) | |||
1823 | free_extent_buffer(info->extent_root->commit_root); | 1902 | free_extent_buffer(info->extent_root->commit_root); |
1824 | free_extent_buffer(info->csum_root->node); | 1903 | free_extent_buffer(info->csum_root->node); |
1825 | free_extent_buffer(info->csum_root->commit_root); | 1904 | free_extent_buffer(info->csum_root->commit_root); |
1905 | if (info->quota_root) { | ||
1906 | free_extent_buffer(info->quota_root->node); | ||
1907 | free_extent_buffer(info->quota_root->commit_root); | ||
1908 | } | ||
1826 | 1909 | ||
1827 | info->tree_root->node = NULL; | 1910 | info->tree_root->node = NULL; |
1828 | info->tree_root->commit_root = NULL; | 1911 | info->tree_root->commit_root = NULL; |
@@ -1832,6 +1915,10 @@ static void free_root_pointers(struct btrfs_fs_info *info, int chunk_root) | |||
1832 | info->extent_root->commit_root = NULL; | 1915 | info->extent_root->commit_root = NULL; |
1833 | info->csum_root->node = NULL; | 1916 | info->csum_root->node = NULL; |
1834 | info->csum_root->commit_root = NULL; | 1917 | info->csum_root->commit_root = NULL; |
1918 | if (info->quota_root) { | ||
1919 | info->quota_root->node = NULL; | ||
1920 | info->quota_root->commit_root = NULL; | ||
1921 | } | ||
1835 | 1922 | ||
1836 | if (chunk_root) { | 1923 | if (chunk_root) { |
1837 | free_extent_buffer(info->chunk_root->node); | 1924 | free_extent_buffer(info->chunk_root->node); |
@@ -1862,6 +1949,7 @@ int open_ctree(struct super_block *sb, | |||
1862 | struct btrfs_root *csum_root; | 1949 | struct btrfs_root *csum_root; |
1863 | struct btrfs_root *chunk_root; | 1950 | struct btrfs_root *chunk_root; |
1864 | struct btrfs_root *dev_root; | 1951 | struct btrfs_root *dev_root; |
1952 | struct btrfs_root *quota_root; | ||
1865 | struct btrfs_root *log_tree_root; | 1953 | struct btrfs_root *log_tree_root; |
1866 | int ret; | 1954 | int ret; |
1867 | int err = -EINVAL; | 1955 | int err = -EINVAL; |
@@ -1873,9 +1961,10 @@ int open_ctree(struct super_block *sb, | |||
1873 | csum_root = fs_info->csum_root = btrfs_alloc_root(fs_info); | 1961 | csum_root = fs_info->csum_root = btrfs_alloc_root(fs_info); |
1874 | chunk_root = fs_info->chunk_root = btrfs_alloc_root(fs_info); | 1962 | chunk_root = fs_info->chunk_root = btrfs_alloc_root(fs_info); |
1875 | dev_root = fs_info->dev_root = btrfs_alloc_root(fs_info); | 1963 | dev_root = fs_info->dev_root = btrfs_alloc_root(fs_info); |
1964 | quota_root = fs_info->quota_root = btrfs_alloc_root(fs_info); | ||
1876 | 1965 | ||
1877 | if (!tree_root || !extent_root || !csum_root || | 1966 | if (!tree_root || !extent_root || !csum_root || |
1878 | !chunk_root || !dev_root) { | 1967 | !chunk_root || !dev_root || !quota_root) { |
1879 | err = -ENOMEM; | 1968 | err = -ENOMEM; |
1880 | goto fail; | 1969 | goto fail; |
1881 | } | 1970 | } |
@@ -1944,6 +2033,8 @@ int open_ctree(struct super_block *sb, | |||
1944 | fs_info->free_chunk_space = 0; | 2033 | fs_info->free_chunk_space = 0; |
1945 | fs_info->tree_mod_log = RB_ROOT; | 2034 | fs_info->tree_mod_log = RB_ROOT; |
1946 | 2035 | ||
2036 | init_waitqueue_head(&fs_info->tree_mod_seq_wait); | ||
2037 | |||
1947 | /* readahead state */ | 2038 | /* readahead state */ |
1948 | INIT_RADIX_TREE(&fs_info->reada_tree, GFP_NOFS & ~__GFP_WAIT); | 2039 | INIT_RADIX_TREE(&fs_info->reada_tree, GFP_NOFS & ~__GFP_WAIT); |
1949 | spin_lock_init(&fs_info->reada_lock); | 2040 | spin_lock_init(&fs_info->reada_lock); |
@@ -2032,6 +2123,13 @@ int open_ctree(struct super_block *sb, | |||
2032 | init_rwsem(&fs_info->cleanup_work_sem); | 2123 | init_rwsem(&fs_info->cleanup_work_sem); |
2033 | init_rwsem(&fs_info->subvol_sem); | 2124 | init_rwsem(&fs_info->subvol_sem); |
2034 | 2125 | ||
2126 | spin_lock_init(&fs_info->qgroup_lock); | ||
2127 | fs_info->qgroup_tree = RB_ROOT; | ||
2128 | INIT_LIST_HEAD(&fs_info->dirty_qgroups); | ||
2129 | fs_info->qgroup_seq = 1; | ||
2130 | fs_info->quota_enabled = 0; | ||
2131 | fs_info->pending_quota_state = 0; | ||
2132 | |||
2035 | btrfs_init_free_cluster(&fs_info->meta_alloc_cluster); | 2133 | btrfs_init_free_cluster(&fs_info->meta_alloc_cluster); |
2036 | btrfs_init_free_cluster(&fs_info->data_alloc_cluster); | 2134 | btrfs_init_free_cluster(&fs_info->data_alloc_cluster); |
2037 | 2135 | ||
@@ -2356,6 +2454,17 @@ retry_root_backup: | |||
2356 | goto recovery_tree_root; | 2454 | goto recovery_tree_root; |
2357 | csum_root->track_dirty = 1; | 2455 | csum_root->track_dirty = 1; |
2358 | 2456 | ||
2457 | ret = find_and_setup_root(tree_root, fs_info, | ||
2458 | BTRFS_QUOTA_TREE_OBJECTID, quota_root); | ||
2459 | if (ret) { | ||
2460 | kfree(quota_root); | ||
2461 | quota_root = fs_info->quota_root = NULL; | ||
2462 | } else { | ||
2463 | quota_root->track_dirty = 1; | ||
2464 | fs_info->quota_enabled = 1; | ||
2465 | fs_info->pending_quota_state = 1; | ||
2466 | } | ||
2467 | |||
2359 | fs_info->generation = generation; | 2468 | fs_info->generation = generation; |
2360 | fs_info->last_trans_committed = generation; | 2469 | fs_info->last_trans_committed = generation; |
2361 | 2470 | ||
@@ -2415,6 +2524,9 @@ retry_root_backup: | |||
2415 | " integrity check module %s\n", sb->s_id); | 2524 | " integrity check module %s\n", sb->s_id); |
2416 | } | 2525 | } |
2417 | #endif | 2526 | #endif |
2527 | ret = btrfs_read_qgroup_config(fs_info); | ||
2528 | if (ret) | ||
2529 | goto fail_trans_kthread; | ||
2418 | 2530 | ||
2419 | /* do not make disk changes in broken FS */ | 2531 | /* do not make disk changes in broken FS */ |
2420 | if (btrfs_super_log_root(disk_super) != 0 && | 2532 | if (btrfs_super_log_root(disk_super) != 0 && |
@@ -2425,7 +2537,7 @@ retry_root_backup: | |||
2425 | printk(KERN_WARNING "Btrfs log replay required " | 2537 | printk(KERN_WARNING "Btrfs log replay required " |
2426 | "on RO media\n"); | 2538 | "on RO media\n"); |
2427 | err = -EIO; | 2539 | err = -EIO; |
2428 | goto fail_trans_kthread; | 2540 | goto fail_qgroup; |
2429 | } | 2541 | } |
2430 | blocksize = | 2542 | blocksize = |
2431 | btrfs_level_size(tree_root, | 2543 | btrfs_level_size(tree_root, |
@@ -2434,7 +2546,7 @@ retry_root_backup: | |||
2434 | log_tree_root = btrfs_alloc_root(fs_info); | 2546 | log_tree_root = btrfs_alloc_root(fs_info); |
2435 | if (!log_tree_root) { | 2547 | if (!log_tree_root) { |
2436 | err = -ENOMEM; | 2548 | err = -ENOMEM; |
2437 | goto fail_trans_kthread; | 2549 | goto fail_qgroup; |
2438 | } | 2550 | } |
2439 | 2551 | ||
2440 | __setup_root(nodesize, leafsize, sectorsize, stripesize, | 2552 | __setup_root(nodesize, leafsize, sectorsize, stripesize, |
@@ -2474,7 +2586,7 @@ retry_root_backup: | |||
2474 | printk(KERN_WARNING | 2586 | printk(KERN_WARNING |
2475 | "btrfs: failed to recover relocation\n"); | 2587 | "btrfs: failed to recover relocation\n"); |
2476 | err = -EINVAL; | 2588 | err = -EINVAL; |
2477 | goto fail_trans_kthread; | 2589 | goto fail_qgroup; |
2478 | } | 2590 | } |
2479 | } | 2591 | } |
2480 | 2592 | ||
@@ -2484,10 +2596,10 @@ retry_root_backup: | |||
2484 | 2596 | ||
2485 | fs_info->fs_root = btrfs_read_fs_root_no_name(fs_info, &location); | 2597 | fs_info->fs_root = btrfs_read_fs_root_no_name(fs_info, &location); |
2486 | if (!fs_info->fs_root) | 2598 | if (!fs_info->fs_root) |
2487 | goto fail_trans_kthread; | 2599 | goto fail_qgroup; |
2488 | if (IS_ERR(fs_info->fs_root)) { | 2600 | if (IS_ERR(fs_info->fs_root)) { |
2489 | err = PTR_ERR(fs_info->fs_root); | 2601 | err = PTR_ERR(fs_info->fs_root); |
2490 | goto fail_trans_kthread; | 2602 | goto fail_qgroup; |
2491 | } | 2603 | } |
2492 | 2604 | ||
2493 | if (sb->s_flags & MS_RDONLY) | 2605 | if (sb->s_flags & MS_RDONLY) |
@@ -2511,6 +2623,8 @@ retry_root_backup: | |||
2511 | 2623 | ||
2512 | return 0; | 2624 | return 0; |
2513 | 2625 | ||
2626 | fail_qgroup: | ||
2627 | btrfs_free_qgroup_config(fs_info); | ||
2514 | fail_trans_kthread: | 2628 | fail_trans_kthread: |
2515 | kthread_stop(fs_info->transaction_kthread); | 2629 | kthread_stop(fs_info->transaction_kthread); |
2516 | fail_cleaner: | 2630 | fail_cleaner: |
@@ -3109,6 +3223,8 @@ int close_ctree(struct btrfs_root *root) | |||
3109 | fs_info->closing = 2; | 3223 | fs_info->closing = 2; |
3110 | smp_mb(); | 3224 | smp_mb(); |
3111 | 3225 | ||
3226 | btrfs_free_qgroup_config(root->fs_info); | ||
3227 | |||
3112 | if (fs_info->delalloc_bytes) { | 3228 | if (fs_info->delalloc_bytes) { |
3113 | printk(KERN_INFO "btrfs: at unmount delalloc count %llu\n", | 3229 | printk(KERN_INFO "btrfs: at unmount delalloc count %llu\n", |
3114 | (unsigned long long)fs_info->delalloc_bytes); | 3230 | (unsigned long long)fs_info->delalloc_bytes); |
@@ -3128,6 +3244,10 @@ int close_ctree(struct btrfs_root *root) | |||
3128 | free_extent_buffer(fs_info->dev_root->commit_root); | 3244 | free_extent_buffer(fs_info->dev_root->commit_root); |
3129 | free_extent_buffer(fs_info->csum_root->node); | 3245 | free_extent_buffer(fs_info->csum_root->node); |
3130 | free_extent_buffer(fs_info->csum_root->commit_root); | 3246 | free_extent_buffer(fs_info->csum_root->commit_root); |
3247 | if (fs_info->quota_root) { | ||
3248 | free_extent_buffer(fs_info->quota_root->node); | ||
3249 | free_extent_buffer(fs_info->quota_root->commit_root); | ||
3250 | } | ||
3131 | 3251 | ||
3132 | btrfs_free_block_groups(fs_info); | 3252 | btrfs_free_block_groups(fs_info); |
3133 | 3253 | ||
@@ -3258,7 +3378,7 @@ int btrfs_read_buffer(struct extent_buffer *buf, u64 parent_transid) | |||
3258 | return btree_read_extent_buffer_pages(root, buf, 0, parent_transid); | 3378 | return btree_read_extent_buffer_pages(root, buf, 0, parent_transid); |
3259 | } | 3379 | } |
3260 | 3380 | ||
3261 | static int btree_lock_page_hook(struct page *page, void *data, | 3381 | int btree_lock_page_hook(struct page *page, void *data, |
3262 | void (*flush_fn)(void *)) | 3382 | void (*flush_fn)(void *)) |
3263 | { | 3383 | { |
3264 | struct inode *inode = page->mapping->host; | 3384 | struct inode *inode = page->mapping->host; |