diff options
| -rw-r--r-- | fs/btrfs/extent-tree.c | 17 | ||||
| -rw-r--r-- | fs/btrfs/volumes.c | 20 | ||||
| -rw-r--r-- | fs/btrfs/volumes.h | 2 |
3 files changed, 36 insertions, 3 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 41133b064d72..4be231e0d2bd 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -3044,7 +3044,13 @@ static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) | |||
| 3044 | 3044 | ||
| 3045 | u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags) | 3045 | u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags) |
| 3046 | { | 3046 | { |
| 3047 | u64 num_devices = root->fs_info->fs_devices->rw_devices; | 3047 | /* |
| 3048 | * we add in the count of missing devices because we want | ||
| 3049 | * to make sure that any RAID levels on a degraded FS | ||
| 3050 | * continue to be honored. | ||
| 3051 | */ | ||
| 3052 | u64 num_devices = root->fs_info->fs_devices->rw_devices + | ||
| 3053 | root->fs_info->fs_devices->missing_devices; | ||
| 3048 | 3054 | ||
| 3049 | if (num_devices == 1) | 3055 | if (num_devices == 1) |
| 3050 | flags &= ~(BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID0); | 3056 | flags &= ~(BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID0); |
| @@ -7891,7 +7897,14 @@ static u64 update_block_group_flags(struct btrfs_root *root, u64 flags) | |||
| 7891 | u64 stripped = BTRFS_BLOCK_GROUP_RAID0 | | 7897 | u64 stripped = BTRFS_BLOCK_GROUP_RAID0 | |
| 7892 | BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10; | 7898 | BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10; |
| 7893 | 7899 | ||
| 7894 | num_devices = root->fs_info->fs_devices->rw_devices; | 7900 | /* |
| 7901 | * we add in the count of missing devices because we want | ||
| 7902 | * to make sure that any RAID levels on a degraded FS | ||
| 7903 | * continue to be honored. | ||
| 7904 | */ | ||
| 7905 | num_devices = root->fs_info->fs_devices->rw_devices + | ||
| 7906 | root->fs_info->fs_devices->missing_devices; | ||
| 7907 | |||
| 7895 | if (num_devices == 1) { | 7908 | if (num_devices == 1) { |
| 7896 | stripped |= BTRFS_BLOCK_GROUP_DUP; | 7909 | stripped |= BTRFS_BLOCK_GROUP_DUP; |
| 7897 | stripped = flags & ~stripped; | 7910 | stripped = flags & ~stripped; |
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 | ||
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index 31b0fabdd2ea..a668c0116982 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h | |||
| @@ -45,6 +45,7 @@ struct btrfs_device { | |||
| 45 | int barriers; | 45 | int barriers; |
| 46 | int writeable; | 46 | int writeable; |
| 47 | int in_fs_metadata; | 47 | int in_fs_metadata; |
| 48 | int missing; | ||
| 48 | 49 | ||
| 49 | spinlock_t io_lock; | 50 | spinlock_t io_lock; |
| 50 | 51 | ||
| @@ -94,6 +95,7 @@ struct btrfs_fs_devices { | |||
| 94 | u64 num_devices; | 95 | u64 num_devices; |
| 95 | u64 open_devices; | 96 | u64 open_devices; |
| 96 | u64 rw_devices; | 97 | u64 rw_devices; |
| 98 | u64 missing_devices; | ||
| 97 | u64 total_rw_bytes; | 99 | u64 total_rw_bytes; |
| 98 | struct block_device *latest_bdev; | 100 | struct block_device *latest_bdev; |
| 99 | 101 | ||
