Loading fs/btrfs/disk-io.c +121 −7 Original line number Diff line number Diff line Loading @@ -16,6 +16,28 @@ struct dev_lookup { struct block_device *bdev; }; int btrfs_insert_dev_radix(struct btrfs_root *root, struct block_device *bdev, u64 block_start, u64 num_blocks) { struct dev_lookup *lookup; char b[BDEVNAME_SIZE]; int ret; lookup = kmalloc(sizeof(*lookup), GFP_NOFS); if (!lookup) return -ENOMEM; lookup->block_start = block_start; lookup->num_blocks = num_blocks; lookup->bdev = bdev; printk("inserting %s into dev radix %Lu %Lu\n", bdevname(bdev, b), block_start, num_blocks); ret = radix_tree_insert(&root->fs_info->dev_radix, block_start + num_blocks - 1, lookup); return ret; } u64 bh_blocknr(struct buffer_head *bh) { int blkbits = bh->b_page->mapping->host->i_blkbits; Loading @@ -34,6 +56,8 @@ static int check_tree_block(struct btrfs_root *root, struct buffer_head *buf) { struct btrfs_node *node = btrfs_buffer_node(buf); if (bh_blocknr(buf) != btrfs_header_blocknr(&node->header)) { printk(KERN_CRIT "bh_blocknr(buf) is %Lu, header is %Lu\n", bh_blocknr(buf), btrfs_header_blocknr(&node->header)); BUG(); } return 0; Loading Loading @@ -76,11 +100,10 @@ struct buffer_head *btrfs_find_tree_block(struct btrfs_root *root, u64 blocknr) return ret; } static int map_bh_to_logical(struct btrfs_root *root, struct buffer_head *bh, int btrfs_map_bh_to_logical(struct btrfs_root *root, struct buffer_head *bh, u64 logical) { struct dev_lookup *lookup[2]; char b[BDEVNAME_SIZE]; int ret; Loading @@ -96,7 +119,6 @@ static int map_bh_to_logical(struct btrfs_root *root, struct buffer_head *bh, } bh->b_bdev = lookup[0]->bdev; bh->b_blocknr = logical - lookup[0]->block_start; printk("logical mapping %Lu to %lu bdev %s\n", logical, bh->b_blocknr, bdevname(bh->b_bdev, b)); set_buffer_mapped(bh); ret = 0; out: Loading Loading @@ -126,7 +148,7 @@ struct buffer_head *btrfs_find_create_tree_block(struct btrfs_root *root, bh = head; do { if (!buffer_mapped(bh)) { err = map_bh_to_logical(root, bh, first_block); err = btrfs_map_bh_to_logical(root, bh, first_block); BUG_ON(err); } if (bh_blocknr(bh) == blocknr) { Loading @@ -150,7 +172,7 @@ static int btree_get_block(struct inode *inode, sector_t iblock, { int err; struct btrfs_root *root = BTRFS_I(bh->b_page->mapping->host)->root; err = map_bh_to_logical(root, bh, iblock); err = btrfs_map_bh_to_logical(root, bh, iblock); return err; } Loading Loading @@ -396,6 +418,89 @@ printk("all worked\n"); return root; } int btrfs_open_disk(struct btrfs_root *root, u64 block_start, u64 num_blocks, char *filename, int name_len) { char *null_filename; struct block_device *bdev; int ret; if (block_start == 0) { printk("skipping disk with block_start == 0\n"); return 0; } null_filename = kmalloc(name_len + 1, GFP_NOFS); if (!null_filename) return -ENOMEM; memcpy(null_filename, filename, name_len); null_filename[name_len] = '\0'; bdev = open_bdev_excl(null_filename, O_RDWR, root->fs_info->sb); if (IS_ERR(bdev)) { ret = PTR_ERR(bdev); goto out; } set_blocksize(bdev, root->fs_info->sb->s_blocksize); ret = btrfs_insert_dev_radix(root, bdev, block_start, num_blocks); BUG_ON(ret); ret = 0; out: kfree(null_filename); return ret; } static int read_device_info(struct btrfs_root *root) { struct btrfs_path *path; int ret; struct btrfs_key key; struct btrfs_leaf *leaf; struct btrfs_device_item *dev_item; int nritems; int slot; root = root->fs_info->dev_root; path = btrfs_alloc_path(); if (!path) return -ENOMEM; key.objectid = 0; key.offset = 0; key.flags = 0; btrfs_set_key_type(&key, BTRFS_DEV_ITEM_KEY); mutex_lock(&root->fs_info->fs_mutex); ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); leaf = btrfs_buffer_leaf(path->nodes[0]); nritems = btrfs_header_nritems(&leaf->header); while(1) { slot = path->slots[0]; if (slot >= nritems) { ret = btrfs_next_leaf(root, path); if (ret) break; leaf = btrfs_buffer_leaf(path->nodes[0]); nritems = btrfs_header_nritems(&leaf->header); slot = path->slots[0]; } btrfs_disk_key_to_cpu(&key, &leaf->items[slot].key); if (btrfs_key_type(&key) != BTRFS_DEV_ITEM_KEY) { path->slots[0]++; continue; } dev_item = btrfs_item_ptr(leaf, slot, struct btrfs_device_item); printk("found key %Lu %Lu\n", key.objectid, key.offset); ret = btrfs_open_disk(root, key.objectid, key.offset, (char *)(dev_item + 1), btrfs_device_pathlen(dev_item)); BUG_ON(ret); path->slots[0]++; } btrfs_free_path(path); mutex_unlock(&root->fs_info->fs_mutex); return 0; } struct btrfs_root *open_ctree(struct super_block *sb) { struct btrfs_root *extent_root = kmalloc(sizeof(struct btrfs_root), Loading Loading @@ -463,17 +568,26 @@ struct btrfs_root *open_ctree(struct super_block *sb) if (!btrfs_super_root(disk_super)) return NULL; i_size_write(fs_info->btree_inode, btrfs_super_total_blocks(disk_super) << fs_info->btree_inode->i_blkbits); radix_tree_delete(&fs_info->dev_radix, (u32)-2); dev_lookup->block_start = btrfs_super_device_block_start(disk_super); dev_lookup->num_blocks = btrfs_super_device_num_blocks(disk_super); ret = radix_tree_insert(&fs_info->dev_radix, dev_lookup->block_start + dev_lookup->num_blocks, dev_lookup); dev_lookup->num_blocks - 1, dev_lookup); BUG_ON(ret); fs_info->disk_super = disk_super; dev_root->node = read_tree_block(tree_root, btrfs_super_device_root(disk_super)); ret = read_device_info(dev_root); BUG_ON(ret); tree_root->node = read_tree_block(tree_root, btrfs_super_root(disk_super)); BUG_ON(!tree_root->node); Loading Loading @@ -562,7 +676,7 @@ static int free_dev_radix(struct btrfs_fs_info *fs_info) close_bdev_excl(lookup[i]->bdev); radix_tree_delete(&fs_info->dev_radix, lookup[i]->block_start + lookup[i]->num_blocks); lookup[i]->num_blocks - 1); kfree(lookup[i]); } } Loading fs/btrfs/disk-io.h +6 −0 Original line number Diff line number Diff line Loading @@ -42,4 +42,10 @@ int btrfs_csum_data(struct btrfs_root * root, char *data, size_t len, struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_key *location); u64 bh_blocknr(struct buffer_head *bh); int btrfs_insert_dev_radix(struct btrfs_root *root, struct block_device *bdev, u64 block_start, u64 num_blocks); int btrfs_map_bh_to_logical(struct btrfs_root *root, struct buffer_head *bh, u64 logical); #endif fs/btrfs/ioctl.h +2 −0 Original line number Diff line number Diff line Loading @@ -10,4 +10,6 @@ struct btrfs_ioctl_vol_args { #define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \ struct btrfs_ioctl_vol_args) #define BTRFS_IOC_ADD_DISK _IOW(BTRFS_IOCTL_MAGIC, 2, \ struct btrfs_ioctl_vol_args) #endif fs/btrfs/super.c +86 −10 Original line number Diff line number Diff line Loading @@ -1073,6 +1073,7 @@ static int btrfs_get_block_lock(struct inode *inode, sector_t iblock, } map_bh(result, inode->i_sb, blocknr); btrfs_map_bh_to_logical(root, result, blocknr); goto out; } Loading @@ -1092,7 +1093,8 @@ static int btrfs_get_block_lock(struct inode *inode, sector_t iblock, extent_end = extent_start + btrfs_file_extent_num_blocks(item); if (iblock >= extent_start && iblock < extent_end) { err = 0; map_bh(result, inode->i_sb, blocknr + iblock - extent_start); btrfs_map_bh_to_logical(root, result, blocknr + iblock - extent_start); goto out; } allocate: Loading @@ -1112,6 +1114,7 @@ static int btrfs_get_block_lock(struct inode *inode, sector_t iblock, set_buffer_new(result); map_bh(result, inode->i_sb, blocknr); btrfs_map_bh_to_logical(root, result, blocknr); out: btrfs_release_path(root, path); btrfs_free_path(path); Loading Loading @@ -1153,12 +1156,6 @@ static int btrfs_readpage(struct file *file, struct page *page) return mpage_readpage(page, btrfs_get_block); } static int btrfs_readpages(struct file *file, struct address_space *mapping, struct list_head *pages, unsigned nr_pages) { return mpage_readpages(mapping, pages, nr_pages, btrfs_get_block); } static int btrfs_writepage(struct page *page, struct writeback_control *wbc) { return nobh_writepage(page, btrfs_get_block, wbc); Loading Loading @@ -1831,12 +1828,81 @@ printk("adding snapshot name %.*s root %Lu %Lu %u\n", namelen, name, key.objecti return 0; } static int add_disk(struct btrfs_root *root, char *name, int namelen) { struct block_device *bdev; struct btrfs_path *path; struct super_block *sb = root->fs_info->sb; struct btrfs_root *dev_root = root->fs_info->dev_root; struct btrfs_trans_handle *trans; struct btrfs_device_item *dev_item; struct btrfs_key key; u16 item_size; u64 num_blocks; u64 new_blocks; int ret; printk("adding disk %s\n", name); path = btrfs_alloc_path(); if (!path) return -ENOMEM; num_blocks = btrfs_super_total_blocks(root->fs_info->disk_super); bdev = open_bdev_excl(name, O_RDWR, sb); if (IS_ERR(bdev)) { ret = PTR_ERR(bdev); printk("open bdev excl failed ret %d\n", ret); goto out_nolock; } set_blocksize(bdev, sb->s_blocksize); new_blocks = bdev->bd_inode->i_size >> sb->s_blocksize_bits; key.objectid = num_blocks; key.offset = new_blocks; key.flags = 0; btrfs_set_key_type(&key, BTRFS_DEV_ITEM_KEY); mutex_lock(&dev_root->fs_info->fs_mutex); trans = btrfs_start_transaction(dev_root, 1); item_size = sizeof(*dev_item) + namelen; printk("insert empty on %Lu %Lu %u size %d\n", num_blocks, new_blocks, key.flags, item_size); ret = btrfs_insert_empty_item(trans, dev_root, path, &key, item_size); if (ret) { printk("insert failed %d\n", ret); close_bdev_excl(bdev); if (ret > 0) ret = -EEXIST; goto out; } dev_item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], struct btrfs_device_item); btrfs_set_device_pathlen(dev_item, namelen); memcpy(dev_item + 1, name, namelen); mark_buffer_dirty(path->nodes[0]); ret = btrfs_insert_dev_radix(root, bdev, num_blocks, new_blocks); if (!ret) { btrfs_set_super_total_blocks(root->fs_info->disk_super, num_blocks + new_blocks); i_size_write(root->fs_info->btree_inode, (num_blocks + new_blocks) << root->fs_info->btree_inode->i_blkbits); } out: ret = btrfs_commit_transaction(trans, dev_root); BUG_ON(ret); mutex_unlock(&root->fs_info->fs_mutex); out_nolock: btrfs_free_path(path); return ret; } static int btrfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_ioctl_vol_args vol_args; int ret; int ret = 0; int namelen; struct btrfs_path *path; u64 root_dirid; Loading Loading @@ -1869,10 +1935,21 @@ static int btrfs_ioctl(struct inode *inode, struct file *filp, unsigned int ret = create_snapshot(root, vol_args.name, namelen); WARN_ON(ret); break; case BTRFS_IOC_ADD_DISK: if (copy_from_user(&vol_args, (struct btrfs_ioctl_vol_args __user *)arg, sizeof(vol_args))) return -EFAULT; namelen = strlen(vol_args.name); if (namelen > BTRFS_VOL_NAME_MAX) return -EINVAL; vol_args.name[namelen] = '\0'; ret = add_disk(root, vol_args.name, namelen); break; default: return -ENOTTY; } return 0; return ret; } static struct kmem_cache *btrfs_inode_cachep; Loading Loading @@ -2004,7 +2081,6 @@ static struct file_operations btrfs_dir_file_operations = { static struct address_space_operations btrfs_aops = { .readpage = btrfs_readpage, .readpages = btrfs_readpages, .writepage = btrfs_writepage, .sync_page = block_sync_page, .prepare_write = btrfs_prepare_write, Loading fs/btrfs/transaction.c +6 −0 Original line number Diff line number Diff line Loading @@ -116,7 +116,13 @@ int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_root *tree_root = fs_info->tree_root; struct btrfs_root *extent_root = fs_info->extent_root; struct btrfs_root *dev_root = fs_info->dev_root; if (btrfs_super_device_root(fs_info->disk_super) != bh_blocknr(dev_root->node)) { btrfs_set_super_device_root(fs_info->disk_super, bh_blocknr(dev_root->node)); } while(1) { old_extent_block = btrfs_root_blocknr(&extent_root->root_item); if (old_extent_block == bh_blocknr(extent_root->node)) Loading Loading
fs/btrfs/disk-io.c +121 −7 Original line number Diff line number Diff line Loading @@ -16,6 +16,28 @@ struct dev_lookup { struct block_device *bdev; }; int btrfs_insert_dev_radix(struct btrfs_root *root, struct block_device *bdev, u64 block_start, u64 num_blocks) { struct dev_lookup *lookup; char b[BDEVNAME_SIZE]; int ret; lookup = kmalloc(sizeof(*lookup), GFP_NOFS); if (!lookup) return -ENOMEM; lookup->block_start = block_start; lookup->num_blocks = num_blocks; lookup->bdev = bdev; printk("inserting %s into dev radix %Lu %Lu\n", bdevname(bdev, b), block_start, num_blocks); ret = radix_tree_insert(&root->fs_info->dev_radix, block_start + num_blocks - 1, lookup); return ret; } u64 bh_blocknr(struct buffer_head *bh) { int blkbits = bh->b_page->mapping->host->i_blkbits; Loading @@ -34,6 +56,8 @@ static int check_tree_block(struct btrfs_root *root, struct buffer_head *buf) { struct btrfs_node *node = btrfs_buffer_node(buf); if (bh_blocknr(buf) != btrfs_header_blocknr(&node->header)) { printk(KERN_CRIT "bh_blocknr(buf) is %Lu, header is %Lu\n", bh_blocknr(buf), btrfs_header_blocknr(&node->header)); BUG(); } return 0; Loading Loading @@ -76,11 +100,10 @@ struct buffer_head *btrfs_find_tree_block(struct btrfs_root *root, u64 blocknr) return ret; } static int map_bh_to_logical(struct btrfs_root *root, struct buffer_head *bh, int btrfs_map_bh_to_logical(struct btrfs_root *root, struct buffer_head *bh, u64 logical) { struct dev_lookup *lookup[2]; char b[BDEVNAME_SIZE]; int ret; Loading @@ -96,7 +119,6 @@ static int map_bh_to_logical(struct btrfs_root *root, struct buffer_head *bh, } bh->b_bdev = lookup[0]->bdev; bh->b_blocknr = logical - lookup[0]->block_start; printk("logical mapping %Lu to %lu bdev %s\n", logical, bh->b_blocknr, bdevname(bh->b_bdev, b)); set_buffer_mapped(bh); ret = 0; out: Loading Loading @@ -126,7 +148,7 @@ struct buffer_head *btrfs_find_create_tree_block(struct btrfs_root *root, bh = head; do { if (!buffer_mapped(bh)) { err = map_bh_to_logical(root, bh, first_block); err = btrfs_map_bh_to_logical(root, bh, first_block); BUG_ON(err); } if (bh_blocknr(bh) == blocknr) { Loading @@ -150,7 +172,7 @@ static int btree_get_block(struct inode *inode, sector_t iblock, { int err; struct btrfs_root *root = BTRFS_I(bh->b_page->mapping->host)->root; err = map_bh_to_logical(root, bh, iblock); err = btrfs_map_bh_to_logical(root, bh, iblock); return err; } Loading Loading @@ -396,6 +418,89 @@ printk("all worked\n"); return root; } int btrfs_open_disk(struct btrfs_root *root, u64 block_start, u64 num_blocks, char *filename, int name_len) { char *null_filename; struct block_device *bdev; int ret; if (block_start == 0) { printk("skipping disk with block_start == 0\n"); return 0; } null_filename = kmalloc(name_len + 1, GFP_NOFS); if (!null_filename) return -ENOMEM; memcpy(null_filename, filename, name_len); null_filename[name_len] = '\0'; bdev = open_bdev_excl(null_filename, O_RDWR, root->fs_info->sb); if (IS_ERR(bdev)) { ret = PTR_ERR(bdev); goto out; } set_blocksize(bdev, root->fs_info->sb->s_blocksize); ret = btrfs_insert_dev_radix(root, bdev, block_start, num_blocks); BUG_ON(ret); ret = 0; out: kfree(null_filename); return ret; } static int read_device_info(struct btrfs_root *root) { struct btrfs_path *path; int ret; struct btrfs_key key; struct btrfs_leaf *leaf; struct btrfs_device_item *dev_item; int nritems; int slot; root = root->fs_info->dev_root; path = btrfs_alloc_path(); if (!path) return -ENOMEM; key.objectid = 0; key.offset = 0; key.flags = 0; btrfs_set_key_type(&key, BTRFS_DEV_ITEM_KEY); mutex_lock(&root->fs_info->fs_mutex); ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); leaf = btrfs_buffer_leaf(path->nodes[0]); nritems = btrfs_header_nritems(&leaf->header); while(1) { slot = path->slots[0]; if (slot >= nritems) { ret = btrfs_next_leaf(root, path); if (ret) break; leaf = btrfs_buffer_leaf(path->nodes[0]); nritems = btrfs_header_nritems(&leaf->header); slot = path->slots[0]; } btrfs_disk_key_to_cpu(&key, &leaf->items[slot].key); if (btrfs_key_type(&key) != BTRFS_DEV_ITEM_KEY) { path->slots[0]++; continue; } dev_item = btrfs_item_ptr(leaf, slot, struct btrfs_device_item); printk("found key %Lu %Lu\n", key.objectid, key.offset); ret = btrfs_open_disk(root, key.objectid, key.offset, (char *)(dev_item + 1), btrfs_device_pathlen(dev_item)); BUG_ON(ret); path->slots[0]++; } btrfs_free_path(path); mutex_unlock(&root->fs_info->fs_mutex); return 0; } struct btrfs_root *open_ctree(struct super_block *sb) { struct btrfs_root *extent_root = kmalloc(sizeof(struct btrfs_root), Loading Loading @@ -463,17 +568,26 @@ struct btrfs_root *open_ctree(struct super_block *sb) if (!btrfs_super_root(disk_super)) return NULL; i_size_write(fs_info->btree_inode, btrfs_super_total_blocks(disk_super) << fs_info->btree_inode->i_blkbits); radix_tree_delete(&fs_info->dev_radix, (u32)-2); dev_lookup->block_start = btrfs_super_device_block_start(disk_super); dev_lookup->num_blocks = btrfs_super_device_num_blocks(disk_super); ret = radix_tree_insert(&fs_info->dev_radix, dev_lookup->block_start + dev_lookup->num_blocks, dev_lookup); dev_lookup->num_blocks - 1, dev_lookup); BUG_ON(ret); fs_info->disk_super = disk_super; dev_root->node = read_tree_block(tree_root, btrfs_super_device_root(disk_super)); ret = read_device_info(dev_root); BUG_ON(ret); tree_root->node = read_tree_block(tree_root, btrfs_super_root(disk_super)); BUG_ON(!tree_root->node); Loading Loading @@ -562,7 +676,7 @@ static int free_dev_radix(struct btrfs_fs_info *fs_info) close_bdev_excl(lookup[i]->bdev); radix_tree_delete(&fs_info->dev_radix, lookup[i]->block_start + lookup[i]->num_blocks); lookup[i]->num_blocks - 1); kfree(lookup[i]); } } Loading
fs/btrfs/disk-io.h +6 −0 Original line number Diff line number Diff line Loading @@ -42,4 +42,10 @@ int btrfs_csum_data(struct btrfs_root * root, char *data, size_t len, struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_key *location); u64 bh_blocknr(struct buffer_head *bh); int btrfs_insert_dev_radix(struct btrfs_root *root, struct block_device *bdev, u64 block_start, u64 num_blocks); int btrfs_map_bh_to_logical(struct btrfs_root *root, struct buffer_head *bh, u64 logical); #endif
fs/btrfs/ioctl.h +2 −0 Original line number Diff line number Diff line Loading @@ -10,4 +10,6 @@ struct btrfs_ioctl_vol_args { #define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \ struct btrfs_ioctl_vol_args) #define BTRFS_IOC_ADD_DISK _IOW(BTRFS_IOCTL_MAGIC, 2, \ struct btrfs_ioctl_vol_args) #endif
fs/btrfs/super.c +86 −10 Original line number Diff line number Diff line Loading @@ -1073,6 +1073,7 @@ static int btrfs_get_block_lock(struct inode *inode, sector_t iblock, } map_bh(result, inode->i_sb, blocknr); btrfs_map_bh_to_logical(root, result, blocknr); goto out; } Loading @@ -1092,7 +1093,8 @@ static int btrfs_get_block_lock(struct inode *inode, sector_t iblock, extent_end = extent_start + btrfs_file_extent_num_blocks(item); if (iblock >= extent_start && iblock < extent_end) { err = 0; map_bh(result, inode->i_sb, blocknr + iblock - extent_start); btrfs_map_bh_to_logical(root, result, blocknr + iblock - extent_start); goto out; } allocate: Loading @@ -1112,6 +1114,7 @@ static int btrfs_get_block_lock(struct inode *inode, sector_t iblock, set_buffer_new(result); map_bh(result, inode->i_sb, blocknr); btrfs_map_bh_to_logical(root, result, blocknr); out: btrfs_release_path(root, path); btrfs_free_path(path); Loading Loading @@ -1153,12 +1156,6 @@ static int btrfs_readpage(struct file *file, struct page *page) return mpage_readpage(page, btrfs_get_block); } static int btrfs_readpages(struct file *file, struct address_space *mapping, struct list_head *pages, unsigned nr_pages) { return mpage_readpages(mapping, pages, nr_pages, btrfs_get_block); } static int btrfs_writepage(struct page *page, struct writeback_control *wbc) { return nobh_writepage(page, btrfs_get_block, wbc); Loading Loading @@ -1831,12 +1828,81 @@ printk("adding snapshot name %.*s root %Lu %Lu %u\n", namelen, name, key.objecti return 0; } static int add_disk(struct btrfs_root *root, char *name, int namelen) { struct block_device *bdev; struct btrfs_path *path; struct super_block *sb = root->fs_info->sb; struct btrfs_root *dev_root = root->fs_info->dev_root; struct btrfs_trans_handle *trans; struct btrfs_device_item *dev_item; struct btrfs_key key; u16 item_size; u64 num_blocks; u64 new_blocks; int ret; printk("adding disk %s\n", name); path = btrfs_alloc_path(); if (!path) return -ENOMEM; num_blocks = btrfs_super_total_blocks(root->fs_info->disk_super); bdev = open_bdev_excl(name, O_RDWR, sb); if (IS_ERR(bdev)) { ret = PTR_ERR(bdev); printk("open bdev excl failed ret %d\n", ret); goto out_nolock; } set_blocksize(bdev, sb->s_blocksize); new_blocks = bdev->bd_inode->i_size >> sb->s_blocksize_bits; key.objectid = num_blocks; key.offset = new_blocks; key.flags = 0; btrfs_set_key_type(&key, BTRFS_DEV_ITEM_KEY); mutex_lock(&dev_root->fs_info->fs_mutex); trans = btrfs_start_transaction(dev_root, 1); item_size = sizeof(*dev_item) + namelen; printk("insert empty on %Lu %Lu %u size %d\n", num_blocks, new_blocks, key.flags, item_size); ret = btrfs_insert_empty_item(trans, dev_root, path, &key, item_size); if (ret) { printk("insert failed %d\n", ret); close_bdev_excl(bdev); if (ret > 0) ret = -EEXIST; goto out; } dev_item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], struct btrfs_device_item); btrfs_set_device_pathlen(dev_item, namelen); memcpy(dev_item + 1, name, namelen); mark_buffer_dirty(path->nodes[0]); ret = btrfs_insert_dev_radix(root, bdev, num_blocks, new_blocks); if (!ret) { btrfs_set_super_total_blocks(root->fs_info->disk_super, num_blocks + new_blocks); i_size_write(root->fs_info->btree_inode, (num_blocks + new_blocks) << root->fs_info->btree_inode->i_blkbits); } out: ret = btrfs_commit_transaction(trans, dev_root); BUG_ON(ret); mutex_unlock(&root->fs_info->fs_mutex); out_nolock: btrfs_free_path(path); return ret; } static int btrfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_ioctl_vol_args vol_args; int ret; int ret = 0; int namelen; struct btrfs_path *path; u64 root_dirid; Loading Loading @@ -1869,10 +1935,21 @@ static int btrfs_ioctl(struct inode *inode, struct file *filp, unsigned int ret = create_snapshot(root, vol_args.name, namelen); WARN_ON(ret); break; case BTRFS_IOC_ADD_DISK: if (copy_from_user(&vol_args, (struct btrfs_ioctl_vol_args __user *)arg, sizeof(vol_args))) return -EFAULT; namelen = strlen(vol_args.name); if (namelen > BTRFS_VOL_NAME_MAX) return -EINVAL; vol_args.name[namelen] = '\0'; ret = add_disk(root, vol_args.name, namelen); break; default: return -ENOTTY; } return 0; return ret; } static struct kmem_cache *btrfs_inode_cachep; Loading Loading @@ -2004,7 +2081,6 @@ static struct file_operations btrfs_dir_file_operations = { static struct address_space_operations btrfs_aops = { .readpage = btrfs_readpage, .readpages = btrfs_readpages, .writepage = btrfs_writepage, .sync_page = block_sync_page, .prepare_write = btrfs_prepare_write, Loading
fs/btrfs/transaction.c +6 −0 Original line number Diff line number Diff line Loading @@ -116,7 +116,13 @@ int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_root *tree_root = fs_info->tree_root; struct btrfs_root *extent_root = fs_info->extent_root; struct btrfs_root *dev_root = fs_info->dev_root; if (btrfs_super_device_root(fs_info->disk_super) != bh_blocknr(dev_root->node)) { btrfs_set_super_device_root(fs_info->disk_super, bh_blocknr(dev_root->node)); } while(1) { old_extent_block = btrfs_root_blocknr(&extent_root->root_item); if (old_extent_block == bh_blocknr(extent_root->node)) Loading