Btrfs: add balance progress reporting
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
This commit is contained in:
Родитель
de322263d3
Коммит
19a39dce3b
|
@ -3065,7 +3065,7 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
void update_ioctl_balance_args(struct btrfs_fs_info *fs_info,
|
||||
void update_ioctl_balance_args(struct btrfs_fs_info *fs_info, int lock,
|
||||
struct btrfs_ioctl_balance_args *bargs)
|
||||
{
|
||||
struct btrfs_balance_control *bctl = fs_info->balance_ctl;
|
||||
|
@ -3082,6 +3082,14 @@ void update_ioctl_balance_args(struct btrfs_fs_info *fs_info,
|
|||
memcpy(&bargs->data, &bctl->data, sizeof(bargs->data));
|
||||
memcpy(&bargs->meta, &bctl->meta, sizeof(bargs->meta));
|
||||
memcpy(&bargs->sys, &bctl->sys, sizeof(bargs->sys));
|
||||
|
||||
if (lock) {
|
||||
spin_lock(&fs_info->balance_lock);
|
||||
memcpy(&bargs->stat, &bctl->stat, sizeof(bargs->stat));
|
||||
spin_unlock(&fs_info->balance_lock);
|
||||
} else {
|
||||
memcpy(&bargs->stat, &bctl->stat, sizeof(bargs->stat));
|
||||
}
|
||||
}
|
||||
|
||||
static long btrfs_ioctl_balance(struct btrfs_root *root, void __user *arg)
|
||||
|
@ -3181,6 +3189,39 @@ static long btrfs_ioctl_balance_ctl(struct btrfs_root *root, int cmd)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static long btrfs_ioctl_balance_progress(struct btrfs_root *root,
|
||||
void __user *arg)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = root->fs_info;
|
||||
struct btrfs_ioctl_balance_args *bargs;
|
||||
int ret = 0;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
mutex_lock(&fs_info->balance_mutex);
|
||||
if (!fs_info->balance_ctl) {
|
||||
ret = -ENOTCONN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
bargs = kzalloc(sizeof(*bargs), GFP_NOFS);
|
||||
if (!bargs) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
update_ioctl_balance_args(fs_info, 1, bargs);
|
||||
|
||||
if (copy_to_user(arg, bargs, sizeof(*bargs)))
|
||||
ret = -EFAULT;
|
||||
|
||||
kfree(bargs);
|
||||
out:
|
||||
mutex_unlock(&fs_info->balance_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
long btrfs_ioctl(struct file *file, unsigned int
|
||||
cmd, unsigned long arg)
|
||||
{
|
||||
|
@ -3261,6 +3302,8 @@ long btrfs_ioctl(struct file *file, unsigned int
|
|||
return btrfs_ioctl_balance(root, argp);
|
||||
case BTRFS_IOC_BALANCE_CTL:
|
||||
return btrfs_ioctl_balance_ctl(root, arg);
|
||||
case BTRFS_IOC_BALANCE_PROGRESS:
|
||||
return btrfs_ioctl_balance_progress(root, argp);
|
||||
}
|
||||
|
||||
return -ENOTTY;
|
||||
|
|
|
@ -324,6 +324,8 @@ struct btrfs_ioctl_logical_ino_args {
|
|||
#define BTRFS_IOC_BALANCE_V2 _IOWR(BTRFS_IOCTL_MAGIC, 32, \
|
||||
struct btrfs_ioctl_balance_args)
|
||||
#define BTRFS_IOC_BALANCE_CTL _IOW(BTRFS_IOCTL_MAGIC, 33, int)
|
||||
#define BTRFS_IOC_BALANCE_PROGRESS _IOR(BTRFS_IOCTL_MAGIC, 34, \
|
||||
struct btrfs_ioctl_balance_args)
|
||||
#define BTRFS_IOC_INO_PATHS _IOWR(BTRFS_IOCTL_MAGIC, 35, \
|
||||
struct btrfs_ioctl_ino_path_args)
|
||||
#define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \
|
||||
|
|
|
@ -2441,6 +2441,7 @@ static u64 div_factor(u64 num, int factor)
|
|||
|
||||
static int __btrfs_balance(struct btrfs_fs_info *fs_info)
|
||||
{
|
||||
struct btrfs_balance_control *bctl = fs_info->balance_ctl;
|
||||
struct btrfs_root *chunk_root = fs_info->chunk_root;
|
||||
struct btrfs_root *dev_root = fs_info->dev_root;
|
||||
struct list_head *devices;
|
||||
|
@ -2456,6 +2457,7 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info)
|
|||
int slot;
|
||||
int ret;
|
||||
int enospc_errors = 0;
|
||||
bool counting = true;
|
||||
|
||||
/* step one make some room on all the devices */
|
||||
devices = &fs_info->fs_devices->devices;
|
||||
|
@ -2487,12 +2489,18 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info)
|
|||
ret = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* zero out stat counters */
|
||||
spin_lock(&fs_info->balance_lock);
|
||||
memset(&bctl->stat, 0, sizeof(bctl->stat));
|
||||
spin_unlock(&fs_info->balance_lock);
|
||||
again:
|
||||
key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID;
|
||||
key.offset = (u64)-1;
|
||||
key.type = BTRFS_CHUNK_ITEM_KEY;
|
||||
|
||||
while (1) {
|
||||
if (atomic_read(&fs_info->balance_pause_req) ||
|
||||
if ((!counting && atomic_read(&fs_info->balance_pause_req)) ||
|
||||
atomic_read(&fs_info->balance_cancel_req)) {
|
||||
ret = -ECANCELED;
|
||||
goto error;
|
||||
|
@ -2529,24 +2537,47 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info)
|
|||
|
||||
chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk);
|
||||
|
||||
if (!counting) {
|
||||
spin_lock(&fs_info->balance_lock);
|
||||
bctl->stat.considered++;
|
||||
spin_unlock(&fs_info->balance_lock);
|
||||
}
|
||||
|
||||
ret = should_balance_chunk(chunk_root, leaf, chunk,
|
||||
found_key.offset);
|
||||
btrfs_release_path(path);
|
||||
if (!ret)
|
||||
goto loop;
|
||||
|
||||
if (counting) {
|
||||
spin_lock(&fs_info->balance_lock);
|
||||
bctl->stat.expected++;
|
||||
spin_unlock(&fs_info->balance_lock);
|
||||
goto loop;
|
||||
}
|
||||
|
||||
ret = btrfs_relocate_chunk(chunk_root,
|
||||
chunk_root->root_key.objectid,
|
||||
found_key.objectid,
|
||||
found_key.offset);
|
||||
if (ret && ret != -ENOSPC)
|
||||
goto error;
|
||||
if (ret == -ENOSPC)
|
||||
if (ret == -ENOSPC) {
|
||||
enospc_errors++;
|
||||
} else {
|
||||
spin_lock(&fs_info->balance_lock);
|
||||
bctl->stat.completed++;
|
||||
spin_unlock(&fs_info->balance_lock);
|
||||
}
|
||||
loop:
|
||||
key.offset = found_key.offset - 1;
|
||||
}
|
||||
|
||||
if (counting) {
|
||||
btrfs_release_path(path);
|
||||
counting = false;
|
||||
goto again;
|
||||
}
|
||||
error:
|
||||
btrfs_free_path(path);
|
||||
if (enospc_errors) {
|
||||
|
@ -2576,7 +2607,7 @@ static void __cancel_balance(struct btrfs_fs_info *fs_info)
|
|||
BUG_ON(ret);
|
||||
}
|
||||
|
||||
void update_ioctl_balance_args(struct btrfs_fs_info *fs_info,
|
||||
void update_ioctl_balance_args(struct btrfs_fs_info *fs_info, int lock,
|
||||
struct btrfs_ioctl_balance_args *bargs);
|
||||
|
||||
/*
|
||||
|
@ -2706,7 +2737,7 @@ do_balance:
|
|||
|
||||
if (bargs) {
|
||||
memset(bargs, 0, sizeof(*bargs));
|
||||
update_ioctl_balance_args(fs_info, bargs);
|
||||
update_ioctl_balance_args(fs_info, 0, bargs);
|
||||
}
|
||||
|
||||
if ((ret && ret != -ECANCELED && ret != -ENOSPC) ||
|
||||
|
|
|
@ -218,6 +218,7 @@ struct map_lookup {
|
|||
#define BTRFS_BALANCE_ARGS_SOFT (1ULL << 9)
|
||||
|
||||
struct btrfs_balance_args;
|
||||
struct btrfs_balance_progress;
|
||||
struct btrfs_balance_control {
|
||||
struct btrfs_fs_info *fs_info;
|
||||
|
||||
|
@ -226,6 +227,8 @@ struct btrfs_balance_control {
|
|||
struct btrfs_balance_args sys;
|
||||
|
||||
u64 flags;
|
||||
|
||||
struct btrfs_balance_progress stat;
|
||||
};
|
||||
|
||||
int btrfs_account_dev_extents_size(struct btrfs_device *device, u64 start,
|
||||
|
|
Загрузка…
Ссылка в новой задаче