diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-04-12 10:43:05 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-04-12 10:43:05 -0400 |
commit | 8352d8a473ac84bf7a1c69690b626946d744ca58 (patch) | |
tree | 58686bb1de3d994a881d6176dafd7c16dfadeeca /fs | |
parent | 7eccb903a817e890c947ba4bc90c6a9af9b4219a (diff) |
Btrfs: add disk ioctl, mostly working
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/disk-io.c | 128 | ||||
-rw-r--r-- | fs/btrfs/disk-io.h | 6 | ||||
-rw-r--r-- | fs/btrfs/ioctl.h | 2 | ||||
-rw-r--r-- | fs/btrfs/super.c | 96 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 6 |
5 files changed, 221 insertions, 17 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index c872a7e67abd..3ba4df20c913 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -16,6 +16,28 @@ struct dev_lookup { | |||
16 | struct block_device *bdev; | 16 | struct block_device *bdev; |
17 | }; | 17 | }; |
18 | 18 | ||
19 | int btrfs_insert_dev_radix(struct btrfs_root *root, | ||
20 | struct block_device *bdev, | ||
21 | u64 block_start, | ||
22 | u64 num_blocks) | ||
23 | { | ||
24 | struct dev_lookup *lookup; | ||
25 | char b[BDEVNAME_SIZE]; | ||
26 | int ret; | ||
27 | |||
28 | lookup = kmalloc(sizeof(*lookup), GFP_NOFS); | ||
29 | if (!lookup) | ||
30 | return -ENOMEM; | ||
31 | lookup->block_start = block_start; | ||
32 | lookup->num_blocks = num_blocks; | ||
33 | lookup->bdev = bdev; | ||
34 | printk("inserting %s into dev radix %Lu %Lu\n", bdevname(bdev, b), block_start, num_blocks); | ||
35 | |||
36 | ret = radix_tree_insert(&root->fs_info->dev_radix, block_start + | ||
37 | num_blocks - 1, lookup); | ||
38 | return ret; | ||
39 | } | ||
40 | |||
19 | u64 bh_blocknr(struct buffer_head *bh) | 41 | u64 bh_blocknr(struct buffer_head *bh) |
20 | { | 42 | { |
21 | int blkbits = bh->b_page->mapping->host->i_blkbits; | 43 | int blkbits = bh->b_page->mapping->host->i_blkbits; |
@@ -34,6 +56,8 @@ static int check_tree_block(struct btrfs_root *root, struct buffer_head *buf) | |||
34 | { | 56 | { |
35 | struct btrfs_node *node = btrfs_buffer_node(buf); | 57 | struct btrfs_node *node = btrfs_buffer_node(buf); |
36 | if (bh_blocknr(buf) != btrfs_header_blocknr(&node->header)) { | 58 | if (bh_blocknr(buf) != btrfs_header_blocknr(&node->header)) { |
59 | printk(KERN_CRIT "bh_blocknr(buf) is %Lu, header is %Lu\n", | ||
60 | bh_blocknr(buf), btrfs_header_blocknr(&node->header)); | ||
37 | BUG(); | 61 | BUG(); |
38 | } | 62 | } |
39 | return 0; | 63 | return 0; |
@@ -76,11 +100,10 @@ out_unlock: | |||
76 | return ret; | 100 | return ret; |
77 | } | 101 | } |
78 | 102 | ||
79 | static int map_bh_to_logical(struct btrfs_root *root, struct buffer_head *bh, | 103 | int btrfs_map_bh_to_logical(struct btrfs_root *root, struct buffer_head *bh, |
80 | u64 logical) | 104 | u64 logical) |
81 | { | 105 | { |
82 | struct dev_lookup *lookup[2]; | 106 | struct dev_lookup *lookup[2]; |
83 | char b[BDEVNAME_SIZE]; | ||
84 | 107 | ||
85 | int ret; | 108 | int ret; |
86 | 109 | ||
@@ -96,7 +119,6 @@ static int map_bh_to_logical(struct btrfs_root *root, struct buffer_head *bh, | |||
96 | } | 119 | } |
97 | bh->b_bdev = lookup[0]->bdev; | 120 | bh->b_bdev = lookup[0]->bdev; |
98 | bh->b_blocknr = logical - lookup[0]->block_start; | 121 | bh->b_blocknr = logical - lookup[0]->block_start; |
99 | printk("logical mapping %Lu to %lu bdev %s\n", logical, bh->b_blocknr, bdevname(bh->b_bdev, b)); | ||
100 | set_buffer_mapped(bh); | 122 | set_buffer_mapped(bh); |
101 | ret = 0; | 123 | ret = 0; |
102 | out: | 124 | out: |
@@ -126,7 +148,7 @@ struct buffer_head *btrfs_find_create_tree_block(struct btrfs_root *root, | |||
126 | bh = head; | 148 | bh = head; |
127 | do { | 149 | do { |
128 | if (!buffer_mapped(bh)) { | 150 | if (!buffer_mapped(bh)) { |
129 | err = map_bh_to_logical(root, bh, first_block); | 151 | err = btrfs_map_bh_to_logical(root, bh, first_block); |
130 | BUG_ON(err); | 152 | BUG_ON(err); |
131 | } | 153 | } |
132 | if (bh_blocknr(bh) == blocknr) { | 154 | if (bh_blocknr(bh) == blocknr) { |
@@ -150,7 +172,7 @@ static int btree_get_block(struct inode *inode, sector_t iblock, | |||
150 | { | 172 | { |
151 | int err; | 173 | int err; |
152 | struct btrfs_root *root = BTRFS_I(bh->b_page->mapping->host)->root; | 174 | struct btrfs_root *root = BTRFS_I(bh->b_page->mapping->host)->root; |
153 | err = map_bh_to_logical(root, bh, iblock); | 175 | err = btrfs_map_bh_to_logical(root, bh, iblock); |
154 | return err; | 176 | return err; |
155 | } | 177 | } |
156 | 178 | ||
@@ -396,6 +418,89 @@ printk("all worked\n"); | |||
396 | return root; | 418 | return root; |
397 | } | 419 | } |
398 | 420 | ||
421 | int btrfs_open_disk(struct btrfs_root *root, u64 block_start, u64 num_blocks, | ||
422 | char *filename, int name_len) | ||
423 | { | ||
424 | char *null_filename; | ||
425 | struct block_device *bdev; | ||
426 | int ret; | ||
427 | |||
428 | if (block_start == 0) { | ||
429 | printk("skipping disk with block_start == 0\n"); | ||
430 | return 0; | ||
431 | } | ||
432 | null_filename = kmalloc(name_len + 1, GFP_NOFS); | ||
433 | if (!null_filename) | ||
434 | return -ENOMEM; | ||
435 | memcpy(null_filename, filename, name_len); | ||
436 | null_filename[name_len] = '\0'; | ||
437 | |||
438 | bdev = open_bdev_excl(null_filename, O_RDWR, root->fs_info->sb); | ||
439 | if (IS_ERR(bdev)) { | ||
440 | ret = PTR_ERR(bdev); | ||
441 | goto out; | ||
442 | } | ||
443 | set_blocksize(bdev, root->fs_info->sb->s_blocksize); | ||
444 | ret = btrfs_insert_dev_radix(root, bdev, block_start, num_blocks); | ||
445 | BUG_ON(ret); | ||
446 | ret = 0; | ||
447 | out: | ||
448 | kfree(null_filename); | ||
449 | return ret; | ||
450 | } | ||
451 | |||
452 | static int read_device_info(struct btrfs_root *root) | ||
453 | { | ||
454 | struct btrfs_path *path; | ||
455 | int ret; | ||
456 | struct btrfs_key key; | ||
457 | struct btrfs_leaf *leaf; | ||
458 | struct btrfs_device_item *dev_item; | ||
459 | int nritems; | ||
460 | int slot; | ||
461 | |||
462 | root = root->fs_info->dev_root; | ||
463 | |||
464 | path = btrfs_alloc_path(); | ||
465 | if (!path) | ||
466 | return -ENOMEM; | ||
467 | key.objectid = 0; | ||
468 | key.offset = 0; | ||
469 | key.flags = 0; | ||
470 | btrfs_set_key_type(&key, BTRFS_DEV_ITEM_KEY); | ||
471 | |||
472 | mutex_lock(&root->fs_info->fs_mutex); | ||
473 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | ||
474 | leaf = btrfs_buffer_leaf(path->nodes[0]); | ||
475 | nritems = btrfs_header_nritems(&leaf->header); | ||
476 | while(1) { | ||
477 | slot = path->slots[0]; | ||
478 | if (slot >= nritems) { | ||
479 | ret = btrfs_next_leaf(root, path); | ||
480 | if (ret) | ||
481 | break; | ||
482 | leaf = btrfs_buffer_leaf(path->nodes[0]); | ||
483 | nritems = btrfs_header_nritems(&leaf->header); | ||
484 | slot = path->slots[0]; | ||
485 | } | ||
486 | btrfs_disk_key_to_cpu(&key, &leaf->items[slot].key); | ||
487 | if (btrfs_key_type(&key) != BTRFS_DEV_ITEM_KEY) { | ||
488 | path->slots[0]++; | ||
489 | continue; | ||
490 | } | ||
491 | dev_item = btrfs_item_ptr(leaf, slot, struct btrfs_device_item); | ||
492 | printk("found key %Lu %Lu\n", key.objectid, key.offset); | ||
493 | ret = btrfs_open_disk(root, key.objectid, key.offset, | ||
494 | (char *)(dev_item + 1), | ||
495 | btrfs_device_pathlen(dev_item)); | ||
496 | BUG_ON(ret); | ||
497 | path->slots[0]++; | ||
498 | } | ||
499 | btrfs_free_path(path); | ||
500 | mutex_unlock(&root->fs_info->fs_mutex); | ||
501 | return 0; | ||
502 | } | ||
503 | |||
399 | struct btrfs_root *open_ctree(struct super_block *sb) | 504 | struct btrfs_root *open_ctree(struct super_block *sb) |
400 | { | 505 | { |
401 | struct btrfs_root *extent_root = kmalloc(sizeof(struct btrfs_root), | 506 | struct btrfs_root *extent_root = kmalloc(sizeof(struct btrfs_root), |
@@ -463,17 +568,26 @@ struct btrfs_root *open_ctree(struct super_block *sb) | |||
463 | if (!btrfs_super_root(disk_super)) | 568 | if (!btrfs_super_root(disk_super)) |
464 | return NULL; | 569 | return NULL; |
465 | 570 | ||
571 | i_size_write(fs_info->btree_inode, | ||
572 | btrfs_super_total_blocks(disk_super) << | ||
573 | fs_info->btree_inode->i_blkbits); | ||
574 | |||
466 | radix_tree_delete(&fs_info->dev_radix, (u32)-2); | 575 | radix_tree_delete(&fs_info->dev_radix, (u32)-2); |
467 | dev_lookup->block_start = btrfs_super_device_block_start(disk_super); | 576 | dev_lookup->block_start = btrfs_super_device_block_start(disk_super); |
468 | dev_lookup->num_blocks = btrfs_super_device_num_blocks(disk_super); | 577 | dev_lookup->num_blocks = btrfs_super_device_num_blocks(disk_super); |
469 | ret = radix_tree_insert(&fs_info->dev_radix, | 578 | ret = radix_tree_insert(&fs_info->dev_radix, |
470 | dev_lookup->block_start + | 579 | dev_lookup->block_start + |
471 | dev_lookup->num_blocks, dev_lookup); | 580 | dev_lookup->num_blocks - 1, dev_lookup); |
472 | BUG_ON(ret); | 581 | BUG_ON(ret); |
473 | 582 | ||
474 | fs_info->disk_super = disk_super; | 583 | fs_info->disk_super = disk_super; |
584 | |||
475 | dev_root->node = read_tree_block(tree_root, | 585 | dev_root->node = read_tree_block(tree_root, |
476 | btrfs_super_device_root(disk_super)); | 586 | btrfs_super_device_root(disk_super)); |
587 | |||
588 | ret = read_device_info(dev_root); | ||
589 | BUG_ON(ret); | ||
590 | |||
477 | tree_root->node = read_tree_block(tree_root, | 591 | tree_root->node = read_tree_block(tree_root, |
478 | btrfs_super_root(disk_super)); | 592 | btrfs_super_root(disk_super)); |
479 | BUG_ON(!tree_root->node); | 593 | BUG_ON(!tree_root->node); |
@@ -562,7 +676,7 @@ static int free_dev_radix(struct btrfs_fs_info *fs_info) | |||
562 | close_bdev_excl(lookup[i]->bdev); | 676 | close_bdev_excl(lookup[i]->bdev); |
563 | radix_tree_delete(&fs_info->dev_radix, | 677 | radix_tree_delete(&fs_info->dev_radix, |
564 | lookup[i]->block_start + | 678 | lookup[i]->block_start + |
565 | lookup[i]->num_blocks); | 679 | lookup[i]->num_blocks - 1); |
566 | kfree(lookup[i]); | 680 | kfree(lookup[i]); |
567 | } | 681 | } |
568 | } | 682 | } |
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h index 46cc5dc9d572..aa9f56c38419 100644 --- a/fs/btrfs/disk-io.h +++ b/fs/btrfs/disk-io.h | |||
@@ -42,4 +42,10 @@ int btrfs_csum_data(struct btrfs_root * root, char *data, size_t len, | |||
42 | struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, | 42 | struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, |
43 | struct btrfs_key *location); | 43 | struct btrfs_key *location); |
44 | u64 bh_blocknr(struct buffer_head *bh); | 44 | u64 bh_blocknr(struct buffer_head *bh); |
45 | int btrfs_insert_dev_radix(struct btrfs_root *root, | ||
46 | struct block_device *bdev, | ||
47 | u64 block_start, | ||
48 | u64 num_blocks); | ||
49 | int btrfs_map_bh_to_logical(struct btrfs_root *root, struct buffer_head *bh, | ||
50 | u64 logical); | ||
45 | #endif | 51 | #endif |
diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h index 201fb3270723..497fadd98c3a 100644 --- a/fs/btrfs/ioctl.h +++ b/fs/btrfs/ioctl.h | |||
@@ -10,4 +10,6 @@ struct btrfs_ioctl_vol_args { | |||
10 | 10 | ||
11 | #define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \ | 11 | #define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \ |
12 | struct btrfs_ioctl_vol_args) | 12 | struct btrfs_ioctl_vol_args) |
13 | #define BTRFS_IOC_ADD_DISK _IOW(BTRFS_IOCTL_MAGIC, 2, \ | ||
14 | struct btrfs_ioctl_vol_args) | ||
13 | #endif | 15 | #endif |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 4ff0cc1efb13..c46d7eafcf62 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -1073,6 +1073,7 @@ static int btrfs_get_block_lock(struct inode *inode, sector_t iblock, | |||
1073 | 1073 | ||
1074 | } | 1074 | } |
1075 | map_bh(result, inode->i_sb, blocknr); | 1075 | map_bh(result, inode->i_sb, blocknr); |
1076 | btrfs_map_bh_to_logical(root, result, blocknr); | ||
1076 | goto out; | 1077 | goto out; |
1077 | } | 1078 | } |
1078 | 1079 | ||
@@ -1092,7 +1093,8 @@ static int btrfs_get_block_lock(struct inode *inode, sector_t iblock, | |||
1092 | extent_end = extent_start + btrfs_file_extent_num_blocks(item); | 1093 | extent_end = extent_start + btrfs_file_extent_num_blocks(item); |
1093 | if (iblock >= extent_start && iblock < extent_end) { | 1094 | if (iblock >= extent_start && iblock < extent_end) { |
1094 | err = 0; | 1095 | err = 0; |
1095 | map_bh(result, inode->i_sb, blocknr + iblock - extent_start); | 1096 | btrfs_map_bh_to_logical(root, result, blocknr + iblock - |
1097 | extent_start); | ||
1096 | goto out; | 1098 | goto out; |
1097 | } | 1099 | } |
1098 | allocate: | 1100 | allocate: |
@@ -1112,6 +1114,7 @@ allocate: | |||
1112 | set_buffer_new(result); | 1114 | set_buffer_new(result); |
1113 | map_bh(result, inode->i_sb, blocknr); | 1115 | map_bh(result, inode->i_sb, blocknr); |
1114 | 1116 | ||
1117 | btrfs_map_bh_to_logical(root, result, blocknr); | ||
1115 | out: | 1118 | out: |
1116 | btrfs_release_path(root, path); | 1119 | btrfs_release_path(root, path); |
1117 | btrfs_free_path(path); | 1120 | btrfs_free_path(path); |
@@ -1153,12 +1156,6 @@ static int btrfs_readpage(struct file *file, struct page *page) | |||
1153 | return mpage_readpage(page, btrfs_get_block); | 1156 | return mpage_readpage(page, btrfs_get_block); |
1154 | } | 1157 | } |
1155 | 1158 | ||
1156 | static int btrfs_readpages(struct file *file, struct address_space *mapping, | ||
1157 | struct list_head *pages, unsigned nr_pages) | ||
1158 | { | ||
1159 | return mpage_readpages(mapping, pages, nr_pages, btrfs_get_block); | ||
1160 | } | ||
1161 | |||
1162 | static int btrfs_writepage(struct page *page, struct writeback_control *wbc) | 1159 | static int btrfs_writepage(struct page *page, struct writeback_control *wbc) |
1163 | { | 1160 | { |
1164 | return nobh_writepage(page, btrfs_get_block, wbc); | 1161 | return nobh_writepage(page, btrfs_get_block, wbc); |
@@ -1831,12 +1828,81 @@ printk("adding snapshot name %.*s root %Lu %Lu %u\n", namelen, name, key.objecti | |||
1831 | return 0; | 1828 | return 0; |
1832 | } | 1829 | } |
1833 | 1830 | ||
1831 | static int add_disk(struct btrfs_root *root, char *name, int namelen) | ||
1832 | { | ||
1833 | struct block_device *bdev; | ||
1834 | struct btrfs_path *path; | ||
1835 | struct super_block *sb = root->fs_info->sb; | ||
1836 | struct btrfs_root *dev_root = root->fs_info->dev_root; | ||
1837 | struct btrfs_trans_handle *trans; | ||
1838 | struct btrfs_device_item *dev_item; | ||
1839 | struct btrfs_key key; | ||
1840 | u16 item_size; | ||
1841 | u64 num_blocks; | ||
1842 | u64 new_blocks; | ||
1843 | int ret; | ||
1844 | printk("adding disk %s\n", name); | ||
1845 | path = btrfs_alloc_path(); | ||
1846 | if (!path) | ||
1847 | return -ENOMEM; | ||
1848 | num_blocks = btrfs_super_total_blocks(root->fs_info->disk_super); | ||
1849 | bdev = open_bdev_excl(name, O_RDWR, sb); | ||
1850 | if (IS_ERR(bdev)) { | ||
1851 | ret = PTR_ERR(bdev); | ||
1852 | printk("open bdev excl failed ret %d\n", ret); | ||
1853 | goto out_nolock; | ||
1854 | } | ||
1855 | set_blocksize(bdev, sb->s_blocksize); | ||
1856 | new_blocks = bdev->bd_inode->i_size >> sb->s_blocksize_bits; | ||
1857 | key.objectid = num_blocks; | ||
1858 | key.offset = new_blocks; | ||
1859 | key.flags = 0; | ||
1860 | btrfs_set_key_type(&key, BTRFS_DEV_ITEM_KEY); | ||
1861 | |||
1862 | mutex_lock(&dev_root->fs_info->fs_mutex); | ||
1863 | trans = btrfs_start_transaction(dev_root, 1); | ||
1864 | item_size = sizeof(*dev_item) + namelen; | ||
1865 | printk("insert empty on %Lu %Lu %u size %d\n", num_blocks, new_blocks, key.flags, item_size); | ||
1866 | ret = btrfs_insert_empty_item(trans, dev_root, path, &key, item_size); | ||
1867 | if (ret) { | ||
1868 | printk("insert failed %d\n", ret); | ||
1869 | close_bdev_excl(bdev); | ||
1870 | if (ret > 0) | ||
1871 | ret = -EEXIST; | ||
1872 | goto out; | ||
1873 | } | ||
1874 | dev_item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), | ||
1875 | path->slots[0], struct btrfs_device_item); | ||
1876 | btrfs_set_device_pathlen(dev_item, namelen); | ||
1877 | memcpy(dev_item + 1, name, namelen); | ||
1878 | mark_buffer_dirty(path->nodes[0]); | ||
1879 | |||
1880 | ret = btrfs_insert_dev_radix(root, bdev, num_blocks, new_blocks); | ||
1881 | |||
1882 | if (!ret) { | ||
1883 | btrfs_set_super_total_blocks(root->fs_info->disk_super, | ||
1884 | num_blocks + new_blocks); | ||
1885 | i_size_write(root->fs_info->btree_inode, | ||
1886 | (num_blocks + new_blocks) << | ||
1887 | root->fs_info->btree_inode->i_blkbits); | ||
1888 | } | ||
1889 | |||
1890 | out: | ||
1891 | ret = btrfs_commit_transaction(trans, dev_root); | ||
1892 | BUG_ON(ret); | ||
1893 | mutex_unlock(&root->fs_info->fs_mutex); | ||
1894 | out_nolock: | ||
1895 | btrfs_free_path(path); | ||
1896 | |||
1897 | return ret; | ||
1898 | } | ||
1899 | |||
1834 | static int btrfs_ioctl(struct inode *inode, struct file *filp, unsigned int | 1900 | static int btrfs_ioctl(struct inode *inode, struct file *filp, unsigned int |
1835 | cmd, unsigned long arg) | 1901 | cmd, unsigned long arg) |
1836 | { | 1902 | { |
1837 | struct btrfs_root *root = BTRFS_I(inode)->root; | 1903 | struct btrfs_root *root = BTRFS_I(inode)->root; |
1838 | struct btrfs_ioctl_vol_args vol_args; | 1904 | struct btrfs_ioctl_vol_args vol_args; |
1839 | int ret; | 1905 | int ret = 0; |
1840 | int namelen; | 1906 | int namelen; |
1841 | struct btrfs_path *path; | 1907 | struct btrfs_path *path; |
1842 | u64 root_dirid; | 1908 | u64 root_dirid; |
@@ -1869,10 +1935,21 @@ static int btrfs_ioctl(struct inode *inode, struct file *filp, unsigned int | |||
1869 | ret = create_snapshot(root, vol_args.name, namelen); | 1935 | ret = create_snapshot(root, vol_args.name, namelen); |
1870 | WARN_ON(ret); | 1936 | WARN_ON(ret); |
1871 | break; | 1937 | break; |
1938 | case BTRFS_IOC_ADD_DISK: | ||
1939 | if (copy_from_user(&vol_args, | ||
1940 | (struct btrfs_ioctl_vol_args __user *)arg, | ||
1941 | sizeof(vol_args))) | ||
1942 | return -EFAULT; | ||
1943 | namelen = strlen(vol_args.name); | ||
1944 | if (namelen > BTRFS_VOL_NAME_MAX) | ||
1945 | return -EINVAL; | ||
1946 | vol_args.name[namelen] = '\0'; | ||
1947 | ret = add_disk(root, vol_args.name, namelen); | ||
1948 | break; | ||
1872 | default: | 1949 | default: |
1873 | return -ENOTTY; | 1950 | return -ENOTTY; |
1874 | } | 1951 | } |
1875 | return 0; | 1952 | return ret; |
1876 | } | 1953 | } |
1877 | 1954 | ||
1878 | static struct kmem_cache *btrfs_inode_cachep; | 1955 | static struct kmem_cache *btrfs_inode_cachep; |
@@ -2004,7 +2081,6 @@ static struct file_operations btrfs_dir_file_operations = { | |||
2004 | 2081 | ||
2005 | static struct address_space_operations btrfs_aops = { | 2082 | static struct address_space_operations btrfs_aops = { |
2006 | .readpage = btrfs_readpage, | 2083 | .readpage = btrfs_readpage, |
2007 | .readpages = btrfs_readpages, | ||
2008 | .writepage = btrfs_writepage, | 2084 | .writepage = btrfs_writepage, |
2009 | .sync_page = block_sync_page, | 2085 | .sync_page = block_sync_page, |
2010 | .prepare_write = btrfs_prepare_write, | 2086 | .prepare_write = btrfs_prepare_write, |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 3a15943ea8ed..8740752f3845 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -116,7 +116,13 @@ int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans, | |||
116 | struct btrfs_fs_info *fs_info = root->fs_info; | 116 | struct btrfs_fs_info *fs_info = root->fs_info; |
117 | struct btrfs_root *tree_root = fs_info->tree_root; | 117 | struct btrfs_root *tree_root = fs_info->tree_root; |
118 | struct btrfs_root *extent_root = fs_info->extent_root; | 118 | struct btrfs_root *extent_root = fs_info->extent_root; |
119 | struct btrfs_root *dev_root = fs_info->dev_root; | ||
119 | 120 | ||
121 | if (btrfs_super_device_root(fs_info->disk_super) != | ||
122 | bh_blocknr(dev_root->node)) { | ||
123 | btrfs_set_super_device_root(fs_info->disk_super, | ||
124 | bh_blocknr(dev_root->node)); | ||
125 | } | ||
120 | while(1) { | 126 | while(1) { |
121 | old_extent_block = btrfs_root_blocknr(&extent_root->root_item); | 127 | old_extent_block = btrfs_root_blocknr(&extent_root->root_item); |
122 | if (old_extent_block == bh_blocknr(extent_root->node)) | 128 | if (old_extent_block == bh_blocknr(extent_root->node)) |