diff options
Diffstat (limited to 'fs/btrfs/super.c')
-rw-r--r-- | fs/btrfs/super.c | 96 |
1 files changed, 86 insertions, 10 deletions
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, |