Btrfs: Add a special device list for chunk allocations
authorChris Mason <chris.mason@oracle.com>
Tue, 22 Apr 2008 13:22:07 +0000 (09:22 -0400)
committerChris Mason <chris.mason@oracle.com>
Thu, 25 Sep 2008 15:04:02 +0000 (11:04 -0400)
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>
fs/btrfs/volumes.c
fs/btrfs/volumes.h

index 107fc74c3ab846613a6d34c9d921c15b04d0a6eb..5619e50583e3bfc9222a0720d58edba7f97d1433 100644 (file)
@@ -111,6 +111,7 @@ static int device_list_add(const char *path,
                if (!fs_devices)
                        return -ENOMEM;
                INIT_LIST_HEAD(&fs_devices->devices);
+               INIT_LIST_HEAD(&fs_devices->alloc_list);
                list_add(&fs_devices->list, &fs_uuids);
                memcpy(fs_devices->fsid, disk_super->fsid, BTRFS_FSID_SIZE);
                fs_devices->latest_devid = devid;
@@ -139,6 +140,7 @@ static int device_list_add(const char *path,
                        return -ENOMEM;
                }
                list_add(&device->dev_list, &fs_devices->devices);
+               list_add(&device->dev_alloc_list, &fs_devices->alloc_list);
                fs_devices->num_devices++;
        }
 
@@ -660,7 +662,7 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
        struct btrfs_device *device = NULL;
        struct btrfs_chunk *chunk;
        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 extent_map_tree *em_tree;
        struct map_lookup *map;
@@ -682,6 +684,7 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
        int stripe_len = 64 * 1024;
        struct btrfs_key key;
 
+       dev_list = &extent_root->fs_info->fs_devices->alloc_list;
        if (list_empty(dev_list))
                return -ENOSPC;
 
@@ -752,12 +755,12 @@ again:
 
        /* build a private list of devices we will allocate from */
        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;
                cur = cur->next;
                if (avail >= min_free) {
-                       list_move_tail(&device->dev_list, &private_devs);
+                       list_move_tail(&device->dev_alloc_list, &private_devs);
                        index++;
                        if (type & BTRFS_BLOCK_GROUP_DUP)
                                index++;
@@ -812,12 +815,12 @@ printk("new chunk type %Lu start %Lu size %Lu\n", type, key.offset, *num_bytes);
                struct btrfs_stripe *stripe;
                BUG_ON(list_empty(&private_devs));
                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 */
                if (!(type & BTRFS_BLOCK_GROUP_DUP) ||
                    (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,
                             info->chunk_root->root_key.objectid,
@@ -1329,6 +1332,8 @@ static int read_one_dev(struct btrfs_root *root,
                        return -ENOMEM;
                list_add(&device->dev_list,
                         &root->fs_info->fs_devices->devices);
+               list_add(&device->dev_alloc_list,
+                        &root->fs_info->fs_devices->alloc_list);
                device->barriers = 1;
                spin_lock_init(&device->io_lock);
        }
index dfe7e8a9507ce38e8b63b4b8928493fcbbbd9e13..a2660d2b6b344a1ccfaedbc7f9e72911441f57c3 100644 (file)
 struct buffer_head;
 struct btrfs_device {
        struct list_head dev_list;
+       struct list_head dev_alloc_list;
        struct btrfs_root *dev_root;
        struct buffer_head *pending_io;
+
        int barriers;
+
        spinlock_t io_lock;
 
        struct block_device *bdev;
@@ -70,7 +73,11 @@ struct btrfs_fs_devices {
        u64 num_devices;
        struct block_device *latest_bdev;
        struct block_device *lowest_bdev;
+       /* all of the devices in the FS */
        struct list_head devices;
+
+       /* devices not currently being allocated */
+       struct list_head alloc_list;
        struct list_head list;
 };