Skip to content

Commit 36fac9e

Browse files
committed
Merge branch 'foreign/anand/dev-del-by-id-ext' into for-chris-4.7-20160516
2 parents 5ef64a3 + 88acff6 commit 36fac9e

File tree

6 files changed

+324
-242
lines changed

6 files changed

+324
-242
lines changed

fs/btrfs/dev-replace.c

Lines changed: 44 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,6 @@ static void btrfs_dev_replace_update_device_in_mapping_tree(
4444
struct btrfs_fs_info *fs_info,
4545
struct btrfs_device *srcdev,
4646
struct btrfs_device *tgtdev);
47-
static int btrfs_dev_replace_find_srcdev(struct btrfs_root *root, u64 srcdevid,
48-
char *srcdev_name,
49-
struct btrfs_device **device);
5047
static u64 __btrfs_dev_replace_cancel(struct btrfs_fs_info *fs_info);
5148
static int btrfs_dev_replace_kthread(void *data);
5249
static int btrfs_dev_replace_continue_on_mount(struct btrfs_fs_info *fs_info);
@@ -305,8 +302,8 @@ void btrfs_after_dev_replace_commit(struct btrfs_fs_info *fs_info)
305302
dev_replace->cursor_left_last_write_of_item;
306303
}
307304

308-
int btrfs_dev_replace_start(struct btrfs_root *root,
309-
struct btrfs_ioctl_dev_replace_args *args)
305+
int btrfs_dev_replace_start(struct btrfs_root *root, char *tgtdev_name,
306+
u64 srcdevid, char *srcdev_name, int read_src)
310307
{
311308
struct btrfs_trans_handle *trans;
312309
struct btrfs_fs_info *fs_info = root->fs_info;
@@ -315,29 +312,16 @@ int btrfs_dev_replace_start(struct btrfs_root *root,
315312
struct btrfs_device *tgt_device = NULL;
316313
struct btrfs_device *src_device = NULL;
317314

318-
switch (args->start.cont_reading_from_srcdev_mode) {
319-
case BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_ALWAYS:
320-
case BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_AVOID:
321-
break;
322-
default:
323-
return -EINVAL;
324-
}
325-
326-
if ((args->start.srcdevid == 0 && args->start.srcdev_name[0] == '\0') ||
327-
args->start.tgtdev_name[0] == '\0')
328-
return -EINVAL;
329-
330315
/* the disk copy procedure reuses the scrub code */
331316
mutex_lock(&fs_info->volume_mutex);
332-
ret = btrfs_dev_replace_find_srcdev(root, args->start.srcdevid,
333-
args->start.srcdev_name,
334-
&src_device);
317+
ret = btrfs_find_device_by_devspec(root, srcdevid,
318+
srcdev_name, &src_device);
335319
if (ret) {
336320
mutex_unlock(&fs_info->volume_mutex);
337321
return ret;
338322
}
339323

340-
ret = btrfs_init_dev_replace_tgtdev(root, args->start.tgtdev_name,
324+
ret = btrfs_init_dev_replace_tgtdev(root, tgtdev_name,
341325
src_device, &tgt_device);
342326
mutex_unlock(&fs_info->volume_mutex);
343327
if (ret)
@@ -364,18 +348,17 @@ int btrfs_dev_replace_start(struct btrfs_root *root,
364348
break;
365349
case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED:
366350
case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED:
367-
args->result = BTRFS_IOCTL_DEV_REPLACE_RESULT_ALREADY_STARTED;
351+
ret = BTRFS_IOCTL_DEV_REPLACE_RESULT_ALREADY_STARTED;
368352
goto leave;
369353
}
370354

371-
dev_replace->cont_reading_from_srcdev_mode =
372-
args->start.cont_reading_from_srcdev_mode;
355+
dev_replace->cont_reading_from_srcdev_mode = read_src;
373356
WARN_ON(!src_device);
374357
dev_replace->srcdev = src_device;
375358
WARN_ON(!tgt_device);
376359
dev_replace->tgtdev = tgt_device;
377360

378-
btrfs_info_in_rcu(root->fs_info,
361+
btrfs_info_in_rcu(fs_info,
379362
"dev_replace from %s (devid %llu) to %s started",
380363
src_device->missing ? "<missing disk>" :
381364
rcu_str_deref(src_device->name),
@@ -396,14 +379,13 @@ int btrfs_dev_replace_start(struct btrfs_root *root,
396379
dev_replace->item_needs_writeback = 1;
397380
atomic64_set(&dev_replace->num_write_errors, 0);
398381
atomic64_set(&dev_replace->num_uncorrectable_read_errors, 0);
399-
args->result = BTRFS_IOCTL_DEV_REPLACE_RESULT_NO_ERROR;
400382
btrfs_dev_replace_unlock(dev_replace, 1);
401383

402384
ret = btrfs_sysfs_add_device_link(tgt_device->fs_devices, tgt_device);
403385
if (ret)
404-
btrfs_err(root->fs_info, "kobj add dev failed %d\n", ret);
386+
btrfs_err(fs_info, "kobj add dev failed %d\n", ret);
405387

406-
btrfs_wait_ordered_roots(root->fs_info, -1);
388+
btrfs_wait_ordered_roots(fs_info, -1);
407389

408390
/* force writing the updated state information to disk */
409391
trans = btrfs_start_transaction(root, 0);
@@ -421,11 +403,9 @@ int btrfs_dev_replace_start(struct btrfs_root *root,
421403
btrfs_device_get_total_bytes(src_device),
422404
&dev_replace->scrub_progress, 0, 1);
423405

424-
ret = btrfs_dev_replace_finishing(root->fs_info, ret);
425-
/* don't warn if EINPROGRESS, someone else might be running scrub */
406+
ret = btrfs_dev_replace_finishing(fs_info, ret);
426407
if (ret == -EINPROGRESS) {
427-
args->result = BTRFS_IOCTL_DEV_REPLACE_RESULT_SCRUB_INPROGRESS;
428-
ret = 0;
408+
ret = BTRFS_IOCTL_DEV_REPLACE_RESULT_SCRUB_INPROGRESS;
429409
} else {
430410
WARN_ON(ret);
431411
}
@@ -440,6 +420,35 @@ int btrfs_dev_replace_start(struct btrfs_root *root,
440420
return ret;
441421
}
442422

423+
int btrfs_dev_replace_by_ioctl(struct btrfs_root *root,
424+
struct btrfs_ioctl_dev_replace_args *args)
425+
{
426+
int ret;
427+
428+
switch (args->start.cont_reading_from_srcdev_mode) {
429+
case BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_ALWAYS:
430+
case BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_AVOID:
431+
break;
432+
default:
433+
return -EINVAL;
434+
}
435+
436+
if ((args->start.srcdevid == 0 && args->start.srcdev_name[0] == '\0') ||
437+
args->start.tgtdev_name[0] == '\0')
438+
return -EINVAL;
439+
440+
ret = btrfs_dev_replace_start(root, args->start.tgtdev_name,
441+
args->start.srcdevid,
442+
args->start.srcdev_name,
443+
args->start.cont_reading_from_srcdev_mode);
444+
args->result = ret;
445+
/* don't warn if EINPROGRESS, someone else might be running scrub */
446+
if (ret == BTRFS_IOCTL_DEV_REPLACE_RESULT_SCRUB_INPROGRESS)
447+
ret = 0;
448+
449+
return ret;
450+
}
451+
443452
/*
444453
* blocked until all flighting bios are finished.
445454
*/
@@ -560,10 +569,9 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
560569
ASSERT(list_empty(&src_device->resized_list));
561570
tgt_device->commit_total_bytes = src_device->commit_total_bytes;
562571
tgt_device->commit_bytes_used = src_device->bytes_used;
563-
if (fs_info->sb->s_bdev == src_device->bdev)
564-
fs_info->sb->s_bdev = tgt_device->bdev;
565-
if (fs_info->fs_devices->latest_bdev == src_device->bdev)
566-
fs_info->fs_devices->latest_bdev = tgt_device->bdev;
572+
573+
btrfs_assign_next_active_device(fs_info, src_device, tgt_device);
574+
567575
list_add(&tgt_device->dev_alloc_list, &fs_info->fs_devices->alloc_list);
568576
fs_info->fs_devices->rw_devices++;
569577

@@ -626,25 +634,6 @@ static void btrfs_dev_replace_update_device_in_mapping_tree(
626634
write_unlock(&em_tree->lock);
627635
}
628636

629-
static int btrfs_dev_replace_find_srcdev(struct btrfs_root *root, u64 srcdevid,
630-
char *srcdev_name,
631-
struct btrfs_device **device)
632-
{
633-
int ret;
634-
635-
if (srcdevid) {
636-
ret = 0;
637-
*device = btrfs_find_device(root->fs_info, srcdevid, NULL,
638-
NULL);
639-
if (!*device)
640-
ret = -ENOENT;
641-
} else {
642-
ret = btrfs_find_device_missing_or_by_path(root, srcdev_name,
643-
device);
644-
}
645-
return ret;
646-
}
647-
648637
void btrfs_dev_replace_status(struct btrfs_fs_info *fs_info,
649638
struct btrfs_ioctl_dev_replace_args *args)
650639
{

fs/btrfs/dev-replace.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@ int btrfs_init_dev_replace(struct btrfs_fs_info *fs_info);
2525
int btrfs_run_dev_replace(struct btrfs_trans_handle *trans,
2626
struct btrfs_fs_info *fs_info);
2727
void btrfs_after_dev_replace_commit(struct btrfs_fs_info *fs_info);
28-
int btrfs_dev_replace_start(struct btrfs_root *root,
28+
int btrfs_dev_replace_by_ioctl(struct btrfs_root *root,
2929
struct btrfs_ioctl_dev_replace_args *args);
30+
int btrfs_dev_replace_start(struct btrfs_root *root, char *tgtdev_name,
31+
u64 srcdevid, char *srcdev_name, int read_src);
3032
void btrfs_dev_replace_status(struct btrfs_fs_info *fs_info,
3133
struct btrfs_ioctl_dev_replace_args *args);
3234
int btrfs_dev_replace_cancel(struct btrfs_fs_info *fs_info,

fs/btrfs/ioctl.c

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2676,6 +2676,60 @@ static long btrfs_ioctl_add_dev(struct btrfs_root *root, void __user *arg)
26762676
return ret;
26772677
}
26782678

2679+
static long btrfs_ioctl_rm_dev_v2(struct file *file, void __user *arg)
2680+
{
2681+
struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
2682+
struct btrfs_ioctl_vol_args_v2 *vol_args;
2683+
int ret;
2684+
2685+
if (!capable(CAP_SYS_ADMIN))
2686+
return -EPERM;
2687+
2688+
ret = mnt_want_write_file(file);
2689+
if (ret)
2690+
return ret;
2691+
2692+
vol_args = memdup_user(arg, sizeof(*vol_args));
2693+
if (IS_ERR(vol_args)) {
2694+
ret = PTR_ERR(vol_args);
2695+
goto err_drop;
2696+
}
2697+
2698+
/* Check for compatibility reject unknown flags */
2699+
if (vol_args->flags & ~BTRFS_VOL_ARG_V2_FLAGS_SUPPORTED)
2700+
return -EOPNOTSUPP;
2701+
2702+
if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running,
2703+
1)) {
2704+
ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
2705+
goto out;
2706+
}
2707+
2708+
mutex_lock(&root->fs_info->volume_mutex);
2709+
if (vol_args->flags & BTRFS_DEVICE_SPEC_BY_ID) {
2710+
ret = btrfs_rm_device(root, NULL, vol_args->devid);
2711+
} else {
2712+
vol_args->name[BTRFS_SUBVOL_NAME_MAX] = '\0';
2713+
ret = btrfs_rm_device(root, vol_args->name, 0);
2714+
}
2715+
mutex_unlock(&root->fs_info->volume_mutex);
2716+
atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0);
2717+
2718+
if (!ret) {
2719+
if (vol_args->flags & BTRFS_DEVICE_SPEC_BY_ID)
2720+
btrfs_info(root->fs_info, "device deleted: id %llu",
2721+
vol_args->devid);
2722+
else
2723+
btrfs_info(root->fs_info, "device deleted: %s",
2724+
vol_args->name);
2725+
}
2726+
out:
2727+
kfree(vol_args);
2728+
err_drop:
2729+
mnt_drop_write_file(file);
2730+
return ret;
2731+
}
2732+
26792733
static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg)
26802734
{
26812735
struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
@@ -2703,7 +2757,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg)
27032757

27042758
vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
27052759
mutex_lock(&root->fs_info->volume_mutex);
2706-
ret = btrfs_rm_device(root, vol_args->name);
2760+
ret = btrfs_rm_device(root, vol_args->name, 0);
27072761
mutex_unlock(&root->fs_info->volume_mutex);
27082762

27092763
if (!ret)
@@ -4387,7 +4441,7 @@ static long btrfs_ioctl_dev_replace(struct btrfs_root *root, void __user *arg)
43874441
1)) {
43884442
ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
43894443
} else {
4390-
ret = btrfs_dev_replace_start(root, p);
4444+
ret = btrfs_dev_replace_by_ioctl(root, p);
43914445
atomic_set(
43924446
&root->fs_info->mutually_exclusive_operation_running,
43934447
0);
@@ -5480,6 +5534,8 @@ long btrfs_ioctl(struct file *file, unsigned int
54805534
return btrfs_ioctl_add_dev(root, argp);
54815535
case BTRFS_IOC_RM_DEV:
54825536
return btrfs_ioctl_rm_dev(file, argp);
5537+
case BTRFS_IOC_RM_DEV_V2:
5538+
return btrfs_ioctl_rm_dev_v2(file, argp);
54835539
case BTRFS_IOC_FS_INFO:
54845540
return btrfs_ioctl_fs_info(root, argp);
54855541
case BTRFS_IOC_DEV_INFO:

0 commit comments

Comments
 (0)