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 91851b555e2e..177b73179590 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -413,12 +413,16 @@ static noinline int device_list_add(const char *path, | |||
413 | 413 | ||
414 | device->fs_devices = fs_devices; | 414 | device->fs_devices = fs_devices; |
415 | fs_devices->num_devices++; | 415 | fs_devices->num_devices++; |
416 | } else if (strcmp(device->name, path)) { | 416 | } else if (!device->name || strcmp(device->name, path)) { |
417 | name = kstrdup(path, GFP_NOFS); | 417 | name = kstrdup(path, GFP_NOFS); |
418 | if (!name) | 418 | if (!name) |
419 | return -ENOMEM; | 419 | return -ENOMEM; |
420 | kfree(device->name); | 420 | kfree(device->name); |
421 | device->name = name; | 421 | device->name = name; |
422 | if (device->missing) { | ||
423 | fs_devices->missing_devices--; | ||
424 | device->missing = 0; | ||
425 | } | ||
422 | } | 426 | } |
423 | 427 | ||
424 | if (found_transid > fs_devices->latest_trans) { | 428 | if (found_transid > fs_devices->latest_trans) { |
@@ -1238,6 +1242,9 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) | |||
1238 | 1242 | ||
1239 | device->fs_devices->num_devices--; | 1243 | device->fs_devices->num_devices--; |
1240 | 1244 | ||
1245 | if (device->missing) | ||
1246 | root->fs_info->fs_devices->missing_devices--; | ||
1247 | |||
1241 | next_device = list_entry(root->fs_info->fs_devices->devices.next, | 1248 | next_device = list_entry(root->fs_info->fs_devices->devices.next, |
1242 | struct btrfs_device, dev_list); | 1249 | struct btrfs_device, dev_list); |
1243 | if (device->bdev == root->fs_info->sb->s_bdev) | 1250 | if (device->bdev == root->fs_info->sb->s_bdev) |
@@ -3084,7 +3091,9 @@ static struct btrfs_device *add_missing_dev(struct btrfs_root *root, | |||
3084 | device->devid = devid; | 3091 | device->devid = devid; |
3085 | device->work.func = pending_bios_fn; | 3092 | device->work.func = pending_bios_fn; |
3086 | device->fs_devices = fs_devices; | 3093 | device->fs_devices = fs_devices; |
3094 | device->missing = 1; | ||
3087 | fs_devices->num_devices++; | 3095 | fs_devices->num_devices++; |
3096 | fs_devices->missing_devices++; | ||
3088 | spin_lock_init(&device->io_lock); | 3097 | spin_lock_init(&device->io_lock); |
3089 | INIT_LIST_HEAD(&device->dev_alloc_list); | 3098 | INIT_LIST_HEAD(&device->dev_alloc_list); |
3090 | memcpy(device->uuid, dev_uuid, BTRFS_UUID_SIZE); | 3099 | memcpy(device->uuid, dev_uuid, BTRFS_UUID_SIZE); |
@@ -3282,6 +3291,15 @@ static int read_one_dev(struct btrfs_root *root, | |||
3282 | device = add_missing_dev(root, devid, dev_uuid); | 3291 | device = add_missing_dev(root, devid, dev_uuid); |
3283 | if (!device) | 3292 | if (!device) |
3284 | return -ENOMEM; | 3293 | return -ENOMEM; |
3294 | } else if (!device->missing) { | ||
3295 | /* | ||
3296 | * this happens when a device that was properly setup | ||
3297 | * in the device info lists suddenly goes bad. | ||
3298 | * device->bdev is NULL, and so we have to set | ||
3299 | * device->missing to one here | ||
3300 | */ | ||
3301 | root->fs_info->fs_devices->missing_devices++; | ||
3302 | device->missing = 1; | ||
3285 | } | 3303 | } |
3286 | } | 3304 | } |
3287 | 3305 | ||