diff options
author | Ilya Dryomov <idryomov@gmail.com> | 2013-08-23 06:20:17 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@fusionio.com> | 2013-09-01 08:16:04 -0400 |
commit | 12bd2fc0d2f589f9605b8f497eee2e7724f3af24 (patch) | |
tree | df82467f721c91a82db67d6820dadb6815078648 /fs/btrfs | |
parent | 53f10659f9994df8efe788f82d3da78d48e650c5 (diff) |
Btrfs: add btrfs_alloc_device and switch to it
Currently btrfs_device is allocated ad-hoc in a few different places,
and as a result not all fields are initialized properly. In particular,
readahead state is only initialized in device_list_add (at scan time),
and not in btrfs_init_new_device (when the new device is added with
'btrfs dev add'). Fix this by adding an allocation helper and switch
everybody but __btrfs_close_devices to it. (__btrfs_close_devices is
dealt with in a later commit.)
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/volumes.c | 151 | ||||
-rw-r--r-- | fs/btrfs/volumes.h | 3 |
2 files changed, 97 insertions, 57 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 9b3595e370f8..4bc07d910e54 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -102,6 +102,27 @@ void btrfs_cleanup_fs_uuids(void) | |||
102 | } | 102 | } |
103 | } | 103 | } |
104 | 104 | ||
105 | static struct btrfs_device *__alloc_device(void) | ||
106 | { | ||
107 | struct btrfs_device *dev; | ||
108 | |||
109 | dev = kzalloc(sizeof(*dev), GFP_NOFS); | ||
110 | if (!dev) | ||
111 | return ERR_PTR(-ENOMEM); | ||
112 | |||
113 | INIT_LIST_HEAD(&dev->dev_list); | ||
114 | INIT_LIST_HEAD(&dev->dev_alloc_list); | ||
115 | |||
116 | spin_lock_init(&dev->io_lock); | ||
117 | |||
118 | spin_lock_init(&dev->reada_lock); | ||
119 | atomic_set(&dev->reada_in_flight, 0); | ||
120 | INIT_RADIX_TREE(&dev->reada_zones, GFP_NOFS & ~__GFP_WAIT); | ||
121 | INIT_RADIX_TREE(&dev->reada_extents, GFP_NOFS & ~__GFP_WAIT); | ||
122 | |||
123 | return dev; | ||
124 | } | ||
125 | |||
105 | static noinline struct btrfs_device *__find_device(struct list_head *head, | 126 | static noinline struct btrfs_device *__find_device(struct list_head *head, |
106 | u64 devid, u8 *uuid) | 127 | u64 devid, u8 *uuid) |
107 | { | 128 | { |
@@ -415,17 +436,12 @@ static noinline int device_list_add(const char *path, | |||
415 | if (fs_devices->opened) | 436 | if (fs_devices->opened) |
416 | return -EBUSY; | 437 | return -EBUSY; |
417 | 438 | ||
418 | device = kzalloc(sizeof(*device), GFP_NOFS); | 439 | device = btrfs_alloc_device(NULL, &devid, |
419 | if (!device) { | 440 | disk_super->dev_item.uuid); |
441 | if (IS_ERR(device)) { | ||
420 | /* we can safely leave the fs_devices entry around */ | 442 | /* we can safely leave the fs_devices entry around */ |
421 | return -ENOMEM; | 443 | return PTR_ERR(device); |
422 | } | 444 | } |
423 | device->devid = devid; | ||
424 | device->dev_stats_valid = 0; | ||
425 | device->work.func = pending_bios_fn; | ||
426 | memcpy(device->uuid, disk_super->dev_item.uuid, | ||
427 | BTRFS_UUID_SIZE); | ||
428 | spin_lock_init(&device->io_lock); | ||
429 | 445 | ||
430 | name = rcu_string_strdup(path, GFP_NOFS); | 446 | name = rcu_string_strdup(path, GFP_NOFS); |
431 | if (!name) { | 447 | if (!name) { |
@@ -433,15 +449,6 @@ static noinline int device_list_add(const char *path, | |||
433 | return -ENOMEM; | 449 | return -ENOMEM; |
434 | } | 450 | } |
435 | rcu_assign_pointer(device->name, name); | 451 | rcu_assign_pointer(device->name, name); |
436 | INIT_LIST_HEAD(&device->dev_alloc_list); | ||
437 | |||
438 | /* init readahead state */ | ||
439 | spin_lock_init(&device->reada_lock); | ||
440 | device->reada_curr_zone = NULL; | ||
441 | atomic_set(&device->reada_in_flight, 0); | ||
442 | device->reada_next = 0; | ||
443 | INIT_RADIX_TREE(&device->reada_zones, GFP_NOFS & ~__GFP_WAIT); | ||
444 | INIT_RADIX_TREE(&device->reada_extents, GFP_NOFS & ~__GFP_WAIT); | ||
445 | 452 | ||
446 | mutex_lock(&fs_devices->device_list_mutex); | 453 | mutex_lock(&fs_devices->device_list_mutex); |
447 | list_add_rcu(&device->dev_list, &fs_devices->devices); | 454 | list_add_rcu(&device->dev_list, &fs_devices->devices); |
@@ -492,8 +499,9 @@ static struct btrfs_fs_devices *clone_fs_devices(struct btrfs_fs_devices *orig) | |||
492 | list_for_each_entry(orig_dev, &orig->devices, dev_list) { | 499 | list_for_each_entry(orig_dev, &orig->devices, dev_list) { |
493 | struct rcu_string *name; | 500 | struct rcu_string *name; |
494 | 501 | ||
495 | device = kzalloc(sizeof(*device), GFP_NOFS); | 502 | device = btrfs_alloc_device(NULL, &orig_dev->devid, |
496 | if (!device) | 503 | orig_dev->uuid); |
504 | if (IS_ERR(device)) | ||
497 | goto error; | 505 | goto error; |
498 | 506 | ||
499 | /* | 507 | /* |
@@ -507,13 +515,6 @@ static struct btrfs_fs_devices *clone_fs_devices(struct btrfs_fs_devices *orig) | |||
507 | } | 515 | } |
508 | rcu_assign_pointer(device->name, name); | 516 | rcu_assign_pointer(device->name, name); |
509 | 517 | ||
510 | device->devid = orig_dev->devid; | ||
511 | device->work.func = pending_bios_fn; | ||
512 | memcpy(device->uuid, orig_dev->uuid, sizeof(device->uuid)); | ||
513 | spin_lock_init(&device->io_lock); | ||
514 | INIT_LIST_HEAD(&device->dev_list); | ||
515 | INIT_LIST_HEAD(&device->dev_alloc_list); | ||
516 | |||
517 | list_add(&device->dev_list, &fs_devices->devices); | 518 | list_add(&device->dev_list, &fs_devices->devices); |
518 | device->fs_devices = fs_devices; | 519 | device->fs_devices = fs_devices; |
519 | fs_devices->num_devices++; | 520 | fs_devices->num_devices++; |
@@ -1959,10 +1960,10 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) | |||
1959 | } | 1960 | } |
1960 | mutex_unlock(&root->fs_info->fs_devices->device_list_mutex); | 1961 | mutex_unlock(&root->fs_info->fs_devices->device_list_mutex); |
1961 | 1962 | ||
1962 | device = kzalloc(sizeof(*device), GFP_NOFS); | 1963 | device = btrfs_alloc_device(root->fs_info, NULL, NULL); |
1963 | if (!device) { | 1964 | if (IS_ERR(device)) { |
1964 | /* we can safely leave the fs_devices entry around */ | 1965 | /* we can safely leave the fs_devices entry around */ |
1965 | ret = -ENOMEM; | 1966 | ret = PTR_ERR(device); |
1966 | goto error; | 1967 | goto error; |
1967 | } | 1968 | } |
1968 | 1969 | ||
@@ -1974,13 +1975,6 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) | |||
1974 | } | 1975 | } |
1975 | rcu_assign_pointer(device->name, name); | 1976 | rcu_assign_pointer(device->name, name); |
1976 | 1977 | ||
1977 | ret = find_next_devid(root->fs_info, &device->devid); | ||
1978 | if (ret) { | ||
1979 | rcu_string_free(device->name); | ||
1980 | kfree(device); | ||
1981 | goto error; | ||
1982 | } | ||
1983 | |||
1984 | trans = btrfs_start_transaction(root, 0); | 1978 | trans = btrfs_start_transaction(root, 0); |
1985 | if (IS_ERR(trans)) { | 1979 | if (IS_ERR(trans)) { |
1986 | rcu_string_free(device->name); | 1980 | rcu_string_free(device->name); |
@@ -1995,9 +1989,6 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) | |||
1995 | if (blk_queue_discard(q)) | 1989 | if (blk_queue_discard(q)) |
1996 | device->can_discard = 1; | 1990 | device->can_discard = 1; |
1997 | device->writeable = 1; | 1991 | device->writeable = 1; |
1998 | device->work.func = pending_bios_fn; | ||
1999 | generate_random_uuid(device->uuid); | ||
2000 | spin_lock_init(&device->io_lock); | ||
2001 | device->generation = trans->transid; | 1992 | device->generation = trans->transid; |
2002 | device->io_width = root->sectorsize; | 1993 | device->io_width = root->sectorsize; |
2003 | device->io_align = root->sectorsize; | 1994 | device->io_align = root->sectorsize; |
@@ -2124,6 +2115,7 @@ int btrfs_init_dev_replace_tgtdev(struct btrfs_root *root, char *device_path, | |||
2124 | struct btrfs_fs_info *fs_info = root->fs_info; | 2115 | struct btrfs_fs_info *fs_info = root->fs_info; |
2125 | struct list_head *devices; | 2116 | struct list_head *devices; |
2126 | struct rcu_string *name; | 2117 | struct rcu_string *name; |
2118 | u64 devid = BTRFS_DEV_REPLACE_DEVID; | ||
2127 | int ret = 0; | 2119 | int ret = 0; |
2128 | 2120 | ||
2129 | *device_out = NULL; | 2121 | *device_out = NULL; |
@@ -2145,9 +2137,9 @@ int btrfs_init_dev_replace_tgtdev(struct btrfs_root *root, char *device_path, | |||
2145 | } | 2137 | } |
2146 | } | 2138 | } |
2147 | 2139 | ||
2148 | device = kzalloc(sizeof(*device), GFP_NOFS); | 2140 | device = btrfs_alloc_device(NULL, &devid, NULL); |
2149 | if (!device) { | 2141 | if (IS_ERR(device)) { |
2150 | ret = -ENOMEM; | 2142 | ret = PTR_ERR(device); |
2151 | goto error; | 2143 | goto error; |
2152 | } | 2144 | } |
2153 | 2145 | ||
@@ -2164,10 +2156,6 @@ int btrfs_init_dev_replace_tgtdev(struct btrfs_root *root, char *device_path, | |||
2164 | device->can_discard = 1; | 2156 | device->can_discard = 1; |
2165 | mutex_lock(&root->fs_info->fs_devices->device_list_mutex); | 2157 | mutex_lock(&root->fs_info->fs_devices->device_list_mutex); |
2166 | device->writeable = 1; | 2158 | device->writeable = 1; |
2167 | device->work.func = pending_bios_fn; | ||
2168 | generate_random_uuid(device->uuid); | ||
2169 | device->devid = BTRFS_DEV_REPLACE_DEVID; | ||
2170 | spin_lock_init(&device->io_lock); | ||
2171 | device->generation = 0; | 2159 | device->generation = 0; |
2172 | device->io_width = root->sectorsize; | 2160 | device->io_width = root->sectorsize; |
2173 | device->io_align = root->sectorsize; | 2161 | device->io_align = root->sectorsize; |
@@ -5572,23 +5560,72 @@ static struct btrfs_device *add_missing_dev(struct btrfs_root *root, | |||
5572 | struct btrfs_device *device; | 5560 | struct btrfs_device *device; |
5573 | struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices; | 5561 | struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices; |
5574 | 5562 | ||
5575 | device = kzalloc(sizeof(*device), GFP_NOFS); | 5563 | device = btrfs_alloc_device(NULL, &devid, dev_uuid); |
5576 | if (!device) | 5564 | if (IS_ERR(device)) |
5577 | return NULL; | 5565 | return NULL; |
5578 | list_add(&device->dev_list, | 5566 | |
5579 | &fs_devices->devices); | 5567 | list_add(&device->dev_list, &fs_devices->devices); |
5580 | device->devid = devid; | ||
5581 | device->work.func = pending_bios_fn; | ||
5582 | device->fs_devices = fs_devices; | 5568 | device->fs_devices = fs_devices; |
5583 | device->missing = 1; | ||
5584 | fs_devices->num_devices++; | 5569 | fs_devices->num_devices++; |
5570 | |||
5571 | device->missing = 1; | ||
5585 | fs_devices->missing_devices++; | 5572 | fs_devices->missing_devices++; |
5586 | spin_lock_init(&device->io_lock); | 5573 | |
5587 | INIT_LIST_HEAD(&device->dev_alloc_list); | ||
5588 | memcpy(device->uuid, dev_uuid, BTRFS_UUID_SIZE); | ||
5589 | return device; | 5574 | return device; |
5590 | } | 5575 | } |
5591 | 5576 | ||
5577 | /** | ||
5578 | * btrfs_alloc_device - allocate struct btrfs_device | ||
5579 | * @fs_info: used only for generating a new devid, can be NULL if | ||
5580 | * devid is provided (i.e. @devid != NULL). | ||
5581 | * @devid: a pointer to devid for this device. If NULL a new devid | ||
5582 | * is generated. | ||
5583 | * @uuid: a pointer to UUID for this device. If NULL a new UUID | ||
5584 | * is generated. | ||
5585 | * | ||
5586 | * Return: a pointer to a new &struct btrfs_device on success; ERR_PTR() | ||
5587 | * on error. Returned struct is not linked onto any lists and can be | ||
5588 | * destroyed with kfree() right away. | ||
5589 | */ | ||
5590 | struct btrfs_device *btrfs_alloc_device(struct btrfs_fs_info *fs_info, | ||
5591 | const u64 *devid, | ||
5592 | const u8 *uuid) | ||
5593 | { | ||
5594 | struct btrfs_device *dev; | ||
5595 | u64 tmp; | ||
5596 | |||
5597 | if (!devid && !fs_info) { | ||
5598 | WARN_ON(1); | ||
5599 | return ERR_PTR(-EINVAL); | ||
5600 | } | ||
5601 | |||
5602 | dev = __alloc_device(); | ||
5603 | if (IS_ERR(dev)) | ||
5604 | return dev; | ||
5605 | |||
5606 | if (devid) | ||
5607 | tmp = *devid; | ||
5608 | else { | ||
5609 | int ret; | ||
5610 | |||
5611 | ret = find_next_devid(fs_info, &tmp); | ||
5612 | if (ret) { | ||
5613 | kfree(dev); | ||
5614 | return ERR_PTR(ret); | ||
5615 | } | ||
5616 | } | ||
5617 | dev->devid = tmp; | ||
5618 | |||
5619 | if (uuid) | ||
5620 | memcpy(dev->uuid, uuid, BTRFS_UUID_SIZE); | ||
5621 | else | ||
5622 | generate_random_uuid(dev->uuid); | ||
5623 | |||
5624 | dev->work.func = pending_bios_fn; | ||
5625 | |||
5626 | return dev; | ||
5627 | } | ||
5628 | |||
5592 | static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key, | 5629 | static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key, |
5593 | struct extent_buffer *leaf, | 5630 | struct extent_buffer *leaf, |
5594 | struct btrfs_chunk *chunk) | 5631 | struct btrfs_chunk *chunk) |
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index d98b942c3896..b72f540c8b29 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h | |||
@@ -305,6 +305,9 @@ void btrfs_close_extra_devices(struct btrfs_fs_info *fs_info, | |||
305 | int btrfs_find_device_missing_or_by_path(struct btrfs_root *root, | 305 | int btrfs_find_device_missing_or_by_path(struct btrfs_root *root, |
306 | char *device_path, | 306 | char *device_path, |
307 | struct btrfs_device **device); | 307 | struct btrfs_device **device); |
308 | struct btrfs_device *btrfs_alloc_device(struct btrfs_fs_info *fs_info, | ||
309 | const u64 *devid, | ||
310 | const u8 *uuid); | ||
308 | int btrfs_rm_device(struct btrfs_root *root, char *device_path); | 311 | int btrfs_rm_device(struct btrfs_root *root, char *device_path); |
309 | void btrfs_cleanup_fs_uuids(void); | 312 | void btrfs_cleanup_fs_uuids(void); |
310 | int btrfs_num_copies(struct btrfs_fs_info *fs_info, u64 logical, u64 len); | 313 | int btrfs_num_copies(struct btrfs_fs_info *fs_info, u64 logical, u64 len); |