aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-04-28 15:29:42 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:02 -0400
commit788f20eb5affef584e75ea84bb80a4c3352a2c0e (patch)
tree8d803c865e8f0dd7fa14bdd1f2157b4c8649baa9
parent8e7bf94fd5f44fa585e29fbe6a1bfabc04aea7cf (diff)
Btrfs: Add new ioctl to add devices
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r--fs/btrfs/ctree.h2
-rw-r--r--fs/btrfs/inode.c23
-rw-r--r--fs/btrfs/ioctl.h6
-rw-r--r--fs/btrfs/super.c1
-rw-r--r--fs/btrfs/volumes.c75
-rw-r--r--fs/btrfs/volumes.h1
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
3073long 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
3089out:
3090 kfree(vol_args);
3091 return ret;
3092}
3093
3073long btrfs_ioctl(struct file *file, unsigned int 3094long 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
596int 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++;
660out:
661 btrfs_end_transaction(trans, root);
662 mutex_unlock(&root->fs_info->fs_mutex);
663 return ret;
664
665out_close_bdev:
666 close_bdev_excl(bdev);
667 goto out;
668}
669
595int btrfs_update_device(struct btrfs_trans_handle *trans, 670int 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,
133struct btrfs_device *btrfs_find_device(struct btrfs_root *root, u64 devid, 133struct btrfs_device *btrfs_find_device(struct btrfs_root *root, u64 devid,
134 u8 *uuid); 134 u8 *uuid);
135int btrfs_shrink_device(struct btrfs_device *device, u64 new_size); 135int btrfs_shrink_device(struct btrfs_device *device, u64 new_size);
136int btrfs_init_new_device(struct btrfs_root *root, char *path);
136#endif 137#endif