forked from Minki/linux
Btrfs: Add a special device list for chunk allocations
This allows other code that needs to walk every device in the FS to do so without locking against allocations. Signed-off-by: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
parent
3c12ac7205
commit
b30757178d
@ -111,6 +111,7 @@ static int device_list_add(const char *path,
|
|||||||
if (!fs_devices)
|
if (!fs_devices)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
INIT_LIST_HEAD(&fs_devices->devices);
|
INIT_LIST_HEAD(&fs_devices->devices);
|
||||||
|
INIT_LIST_HEAD(&fs_devices->alloc_list);
|
||||||
list_add(&fs_devices->list, &fs_uuids);
|
list_add(&fs_devices->list, &fs_uuids);
|
||||||
memcpy(fs_devices->fsid, disk_super->fsid, BTRFS_FSID_SIZE);
|
memcpy(fs_devices->fsid, disk_super->fsid, BTRFS_FSID_SIZE);
|
||||||
fs_devices->latest_devid = devid;
|
fs_devices->latest_devid = devid;
|
||||||
@ -139,6 +140,7 @@ static int device_list_add(const char *path,
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
list_add(&device->dev_list, &fs_devices->devices);
|
list_add(&device->dev_list, &fs_devices->devices);
|
||||||
|
list_add(&device->dev_alloc_list, &fs_devices->alloc_list);
|
||||||
fs_devices->num_devices++;
|
fs_devices->num_devices++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -660,7 +662,7 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
|
|||||||
struct btrfs_device *device = NULL;
|
struct btrfs_device *device = NULL;
|
||||||
struct btrfs_chunk *chunk;
|
struct btrfs_chunk *chunk;
|
||||||
struct list_head private_devs;
|
struct list_head private_devs;
|
||||||
struct list_head *dev_list = &extent_root->fs_info->fs_devices->devices;
|
struct list_head *dev_list;
|
||||||
struct list_head *cur;
|
struct list_head *cur;
|
||||||
struct extent_map_tree *em_tree;
|
struct extent_map_tree *em_tree;
|
||||||
struct map_lookup *map;
|
struct map_lookup *map;
|
||||||
@ -682,6 +684,7 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
|
|||||||
int stripe_len = 64 * 1024;
|
int stripe_len = 64 * 1024;
|
||||||
struct btrfs_key key;
|
struct btrfs_key key;
|
||||||
|
|
||||||
|
dev_list = &extent_root->fs_info->fs_devices->alloc_list;
|
||||||
if (list_empty(dev_list))
|
if (list_empty(dev_list))
|
||||||
return -ENOSPC;
|
return -ENOSPC;
|
||||||
|
|
||||||
@ -752,12 +755,12 @@ again:
|
|||||||
|
|
||||||
/* build a private list of devices we will allocate from */
|
/* build a private list of devices we will allocate from */
|
||||||
while(index < num_stripes) {
|
while(index < num_stripes) {
|
||||||
device = list_entry(cur, struct btrfs_device, dev_list);
|
device = list_entry(cur, struct btrfs_device, dev_alloc_list);
|
||||||
|
|
||||||
avail = device->total_bytes - device->bytes_used;
|
avail = device->total_bytes - device->bytes_used;
|
||||||
cur = cur->next;
|
cur = cur->next;
|
||||||
if (avail >= min_free) {
|
if (avail >= min_free) {
|
||||||
list_move_tail(&device->dev_list, &private_devs);
|
list_move_tail(&device->dev_alloc_list, &private_devs);
|
||||||
index++;
|
index++;
|
||||||
if (type & BTRFS_BLOCK_GROUP_DUP)
|
if (type & BTRFS_BLOCK_GROUP_DUP)
|
||||||
index++;
|
index++;
|
||||||
@ -812,12 +815,12 @@ printk("new chunk type %Lu start %Lu size %Lu\n", type, key.offset, *num_bytes);
|
|||||||
struct btrfs_stripe *stripe;
|
struct btrfs_stripe *stripe;
|
||||||
BUG_ON(list_empty(&private_devs));
|
BUG_ON(list_empty(&private_devs));
|
||||||
cur = private_devs.next;
|
cur = private_devs.next;
|
||||||
device = list_entry(cur, struct btrfs_device, dev_list);
|
device = list_entry(cur, struct btrfs_device, dev_alloc_list);
|
||||||
|
|
||||||
/* loop over this device again if we're doing a dup group */
|
/* loop over this device again if we're doing a dup group */
|
||||||
if (!(type & BTRFS_BLOCK_GROUP_DUP) ||
|
if (!(type & BTRFS_BLOCK_GROUP_DUP) ||
|
||||||
(index == num_stripes - 1))
|
(index == num_stripes - 1))
|
||||||
list_move_tail(&device->dev_list, dev_list);
|
list_move_tail(&device->dev_alloc_list, dev_list);
|
||||||
|
|
||||||
ret = btrfs_alloc_dev_extent(trans, device,
|
ret = btrfs_alloc_dev_extent(trans, device,
|
||||||
info->chunk_root->root_key.objectid,
|
info->chunk_root->root_key.objectid,
|
||||||
@ -1329,6 +1332,8 @@ static int read_one_dev(struct btrfs_root *root,
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
list_add(&device->dev_list,
|
list_add(&device->dev_list,
|
||||||
&root->fs_info->fs_devices->devices);
|
&root->fs_info->fs_devices->devices);
|
||||||
|
list_add(&device->dev_alloc_list,
|
||||||
|
&root->fs_info->fs_devices->alloc_list);
|
||||||
device->barriers = 1;
|
device->barriers = 1;
|
||||||
spin_lock_init(&device->io_lock);
|
spin_lock_init(&device->io_lock);
|
||||||
}
|
}
|
||||||
|
@ -24,9 +24,12 @@
|
|||||||
struct buffer_head;
|
struct buffer_head;
|
||||||
struct btrfs_device {
|
struct btrfs_device {
|
||||||
struct list_head dev_list;
|
struct list_head dev_list;
|
||||||
|
struct list_head dev_alloc_list;
|
||||||
struct btrfs_root *dev_root;
|
struct btrfs_root *dev_root;
|
||||||
struct buffer_head *pending_io;
|
struct buffer_head *pending_io;
|
||||||
|
|
||||||
int barriers;
|
int barriers;
|
||||||
|
|
||||||
spinlock_t io_lock;
|
spinlock_t io_lock;
|
||||||
|
|
||||||
struct block_device *bdev;
|
struct block_device *bdev;
|
||||||
@ -70,7 +73,11 @@ struct btrfs_fs_devices {
|
|||||||
u64 num_devices;
|
u64 num_devices;
|
||||||
struct block_device *latest_bdev;
|
struct block_device *latest_bdev;
|
||||||
struct block_device *lowest_bdev;
|
struct block_device *lowest_bdev;
|
||||||
|
/* all of the devices in the FS */
|
||||||
struct list_head devices;
|
struct list_head devices;
|
||||||
|
|
||||||
|
/* devices not currently being allocated */
|
||||||
|
struct list_head alloc_list;
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user