Merge branch 'anand/sysfs-updates-v4.3-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux into for-linus-4.4

Signed-off-by: Chris Mason <clm@fb.com>
This commit is contained in:
Chris Mason 2015-10-12 16:24:15 -07:00
commit 62fb50ab7c
17 changed files with 198 additions and 177 deletions

View file

@ -1011,7 +1011,7 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
return ret; return ret;
if (refs == 0) { if (refs == 0) {
ret = -EROFS; ret = -EROFS;
btrfs_std_error(root->fs_info, ret); btrfs_std_error(root->fs_info, ret, NULL);
return ret; return ret;
} }
} else { } else {
@ -1927,7 +1927,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
child = read_node_slot(root, mid, 0); child = read_node_slot(root, mid, 0);
if (!child) { if (!child) {
ret = -EROFS; ret = -EROFS;
btrfs_std_error(root->fs_info, ret); btrfs_std_error(root->fs_info, ret, NULL);
goto enospc; goto enospc;
} }
@ -2030,7 +2030,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
*/ */
if (!left) { if (!left) {
ret = -EROFS; ret = -EROFS;
btrfs_std_error(root->fs_info, ret); btrfs_std_error(root->fs_info, ret, NULL);
goto enospc; goto enospc;
} }
wret = balance_node_right(trans, root, mid, left); wret = balance_node_right(trans, root, mid, left);

View file

@ -4004,8 +4004,8 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
/* sysfs.c */ /* sysfs.c */
int btrfs_init_sysfs(void); int btrfs_init_sysfs(void);
void btrfs_exit_sysfs(void); void btrfs_exit_sysfs(void);
int btrfs_sysfs_add_one(struct btrfs_fs_info *fs_info); int btrfs_sysfs_add_mounted(struct btrfs_fs_info *fs_info);
void btrfs_sysfs_remove_one(struct btrfs_fs_info *fs_info); void btrfs_sysfs_remove_mounted(struct btrfs_fs_info *fs_info);
/* xattr.c */ /* xattr.c */
ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size); ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size);
@ -4215,14 +4215,7 @@ do { \
__LINE__, (errno)); \ __LINE__, (errno)); \
} while (0) } while (0)
#define btrfs_std_error(fs_info, errno) \ #define btrfs_std_error(fs_info, errno, fmt, args...) \
do { \
if ((errno)) \
__btrfs_std_error((fs_info), __func__, \
__LINE__, (errno), NULL); \
} while (0)
#define btrfs_error(fs_info, errno, fmt, args...) \
do { \ do { \
__btrfs_std_error((fs_info), __func__, __LINE__, \ __btrfs_std_error((fs_info), __func__, __LINE__, \
(errno), fmt, ##args); \ (errno), fmt, ##args); \

View file

@ -327,19 +327,6 @@ int btrfs_dev_replace_start(struct btrfs_root *root,
args->start.tgtdev_name[0] == '\0') args->start.tgtdev_name[0] == '\0')
return -EINVAL; return -EINVAL;
/*
* Here we commit the transaction to make sure commit_total_bytes
* of all the devices are updated.
*/
trans = btrfs_attach_transaction(root);
if (!IS_ERR(trans)) {
ret = btrfs_commit_transaction(trans, root);
if (ret)
return ret;
} else if (PTR_ERR(trans) != -ENOENT) {
return PTR_ERR(trans);
}
/* the disk copy procedure reuses the scrub code */ /* the disk copy procedure reuses the scrub code */
mutex_lock(&fs_info->volume_mutex); mutex_lock(&fs_info->volume_mutex);
ret = btrfs_dev_replace_find_srcdev(root, args->start.srcdevid, ret = btrfs_dev_replace_find_srcdev(root, args->start.srcdevid,
@ -356,6 +343,19 @@ int btrfs_dev_replace_start(struct btrfs_root *root,
if (ret) if (ret)
return ret; return ret;
/*
* Here we commit the transaction to make sure commit_total_bytes
* of all the devices are updated.
*/
trans = btrfs_attach_transaction(root);
if (!IS_ERR(trans)) {
ret = btrfs_commit_transaction(trans, root);
if (ret)
return ret;
} else if (PTR_ERR(trans) != -ENOENT) {
return PTR_ERR(trans);
}
btrfs_dev_replace_lock(dev_replace); btrfs_dev_replace_lock(dev_replace);
switch (dev_replace->replace_state) { switch (dev_replace->replace_state) {
case BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED: case BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED:
@ -375,10 +375,6 @@ int btrfs_dev_replace_start(struct btrfs_root *root,
WARN_ON(!tgt_device); WARN_ON(!tgt_device);
dev_replace->tgtdev = tgt_device; dev_replace->tgtdev = tgt_device;
ret = btrfs_kobj_add_device(tgt_device->fs_devices, tgt_device);
if (ret)
btrfs_err(root->fs_info, "kobj add dev failed %d\n", ret);
btrfs_info_in_rcu(root->fs_info, btrfs_info_in_rcu(root->fs_info,
"dev_replace from %s (devid %llu) to %s started", "dev_replace from %s (devid %llu) to %s started",
src_device->missing ? "<missing disk>" : src_device->missing ? "<missing disk>" :
@ -401,6 +397,10 @@ int btrfs_dev_replace_start(struct btrfs_root *root,
args->result = BTRFS_IOCTL_DEV_REPLACE_RESULT_NO_ERROR; args->result = BTRFS_IOCTL_DEV_REPLACE_RESULT_NO_ERROR;
btrfs_dev_replace_unlock(dev_replace); btrfs_dev_replace_unlock(dev_replace);
ret = btrfs_sysfs_add_device_link(tgt_device->fs_devices, tgt_device);
if (ret)
btrfs_err(root->fs_info, "kobj add dev failed %d\n", ret);
btrfs_wait_ordered_roots(root->fs_info, -1); btrfs_wait_ordered_roots(root->fs_info, -1);
/* force writing the updated state information to disk */ /* force writing the updated state information to disk */
@ -586,7 +586,7 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
mutex_unlock(&uuid_mutex); mutex_unlock(&uuid_mutex);
/* replace the sysfs entry */ /* replace the sysfs entry */
btrfs_kobj_rm_device(fs_info->fs_devices, src_device); btrfs_sysfs_rm_device_link(fs_info->fs_devices, src_device);
btrfs_rm_dev_replace_free_srcdev(fs_info, src_device); btrfs_rm_dev_replace_free_srcdev(fs_info, src_device);
/* write back the superblocks */ /* write back the superblocks */

View file

@ -2375,7 +2375,7 @@ static int btrfs_replay_log(struct btrfs_fs_info *fs_info,
/* returns with log_tree_root freed on success */ /* returns with log_tree_root freed on success */
ret = btrfs_recover_log_trees(log_tree_root); ret = btrfs_recover_log_trees(log_tree_root);
if (ret) { if (ret) {
btrfs_error(tree_root->fs_info, ret, btrfs_std_error(tree_root->fs_info, ret,
"Failed to recover log tree"); "Failed to recover log tree");
free_extent_buffer(log_tree_root->node); free_extent_buffer(log_tree_root->node);
kfree(log_tree_root); kfree(log_tree_root);
@ -2651,8 +2651,8 @@ int open_ctree(struct super_block *sb,
* Read super block and check the signature bytes only * Read super block and check the signature bytes only
*/ */
bh = btrfs_read_dev_super(fs_devices->latest_bdev); bh = btrfs_read_dev_super(fs_devices->latest_bdev);
if (!bh) { if (IS_ERR(bh)) {
err = -EINVAL; err = PTR_ERR(bh);
goto fail_alloc; goto fail_alloc;
} }
@ -2935,7 +2935,7 @@ retry_root_backup:
goto fail_fsdev_sysfs; goto fail_fsdev_sysfs;
} }
ret = btrfs_sysfs_add_one(fs_info); ret = btrfs_sysfs_add_mounted(fs_info);
if (ret) { if (ret) {
pr_err("BTRFS: failed to init sysfs interface: %d\n", ret); pr_err("BTRFS: failed to init sysfs interface: %d\n", ret);
goto fail_fsdev_sysfs; goto fail_fsdev_sysfs;
@ -3115,7 +3115,7 @@ fail_cleaner:
filemap_write_and_wait(fs_info->btree_inode->i_mapping); filemap_write_and_wait(fs_info->btree_inode->i_mapping);
fail_sysfs: fail_sysfs:
btrfs_sysfs_remove_one(fs_info); btrfs_sysfs_remove_mounted(fs_info);
fail_fsdev_sysfs: fail_fsdev_sysfs:
btrfs_sysfs_remove_fsid(fs_info->fs_devices); btrfs_sysfs_remove_fsid(fs_info->fs_devices);
@ -3190,6 +3190,37 @@ static void btrfs_end_buffer_write_sync(struct buffer_head *bh, int uptodate)
put_bh(bh); put_bh(bh);
} }
int btrfs_read_dev_one_super(struct block_device *bdev, int copy_num,
struct buffer_head **bh_ret)
{
struct buffer_head *bh;
struct btrfs_super_block *super;
u64 bytenr;
bytenr = btrfs_sb_offset(copy_num);
if (bytenr + BTRFS_SUPER_INFO_SIZE >= i_size_read(bdev->bd_inode))
return -EINVAL;
bh = __bread(bdev, bytenr / 4096, BTRFS_SUPER_INFO_SIZE);
/*
* If we fail to read from the underlying devices, as of now
* the best option we have is to mark it EIO.
*/
if (!bh)
return -EIO;
super = (struct btrfs_super_block *)bh->b_data;
if (btrfs_super_bytenr(super) != bytenr ||
btrfs_super_magic(super) != BTRFS_MAGIC) {
brelse(bh);
return -EINVAL;
}
*bh_ret = bh;
return 0;
}
struct buffer_head *btrfs_read_dev_super(struct block_device *bdev) struct buffer_head *btrfs_read_dev_super(struct block_device *bdev)
{ {
struct buffer_head *bh; struct buffer_head *bh;
@ -3197,7 +3228,7 @@ struct buffer_head *btrfs_read_dev_super(struct block_device *bdev)
struct btrfs_super_block *super; struct btrfs_super_block *super;
int i; int i;
u64 transid = 0; u64 transid = 0;
u64 bytenr; int ret = -EINVAL;
/* we would like to check all the supers, but that would make /* we would like to check all the supers, but that would make
* a btrfs mount succeed after a mkfs from a different FS. * a btrfs mount succeed after a mkfs from a different FS.
@ -3205,21 +3236,11 @@ struct buffer_head *btrfs_read_dev_super(struct block_device *bdev)
* later supers, using BTRFS_SUPER_MIRROR_MAX instead * later supers, using BTRFS_SUPER_MIRROR_MAX instead
*/ */
for (i = 0; i < 1; i++) { for (i = 0; i < 1; i++) {
bytenr = btrfs_sb_offset(i); ret = btrfs_read_dev_one_super(bdev, i, &bh);
if (bytenr + BTRFS_SUPER_INFO_SIZE >= if (ret)
i_size_read(bdev->bd_inode))
break;
bh = __bread(bdev, bytenr / 4096,
BTRFS_SUPER_INFO_SIZE);
if (!bh)
continue; continue;
super = (struct btrfs_super_block *)bh->b_data; super = (struct btrfs_super_block *)bh->b_data;
if (btrfs_super_bytenr(super) != bytenr ||
btrfs_super_magic(super) != BTRFS_MAGIC) {
brelse(bh);
continue;
}
if (!latest || btrfs_super_generation(super) > transid) { if (!latest || btrfs_super_generation(super) > transid) {
brelse(latest); brelse(latest);
@ -3229,6 +3250,10 @@ struct buffer_head *btrfs_read_dev_super(struct block_device *bdev)
brelse(bh); brelse(bh);
} }
} }
if (!latest)
return ERR_PTR(ret);
return latest; return latest;
} }
@ -3547,7 +3572,7 @@ static int write_all_supers(struct btrfs_root *root, int max_mirrors)
if (ret) { if (ret) {
mutex_unlock( mutex_unlock(
&root->fs_info->fs_devices->device_list_mutex); &root->fs_info->fs_devices->device_list_mutex);
btrfs_error(root->fs_info, ret, btrfs_std_error(root->fs_info, ret,
"errors while submitting device barriers."); "errors while submitting device barriers.");
return ret; return ret;
} }
@ -3587,7 +3612,7 @@ static int write_all_supers(struct btrfs_root *root, int max_mirrors)
mutex_unlock(&root->fs_info->fs_devices->device_list_mutex); mutex_unlock(&root->fs_info->fs_devices->device_list_mutex);
/* FUA is masked off if unsupported and can't be the reason */ /* FUA is masked off if unsupported and can't be the reason */
btrfs_error(root->fs_info, -EIO, btrfs_std_error(root->fs_info, -EIO,
"%d errors while writing supers", total_errors); "%d errors while writing supers", total_errors);
return -EIO; return -EIO;
} }
@ -3605,7 +3630,7 @@ static int write_all_supers(struct btrfs_root *root, int max_mirrors)
} }
mutex_unlock(&root->fs_info->fs_devices->device_list_mutex); mutex_unlock(&root->fs_info->fs_devices->device_list_mutex);
if (total_errors > max_errors) { if (total_errors > max_errors) {
btrfs_error(root->fs_info, -EIO, btrfs_std_error(root->fs_info, -EIO,
"%d errors while writing supers", total_errors); "%d errors while writing supers", total_errors);
return -EIO; return -EIO;
} }
@ -3791,7 +3816,7 @@ void close_ctree(struct btrfs_root *root)
percpu_counter_sum(&fs_info->delalloc_bytes)); percpu_counter_sum(&fs_info->delalloc_bytes));
} }
btrfs_sysfs_remove_one(fs_info); btrfs_sysfs_remove_mounted(fs_info);
btrfs_sysfs_remove_fsid(fs_info->fs_devices); btrfs_sysfs_remove_fsid(fs_info->fs_devices);
btrfs_free_fs_roots(fs_info); btrfs_free_fs_roots(fs_info);

View file

@ -60,6 +60,8 @@ void close_ctree(struct btrfs_root *root);
int write_ctree_super(struct btrfs_trans_handle *trans, int write_ctree_super(struct btrfs_trans_handle *trans,
struct btrfs_root *root, int max_mirrors); struct btrfs_root *root, int max_mirrors);
struct buffer_head *btrfs_read_dev_super(struct block_device *bdev); struct buffer_head *btrfs_read_dev_super(struct block_device *bdev);
int btrfs_read_dev_one_super(struct block_device *bdev, int copy_num,
struct buffer_head **bh_ret);
int btrfs_commit_super(struct btrfs_root *root); int btrfs_commit_super(struct btrfs_root *root);
struct extent_buffer *btrfs_find_tree_block(struct btrfs_fs_info *fs_info, struct extent_buffer *btrfs_find_tree_block(struct btrfs_fs_info *fs_info,
u64 bytenr); u64 bytenr);

View file

@ -8694,7 +8694,7 @@ out:
if (!for_reloc && root_dropped == false) if (!for_reloc && root_dropped == false)
btrfs_add_dead_root(root); btrfs_add_dead_root(root);
if (err && err != -EAGAIN) if (err && err != -EAGAIN)
btrfs_std_error(root->fs_info, err); btrfs_std_error(root->fs_info, err, NULL);
return err; return err;
} }

View file

@ -157,7 +157,7 @@ static int btrfs_del_inode_extref(struct btrfs_trans_handle *trans,
*/ */
if (!btrfs_find_name_in_ext_backref(path, ref_objectid, if (!btrfs_find_name_in_ext_backref(path, ref_objectid,
name, name_len, &extref)) { name, name_len, &extref)) {
btrfs_std_error(root->fs_info, -ENOENT); btrfs_std_error(root->fs_info, -ENOENT, NULL);
ret = -EROFS; ret = -EROFS;
goto out; goto out;
} }

View file

@ -4806,7 +4806,7 @@ static long btrfs_ioctl_qgroup_assign(struct file *file, void __user *arg)
/* update qgroup status and info */ /* update qgroup status and info */
err = btrfs_run_qgroups(trans, root->fs_info); err = btrfs_run_qgroups(trans, root->fs_info);
if (err < 0) if (err < 0)
btrfs_error(root->fs_info, ret, btrfs_std_error(root->fs_info, ret,
"failed to update qgroup status and info\n"); "failed to update qgroup status and info\n");
err = btrfs_end_transaction(trans, root); err = btrfs_end_transaction(trans, root);
if (err && !ret) if (err && !ret)

View file

@ -2418,7 +2418,7 @@ again:
} }
out: out:
if (ret) { if (ret) {
btrfs_std_error(root->fs_info, ret); btrfs_std_error(root->fs_info, ret, NULL);
if (!list_empty(&reloc_roots)) if (!list_empty(&reloc_roots))
free_reloc_roots(&reloc_roots); free_reloc_roots(&reloc_roots);

View file

@ -284,7 +284,7 @@ int btrfs_find_orphan_roots(struct btrfs_root *tree_root)
trans = btrfs_join_transaction(tree_root); trans = btrfs_join_transaction(tree_root);
if (IS_ERR(trans)) { if (IS_ERR(trans)) {
err = PTR_ERR(trans); err = PTR_ERR(trans);
btrfs_error(tree_root->fs_info, err, btrfs_std_error(tree_root->fs_info, err,
"Failed to start trans to delete " "Failed to start trans to delete "
"orphan item"); "orphan item");
break; break;
@ -293,7 +293,7 @@ int btrfs_find_orphan_roots(struct btrfs_root *tree_root)
root_key.objectid); root_key.objectid);
btrfs_end_transaction(trans, tree_root); btrfs_end_transaction(trans, tree_root);
if (err) { if (err) {
btrfs_error(tree_root->fs_info, err, btrfs_std_error(tree_root->fs_info, err,
"Failed to delete root orphan " "Failed to delete root orphan "
"item"); "item");
break; break;

View file

@ -130,7 +130,6 @@ static void btrfs_handle_error(struct btrfs_fs_info *fs_info)
} }
} }
#ifdef CONFIG_PRINTK
/* /*
* __btrfs_std_error decodes expected errors from the caller and * __btrfs_std_error decodes expected errors from the caller and
* invokes the approciate error response. * invokes the approciate error response.
@ -140,7 +139,9 @@ void __btrfs_std_error(struct btrfs_fs_info *fs_info, const char *function,
unsigned int line, int errno, const char *fmt, ...) unsigned int line, int errno, const char *fmt, ...)
{ {
struct super_block *sb = fs_info->sb; struct super_block *sb = fs_info->sb;
#ifdef CONFIG_PRINTK
const char *errstr; const char *errstr;
#endif
/* /*
* Special case: if the error is EROFS, and we're already * Special case: if the error is EROFS, and we're already
@ -149,6 +150,7 @@ void __btrfs_std_error(struct btrfs_fs_info *fs_info, const char *function,
if (errno == -EROFS && (sb->s_flags & MS_RDONLY)) if (errno == -EROFS && (sb->s_flags & MS_RDONLY))
return; return;
#ifdef CONFIG_PRINTK
errstr = btrfs_decode_error(errno); errstr = btrfs_decode_error(errno);
if (fmt) { if (fmt) {
struct va_format vaf; struct va_format vaf;
@ -166,6 +168,7 @@ void __btrfs_std_error(struct btrfs_fs_info *fs_info, const char *function,
printk(KERN_CRIT "BTRFS: error (device %s) in %s:%d: errno=%d %s\n", printk(KERN_CRIT "BTRFS: error (device %s) in %s:%d: errno=%d %s\n",
sb->s_id, function, line, errno, errstr); sb->s_id, function, line, errno, errstr);
} }
#endif
/* Don't go through full error handling during mount */ /* Don't go through full error handling during mount */
save_error_info(fs_info); save_error_info(fs_info);
@ -173,6 +176,7 @@ void __btrfs_std_error(struct btrfs_fs_info *fs_info, const char *function,
btrfs_handle_error(fs_info); btrfs_handle_error(fs_info);
} }
#ifdef CONFIG_PRINTK
static const char * const logtypes[] = { static const char * const logtypes[] = {
"emergency", "emergency",
"alert", "alert",
@ -212,27 +216,6 @@ void btrfs_printk(const struct btrfs_fs_info *fs_info, const char *fmt, ...)
va_end(args); va_end(args);
} }
#else
void __btrfs_std_error(struct btrfs_fs_info *fs_info, const char *function,
unsigned int line, int errno, const char *fmt, ...)
{
struct super_block *sb = fs_info->sb;
/*
* Special case: if the error is EROFS, and we're already
* under MS_RDONLY, then it is safe here.
*/
if (errno == -EROFS && (sb->s_flags & MS_RDONLY))
return;
/* Don't go through full error handling during mount */
if (sb->s_flags & MS_BORN) {
save_error_info(fs_info);
btrfs_handle_error(fs_info);
}
}
#endif #endif
/* /*

View file

@ -437,24 +437,24 @@ static const struct attribute *btrfs_attrs[] = {
NULL, NULL,
}; };
static void btrfs_release_super_kobj(struct kobject *kobj) static void btrfs_release_fsid_kobj(struct kobject *kobj)
{ {
struct btrfs_fs_devices *fs_devs = to_fs_devs(kobj); struct btrfs_fs_devices *fs_devs = to_fs_devs(kobj);
memset(&fs_devs->super_kobj, 0, sizeof(struct kobject)); memset(&fs_devs->fsid_kobj, 0, sizeof(struct kobject));
complete(&fs_devs->kobj_unregister); complete(&fs_devs->kobj_unregister);
} }
static struct kobj_type btrfs_ktype = { static struct kobj_type btrfs_ktype = {
.sysfs_ops = &kobj_sysfs_ops, .sysfs_ops = &kobj_sysfs_ops,
.release = btrfs_release_super_kobj, .release = btrfs_release_fsid_kobj,
}; };
static inline struct btrfs_fs_devices *to_fs_devs(struct kobject *kobj) static inline struct btrfs_fs_devices *to_fs_devs(struct kobject *kobj)
{ {
if (kobj->ktype != &btrfs_ktype) if (kobj->ktype != &btrfs_ktype)
return NULL; return NULL;
return container_of(kobj, struct btrfs_fs_devices, super_kobj); return container_of(kobj, struct btrfs_fs_devices, fsid_kobj);
} }
static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj) static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj)
@ -502,12 +502,12 @@ static int addrm_unknown_feature_attrs(struct btrfs_fs_info *fs_info, bool add)
attrs[0] = &fa->kobj_attr.attr; attrs[0] = &fa->kobj_attr.attr;
if (add) { if (add) {
int ret; int ret;
ret = sysfs_merge_group(&fs_info->fs_devices->super_kobj, ret = sysfs_merge_group(&fs_info->fs_devices->fsid_kobj,
&agroup); &agroup);
if (ret) if (ret)
return ret; return ret;
} else } else
sysfs_unmerge_group(&fs_info->fs_devices->super_kobj, sysfs_unmerge_group(&fs_info->fs_devices->fsid_kobj,
&agroup); &agroup);
} }
@ -523,9 +523,9 @@ static void __btrfs_sysfs_remove_fsid(struct btrfs_fs_devices *fs_devs)
fs_devs->device_dir_kobj = NULL; fs_devs->device_dir_kobj = NULL;
} }
if (fs_devs->super_kobj.state_initialized) { if (fs_devs->fsid_kobj.state_initialized) {
kobject_del(&fs_devs->super_kobj); kobject_del(&fs_devs->fsid_kobj);
kobject_put(&fs_devs->super_kobj); kobject_put(&fs_devs->fsid_kobj);
wait_for_completion(&fs_devs->kobj_unregister); wait_for_completion(&fs_devs->kobj_unregister);
} }
} }
@ -545,7 +545,7 @@ void btrfs_sysfs_remove_fsid(struct btrfs_fs_devices *fs_devs)
} }
} }
void btrfs_sysfs_remove_one(struct btrfs_fs_info *fs_info) void btrfs_sysfs_remove_mounted(struct btrfs_fs_info *fs_info)
{ {
btrfs_reset_fs_info_ptr(fs_info); btrfs_reset_fs_info_ptr(fs_info);
@ -555,9 +555,9 @@ void btrfs_sysfs_remove_one(struct btrfs_fs_info *fs_info)
kobject_put(fs_info->space_info_kobj); kobject_put(fs_info->space_info_kobj);
} }
addrm_unknown_feature_attrs(fs_info, false); addrm_unknown_feature_attrs(fs_info, false);
sysfs_remove_group(&fs_info->fs_devices->super_kobj, &btrfs_feature_attr_group); sysfs_remove_group(&fs_info->fs_devices->fsid_kobj, &btrfs_feature_attr_group);
sysfs_remove_files(&fs_info->fs_devices->super_kobj, btrfs_attrs); sysfs_remove_files(&fs_info->fs_devices->fsid_kobj, btrfs_attrs);
btrfs_kobj_rm_device(fs_info->fs_devices, NULL); btrfs_sysfs_rm_device_link(fs_info->fs_devices, NULL);
} }
const char * const btrfs_feature_set_names[3] = { const char * const btrfs_feature_set_names[3] = {
@ -637,7 +637,7 @@ static void init_feature_attrs(void)
/* when one_device is NULL, it removes all device links */ /* when one_device is NULL, it removes all device links */
int btrfs_kobj_rm_device(struct btrfs_fs_devices *fs_devices, int btrfs_sysfs_rm_device_link(struct btrfs_fs_devices *fs_devices,
struct btrfs_device *one_device) struct btrfs_device *one_device)
{ {
struct hd_struct *disk; struct hd_struct *disk;
@ -675,7 +675,7 @@ int btrfs_sysfs_add_device(struct btrfs_fs_devices *fs_devs)
{ {
if (!fs_devs->device_dir_kobj) if (!fs_devs->device_dir_kobj)
fs_devs->device_dir_kobj = kobject_create_and_add("devices", fs_devs->device_dir_kobj = kobject_create_and_add("devices",
&fs_devs->super_kobj); &fs_devs->fsid_kobj);
if (!fs_devs->device_dir_kobj) if (!fs_devs->device_dir_kobj)
return -ENOMEM; return -ENOMEM;
@ -683,7 +683,7 @@ int btrfs_sysfs_add_device(struct btrfs_fs_devices *fs_devs)
return 0; return 0;
} }
int btrfs_kobj_add_device(struct btrfs_fs_devices *fs_devices, int btrfs_sysfs_add_device_link(struct btrfs_fs_devices *fs_devices,
struct btrfs_device *one_device) struct btrfs_device *one_device)
{ {
int error = 0; int error = 0;
@ -730,31 +730,31 @@ int btrfs_sysfs_add_fsid(struct btrfs_fs_devices *fs_devs,
int error; int error;
init_completion(&fs_devs->kobj_unregister); init_completion(&fs_devs->kobj_unregister);
fs_devs->super_kobj.kset = btrfs_kset; fs_devs->fsid_kobj.kset = btrfs_kset;
error = kobject_init_and_add(&fs_devs->super_kobj, error = kobject_init_and_add(&fs_devs->fsid_kobj,
&btrfs_ktype, parent, "%pU", fs_devs->fsid); &btrfs_ktype, parent, "%pU", fs_devs->fsid);
return error; return error;
} }
int btrfs_sysfs_add_one(struct btrfs_fs_info *fs_info) int btrfs_sysfs_add_mounted(struct btrfs_fs_info *fs_info)
{ {
int error; int error;
struct btrfs_fs_devices *fs_devs = fs_info->fs_devices; struct btrfs_fs_devices *fs_devs = fs_info->fs_devices;
struct kobject *super_kobj = &fs_devs->super_kobj; struct kobject *fsid_kobj = &fs_devs->fsid_kobj;
btrfs_set_fs_info_ptr(fs_info); btrfs_set_fs_info_ptr(fs_info);
error = btrfs_kobj_add_device(fs_devs, NULL); error = btrfs_sysfs_add_device_link(fs_devs, NULL);
if (error) if (error)
return error; return error;
error = sysfs_create_files(super_kobj, btrfs_attrs); error = sysfs_create_files(fsid_kobj, btrfs_attrs);
if (error) { if (error) {
btrfs_kobj_rm_device(fs_devs, NULL); btrfs_sysfs_rm_device_link(fs_devs, NULL);
return error; return error;
} }
error = sysfs_create_group(super_kobj, error = sysfs_create_group(fsid_kobj,
&btrfs_feature_attr_group); &btrfs_feature_attr_group);
if (error) if (error)
goto failure; goto failure;
@ -764,7 +764,7 @@ int btrfs_sysfs_add_one(struct btrfs_fs_info *fs_info)
goto failure; goto failure;
fs_info->space_info_kobj = kobject_create_and_add("allocation", fs_info->space_info_kobj = kobject_create_and_add("allocation",
super_kobj); fsid_kobj);
if (!fs_info->space_info_kobj) { if (!fs_info->space_info_kobj) {
error = -ENOMEM; error = -ENOMEM;
goto failure; goto failure;
@ -776,7 +776,7 @@ int btrfs_sysfs_add_one(struct btrfs_fs_info *fs_info)
return 0; return 0;
failure: failure:
btrfs_sysfs_remove_one(fs_info); btrfs_sysfs_remove_mounted(fs_info);
return error; return error;
} }

View file

@ -82,9 +82,9 @@ 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_devices *fs_devices, int btrfs_sysfs_add_device_link(struct btrfs_fs_devices *fs_devices,
struct btrfs_device *one_device); struct btrfs_device *one_device);
int btrfs_kobj_rm_device(struct btrfs_fs_devices *fs_devices, int btrfs_sysfs_rm_device_link(struct btrfs_fs_devices *fs_devices,
struct btrfs_device *one_device); struct btrfs_device *one_device);
int btrfs_sysfs_add_fsid(struct btrfs_fs_devices *fs_devs, int btrfs_sysfs_add_fsid(struct btrfs_fs_devices *fs_devs,
struct kobject *parent); struct kobject *parent);

View file

@ -2136,7 +2136,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
ret = btrfs_write_and_wait_transaction(trans, root); ret = btrfs_write_and_wait_transaction(trans, root);
if (ret) { if (ret) {
btrfs_error(root->fs_info, ret, btrfs_std_error(root->fs_info, ret,
"Error while writing out transaction"); "Error while writing out transaction");
mutex_unlock(&root->fs_info->tree_log_mutex); mutex_unlock(&root->fs_info->tree_log_mutex);
goto scrub_continue; goto scrub_continue;

View file

@ -5314,7 +5314,7 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree)
ret = walk_log_tree(trans, log_root_tree, &wc); ret = walk_log_tree(trans, log_root_tree, &wc);
if (ret) { if (ret) {
btrfs_error(fs_info, ret, "Failed to pin buffers while " btrfs_std_error(fs_info, ret, "Failed to pin buffers while "
"recovering log root tree."); "recovering log root tree.");
goto error; goto error;
} }
@ -5328,7 +5328,7 @@ again:
ret = btrfs_search_slot(NULL, log_root_tree, &key, path, 0, 0); ret = btrfs_search_slot(NULL, log_root_tree, &key, path, 0, 0);
if (ret < 0) { if (ret < 0) {
btrfs_error(fs_info, ret, btrfs_std_error(fs_info, ret,
"Couldn't find tree log root."); "Couldn't find tree log root.");
goto error; goto error;
} }
@ -5346,7 +5346,7 @@ again:
log = btrfs_read_fs_root(log_root_tree, &found_key); log = btrfs_read_fs_root(log_root_tree, &found_key);
if (IS_ERR(log)) { if (IS_ERR(log)) {
ret = PTR_ERR(log); ret = PTR_ERR(log);
btrfs_error(fs_info, ret, btrfs_std_error(fs_info, ret,
"Couldn't read tree log root."); "Couldn't read tree log root.");
goto error; goto error;
} }
@ -5361,7 +5361,7 @@ again:
free_extent_buffer(log->node); free_extent_buffer(log->node);
free_extent_buffer(log->commit_root); free_extent_buffer(log->commit_root);
kfree(log); kfree(log);
btrfs_error(fs_info, ret, "Couldn't read target root " btrfs_std_error(fs_info, ret, "Couldn't read target root "
"for tree log recovery."); "for tree log recovery.");
goto error; goto error;
} }

View file

@ -198,7 +198,6 @@ btrfs_get_bdev_and_sb(const char *device_path, fmode_t flags, void *holder,
if (IS_ERR(*bdev)) { if (IS_ERR(*bdev)) {
ret = PTR_ERR(*bdev); ret = PTR_ERR(*bdev);
printk(KERN_INFO "BTRFS: open %s failed\n", device_path);
goto error; goto error;
} }
@ -211,8 +210,8 @@ btrfs_get_bdev_and_sb(const char *device_path, fmode_t flags, void *holder,
} }
invalidate_bdev(*bdev); invalidate_bdev(*bdev);
*bh = btrfs_read_dev_super(*bdev); *bh = btrfs_read_dev_super(*bdev);
if (!*bh) { if (IS_ERR(*bh)) {
ret = -EINVAL; ret = PTR_ERR(*bh);
blkdev_put(*bdev, flags); blkdev_put(*bdev, flags);
goto error; goto error;
} }
@ -765,36 +764,7 @@ static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
mutex_lock(&fs_devices->device_list_mutex); mutex_lock(&fs_devices->device_list_mutex);
list_for_each_entry_safe(device, tmp, &fs_devices->devices, dev_list) { list_for_each_entry_safe(device, tmp, &fs_devices->devices, dev_list) {
struct btrfs_device *new_device; btrfs_close_one_device(device);
struct rcu_string *name;
if (device->bdev)
fs_devices->open_devices--;
if (device->writeable &&
device->devid != BTRFS_DEV_REPLACE_DEVID) {
list_del_init(&device->dev_alloc_list);
fs_devices->rw_devices--;
}
if (device->missing)
fs_devices->missing_devices--;
new_device = btrfs_alloc_device(NULL, &device->devid,
device->uuid);
BUG_ON(IS_ERR(new_device)); /* -ENOMEM */
/* Safe because we are under uuid_mutex */
if (device->name) {
name = rcu_string_strdup(device->name->str, GFP_NOFS);
BUG_ON(!name); /* -ENOMEM */
rcu_assign_pointer(new_device->name, name);
}
list_replace_rcu(&device->dev_list, &new_device->dev_list);
new_device->fs_devices = device->fs_devices;
call_rcu(&device->rcu, free_device);
} }
mutex_unlock(&fs_devices->device_list_mutex); mutex_unlock(&fs_devices->device_list_mutex);
@ -1402,7 +1372,7 @@ again:
extent = btrfs_item_ptr(leaf, path->slots[0], extent = btrfs_item_ptr(leaf, path->slots[0],
struct btrfs_dev_extent); struct btrfs_dev_extent);
} else { } else {
btrfs_error(root->fs_info, ret, "Slot search failed"); btrfs_std_error(root->fs_info, ret, "Slot search failed");
goto out; goto out;
} }
@ -1410,7 +1380,7 @@ again:
ret = btrfs_del_item(trans, root, path); ret = btrfs_del_item(trans, root, path);
if (ret) { if (ret) {
btrfs_error(root->fs_info, ret, btrfs_std_error(root->fs_info, ret,
"Failed to remove dev extent item"); "Failed to remove dev extent item");
} else { } else {
trans->transaction->have_free_bgs = 1; trans->transaction->have_free_bgs = 1;
@ -1801,7 +1771,7 @@ 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 */ /* remove sysfs entry */
btrfs_kobj_rm_device(root->fs_info->fs_devices, device); btrfs_sysfs_rm_device_link(root->fs_info->fs_devices, device);
} }
call_rcu(&device->rcu, free_device); call_rcu(&device->rcu, free_device);
@ -1924,7 +1894,8 @@ void btrfs_rm_dev_replace_remove_srcdev(struct btrfs_fs_info *fs_info,
if (srcdev->writeable) { if (srcdev->writeable) {
fs_devices->rw_devices--; fs_devices->rw_devices--;
/* zero out the old super if it is writable */ /* zero out the old super if it is writable */
btrfs_scratch_superblock(srcdev); btrfs_scratch_superblocks(srcdev->bdev,
rcu_str_deref(srcdev->name));
} }
if (srcdev->bdev) if (srcdev->bdev)
@ -1971,10 +1942,11 @@ void btrfs_destroy_dev_replace_tgtdev(struct btrfs_fs_info *fs_info,
WARN_ON(!tgtdev); WARN_ON(!tgtdev);
mutex_lock(&fs_info->fs_devices->device_list_mutex); mutex_lock(&fs_info->fs_devices->device_list_mutex);
btrfs_kobj_rm_device(fs_info->fs_devices, tgtdev); btrfs_sysfs_rm_device_link(fs_info->fs_devices, tgtdev);
if (tgtdev->bdev) { if (tgtdev->bdev) {
btrfs_scratch_superblock(tgtdev); btrfs_scratch_superblocks(tgtdev->bdev,
rcu_str_deref(tgtdev->name));
fs_info->fs_devices->open_devices--; fs_info->fs_devices->open_devices--;
} }
fs_info->fs_devices->num_devices--; fs_info->fs_devices->num_devices--;
@ -2041,10 +2013,8 @@ int btrfs_find_device_missing_or_by_path(struct btrfs_root *root,
} }
} }
if (!*device) { if (!*device)
btrfs_err(root->fs_info, "no missing device found"); return BTRFS_ERROR_DEV_MISSING_NOT_FOUND;
return -ENOENT;
}
return 0; return 0;
} else { } else {
@ -2309,7 +2279,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
tmp + 1); tmp + 1);
/* add sysfs device entry */ /* add sysfs device entry */
btrfs_kobj_add_device(root->fs_info->fs_devices, device); btrfs_sysfs_add_device_link(root->fs_info->fs_devices, device);
/* /*
* we've got more storage, clear any full flags on the space * we've got more storage, clear any full flags on the space
@ -2350,7 +2320,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
*/ */
snprintf(fsid_buf, BTRFS_UUID_UNPARSED_SIZE, "%pU", snprintf(fsid_buf, BTRFS_UUID_UNPARSED_SIZE, "%pU",
root->fs_info->fsid); root->fs_info->fsid);
if (kobject_rename(&root->fs_info->fs_devices->super_kobj, if (kobject_rename(&root->fs_info->fs_devices->fsid_kobj,
fsid_buf)) fsid_buf))
btrfs_warn(root->fs_info, btrfs_warn(root->fs_info,
"sysfs: failed to create fsid for sprout"); "sysfs: failed to create fsid for sprout");
@ -2369,7 +2339,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
ret = btrfs_relocate_sys_chunks(root); ret = btrfs_relocate_sys_chunks(root);
if (ret < 0) if (ret < 0)
btrfs_error(root->fs_info, ret, btrfs_std_error(root->fs_info, ret,
"Failed to relocate sys chunks after " "Failed to relocate sys chunks after "
"device initialization. This can be fixed " "device initialization. This can be fixed "
"using the \"btrfs balance\" command."); "using the \"btrfs balance\" command.");
@ -2389,7 +2359,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
error_trans: error_trans:
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->fs_devices, device); btrfs_sysfs_rm_device_link(root->fs_info->fs_devices, device);
kfree(device); kfree(device);
error: error:
blkdev_put(bdev, FMODE_EXCL); blkdev_put(bdev, FMODE_EXCL);
@ -2614,7 +2584,7 @@ static int btrfs_free_chunk(struct btrfs_trans_handle *trans,
if (ret < 0) if (ret < 0)
goto out; goto out;
else if (ret > 0) { /* Logic error or corruption */ else if (ret > 0) { /* Logic error or corruption */
btrfs_error(root->fs_info, -ENOENT, btrfs_std_error(root->fs_info, -ENOENT,
"Failed lookup while freeing chunk."); "Failed lookup while freeing chunk.");
ret = -ENOENT; ret = -ENOENT;
goto out; goto out;
@ -2622,7 +2592,7 @@ static int btrfs_free_chunk(struct btrfs_trans_handle *trans,
ret = btrfs_del_item(trans, root, path); ret = btrfs_del_item(trans, root, path);
if (ret < 0) if (ret < 0)
btrfs_error(root->fs_info, ret, btrfs_std_error(root->fs_info, ret,
"Failed to delete chunk item."); "Failed to delete chunk item.");
out: out:
btrfs_free_path(path); btrfs_free_path(path);
@ -2807,7 +2777,7 @@ static int btrfs_relocate_chunk(struct btrfs_root *root, u64 chunk_offset)
trans = btrfs_start_transaction(root, 0); trans = btrfs_start_transaction(root, 0);
if (IS_ERR(trans)) { if (IS_ERR(trans)) {
ret = PTR_ERR(trans); ret = PTR_ERR(trans);
btrfs_std_error(root->fs_info, ret); btrfs_std_error(root->fs_info, ret, NULL);
return ret; return ret;
} }
@ -3462,7 +3432,7 @@ static void __cancel_balance(struct btrfs_fs_info *fs_info)
unset_balance_control(fs_info); unset_balance_control(fs_info);
ret = del_balance_item(fs_info->tree_root); ret = del_balance_item(fs_info->tree_root);
if (ret) if (ret)
btrfs_std_error(fs_info, ret); btrfs_std_error(fs_info, ret, NULL);
atomic_set(&fs_info->mutually_exclusive_operation_running, 0); atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
} }
@ -6741,22 +6711,34 @@ int btrfs_get_dev_stats(struct btrfs_root *root,
return 0; return 0;
} }
int btrfs_scratch_superblock(struct btrfs_device *device) void btrfs_scratch_superblocks(struct block_device *bdev, char *device_path)
{ {
struct buffer_head *bh; struct buffer_head *bh;
struct btrfs_super_block *disk_super; struct btrfs_super_block *disk_super;
int copy_num;
if (!bdev)
return;
for (copy_num = 0; copy_num < BTRFS_SUPER_MIRROR_MAX;
copy_num++) {
if (btrfs_read_dev_one_super(bdev, copy_num, &bh))
continue;
bh = btrfs_read_dev_super(device->bdev);
if (!bh)
return -EINVAL;
disk_super = (struct btrfs_super_block *)bh->b_data; disk_super = (struct btrfs_super_block *)bh->b_data;
memset(&disk_super->magic, 0, sizeof(disk_super->magic)); memset(&disk_super->magic, 0, sizeof(disk_super->magic));
set_buffer_dirty(bh); set_buffer_dirty(bh);
sync_dirty_buffer(bh); sync_dirty_buffer(bh);
brelse(bh); brelse(bh);
}
return 0; /* Notify udev that device has changed */
btrfs_kobject_uevent(bdev, KOBJ_CHANGE);
/* Update ctime/mtime for device path for libblkid */
update_dev_time(device_path);
} }
/* /*
@ -6824,3 +6806,38 @@ void btrfs_reset_fs_info_ptr(struct btrfs_fs_info *fs_info)
fs_devices = fs_devices->seed; fs_devices = fs_devices->seed;
} }
} }
void btrfs_close_one_device(struct btrfs_device *device)
{
struct btrfs_fs_devices *fs_devices = device->fs_devices;
struct btrfs_device *new_device;
struct rcu_string *name;
if (device->bdev)
fs_devices->open_devices--;
if (device->writeable &&
device->devid != BTRFS_DEV_REPLACE_DEVID) {
list_del_init(&device->dev_alloc_list);
fs_devices->rw_devices--;
}
if (device->missing)
fs_devices->missing_devices--;
new_device = btrfs_alloc_device(NULL, &device->devid,
device->uuid);
BUG_ON(IS_ERR(new_device)); /* -ENOMEM */
/* Safe because we are under uuid_mutex */
if (device->name) {
name = rcu_string_strdup(device->name->str, GFP_NOFS);
BUG_ON(!name); /* -ENOMEM */
rcu_assign_pointer(new_device->name, name);
}
list_replace_rcu(&device->dev_list, &new_device->dev_list);
new_device->fs_devices = device->fs_devices;
call_rcu(&device->rcu, free_device);
}

View file

@ -256,7 +256,7 @@ struct btrfs_fs_devices {
struct btrfs_fs_info *fs_info; struct btrfs_fs_info *fs_info;
/* sysfs kobjects */ /* sysfs kobjects */
struct kobject super_kobj; struct kobject fsid_kobj;
struct kobject *device_dir_kobj; struct kobject *device_dir_kobj;
struct completion kobj_unregister; struct completion kobj_unregister;
}; };
@ -474,7 +474,7 @@ void btrfs_destroy_dev_replace_tgtdev(struct btrfs_fs_info *fs_info,
struct btrfs_device *tgtdev); struct btrfs_device *tgtdev);
void btrfs_init_dev_replace_tgtdev_for_resume(struct btrfs_fs_info *fs_info, void btrfs_init_dev_replace_tgtdev_for_resume(struct btrfs_fs_info *fs_info,
struct btrfs_device *tgtdev); struct btrfs_device *tgtdev);
int btrfs_scratch_superblock(struct btrfs_device *device); void btrfs_scratch_superblocks(struct block_device *bdev, char *device_path);
int btrfs_is_parity_mirror(struct btrfs_mapping_tree *map_tree, int btrfs_is_parity_mirror(struct btrfs_mapping_tree *map_tree,
u64 logical, u64 len, int mirror_num); u64 logical, u64 len, int mirror_num);
unsigned long btrfs_full_stripe_len(struct btrfs_root *root, unsigned long btrfs_full_stripe_len(struct btrfs_root *root,
@ -547,5 +547,6 @@ static inline void unlock_chunks(struct btrfs_root *root)
struct list_head *btrfs_get_fs_uuids(void); struct list_head *btrfs_get_fs_uuids(void);
void btrfs_set_fs_info_ptr(struct btrfs_fs_info *fs_info); void btrfs_set_fs_info_ptr(struct btrfs_fs_info *fs_info);
void btrfs_reset_fs_info_ptr(struct btrfs_fs_info *fs_info); void btrfs_reset_fs_info_ptr(struct btrfs_fs_info *fs_info);
void btrfs_close_one_device(struct btrfs_device *device);
#endif #endif