Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 332608
b: refs/heads/master
c: 5af3e8c
h: refs/heads/master
v: v3
  • Loading branch information
Stefan Behrens authored and Chris Mason committed Oct 9, 2012
1 parent 9f25ab2 commit f66f28f
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 20 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 62856a9b73860cffe2a3d91b069393b88c219aa6
refs/heads/master: 5af3e8cce8b7ba0a2819e18c9146c8c0b452d479
5 changes: 5 additions & 0 deletions trunk/fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -1468,6 +1468,8 @@ struct btrfs_fs_info {

/* next backup root to be overwritten */
int backup_root_index;

int num_tolerated_disk_barrier_failures;
};

/*
Expand Down Expand Up @@ -3361,6 +3363,9 @@ void btrfs_inherit_iflags(struct inode *inode, struct inode *dir);
int btrfs_defrag_file(struct inode *inode, struct file *file,
struct btrfs_ioctl_defrag_range_args *range,
u64 newer_than, unsigned long max_pages);
void btrfs_get_block_group_info(struct list_head *groups_list,
struct btrfs_ioctl_space_info *space);

/* file.c */
int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans,
struct inode *inode);
Expand Down
109 changes: 96 additions & 13 deletions trunk/fs/btrfs/disk-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -2505,6 +2505,8 @@ int open_ctree(struct super_block *sb,
printk(KERN_ERR "Failed to read block groups: %d\n", ret);
goto fail_block_groups;
}
fs_info->num_tolerated_disk_barrier_failures =
btrfs_calc_num_tolerated_disk_barrier_failures(fs_info);

fs_info->cleaner_kthread = kthread_run(cleaner_kthread, tree_root,
"btrfs-cleaner");
Expand Down Expand Up @@ -2888,12 +2890,10 @@ static int write_dev_flush(struct btrfs_device *device, int wait)
printk_in_rcu("btrfs: disabling barriers on dev %s\n",
rcu_str_deref(device->name));
device->nobarriers = 1;
}
if (!bio_flagged(bio, BIO_UPTODATE)) {
} else if (!bio_flagged(bio, BIO_UPTODATE)) {
ret = -EIO;
if (!bio_flagged(bio, BIO_EOPNOTSUPP))
btrfs_dev_stat_inc_and_print(device,
BTRFS_DEV_STAT_FLUSH_ERRS);
btrfs_dev_stat_inc_and_print(device,
BTRFS_DEV_STAT_FLUSH_ERRS);
}

/* drop the reference from the wait == 0 run */
Expand Down Expand Up @@ -2932,42 +2932,117 @@ static int barrier_all_devices(struct btrfs_fs_info *info)
{
struct list_head *head;
struct btrfs_device *dev;
int errors = 0;
int errors_send = 0;
int errors_wait = 0;
int ret;

/* send down all the barriers */
head = &info->fs_devices->devices;
list_for_each_entry_rcu(dev, head, dev_list) {
if (!dev->bdev) {
errors++;
errors_send++;
continue;
}
if (!dev->in_fs_metadata || !dev->writeable)
continue;

ret = write_dev_flush(dev, 0);
if (ret)
errors++;
errors_send++;
}

/* wait for all the barriers */
list_for_each_entry_rcu(dev, head, dev_list) {
if (!dev->bdev) {
errors++;
errors_wait++;
continue;
}
if (!dev->in_fs_metadata || !dev->writeable)
continue;

ret = write_dev_flush(dev, 1);
if (ret)
errors++;
errors_wait++;
}
if (errors)
if (errors_send > info->num_tolerated_disk_barrier_failures ||
errors_wait > info->num_tolerated_disk_barrier_failures)
return -EIO;
return 0;
}

int btrfs_calc_num_tolerated_disk_barrier_failures(
struct btrfs_fs_info *fs_info)
{
struct btrfs_ioctl_space_info space;
struct btrfs_space_info *sinfo;
u64 types[] = {BTRFS_BLOCK_GROUP_DATA,
BTRFS_BLOCK_GROUP_SYSTEM,
BTRFS_BLOCK_GROUP_METADATA,
BTRFS_BLOCK_GROUP_DATA | BTRFS_BLOCK_GROUP_METADATA};
int num_types = 4;
int i;
int c;
int num_tolerated_disk_barrier_failures =
(int)fs_info->fs_devices->num_devices;

for (i = 0; i < num_types; i++) {
struct btrfs_space_info *tmp;

sinfo = NULL;
rcu_read_lock();
list_for_each_entry_rcu(tmp, &fs_info->space_info, list) {
if (tmp->flags == types[i]) {
sinfo = tmp;
break;
}
}
rcu_read_unlock();

if (!sinfo)
continue;

down_read(&sinfo->groups_sem);
for (c = 0; c < BTRFS_NR_RAID_TYPES; c++) {
if (!list_empty(&sinfo->block_groups[c])) {
u64 flags;

btrfs_get_block_group_info(
&sinfo->block_groups[c], &space);
if (space.total_bytes == 0 ||
space.used_bytes == 0)
continue;
flags = space.flags;
/*
* return
* 0: if dup, single or RAID0 is configured for
* any of metadata, system or data, else
* 1: if RAID5 is configured, or if RAID1 or
* RAID10 is configured and only two mirrors
* are used, else
* 2: if RAID6 is configured, else
* num_mirrors - 1: if RAID1 or RAID10 is
* configured and more than
* 2 mirrors are used.
*/
if (num_tolerated_disk_barrier_failures > 0 &&
((flags & (BTRFS_BLOCK_GROUP_DUP |
BTRFS_BLOCK_GROUP_RAID0)) ||
((flags & BTRFS_BLOCK_GROUP_PROFILE_MASK)
== 0)))
num_tolerated_disk_barrier_failures = 0;
else if (num_tolerated_disk_barrier_failures > 1
&&
(flags & (BTRFS_BLOCK_GROUP_RAID1 |
BTRFS_BLOCK_GROUP_RAID10)))
num_tolerated_disk_barrier_failures = 1;
}
}
up_read(&sinfo->groups_sem);
}

return num_tolerated_disk_barrier_failures;
}

