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:
Chris Mason 2008-04-22 09:22:07 -04:00
parent 3c12ac7205
commit b30757178d
2 changed files with 17 additions and 5 deletions

View File

@ -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);
} }

View File

@ -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;
}; };