[05/10] btrfs: fix oops when adding a device
diff mbox

Message ID 4BF4E2D4.2000302@cn.fujitsu.com
State New, archived
Headers show

Commit Message

Miao Xie May 20, 2010, 7:20 a.m. UTC
None

Patch
diff mbox

diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index b584e9a..e344ba9 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -1121,6 +1121,38 @@  out:
 	return ret;
 }
 
+static int btrfs_device_can_remove(struct btrfs_fs_info *fs_info)
+{
+	u64 all_avail;
+
+	all_avail = fs_info->avail_data_alloc_bits |
+		    fs_info->avail_system_alloc_bits |
+		    fs_info->avail_metadata_alloc_bits;
+
+	if ((all_avail & BTRFS_BLOCK_GROUP_RAID10) &&
+	    fs_info->fs_devices->num_devices <= 4) {
+		printk(KERN_ERR "btrfs: unable to go below four devices "
+		       "on raid10\n");
+		return 0;
+	}
+
+	if ((all_avail & BTRFS_BLOCK_GROUP_RAID1) &&
+	    fs_info->fs_devices->num_devices <= 2) {
+		printk(KERN_ERR "btrfs: unable to go below two "
+		       "devices on raid1\n");
+		return 0;
+	}
+
+	if ((all_avail & BTRFS_BLOCK_GROUP_RAID0) &&
+	    fs_info->fs_devices->num_devices <= 2) {
+		printk(KERN_ERR "btrfs: unable to go below two "
+		       "devices on raid0\n");
+		return 0;
+	}
+
+	return 1;
+}
+
 int btrfs_rm_device(struct btrfs_root *root, char *device_path)
 {
 	struct btrfs_device *device;
@@ -1128,7 +1160,6 @@  int btrfs_rm_device(struct btrfs_root *root, char *device_path)
 	struct block_device *bdev;
 	struct buffer_head *bh = NULL;
 	struct btrfs_super_block *disk_super;
-	u64 all_avail;
 	u64 devid;
 	u64 num_devices;
 	u8 *dev_uuid;
@@ -1137,22 +1168,7 @@  int btrfs_rm_device(struct btrfs_root *root, char *device_path)
 	mutex_lock(&uuid_mutex);
 	mutex_lock(&root->fs_info->volume_mutex);
 
-	all_avail = root->fs_info->avail_data_alloc_bits |
-		root->fs_info->avail_system_alloc_bits |
-		root->fs_info->avail_metadata_alloc_bits;
-
-	if ((all_avail & BTRFS_BLOCK_GROUP_RAID10) &&
-	    root->fs_info->fs_devices->num_devices <= 4) {
-		printk(KERN_ERR "btrfs: unable to go below four devices "
-		       "on raid10\n");
-		ret = -EINVAL;
-		goto out;
-	}
-
-	if ((all_avail & BTRFS_BLOCK_GROUP_RAID1) &&
-	    root->fs_info->fs_devices->num_devices <= 2) {
-		printk(KERN_ERR "btrfs: unable to go below two "
-		       "devices on raid1\n");
+	if (!btrfs_device_can_remove(root->fs_info)) {
 		ret = -EINVAL;
 		goto out;
 	}