int write_all_supers(struct btrfs_root *root, int max_mirrors)
{
struct list_head *head;
Expand All @@ -2990,8 +3065,16 @@ int write_all_supers(struct btrfs_root *root, int max_mirrors)
mutex_lock(&root->fs_info->fs_devices->device_list_mutex);
head = &root->fs_info->fs_devices->devices;

if (do_barriers)
barrier_all_devices(root->fs_info);
if (do_barriers) {
ret = barrier_all_devices(root->fs_info);
if (ret) {
mutex_unlock(
&root->fs_info->fs_devices->device_list_mutex);
btrfs_error(root->fs_info, ret,
"errors while submitting device barriers.");
return ret;
}
}

list_for_each_entry_rcu(dev, head, dev_list) {
if (!dev->bdev) {
Expand Down
2 changes: 2 additions & 0 deletions trunk/fs/btrfs/disk-io.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans,
u64 objectid);
int btree_lock_page_hook(struct page *page, void *data,
void (*flush_fn)(void *));
int btrfs_calc_num_tolerated_disk_barrier_failures(
struct btrfs_fs_info *fs_info);

#ifdef CONFIG_DEBUG_LOCK_ALLOC
void btrfs_init_lockdep(void);
Expand Down
8 changes: 4 additions & 4 deletions trunk/fs/btrfs/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2875,8 +2875,8 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp)
return 0;
}

static void get_block_group_info(struct list_head *groups_list,
struct btrfs_ioctl_space_info *space)
void btrfs_get_block_group_info(struct list_head *groups_list,
struct btrfs_ioctl_space_info *space)
{
struct btrfs_block_group_cache *block_group;

Expand Down Expand Up @@ -2984,8 +2984,8 @@ long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg)
down_read(&info->groups_sem);
for (c = 0; c < BTRFS_NR_RAID_TYPES; c++) {
if (!list_empty(&info->block_groups[c])) {
get_block_group_info(&info->block_groups[c],
&space);
btrfs_get_block_group_info(
&info->block_groups[c], &space);
memcpy(dest, &space, sizeof(space));
dest++;
space_args.total_spaces++;
Expand Down
7 changes: 5 additions & 2 deletions trunk/fs/btrfs/tree-log.c
Original file line number Diff line number Diff line change
Expand Up @@ -2425,9 +2425,12 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
* in and cause problems either.
*/
btrfs_scrub_pause_super(root);
write_ctree_super(trans, root->fs_info->tree_root, 1);
ret = write_ctree_super(trans, root->fs_info->tree_root, 1);
btrfs_scrub_continue_super(root);
ret = 0;
if (ret) {
btrfs_abort_transaction(trans, root, ret);
goto out_wake_log_root;
}

mutex_lock(&root->log_mutex);
if (root->last_log_commit < log_transid)
Expand Down
30 changes: 30 additions & 0 deletions trunk/fs/btrfs/volumes.c
Original file line number Diff line number Diff line change
Expand Up @@ -1475,6 +1475,9 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
free_fs_devices(cur_devices);
}

root->fs_info->num_tolerated_disk_barrier_failures =
btrfs_calc_num_tolerated_disk_barrier_failures(root->fs_info);

/*
* at this point, the device is zero sized. We want to
* remove it from the devices list and zero out the old super
Expand Down Expand Up @@ -1799,6 +1802,8 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
btrfs_clear_space_info_full(root->fs_info);

unlock_chunks(root);
root->fs_info->num_tolerated_disk_barrier_failures =
btrfs_calc_num_tolerated_disk_barrier_failures(root->fs_info);
ret = btrfs_commit_transaction(trans, root);

if (seeding_dev) {
Expand Down Expand Up @@ -2809,6 +2814,26 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
}
}

if (bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) {
int num_tolerated_disk_barrier_failures;
u64 target = bctl->sys.target;

num_tolerated_disk_barrier_failures =
btrfs_calc_num_tolerated_disk_barrier_failures(fs_info);
if (num_tolerated_disk_barrier_failures > 0 &&
(target &
(BTRFS_BLOCK_GROUP_DUP | BTRFS_BLOCK_GROUP_RAID0 |
BTRFS_AVAIL_ALLOC_BIT_SINGLE)))
num_tolerated_disk_barrier_failures = 0;
else if (num_tolerated_disk_barrier_failures > 1 &&
(target &
(BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10)))
num_tolerated_disk_barrier_failures = 1;

fs_info->num_tolerated_disk_barrier_failures =
num_tolerated_disk_barrier_failures;
}

ret = insert_balance_item(fs_info->tree_root, bctl);
if (ret && ret != -EEXIST)
goto out;
Expand Down Expand Up @@ -2841,6 +2866,11 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
__cancel_balance(fs_info);
}

if (bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) {
fs_info->num_tolerated_disk_barrier_failures =
btrfs_calc_num_tolerated_disk_barrier_failures(fs_info);
}

wake_up(&fs_info->balance_wait_q);

return ret;
Expand Down

0 comments on commit f66f28f

Please sign in to comment.