diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-04-28 15:29:42 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:02 -0400 |
commit | 788f20eb5affef584e75ea84bb80a4c3352a2c0e (patch) | |
tree | 8d803c865e8f0dd7fa14bdd1f2157b4c8649baa9 /fs/btrfs | |
parent | 8e7bf94fd5f44fa585e29fbe6a1bfabc04aea7cf (diff) |
Btrfs: Add new ioctl to add devices
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
-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 ac7106ec5357..b9257b37bb96 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 ab707c0930df..1a74b5018699 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 4551e82013c8..8ad35fc4ba56 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 892864906880..7153dfaa3404 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 a2c56de1548a..b93c15aa17db 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 6fe8440b37a7..6f173450378b 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 |