Commit b82207b8 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs

Pull btrfs fixes from Chris Mason:
 "We've queued up a few fixes in my for-linus branch"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs:
  Btrfs: fix crash when starting transaction
  Btrfs: fix btrfs_print_leaf for skinny metadata
  Btrfs: fix race of using total_bytes_pinned
  btrfs: use E2BIG instead of EIO if compression does not help
  btrfs: remove stale comment from btrfs_flush_all_pending_stuffs
  Btrfs: fix use-after-free when cloning a trailing file hole
  btrfs: fix null pointer dereference in btrfs_show_devname when name is null
  btrfs: fix null pointer dereference in clone_fs_devices when name is null
  btrfs: fix nossd and ssd_spread mount option regression
  Btrfs: fix race between balance recovery and root deletion
  Btrfs: atomically set inode->i_flags in btrfs_update_iflags
  btrfs: only unlock block in verify_parent_transid if we locked it
  Btrfs: assert send doesn't attempt to start transactions
  btrfs compression: reuse recently used workspace
  Btrfs: fix crash when mounting raid5 btrfs with missing disks
  btrfs: create sprout should rename fsid on the sysfs as well
  btrfs: dev replace should replace the sysfs entry
  btrfs: dev add should add its sysfs entry
  btrfs: dev delete should remove sysfs entry
  btrfs: rename add_device_membership to btrfs_kobj_add_device
