diff options
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r-- | fs/btrfs/volumes.c | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index cc04dc1445d6..6b9884507837 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -412,12 +412,16 @@ static noinline int device_list_add(const char *path, | |||
412 | 412 | ||
413 | device->fs_devices = fs_devices; | 413 | device->fs_devices = fs_devices; |
414 | fs_devices->num_devices++; | 414 | fs_devices->num_devices++; |
415 | } else if (strcmp(device->name, path)) { | 415 | } else if (!device->name || strcmp(device->name, path)) { |
416 | name = kstrdup(path, GFP_NOFS); | 416 | name = kstrdup(path, GFP_NOFS); |
417 | if (!name) | 417 | if (!name) |
418 | return -ENOMEM; | 418 | return -ENOMEM; |
419 | kfree(device->name); | 419 | kfree(device->name); |
420 | device->name = name; | 420 | device->name = name; |
421 | if (device->missing) { | ||
422 | fs_devices->missing_devices--; | ||
423 | device->missing = 0; | ||
424 | } | ||
421 | } | 425 | } |
422 | 426 | ||
423 | if (found_transid > fs_devices->latest_trans) { | 427 | if (found_transid > fs_devices->latest_trans) { |
@@ -1236,6 +1240,9 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) | |||
1236 | 1240 | ||
1237 | device->fs_devices->num_devices--; | 1241 | device->fs_devices->num_devices--; |
1238 | 1242 | ||
1243 | if (device->missing) | ||
1244 | root->fs_info->fs_devices->missing_devices--; | ||
1245 | |||
1239 | next_device = list_entry(root->fs_info->fs_devices->devices.next, | 1246 | next_device = list_entry(root->fs_info->fs_devices->devices.next, |
1240 | struct btrfs_device, dev_list); | 1247 | struct btrfs_device, dev_list); |
1241 | if (device->bdev == root->fs_info->sb->s_bdev) | 1248 | if (device->bdev == root->fs_info->sb->s_bdev) |
@@ -3080,7 +3087,9 @@ static struct btrfs_device *add_missing_dev(struct btrfs_root *root, | |||
3080 | device->devid = devid; | 3087 | device->devid = devid; |
3081 | device->work.func = pending_bios_fn; | 3088 | device->work.func = pending_bios_fn; |
3082 | device->fs_devices = fs_devices; | 3089 | device->fs_devices = fs_devices; |
3090 | device->missing = 1; | ||
3083 | fs_devices->num_devices++; | 3091 | fs_devices->num_devices++; |
3092 | fs_devices->missing_devices++; | ||
3084 | spin_lock_init(&device->io_lock); | 3093 | spin_lock_init(&device->io_lock); |
3085 | INIT_LIST_HEAD(&device->dev_alloc_list); | 3094 | INIT_LIST_HEAD(&device->dev_alloc_list); |
3086 | memcpy(device->uuid, dev_uuid, BTRFS_UUID_SIZE); | 3095 | memcpy(device->uuid, dev_uuid, BTRFS_UUID_SIZE); |
@@ -3278,6 +3287,15 @@ static int read_one_dev(struct btrfs_root *root, | |||
3278 | device = add_missing_dev(root, devid, dev_uuid); | 3287 | device = add_missing_dev(root, devid, dev_uuid); |
3279 | if (!device) | 3288 | if (!device) |
3280 | return -ENOMEM; | 3289 | return -ENOMEM; |
3290 | } else if (!device->missing) { | ||
3291 | /* | ||
3292 | * this happens when a device that was properly setup | ||
3293 | * in the device info lists suddenly goes bad. | ||
3294 | * device->bdev is NULL, and so we have to set | ||
3295 | * device->missing to one here | ||
3296 | */ | ||
3297 | root->fs_info->fs_devices->missing_devices++; | ||
3298 | device->missing = 1; | ||
3281 | } | 3299 | } |
3282 | } | 3300 | } |
3283 | 3301 | ||