diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/btrfs/ctree.h | 2 | ||||
| -rw-r--r-- | fs/btrfs/inode.c | 23 | ||||
| -rw-r--r-- | fs/btrfs/ioctl.h | 6 | ||||
| -rw-r--r-- | fs/btrfs/super.c | 1 | ||||
| -rw-r--r-- | fs/btrfs/volumes.c | 75 | ||||
| -rw-r--r-- | fs/btrfs/volumes.h | 1 |
6 files changed, 108 insertions, 0 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index ac7106ec535..b9257b37bb9 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -551,6 +551,8 @@ struct btrfs_fs_info { | |||
| 551 | u64 data_alloc_profile; | 551 | u64 data_alloc_profile; |
| 552 | u64 metadata_alloc_profile; | 552 | u64 metadata_alloc_profile; |
| 553 | u64 system_alloc_profile; | 553 | u64 system_alloc_profile; |
| 554 | |||
| 555 | void *bdev_holder; | ||
| 554 | }; | 556 | }; |
| 555 | 557 | ||
| 556 | /* | 558 | /* |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index ab707c0930d..1a74b501869 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -3070,6 +3070,27 @@ static int btrfs_ioctl_defrag(struct file *file) | |||
| 3070 | return 0; | 3070 | return 0; |
| 3071 | } | 3071 | } |
| 3072 | 3072 | ||
| 3073 | long btrfs_ioctl_add_dev(struct btrfs_root *root, void __user *arg) | ||
| 3074 | { | ||
| 3075 | struct btrfs_ioctl_vol_args *vol_args; | ||
| 3076 | int ret; | ||
| 3077 | |||
| 3078 | vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS); | ||
| 3079 | |||
| 3080 | if (!vol_args) | ||
| 3081 | return -ENOMEM; | ||
| 3082 | |||
| 3083 | if (copy_from_user(vol_args, arg, sizeof(*vol_args))) { | ||
| 3084 | ret = -EFAULT; | ||
| 3085 | goto out; | ||
| 3086 | } | ||
| 3087 | ret = btrfs_init_new_device(root, vol_args->name); | ||
| 3088 | |||
| 3089 | out: | ||
| 3090 | kfree(vol_args); | ||
| 3091 | return ret; | ||
| 3092 | } | ||
| 3093 | |||
| 3073 | long btrfs_ioctl(struct file *file, unsigned int | 3094 | long btrfs_ioctl(struct file *file, unsigned int |
| 3074 | cmd, unsigned long arg) | 3095 | cmd, unsigned long arg) |
| 3075 | { | 3096 | { |
| @@ -3082,6 +3103,8 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
| 3082 | return btrfs_ioctl_defrag(file); | 3103 | return btrfs_ioctl_defrag(file); |
| 3083 | case BTRFS_IOC_RESIZE: | 3104 | case BTRFS_IOC_RESIZE: |
| 3084 | return btrfs_ioctl_resize(root, (void __user *)arg); | 3105 | return btrfs_ioctl_resize(root, (void __user *)arg); |
| 3106 | case BTRFS_IOC_ADD_DEV: | ||
| 3107 | return btrfs_ioctl_add_dev(root, (void __user *)arg); | ||
| 3085 | } | 3108 | } |
| 3086 | 3109 | ||
| 3087 | return -ENOTTY; | 3110 | return -ENOTTY; |
diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h index 4551e82013c..8ad35fc4ba5 100644 --- a/fs/btrfs/ioctl.h +++ b/fs/btrfs/ioctl.h | |||
| @@ -36,4 +36,10 @@ struct btrfs_ioctl_vol_args { | |||
| 36 | struct btrfs_ioctl_vol_args) | 36 | struct btrfs_ioctl_vol_args) |
| 37 | #define BTRFS_IOC_SCAN_DEV _IOW(BTRFS_IOCTL_MAGIC, 4, \ | 37 | #define BTRFS_IOC_SCAN_DEV _IOW(BTRFS_IOCTL_MAGIC, 4, \ |
| 38 | struct btrfs_ioctl_vol_args) | 38 | struct btrfs_ioctl_vol_args) |
| 39 | #define BTRFS_IOC_ADD_DEV _IOW(BTRFS_IOCTL_MAGIC, 10, \ | ||
| 40 | struct btrfs_ioctl_vol_args) | ||
| 41 | #define BTRFS_IOC_RM_DEV _IOW(BTRFS_IOCTL_MAGIC, 11, \ | ||
| 42 | struct btrfs_ioctl_vol_args) | ||
| 43 | #define BTRFS_IOC_BALANCE _IOW(BTRFS_IOCTL_MAGIC, 12, \ | ||
| 44 | struct btrfs_ioctl_vol_args) | ||
| 39 | #endif | 45 | #endif |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 89286490688..7153dfaa340 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
| @@ -388,6 +388,7 @@ int btrfs_get_sb_bdev(struct file_system_type *fs_type, | |||
| 388 | goto error; | 388 | goto error; |
| 389 | } | 389 | } |
| 390 | 390 | ||
| 391 | btrfs_sb(s)->fs_info->bdev_holder = fs_type; | ||
| 391 | s->s_flags |= MS_ACTIVE; | 392 | s->s_flags |= MS_ACTIVE; |
| 392 | } | 393 | } |
| 393 | 394 | ||
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index a2c56de1548..b93c15aa17d 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <linux/bio.h> | 19 | #include <linux/bio.h> |
| 20 | #include <linux/buffer_head.h> | 20 | #include <linux/buffer_head.h> |
| 21 | #include <linux/blkdev.h> | 21 | #include <linux/blkdev.h> |
| 22 | #include <linux/random.h> | ||
| 22 | #include <asm/div64.h> | 23 | #include <asm/div64.h> |
| 23 | #include "ctree.h" | 24 | #include "ctree.h" |
| 24 | #include "extent_map.h" | 25 | #include "extent_map.h" |
| @@ -592,6 +593,80 @@ out: | |||
| 592 | return ret; | 593 | return ret; |
| 593 | } | 594 | } |
| 594 | 595 | ||
| 596 | int btrfs_init_new_device(struct btrfs_root *root, char *device_path) | ||
| 597 | { | ||
| 598 | struct btrfs_trans_handle *trans; | ||
| 599 | struct btrfs_device *device; | ||
| 600 | struct block_device *bdev; | ||
| 601 | struct list_head *cur; | ||
| 602 | struct list_head *devices; | ||
| 603 | u64 total_bytes; | ||
| 604 | int ret = 0; | ||
| 605 | |||
| 606 | |||
| 607 | bdev = open_bdev_excl(device_path, 0, root->fs_info->bdev_holder); | ||
| 608 | if (!bdev) { | ||
| 609 | return -EIO; | ||
| 610 | } | ||
| 611 | mutex_lock(&root->fs_info->fs_mutex); | ||
| 612 | trans = btrfs_start_transaction(root, 1); | ||
| 613 | devices = &root->fs_info->fs_devices->devices; | ||
| 614 | list_for_each(cur, devices) { | ||
| 615 | device = list_entry(cur, struct btrfs_device, dev_list); | ||
| 616 | if (device->bdev == bdev) { | ||
| 617 | ret = -EEXIST; | ||
| 618 | goto out; | ||
| 619 | } | ||
| 620 | } | ||
| 621 | |||
| 622 | device = kzalloc(sizeof(*device), GFP_NOFS); | ||
| 623 | if (!device) { | ||
| 624 | /* we can safely leave the fs_devices entry around */ | ||
| 625 | ret = -ENOMEM; | ||
| 626 | goto out_close_bdev; | ||
| 627 | } | ||
| 628 | |||
| 629 | device->barriers = 1; | ||
| 630 | generate_random_uuid(device->uuid); | ||
| 631 | spin_lock_init(&device->io_lock); | ||
| 632 | device->name = kstrdup(device_path, GFP_NOFS); | ||
| 633 | if (!device->name) { | ||
| 634 | kfree(device); | ||
| 635 | goto out_close_bdev; | ||
| 636 | } | ||
| 637 | device->io_width = root->sectorsize; | ||
| 638 | device->io_align = root->sectorsize; | ||
| 639 | device->sector_size = root->sectorsize; | ||
| 640 | device->total_bytes = i_size_read(bdev->bd_inode); | ||
| 641 | device->dev_root = root->fs_info->dev_root; | ||
| 642 | device->bdev = bdev; | ||
| 643 | |||
| 644 | ret = btrfs_add_device(trans, root, device); | ||
| 645 | if (ret) | ||
| 646 | goto out_close_bdev; | ||
| 647 | |||
| 648 | total_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy); | ||
| 649 | btrfs_set_super_total_bytes(&root->fs_info->super_copy, | ||
| 650 | total_bytes + device->total_bytes); | ||
| 651 | |||
| 652 | total_bytes = btrfs_super_num_devices(&root->fs_info->super_copy); | ||
| 653 | btrfs_set_super_num_devices(&root->fs_info->super_copy, | ||
| 654 | total_bytes + 1); | ||
| 655 | |||
| 656 | list_add(&device->dev_list, &root->fs_info->fs_devices->devices); | ||
| 657 | list_add(&device->dev_alloc_list, | ||
| 658 | &root->fs_info->fs_devices->alloc_list); | ||
| 659 | root->fs_info->fs_devices->num_devices++; | ||
| 660 | out: | ||
| 661 | btrfs_end_transaction(trans, root); | ||
| 662 | mutex_unlock(&root->fs_info->fs_mutex); | ||
| 663 | return ret; | ||
| 664 | |||
| 665 | out_close_bdev: | ||
| 666 | close_bdev_excl(bdev); | ||
| 667 | goto out; | ||
| 668 | } | ||
| 669 | |||
| 595 | int btrfs_update_device(struct btrfs_trans_handle *trans, | 670 | int btrfs_update_device(struct btrfs_trans_handle *trans, |
| 596 | struct btrfs_device *device) | 671 | struct btrfs_device *device) |
| 597 | { | 672 | { |
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index 6fe8440b37a..6f173450378 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h | |||
| @@ -133,4 +133,5 @@ int btrfs_grow_device(struct btrfs_trans_handle *trans, | |||
| 133 | struct btrfs_device *btrfs_find_device(struct btrfs_root *root, u64 devid, | 133 | struct btrfs_device *btrfs_find_device(struct btrfs_root *root, u64 devid, |
| 134 | u8 *uuid); | 134 | u8 *uuid); |
| 135 | int btrfs_shrink_device(struct btrfs_device *device, u64 new_size); | 135 | int btrfs_shrink_device(struct btrfs_device *device, u64 new_size); |
| 136 | int btrfs_init_new_device(struct btrfs_root *root, char *path); | ||
| 136 | #endif | 137 | #endif |
