Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Btrfs fixes and enhancements. #2

Closed
wants to merge 30 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
96f3136
Btrfs: rename btrfs_sysfs_add_one to btrfs_sysfs_add_mounted
asj Aug 14, 2015
6618a59
Btrfs: rename btrfs_sysfs_remove_one to btrfs_sysfs_remove_mounted
asj Aug 14, 2015
e3bd697
Btrfs: rename btrfs_kobj_add_device to btrfs_sysfs_add_device_link
asj Aug 14, 2015
3257604
Btrfs: rename btrfs_kobj_rm_device to btrfs_sysfs_rm_device_link
asj Aug 14, 2015
c1b7e47
Btrfs: rename super_kobj to fsid_kobj
asj Aug 14, 2015
92fc03f
Btrfs: SB read failure should return EIO for __bread failure
asj Aug 14, 2015
57d816a
Btrfs: __btrfs_std_error() logic should be consistent w/out CONFIG_PR…
asj Aug 14, 2015
a4553fe
Btrfs: consolidate btrfs_error() to btrfs_std_error()
asj Sep 25, 2015
d74a625
Btrfs: use BTRFS_ERROR_DEV_MISSING_NOT_FOUND when missing device is n…
asj Aug 14, 2015
29c36d7
Btrfs: add btrfs_read_dev_one_super() to read one specific SB
asj Aug 14, 2015
12b1c26
Btrfs: enhance btrfs_scratch_superblock to scratch all superblocks
asj Aug 14, 2015
9e271ae
Btrfs: kernel operation should come after user input has been verified
asj Aug 14, 2015
097efc9
Btrfs: don't log error from btrfs_get_bdev_and_sb
asj Aug 14, 2015
f190aa4
Btrfs: add helper for closing one device
asj Aug 14, 2015
73416da
Btrfs: move kobj stuff out of dev_replace lock range
Aug 14, 2015
6247790
Btrfs: pass the error code to the btrfs_std_error and log ret
asj Oct 2, 2015
a1f170f
Btrfs: create a helper function to read the disk super
asj Sep 20, 2015
dbf8590
btrfs: maintain consistency in logging to help debugging
asj Sep 21, 2015
adef2e2
Btrfs: device path change must be logged
asj May 21, 2015
f2c354c
Btrfs: add missing brelse when superblock checksum fails
asj Oct 5, 2015
26239df
Btrfs: sysfs: support seed devices in the sysfs layout
asj Jun 18, 2015
d7c3547
Btrfs: create a framework to create pool attributes
asj Mar 20, 2015
08f4446
Btrfs: create helper function __check_raid_min_devices()
asj Apr 23, 2015
e17012a
Btrfs: clean up and optimize __check_raid_min_device()
asj Oct 1, 2015
cebed27
Btrfs: create helper btrfs_find_device_by_user_input()
asj Apr 23, 2015
a871c3d
Btrfs: make use of btrfs_find_device_by_user_input()
asj Apr 23, 2015
1e5cd99
Btrfs: enhance btrfs_find_device_by_user_input() to check device path
asj May 31, 2015
74b351a
Btrfs: make use of btrfs_scratch_superblocks() in btrfs_rm_device()
asj Apr 24, 2015
cfe509c
Btrfs: Introduce device delete by devid
asj Apr 13, 2015
cd3b237
Btrfs: Introduce device pool sysfs attributes
asj Nov 24, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions fs/btrfs/ctree.c
Original file line number Diff line number Diff line change
Expand Up @@ -1011,7 +1011,7 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
return ret;
if (refs == 0) {
ret = -EROFS;
btrfs_std_error(root->fs_info, ret);
btrfs_std_error(root->fs_info, ret, NULL);
return ret;
}
} else {
Expand Down Expand Up @@ -1927,7 +1927,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
child = read_node_slot(root, mid, 0);
if (!child) {
ret = -EROFS;
btrfs_std_error(root->fs_info, ret);
btrfs_std_error(root->fs_info, ret, NULL);
goto enospc;
}

Expand Down Expand Up @@ -2030,7 +2030,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
*/
if (!left) {
ret = -EROFS;
btrfs_std_error(root->fs_info, ret);
btrfs_std_error(root->fs_info, ret, NULL);
goto enospc;
}
wret = balance_node_right(trans, root, mid, left);
Expand Down
13 changes: 3 additions & 10 deletions fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -4004,8 +4004,8 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
/* sysfs.c */
int btrfs_init_sysfs(void);
void btrfs_exit_sysfs(void);
int btrfs_sysfs_add_one(struct btrfs_fs_info *fs_info);
void btrfs_sysfs_remove_one(struct btrfs_fs_info *fs_info);
int btrfs_sysfs_add_mounted(struct btrfs_fs_info *fs_info);
void btrfs_sysfs_remove_mounted(struct btrfs_fs_info *fs_info);

/* xattr.c */
ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size);
Expand Down Expand Up @@ -4127,14 +4127,7 @@ do { \
__LINE__, (errno)); \
} while (0)