parents 034a0f6b abdd2e80
...@@ -821,7 +821,7 @@ static void free_workspace(int type, struct list_head *workspace) ...@@ -821,7 +821,7 @@ static void free_workspace(int type, struct list_head *workspace)
spin_lock(workspace_lock); spin_lock(workspace_lock);
if (*num_workspace < num_online_cpus()) { if (*num_workspace < num_online_cpus()) {
list_add_tail(workspace, idle_workspace); list_add(workspace, idle_workspace);
(*num_workspace)++; (*num_workspace)++;
spin_unlock(workspace_lock); spin_unlock(workspace_lock);
goto wake; goto wake;
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include "check-integrity.h" #include "check-integrity.h"
#include "rcu-string.h" #include "rcu-string.h"
#include "dev-replace.h" #include "dev-replace.h"
#include "sysfs.h"
static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info, static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
int scrub_ret); int scrub_ret);
...@@ -562,6 +563,10 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info, ...@@ -562,6 +563,10 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
fs_info->fs_devices->latest_bdev = tgt_device->bdev; fs_info->fs_devices->latest_bdev = tgt_device->bdev;
list_add(&tgt_device->dev_alloc_list, &fs_info->fs_devices->alloc_list); list_add(&tgt_device->dev_alloc_list, &fs_info->fs_devices->alloc_list);
/* replace the sysfs entry */
btrfs_kobj_rm_device(fs_info, src_device);
btrfs_kobj_add_device(fs_info, tgt_device);
btrfs_rm_dev_replace_blocked(fs_info); btrfs_rm_dev_replace_blocked(fs_info);
btrfs_rm_dev_replace_srcdev(fs_info, src_device); btrfs_rm_dev_replace_srcdev(fs_info, src_device);
......
...@@ -369,7 +369,8 @@ static int verify_parent_transid(struct extent_io_tree *io_tree, ...@@ -369,7 +369,8 @@ static int verify_parent_transid(struct extent_io_tree *io_tree,
out: out:
unlock_extent_cached(io_tree, eb->start, eb->start + eb->len - 1, unlock_extent_cached(io_tree, eb->start, eb->start + eb->len - 1,
&cached_state, GFP_NOFS); &cached_state, GFP_NOFS);
btrfs_tree_read_unlock_blocking(eb); if (need_lock)
btrfs_tree_read_unlock_blocking(eb);
return ret; return ret;
} }
...@@ -2904,7 +2905,9 @@ int open_ctree(struct super_block *sb, ...@@ -2904,7 +2905,9 @@ int open_ctree(struct super_block *sb,
if (ret) if (ret)
goto fail_qgroup; goto fail_qgroup;
mutex_lock(&fs_info->cleaner_mutex);
ret = btrfs_recover_relocation(tree_root); ret = btrfs_recover_relocation(tree_root);
mutex_unlock(&fs_info->cleaner_mutex);
if (ret < 0) { if (ret < 0) {
printk(KERN_WARNING printk(KERN_WARNING
"BTRFS: failed to recover relocation\n"); "BTRFS: failed to recover relocation\n");
......
...@@ -5678,7 +5678,6 @@ void btrfs_prepare_extent_commit(struct btrfs_trans_handle *trans, ...@@ -5678,7 +5678,6 @@ void btrfs_prepare_extent_commit(struct btrfs_trans_handle *trans,
struct btrfs_caching_control *next; struct btrfs_caching_control *next;
struct btrfs_caching_control *caching_ctl; struct btrfs_caching_control *caching_ctl;
struct btrfs_block_group_cache *cache; struct btrfs_block_group_cache *cache;
struct btrfs_space_info *space_info;
down_write(&fs_info->commit_root_sem); down_write(&fs_info->commit_root_sem);
...@@ -5701,9 +5700,6 @@ void btrfs_prepare_extent_commit(struct btrfs_trans_handle *trans, ...@@ -5701,9 +5700,6 @@ void btrfs_prepare_extent_commit(struct btrfs_trans_handle *trans,
up_write(&fs_info->commit_root_sem); up_write(&fs_info->commit_root_sem);
list_for_each_entry_rcu(space_info, &fs_info->space_info, list)
percpu_counter_set(&space_info->total_bytes_pinned, 0);
update_global_block_rsv(fs_info); update_global_block_rsv(fs_info);
} }
...@@ -5741,6 +5737,7 @@ static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end) ...@@ -5741,6 +5737,7 @@ static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end)
spin_lock(&cache->lock); spin_lock(&cache->lock);
cache->pinned -= len; cache->pinned -= len;
space_info->bytes_pinned -= len; space_info->bytes_pinned -= len;
percpu_counter_add(&space_info->total_bytes_pinned, -len);
if (cache->ro) { if (cache->ro) {
space_info->bytes_readonly += len; space_info->bytes_readonly += len;
readonly = true; readonly = true;
......
...@@ -136,19 +136,22 @@ static unsigned int btrfs_flags_to_ioctl(unsigned int flags) ...@@ -136,19 +136,22 @@ static unsigned int btrfs_flags_to_ioctl(unsigned int flags)
void btrfs_update_iflags(struct inode *inode) void btrfs_update_iflags(struct inode *inode)
{ {
struct btrfs_inode *ip = BTRFS_I(inode); struct btrfs_inode *ip = BTRFS_I(inode);
unsigned int new_fl = 0;
inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC);
if (ip->flags & BTRFS_INODE_SYNC) if (ip->flags & BTRFS_INODE_SYNC)
inode->i_flags |= S_SYNC; new_fl |= S_SYNC;
if (ip->flags & BTRFS_INODE_IMMUTABLE) if (ip->flags & BTRFS_INODE_IMMUTABLE)
inode->i_flags |= S_IMMUTABLE; new_fl |= S_IMMUTABLE;
if (ip->flags & BTRFS_INODE_APPEND) if (ip->flags & BTRFS_INODE_APPEND)
inode->i_flags |= S_APPEND; new_fl |= S_APPEND;
if (ip->flags & BTRFS_INODE_NOATIME) if (ip->flags & BTRFS_INODE_NOATIME)
inode->i_flags |= S_NOATIME; new_fl |= S_NOATIME;
if (ip->flags & BTRFS_INODE_DIRSYNC) if (ip->flags & BTRFS_INODE_DIRSYNC)
inode->i_flags |= S_DIRSYNC; new_fl |= S_DIRSYNC;
set_mask_bits(&inode->i_flags,
S_SYNC | S_APPEND | S_IMMUTABLE | S_NOATIME | S_DIRSYNC,
new_fl);
} }
/* /*
...@@ -3139,7 +3142,6 @@ static int clone_finish_inode_update(struct btrfs_trans_handle *trans, ...@@ -3139,7 +3142,6 @@ static int clone_finish_inode_update(struct btrfs_trans_handle *trans,
static void clone_update_extent_map(struct inode *inode, static void clone_update_extent_map(struct inode *inode,
const struct btrfs_trans_handle *trans, const struct btrfs_trans_handle *trans,
const struct btrfs_path *path, const struct btrfs_path *path,
struct btrfs_file_extent_item *fi,
const u64 hole_offset, const u64 hole_offset,
const u64 hole_len) const u64 hole_len)
{ {
...@@ -3154,7 +3156,11 @@ static void clone_update_extent_map(struct inode *inode, ...@@ -3154,7 +3156,11 @@ static void clone_update_extent_map(struct inode *inode,
return; return;
} }
if (fi) { if (path) {
struct btrfs_file_extent_item *fi;
fi = btrfs_item_ptr(path->nodes[0], path->slots[0],
struct btrfs_file_extent_item);
btrfs_extent_item_to_extent_map(inode, path, fi, false, em); btrfs_extent_item_to_extent_map(inode, path, fi, false, em);
em->generation = -1; em->generation = -1;
if (btrfs_file_extent_type(path->nodes[0], fi) == if (btrfs_file_extent_type(path->nodes[0], fi) ==
...@@ -3508,18 +3514,15 @@ static int btrfs_clone(struct inode *src, struct inode *inode, ...@@ -3508,18 +3514,15 @@ static int btrfs_clone(struct inode *src, struct inode *inode,
btrfs_item_ptr_offset(leaf, slot), btrfs_item_ptr_offset(leaf, slot),
size); size);
inode_add_bytes(inode, datal); inode_add_bytes(inode, datal);
extent = btrfs_item_ptr(leaf, slot,
struct btrfs_file_extent_item);
} }
/* If we have an implicit hole (NO_HOLES feature). */ /* If we have an implicit hole (NO_HOLES feature). */
if (drop_start < new_key.offset) if (drop_start < new_key.offset)
clone_update_extent_map(inode, trans, clone_update_extent_map(inode, trans,
path, NULL, drop_start, NULL, drop_start,
new_key.offset - drop_start); new_key.offset - drop_start);
clone_update_extent_map(inode, trans, path, clone_update_extent_map(inode, trans, path, 0, 0);
extent, 0, 0);
btrfs_mark_buffer_dirty(leaf); btrfs_mark_buffer_dirty(leaf);
btrfs_release_path(path); btrfs_release_path(path);
...@@ -3562,12 +3565,10 @@ static int btrfs_clone(struct inode *src, struct inode *inode, ...@@ -3562,12 +3565,10 @@ static int btrfs_clone(struct inode *src, struct inode *inode,
btrfs_end_transaction(trans, root); btrfs_end_transaction(trans, root);
goto out; goto out;
} }
clone_update_extent_map(inode, trans, NULL, last_dest_end,
destoff + len - last_dest_end);
ret = clone_finish_inode_update(trans, inode, destoff + len, ret = clone_finish_inode_update(trans, inode, destoff + len,
destoff, olen); destoff, olen);
if (ret)
goto out;
clone_update_extent_map(inode, trans, path, NULL, last_dest_end,
destoff + len - last_dest_end);
} }
out: out:
......
...@@ -54,7 +54,7 @@ static void print_extent_data_ref(struct extent_buffer *eb, ...@@ -54,7 +54,7 @@ static void print_extent_data_ref(struct extent_buffer *eb,
btrfs_extent_data_ref_count(eb, ref)); btrfs_extent_data_ref_count(eb, ref));
} }
static void print_extent_item(struct extent_buffer *eb, int slot) static void print_extent_item(struct extent_buffer *eb, int slot, int type)
{ {
struct btrfs_extent_item *ei; struct btrfs_extent_item *ei;
struct btrfs_extent_inline_ref *iref; struct btrfs_extent_inline_ref *iref;
...@@ -63,7 +63,6 @@ static void print_extent_item(struct extent_buffer *eb, int slot) ...@@ -63,7 +63,6 @@ static void print_extent_item(struct extent_buffer *eb, int slot)
struct btrfs_disk_key key; struct btrfs_disk_key key;
unsigned long end; unsigned long end;
unsigned long ptr; unsigned long ptr;
int type;
u32 item_size = btrfs_item_size_nr(eb, slot); u32 item_size = btrfs_item_size_nr(eb, slot);
u64 flags; u64 flags;
u64 offset; u64 offset;
...@@ -88,7 +87,8 @@ static void print_extent_item(struct extent_buffer *eb, int slot) ...@@ -88,7 +87,8 @@ static void print_extent_item(struct extent_buffer *eb, int slot)
btrfs_extent_refs(eb, ei), btrfs_extent_generation(eb, ei), btrfs_extent_refs(eb, ei), btrfs_extent_generation(eb, ei),
flags); flags);
if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) { if ((type == BTRFS_EXTENT_ITEM_KEY) &&
flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) {
struct btrfs_tree_block_info *info; struct btrfs_tree_block_info *info;
info = (struct btrfs_tree_block_info *)(ei + 1); info = (struct btrfs_tree_block_info *)(ei + 1);
btrfs_tree_block_key(eb, info, &key); btrfs_tree_block_key(eb, info, &key);
...@@ -223,7 +223,8 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) ...@@ -223,7 +223,8 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
btrfs_disk_root_refs(l, ri)); btrfs_disk_root_refs(l, ri));
break; break;
case BTRFS_EXTENT_ITEM_KEY: case BTRFS_EXTENT_ITEM_KEY:
print_extent_item(l, i); case BTRFS_METADATA_ITEM_KEY:
print_extent_item(l, i, type);
break; break;
case BTRFS_TREE_BLOCK_REF_KEY: case BTRFS_TREE_BLOCK_REF_KEY:
printk(KERN_INFO "\t\ttree block backref\n"); printk(KERN_INFO "\t\ttree block backref\n");
......
...@@ -1956,9 +1956,10 @@ static int __raid56_parity_recover(struct btrfs_raid_bio *rbio) ...@@ -1956,9 +1956,10 @@ static int __raid56_parity_recover(struct btrfs_raid_bio *rbio)
* pages are going to be uptodate. * pages are going to be uptodate.
*/ */
for (stripe = 0; stripe < bbio->num_stripes; stripe++) { for (stripe = 0; stripe < bbio->num_stripes; stripe++) {
if (rbio->faila == stripe || if (rbio->faila == stripe || rbio->failb == stripe) {
rbio->failb == stripe) atomic_inc(&rbio->bbio->error);
continue; continue;
}
for (pagenr = 0; pagenr < nr_pages; pagenr++) { for (pagenr = 0; pagenr < nr_pages; pagenr++) {
struct page *p; struct page *p;
......
...@@ -522,9 +522,10 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) ...@@ -522,9 +522,10 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
case Opt_ssd_spread: case Opt_ssd_spread:
btrfs_set_and_info(root, SSD_SPREAD, btrfs_set_and_info(root, SSD_SPREAD,
"use spread ssd allocation scheme"); "use spread ssd allocation scheme");
btrfs_set_opt(info->mount_opt, SSD);
break; break;
case Opt_nossd: case Opt_nossd:
btrfs_clear_and_info(root, NOSSD, btrfs_set_and_info(root, NOSSD,
"not using ssd allocation scheme"); "not using ssd allocation scheme");
btrfs_clear_opt(info->mount_opt, SSD); btrfs_clear_opt(info->mount_opt, SSD);
break; break;
...@@ -1467,7 +1468,9 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data) ...@@ -1467,7 +1468,9 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
goto restore; goto restore;
/* recover relocation */ /* recover relocation */
mutex_lock(&fs_info->cleaner_mutex);
ret = btrfs_recover_relocation(root); ret = btrfs_recover_relocation(root);
mutex_unlock(&fs_info->cleaner_mutex);
if (ret) if (ret)
goto restore; goto restore;
...@@ -1808,6 +1811,8 @@ static int btrfs_show_devname(struct seq_file *m, struct dentry *root) ...@@ -1808,6 +1811,8 @@ static int btrfs_show_devname(struct seq_file *m, struct dentry *root)
list_for_each_entry(dev, head, dev_list) { list_for_each_entry(dev, head, dev_list) {
if (dev->missing) if (dev->missing)
continue; continue;
if (!dev->name)
continue;
if (!first_dev || dev->devid < first_dev->devid) if (!first_dev || dev->devid < first_dev->devid)
first_dev = dev; first_dev = dev;
} }
......
...@@ -605,14 +605,37 @@ static void init_feature_attrs(void) ...@@ -605,14 +605,37 @@ static void init_feature_attrs(void)
} }
} }
static int add_device_membership(struct btrfs_fs_info *fs_info) int btrfs_kobj_rm_device(struct btrfs_fs_info *fs_info,
struct btrfs_device *one_device)
{
struct hd_struct *disk;
struct kobject *disk_kobj;
if (!fs_info->device_dir_kobj)
return -EINVAL;
if (one_device) {
disk = one_device->bdev->bd_part;
disk_kobj = &part_to_dev(disk)->kobj;
sysfs_remove_link(fs_info->device_dir_kobj,
disk_kobj->name);
}
return 0;
}
int btrfs_kobj_add_device(struct btrfs_fs_info *fs_info,
struct btrfs_device *one_device)
{ {
int error = 0; int error = 0;
struct btrfs_fs_devices *fs_devices = fs_info->fs_devices; struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
struct btrfs_device *dev; struct btrfs_device *dev;
fs_info->device_dir_kobj = kobject_create_and_add("devices", if (!fs_info->device_dir_kobj)
fs_info->device_dir_kobj = kobject_create_and_add("devices",
&fs_info->super_kobj); &fs_info->super_kobj);
if (!fs_info->device_dir_kobj) if (!fs_info->device_dir_kobj)
return -ENOMEM; return -ENOMEM;
...@@ -623,6 +646,9 @@ static int add_device_membership(struct btrfs_fs_info *fs_info) ...@@ -623,6 +646,9 @@ static int add_device_membership(struct btrfs_fs_info *fs_info)
if (!dev->bdev) if (!dev->bdev)
continue; continue;
if (one_device && one_device != dev)
continue;
disk = dev->bdev->bd_part; disk = dev->bdev->bd_part;
disk_kobj = &part_to_dev(disk)->kobj; disk_kobj = &part_to_dev(disk)->kobj;
...@@ -666,7 +692,7 @@ int btrfs_sysfs_add_one(struct btrfs_fs_info *fs_info) ...@@ -666,7 +692,7 @@ int btrfs_sysfs_add_one(struct btrfs_fs_info *fs_info)
if (error) if (error)
goto failure; goto failure;
error = add_device_membership(fs_info); error = btrfs_kobj_add_device(fs_info, NULL);
if (error) if (error)
goto failure; goto failure;
......
...@@ -66,4 +66,8 @@ char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags); ...@@ -66,4 +66,8 @@ char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags);
extern const char * const btrfs_feature_set_names[3]; extern const char * const btrfs_feature_set_names[3];
extern struct kobj_type space_info_ktype; extern struct kobj_type space_info_ktype;
extern struct kobj_type btrfs_raid_ktype; extern struct kobj_type btrfs_raid_ktype;
int btrfs_kobj_add_device(struct btrfs_fs_info *fs_info,
struct btrfs_device *one_device);
int btrfs_kobj_rm_device(struct btrfs_fs_info *fs_info,
struct btrfs_device *one_device);
#endif /* _BTRFS_SYSFS_H_ */ #endif /* _BTRFS_SYSFS_H_ */
...@@ -386,11 +386,13 @@ start_transaction(struct btrfs_root *root, u64 num_items, unsigned int type, ...@@ -386,11 +386,13 @@ start_transaction(struct btrfs_root *root, u64 num_items, unsigned int type,
bool reloc_reserved = false; bool reloc_reserved = false;
int ret; int ret;
/* Send isn't supposed to start transactions. */
ASSERT(current->journal_info != (void *)BTRFS_SEND_TRANS_STUB);
if (test_bit(BTRFS_FS_STATE_ERROR, &root->fs_info->fs_state)) if (test_bit(BTRFS_FS_STATE_ERROR, &root->fs_info->fs_state))
return ERR_PTR(-EROFS); return ERR_PTR(-EROFS);
if (current->journal_info && if (current->journal_info) {
current->journal_info != (void *)BTRFS_SEND_TRANS_STUB) {
WARN_ON(type & TRANS_EXTWRITERS); WARN_ON(type & TRANS_EXTWRITERS);
h = current->journal_info; h = current->journal_info;
h->use_count++; h->use_count++;
...@@ -491,6 +493,7 @@ start_transaction(struct btrfs_root *root, u64 num_items, unsigned int type, ...@@ -491,6 +493,7 @@ start_transaction(struct btrfs_root *root, u64 num_items, unsigned int type,
smp_mb(); smp_mb();
if (cur_trans->state >= TRANS_STATE_BLOCKED && if (cur_trans->state >= TRANS_STATE_BLOCKED &&
may_wait_transaction(root, type)) { may_wait_transaction(root, type)) {
current->journal_info = h;
btrfs_commit_transaction(h, root); btrfs_commit_transaction(h, root);
goto again; goto again;
} }
...@@ -1615,11 +1618,6 @@ static int btrfs_flush_all_pending_stuffs(struct btrfs_trans_handle *trans, ...@@ -1615,11 +1618,6 @@ static int btrfs_flush_all_pending_stuffs(struct btrfs_trans_handle *trans,
int ret; int ret;
ret = btrfs_run_delayed_items(trans, root); ret = btrfs_run_delayed_items(trans, root);
/*
* running the delayed items may have added new refs. account
* them now so that they hinder processing of more delayed refs
* as little as possible.
*/
if (ret) if (ret)
return ret; return ret;
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include "rcu-string.h" #include "rcu-string.h"
#include "math.h" #include "math.h"
#include "dev-replace.h" #include "dev-replace.h"
#include "sysfs.h"
static int init_first_rw_device(struct btrfs_trans_handle *trans, static int init_first_rw_device(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct btrfs_root *root,
...@@ -554,12 +555,14 @@ static struct btrfs_fs_devices *clone_fs_devices(struct btrfs_fs_devices *orig) ...@@ -554,12 +555,14 @@ static struct btrfs_fs_devices *clone_fs_devices(struct btrfs_fs_devices *orig)
* This is ok to do without rcu read locked because we hold the * This is ok to do without rcu read locked because we hold the
* uuid mutex so nothing we touch in here is going to disappear. * uuid mutex so nothing we touch in here is going to disappear.
*/ */
name = rcu_string_strdup(orig_dev->name->str, GFP_NOFS); if (orig_dev->name) {
if (!name) { name = rcu_string_strdup(orig_dev->name->str, GFP_NOFS);
kfree(device); if (!name) {
goto error; kfree(device);
goto error;
}
rcu_assign_pointer(device->name, name);
} }
rcu_assign_pointer(device->name, name);
list_add(&device->dev_list, &fs_devices->devices); list_add(&device->dev_list, &fs_devices->devices);
device->fs_devices = fs_devices; device->fs_devices = fs_devices;
...@@ -1680,6 +1683,9 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) ...@@ -1680,6 +1683,9 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
if (device->bdev) if (device->bdev)
device->fs_devices->open_devices--; device->fs_devices->open_devices--;
/* remove sysfs entry */
btrfs_kobj_rm_device(root->fs_info, device);
call_rcu(&device->rcu, free_device); call_rcu(&device->rcu, free_device);
num_devices = btrfs_super_num_devices(root->fs_info->super_copy) - 1; num_devices = btrfs_super_num_devices(root->fs_info->super_copy) - 1;
...@@ -2143,9 +2149,14 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) ...@@ -2143,9 +2149,14 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
total_bytes = btrfs_super_num_devices(root->fs_info->super_copy); total_bytes = btrfs_super_num_devices(root->fs_info->super_copy);
btrfs_set_super_num_devices(root->fs_info->super_copy, btrfs_set_super_num_devices(root->fs_info->super_copy,
total_bytes + 1); total_bytes + 1);
/* add sysfs device entry */
btrfs_kobj_add_device(root->fs_info, device);
mutex_unlock(&root->fs_info->fs_devices->device_list_mutex); mutex_unlock(&root->fs_info->fs_devices->device_list_mutex);
if (seeding_dev) { if (seeding_dev) {
char fsid_buf[BTRFS_UUID_UNPARSED_SIZE];
ret = init_first_rw_device(trans, root, device); ret = init_first_rw_device(trans, root, device);
if (ret) { if (ret) {
btrfs_abort_transaction(trans, root, ret); btrfs_abort_transaction(trans, root, ret);
...@@ -2156,6 +2167,14 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) ...@@ -2156,6 +2167,14 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
btrfs_abort_transaction(trans, root, ret); btrfs_abort_transaction(trans, root, ret);
goto error_trans; goto error_trans;
} }
/* Sprouting would change fsid of the mounted root,
* so rename the fsid on the sysfs
*/
snprintf(fsid_buf, BTRFS_UUID_UNPARSED_SIZE, "%pU",
root->fs_info->fsid);
if (kobject_rename(&root->fs_info->super_kobj, fsid_buf))
goto error_trans;
} else { } else {
ret = btrfs_add_device(trans, root, device); ret = btrfs_add_device(trans, root, device);
if (ret) { if (ret) {
...@@ -2205,6 +2224,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) ...@@ -2205,6 +2224,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
unlock_chunks(root); unlock_chunks(root);
btrfs_end_transaction(trans, root); btrfs_end_transaction(trans, root);
rcu_string_free(device->name); rcu_string_free(device->name);
btrfs_kobj_rm_device(root->fs_info, device);
kfree(device); kfree(device);
error: error:
blkdev_put(bdev, FMODE_EXCL); blkdev_put(bdev, FMODE_EXCL);
......
...@@ -136,7 +136,7 @@ static int zlib_compress_pages(struct list_head *ws, ...@@ -136,7 +136,7 @@ static int zlib_compress_pages(struct list_head *ws,
if (workspace->def_strm.total_in > 8192 && if (workspace->def_strm.total_in > 8192 &&
workspace->def_strm.total_in < workspace->def_strm.total_in <
workspace->def_strm.total_out) { workspace->def_strm.total_out) {
ret = -EIO; ret = -E2BIG;
goto out; goto out;
} }
/* we need another page for writing out. Test this /* we need another page for writing out. Test this
......
...@@ -38,6 +38,7 @@ struct btrfs_ioctl_vol_args { ...@@ -38,6 +38,7 @@ struct btrfs_ioctl_vol_args {
#define BTRFS_SUBVOL_QGROUP_INHERIT (1ULL << 2) #define BTRFS_SUBVOL_QGROUP_INHERIT (1ULL << 2)
#define BTRFS_FSID_SIZE 16 #define BTRFS_FSID_SIZE 16
#define BTRFS_UUID_SIZE 16 #define BTRFS_UUID_SIZE 16
#define BTRFS_UUID_UNPARSED_SIZE 37
#define BTRFS_QGROUP_INHERIT_SET_LIMITS (1ULL << 0) #define BTRFS_QGROUP_INHERIT_SET_LIMITS (1ULL << 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment