aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorMiao Xie <miaox@cn.fujitsu.com>2014-09-03 09:35:46 -0400
committerChris Mason <clm@fb.com>2014-09-17 16:38:48 -0400
commit5f375835694426d00a7a4bc7fef72479578f279f (patch)
treebaaaa36a42866954e767b5a2ecc76e18e2c9c572 /fs
parent416d7b802a8bc044e98dc8bd96b59ce7a02287ac (diff)
Btrfs: move the missing device to its own fs device list
For a missing device, we don't know it belong to which fs before we read its fsid from the chunk tree. So we add them into the current fs device list at first. When we get its fsid, we should move them to their own fs device list. Signed-off-by: Miao Xie <miaox@cn.fujitsu.com> Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/volumes.c78
1 files changed, 52 insertions, 26 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index fbe4ead7e22f..57a7f331eb3e 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -5846,10 +5846,10 @@ struct btrfs_device *btrfs_find_device(struct btrfs_fs_info *fs_info, u64 devid,
5846} 5846}
5847 5847
5848static struct btrfs_device *add_missing_dev(struct btrfs_root *root, 5848static struct btrfs_device *add_missing_dev(struct btrfs_root *root,
5849 struct btrfs_fs_devices *fs_devices,
5849 u64 devid, u8 *dev_uuid) 5850 u64 devid, u8 *dev_uuid)
5850{ 5851{
5851 struct btrfs_device *device; 5852 struct btrfs_device *device;
5852 struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices;
5853 5853
5854 device = btrfs_alloc_device(NULL, &devid, dev_uuid); 5854 device = btrfs_alloc_device(NULL, &devid, dev_uuid);
5855 if (IS_ERR(device)) 5855 if (IS_ERR(device))
@@ -5986,7 +5986,8 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
5986 } 5986 }
5987 if (!map->stripes[i].dev) { 5987 if (!map->stripes[i].dev) {
5988 map->stripes[i].dev = 5988 map->stripes[i].dev =
5989 add_missing_dev(root, devid, uuid); 5989 add_missing_dev(root, root->fs_info->fs_devices,
5990 devid, uuid);
5990 if (!map->stripes[i].dev) { 5991 if (!map->stripes[i].dev) {
5991 free_extent_map(em); 5992 free_extent_map(em);
5992 return -EIO; 5993 return -EIO;
@@ -6027,7 +6028,8 @@ static void fill_device_from_item(struct extent_buffer *leaf,
6027 read_extent_buffer(leaf, device->uuid, ptr, BTRFS_UUID_SIZE); 6028 read_extent_buffer(leaf, device->uuid, ptr, BTRFS_UUID_SIZE);
6028} 6029}
6029 6030
6030static int open_seed_devices(struct btrfs_root *root, u8 *fsid) 6031static struct btrfs_fs_devices *open_seed_devices(struct btrfs_root *root,
6032 u8 *fsid)
6031{ 6033{
6032 struct btrfs_fs_devices *fs_devices; 6034 struct btrfs_fs_devices *fs_devices;
6033 int ret; 6035 int ret;
@@ -6036,49 +6038,56 @@ static int open_seed_devices(struct btrfs_root *root, u8 *fsid)
6036 6038
6037 fs_devices = root->fs_info->fs_devices->seed; 6039 fs_devices = root->fs_info->fs_devices->seed;
6038 while (fs_devices) { 6040 while (fs_devices) {
6039 if (!memcmp(fs_devices->fsid, fsid, BTRFS_UUID_SIZE)) { 6041 if (!memcmp(fs_devices->fsid, fsid, BTRFS_UUID_SIZE))
6040 ret = 0; 6042 return fs_devices;
6041 goto out; 6043
6042 }
6043 fs_devices = fs_devices->seed; 6044 fs_devices = fs_devices->seed;
6044 } 6045 }
6045 6046
6046 fs_devices = find_fsid(fsid); 6047 fs_devices = find_fsid(fsid);
6047 if (!fs_devices) { 6048 if (!fs_devices) {
6048 ret = -ENOENT; 6049 if (!btrfs_test_opt(root, DEGRADED))
6049 goto out; 6050 return ERR_PTR(-ENOENT);
6051
6052 fs_devices = alloc_fs_devices(fsid);
6053 if (IS_ERR(fs_devices))
6054 return fs_devices;
6055
6056 fs_devices->seeding = 1;
6057 fs_devices->opened = 1;
6058 return fs_devices;
6050 } 6059 }
6051 6060
6052 fs_devices = clone_fs_devices(fs_devices); 6061 fs_devices = clone_fs_devices(fs_devices);
6053 if (IS_ERR(fs_devices)) { 6062 if (IS_ERR(fs_devices))
6054 ret = PTR_ERR(fs_devices); 6063 return fs_devices;
6055 goto out;
6056 }
6057 6064
6058 ret = __btrfs_open_devices(fs_devices, FMODE_READ, 6065 ret = __btrfs_open_devices(fs_devices, FMODE_READ,
6059 root->fs_info->bdev_holder); 6066 root->fs_info->bdev_holder);
6060 if (ret) { 6067 if (ret) {
6061 free_fs_devices(fs_devices); 6068 free_fs_devices(fs_devices);
6069 fs_devices = ERR_PTR(ret);
6062 goto out; 6070 goto out;
6063 } 6071 }
6064 6072
6065 if (!fs_devices->seeding) { 6073 if (!fs_devices->seeding) {
6066 __btrfs_close_devices(fs_devices); 6074 __btrfs_close_devices(fs_devices);
6067 free_fs_devices(fs_devices); 6075 free_fs_devices(fs_devices);
6068 ret = -EINVAL; 6076 fs_devices = ERR_PTR(-EINVAL);
6069 goto out; 6077 goto out;
6070 } 6078 }
6071 6079
6072 fs_devices->seed = root->fs_info->fs_devices->seed; 6080 fs_devices->seed = root->fs_info->fs_devices->seed;
6073 root->fs_info->fs_devices->seed = fs_devices; 6081 root->fs_info->fs_devices->seed = fs_devices;
6074out: 6082out:
6075 return ret; 6083 return fs_devices;
6076} 6084}
6077 6085
6078static int read_one_dev(struct btrfs_root *root, 6086static int read_one_dev(struct btrfs_root *root,
6079 struct extent_buffer *leaf, 6087 struct extent_buffer *leaf,
6080 struct btrfs_dev_item *dev_item) 6088 struct btrfs_dev_item *dev_item)
6081{ 6089{
6090 struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices;
6082 struct btrfs_device *device; 6091 struct btrfs_device *device;
6083 u64 devid; 6092 u64 devid;
6084 int ret; 6093 int ret;
@@ -6092,31 +6101,48 @@ static int read_one_dev(struct btrfs_root *root,
6092 BTRFS_UUID_SIZE); 6101 BTRFS_UUID_SIZE);
6093 6102
6094 if (memcmp(fs_uuid, root->fs_info->fsid, BTRFS_UUID_SIZE)) { 6103 if (memcmp(fs_uuid, root->fs_info->fsid, BTRFS_UUID_SIZE)) {
6095 ret = open_seed_devices(root, fs_uuid); 6104 fs_devices = open_seed_devices(root, fs_uuid);
6096 if (ret && !(ret == -ENOENT && btrfs_test_opt(root, DEGRADED))) 6105 if (IS_ERR(fs_devices))
6097 return ret; 6106 return PTR_ERR(fs_devices);
6098 } 6107 }
6099 6108
6100 device = btrfs_find_device(root->fs_info, devid, dev_uuid, fs_uuid); 6109 device = btrfs_find_device(root->fs_info, devid, dev_uuid, fs_uuid);
6101 if (!device || !device->bdev) { 6110 if (!device) {
6102 if (!btrfs_test_opt(root, DEGRADED)) 6111 if (!btrfs_test_opt(root, DEGRADED))
6103 return -EIO; 6112 return -EIO;
6104 6113
6105 if (!device) { 6114 btrfs_warn(root->fs_info, "devid %llu missing", devid);
6106 btrfs_warn(root->fs_info, "devid %llu missing", devid); 6115 device = add_missing_dev(root, fs_devices, devid, dev_uuid);
6107 device = add_missing_dev(root, devid, dev_uuid); 6116 if (!device)
6108 if (!device) 6117 return -ENOMEM;
6109 return -ENOMEM; 6118 } else {
6110 } else if (!device->missing) { 6119 if (!device->bdev && !btrfs_test_opt(root, DEGRADED))
6120 return -EIO;
6121
6122 if(!device->bdev && !device->missing) {
6111 /* 6123 /*
6112 * this happens when a device that was properly setup 6124 * this happens when a device that was properly setup
6113 * in the device info lists suddenly goes bad. 6125 * in the device info lists suddenly goes bad.
6114 * device->bdev is NULL, and so we have to set 6126 * device->bdev is NULL, and so we have to set
6115 * device->missing to one here 6127 * device->missing to one here
6116 */ 6128 */
6117 root->fs_info->fs_devices->missing_devices++; 6129 device->fs_devices->missing_devices++;
6118 device->missing = 1; 6130 device->missing = 1;
6119 } 6131 }
6132
6133 /* Move the device to its own fs_devices */
6134 if (device->fs_devices != fs_devices) {
6135 ASSERT(device->missing);
6136
6137 list_move(&device->dev_list, &fs_devices->devices);
6138 device->fs_devices->num_devices--;
6139 fs_devices->num_devices++;
6140
6141 device->fs_devices->missing_devices--;
6142 fs_devices->missing_devices++;
6143
6144 device->fs_devices = fs_devices;
6145 }
6120 } 6146 }
6121 6147
6122 if (device->fs_devices != root->fs_info->fs_devices) { 6148 if (device->fs_devices != root->fs_info->fs_devices) {