#define btrfs_std_error(fs_info, errno) \
do { \
if ((errno)) \
__btrfs_std_error((fs_info), __func__, \
__LINE__, (errno), NULL); \
} while (0)

#define btrfs_error(fs_info, errno, fmt, args...) \
#define btrfs_std_error(fs_info, errno, fmt, args...) \
do { \
__btrfs_std_error((fs_info), __func__, __LINE__, \
(errno), fmt, ##args); \
Expand Down
73 changes: 28 additions & 45 deletions fs/btrfs/dev-replace.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,6 @@ static void btrfs_dev_replace_update_device_in_mapping_tree(
struct btrfs_fs_info *fs_info,
struct btrfs_device *srcdev,
struct btrfs_device *tgtdev);
static int btrfs_dev_replace_find_srcdev(struct btrfs_root *root, u64 srcdevid,
char *srcdev_name,
struct btrfs_device **device);
static u64 __btrfs_dev_replace_cancel(struct btrfs_fs_info *fs_info);
static int btrfs_dev_replace_kthread(void *data);
static int btrfs_dev_replace_continue_on_mount(struct btrfs_fs_info *fs_info);
Expand Down Expand Up @@ -323,26 +320,9 @@ int btrfs_dev_replace_start(struct btrfs_root *root,
return -EINVAL;
}

if ((args->start.srcdevid == 0 && args->start.srcdev_name[0] == '\0') ||
args->start.tgtdev_name[0] == '\0')
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 */
mutex_lock(&fs_info->volume_mutex);
ret = btrfs_dev_replace_find_srcdev(root, args->start.srcdevid,
ret = btrfs_find_device_by_user_input(root, args->start.srcdevid,
args->start.srcdev_name,
&src_device);
if (ret) {
Expand All @@ -356,6 +336,19 @@ int btrfs_dev_replace_start(struct btrfs_root *root,
if (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);
switch (dev_replace->replace_state) {
case BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED:
Expand All @@ -375,10 +368,6 @@ int btrfs_dev_replace_start(struct btrfs_root *root,
WARN_ON(!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);

printk_in_rcu(KERN_INFO
"BTRFS: dev_replace from %s (devid %llu) to %s started\n",
src_device->missing ? "<missing disk>" :
Expand All @@ -401,6 +390,14 @@ int btrfs_dev_replace_start(struct btrfs_root *root,
args->result = BTRFS_IOCTL_DEV_REPLACE_RESULT_NO_ERROR;
btrfs_dev_replace_unlock(dev_replace);

ret = btrfs_sysfs_add_device_link(tgt_device->fs_devices, tgt_device, 0);
if (ret)
btrfs_err(root->fs_info, "kobj add dev failed %d\n", ret);

ret = btrfs_sysfs_add_device_attr(tgt_device);
if (ret && ret != -EEXIST)
btrfs_err(root->fs_info, "sysfs create dev failed %d\n", ret);

btrfs_wait_ordered_roots(root->fs_info, -1);

/* force writing the updated state information to disk */
Expand Down Expand Up @@ -586,7 +583,12 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
mutex_unlock(&uuid_mutex);

/* 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, 0);
if (src_device->fs_devices->seeding &&
!src_device->fs_devices->num_devices)
btrfs_sysfs_remove_fsid(src_device->fs_devices);
else
btrfs_sysfs_rm_device_attr(src_device);
btrfs_rm_dev_replace_free_srcdev(fs_info, src_device);

/* write back the superblocks */
Expand Down Expand Up @@ -625,25 +627,6 @@ static void btrfs_dev_replace_update_device_in_mapping_tree(
write_unlock(&em_tree->lock);
}

static int btrfs_dev_replace_find_srcdev(struct btrfs_root *root, u64 srcdevid,
char *srcdev_name,
struct btrfs_device **device)
{
int ret;

if (srcdevid) {
ret = 0;
*device = btrfs_find_device(root->fs_info, srcdevid, NULL,
NULL);
if (!*device)
ret = -ENOENT;
} else {
ret = btrfs_find_device_missing_or_by_path(root, srcdev_name,
device);
}
return ret;
}

void btrfs_dev_replace_status(struct btrfs_fs_info *fs_info,
struct btrfs_ioctl_dev_replace_args *args)
{
Expand Down
92 changes: 53 additions & 39 deletions fs/btrfs/disk-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -2377,7 +2377,7 @@ static int btrfs_replay_log(struct btrfs_fs_info *fs_info,
/* returns with log_tree_root freed on success */
ret = btrfs_recover_log_trees(log_tree_root);
if (ret) {
btrfs_error(tree_root->fs_info, ret,
btrfs_std_error(tree_root->fs_info, ret,
"Failed to recover log tree");
free_extent_buffer(log_tree_root->node);
kfree(log_tree_root);
Expand Down Expand Up @@ -2653,8 +2653,8 @@ int open_ctree(struct super_block *sb,
* Read super block and check the signature bytes only
*/
bh = btrfs_read_dev_super(fs_devices->latest_bdev);
if (!bh) {
err = -EINVAL;
if (IS_ERR(bh)) {
err = PTR_ERR(bh);
goto fail_alloc;
}

Expand All @@ -2665,6 +2665,7 @@ int open_ctree(struct super_block *sb,
if (btrfs_check_super_csum(bh->b_data)) {
printk(KERN_ERR "BTRFS: superblock checksum mismatch\n");
err = -EINVAL;
brelse(bh);
goto fail_alloc;
}

Expand Down Expand Up @@ -2921,22 +2922,10 @@ int open_ctree(struct super_block *sb,

btrfs_close_extra_devices(fs_devices, 1);

ret = btrfs_sysfs_add_fsid(fs_devices, NULL);
if (ret) {
pr_err("BTRFS: failed to init sysfs fsid interface: %d\n", ret);
goto fail_block_groups;
}

ret = btrfs_sysfs_add_device(fs_devices);
if (ret) {
pr_err("BTRFS: failed to init sysfs device interface: %d\n", ret);
goto fail_fsdev_sysfs;
}

ret = btrfs_sysfs_add_one(fs_info);
ret = btrfs_sysfs_add_mounted(fs_info);
if (ret) {
pr_err("BTRFS: failed to init sysfs interface: %d\n", ret);
goto fail_fsdev_sysfs;
goto fail_block_groups;
}

ret = btrfs_init_space_info(fs_info);
Expand Down Expand Up @@ -3113,10 +3102,7 @@ int open_ctree(struct super_block *sb,
filemap_write_and_wait(fs_info->btree_inode->i_mapping);

fail_sysfs:
btrfs_sysfs_remove_one(fs_info);

fail_fsdev_sysfs:
btrfs_sysfs_remove_fsid(fs_info->fs_devices);
btrfs_sysfs_remove_mounted(fs_info);

fail_block_groups:
btrfs_put_block_group_cache(fs_info);
Expand Down Expand Up @@ -3188,36 +3174,57 @@ static void btrfs_end_buffer_write_sync(struct buffer_head *bh, int uptodate)
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 *bh;
struct buffer_head *latest = NULL;
struct btrfs_super_block *super;
int i;
u64 transid = 0;
u64 bytenr;
int ret = -EINVAL;

/* we would like to check all the supers, but that would make
* a btrfs mount succeed after a mkfs from a different FS.
* So, we need to add a special mount option to scan for
* later supers, using BTRFS_SUPER_MIRROR_MAX instead
*/
for (i = 0; i < 1; i++) {
bytenr = btrfs_sb_offset(i);
if (bytenr + BTRFS_SUPER_INFO_SIZE >=
i_size_read(bdev->bd_inode))
break;
bh = __bread(bdev, bytenr / 4096,
BTRFS_SUPER_INFO_SIZE);
if (!bh)
ret = btrfs_read_dev_one_super(bdev, i, &bh);
if (ret)
continue;

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) {
brelse(latest);
Expand All @@ -3227,6 +3234,10 @@ struct buffer_head *btrfs_read_dev_super(struct block_device *bdev)
brelse(bh);
}
}

if (!latest)
return ERR_PTR(ret);

return latest;
}

Expand Down Expand Up @@ -3544,7 +3555,7 @@ static int write_all_supers(struct btrfs_root *root, int max_mirrors)
if (ret) {
mutex_unlock(
&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.");
return ret;
}
Expand Down Expand Up @@ -3584,7 +3595,7 @@ static int write_all_supers(struct btrfs_root *root, int max_mirrors)
mutex_unlock(&root->fs_info->fs_devices->device_list_mutex);

/* 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);
return -EIO;
}
Expand All @@ -3602,7 +3613,7 @@ static int write_all_supers(struct btrfs_root *root, int max_mirrors)
}
mutex_unlock(&root->fs_info->fs_devices->device_list_mutex);
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);
return -EIO;
}
Expand Down Expand Up @@ -3788,8 +3799,11 @@ void close_ctree(struct btrfs_root *root)
percpu_counter_sum(&fs_info->delalloc_bytes));
}

btrfs_sysfs_remove_one(fs_info);
btrfs_sysfs_remove_fsid(fs_info->fs_devices);
btrfs_sysfs_remove_mounted(fs_info);
if (fs_info->fs_devices->seed) {
btrfs_sysfs_remove_fsid(fs_info->fs_devices->seed);
btrfs_sysfs_rm_seed_dir(fs_info->fs_devices);
}

btrfs_free_fs_roots(fs_info);

Expand Down
2 changes: 2 additions & 0 deletions fs/btrfs/disk-io.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ void close_ctree(struct btrfs_root *root);
int write_ctree_super(struct btrfs_trans_handle *trans,
struct btrfs_root *root, int max_mirrors);
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);
struct extent_buffer *btrfs_find_tree_block(struct btrfs_fs_info *fs_info,
u64 bytenr);
Expand Down
2 changes: 1 addition & 1 deletion fs/btrfs/extent-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -8688,7 +8688,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
if (!for_reloc && root_dropped == false)
btrfs_add_dead_root(root);
if (err && err != -EAGAIN)
btrfs_std_error(root->fs_info, err);
btrfs_std_error(root->fs_info, err, NULL);
return err;
}

Expand Down
2 changes: 1 addition & 1 deletion fs/btrfs/inode-item.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
name, name_len, &extref)) {
btrfs_std_error(root->fs_info, -ENOENT);
btrfs_std_error(root->fs_info, -ENOENT, NULL);
ret = -EROFS;
goto out;
}
Expand Down
Loading