]> Pileus Git - ~andy/linux/blobdiff - fs/btrfs/free-space-cache.c
Merge branch 'imx/fix-irqdomain' of git://git.linaro.org/people/shawnguo/linux-2...
[~andy/linux] / fs / btrfs / free-space-cache.c
index 7a15fcfb3e1fb688f49d0691544a72581a328fa3..ec23d43d0c357870a14bf6e79a0ce5baeb93a43d 100644 (file)
@@ -351,6 +351,11 @@ static int io_ctl_prepare_pages(struct io_ctl *io_ctl, struct inode *inode,
                }
        }
 
+       for (i = 0; i < io_ctl->num_pages; i++) {
+               clear_page_dirty_for_io(io_ctl->pages[i]);
+               set_page_extent_mapped(io_ctl->pages[i]);
+       }
+
        return 0;
 }
 
@@ -537,6 +542,13 @@ static int io_ctl_read_entry(struct io_ctl *io_ctl,
                            struct btrfs_free_space *entry, u8 *type)
 {
        struct btrfs_free_space_entry *e;
+       int ret;
+
+       if (!io_ctl->cur) {
+               ret = io_ctl_check_crc(io_ctl, io_ctl->index);
+               if (ret)
+                       return ret;
+       }
 
        e = io_ctl->cur;
        entry->offset = le64_to_cpu(e->offset);
@@ -550,10 +562,7 @@ static int io_ctl_read_entry(struct io_ctl *io_ctl,
 
        io_ctl_unmap_page(io_ctl);
 
-       if (io_ctl->index >= io_ctl->num_pages)
-               return 0;
-
-       return io_ctl_check_crc(io_ctl, io_ctl->index);
+       return 0;
 }
 
 static int io_ctl_read_bitmap(struct io_ctl *io_ctl,
@@ -561,9 +570,6 @@ static int io_ctl_read_bitmap(struct io_ctl *io_ctl,
 {
        int ret;
 
-       if (io_ctl->cur && io_ctl->cur != io_ctl->orig)
-               io_ctl_unmap_page(io_ctl);
-
        ret = io_ctl_check_crc(io_ctl, io_ctl->index);
        if (ret)
                return ret;
@@ -699,6 +705,8 @@ int __load_free_space_cache(struct btrfs_root *root, struct inode *inode,
                num_entries--;
        }
 
+       io_ctl_unmap_page(&io_ctl);
+
        /*
         * We add the bitmaps at the end of the entries in order that
         * the bitmap entries are added to the cache.
@@ -1462,6 +1470,7 @@ static void add_new_bitmap(struct btrfs_free_space_ctl *ctl,
 {
        info->offset = offset_to_bitmap(ctl, offset);
        info->bytes = 0;
+       INIT_LIST_HEAD(&info->list);
        link_free_space(ctl, info);
        ctl->total_bitmaps++;
 
@@ -1841,7 +1850,13 @@ again:
                info = tree_search_offset(ctl, offset_to_bitmap(ctl, offset),
                                          1, 0);
                if (!info) {
-                       WARN_ON(1);
+                       /* the tree logging code might be calling us before we
+                        * have fully loaded the free space rbtree for this
+                        * block group.  So it is possible the entry won't
+                        * be in the rbtree yet at all.  The caching code
+                        * will make sure not to put it in the rbtree if
+                        * the logging code has pinned it.
+                        */
                        goto out_lock;
                }
        }
@@ -2305,6 +2320,7 @@ again:
 
        if (!found) {
                start = i;
+               cluster->max_size = 0;
                found = true;
        }
 
@@ -2448,16 +2464,23 @@ setup_cluster_bitmap(struct btrfs_block_group_cache *block_group,
 {
        struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
        struct btrfs_free_space *entry;
-       struct rb_node *node;
        int ret = -ENOSPC;
+       u64 bitmap_offset = offset_to_bitmap(ctl, offset);
 
        if (ctl->total_bitmaps == 0)
                return -ENOSPC;
 
        /*
-        * First check our cached list of bitmaps and see if there is an entry
-        * here that will work.
+        * The bitmap that covers offset won't be in the list unless offset
+        * is just its start offset.
         */
+       entry = list_first_entry(bitmaps, struct btrfs_free_space, list);
+       if (entry->offset != bitmap_offset) {
+               entry = tree_search_offset(ctl, bitmap_offset, 1, 0);
+               if (entry && list_empty(&entry->list))
+                       list_add(&entry->list, bitmaps);
+       }
+
        list_for_each_entry(entry, bitmaps, list) {
                if (entry->bytes < min_bytes)
                        continue;
@@ -2468,38 +2491,10 @@ setup_cluster_bitmap(struct btrfs_block_group_cache *block_group,
        }
 
        /*
-        * If we do have entries on our list and we are here then we didn't find
-        * anything, so go ahead and get the next entry after the last entry in
-        * this list and start the search from there.
+        * The bitmaps list has all the bitmaps that record free space
+        * starting after offset, so no more search is required.
         */
-       if (!list_empty(bitmaps)) {
-               entry = list_entry(bitmaps->prev, struct btrfs_free_space,
-                                  list);
-               node = rb_next(&entry->offset_index);
-               if (!node)
-                       return -ENOSPC;
-               entry = rb_entry(node, struct btrfs_free_space, offset_index);
-               goto search;
-       }
-
-       entry = tree_search_offset(ctl, offset_to_bitmap(ctl, offset), 0, 1);
-       if (!entry)
-               return -ENOSPC;
-
-search:
-       node = &entry->offset_index;
-       do {
-               entry = rb_entry(node, struct btrfs_free_space, offset_index);
-               node = rb_next(&entry->offset_index);
-               if (!entry->bitmap)
-                       continue;
-               if (entry->bytes < min_bytes)
-                       continue;
-               ret = btrfs_bitmap_cluster(block_group, entry, cluster, offset,
-                                          bytes, min_bytes);
-       } while (ret && node);
-
-       return ret;
+       return -ENOSPC;
 }
 
 /*
@@ -2517,8 +2512,8 @@ int btrfs_find_space_cluster(struct btrfs_trans_handle *trans,
                             u64 offset, u64 bytes, u64 empty_size)
 {
        struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
-       struct list_head bitmaps;
        struct btrfs_free_space *entry, *tmp;
+       LIST_HEAD(bitmaps);
        u64 min_bytes;
        int ret;
 
@@ -2557,7 +2552,6 @@ int btrfs_find_space_cluster(struct btrfs_trans_handle *trans,
                goto out;
        }
 
-       INIT_LIST_HEAD(&bitmaps);
        ret = setup_cluster_no_bitmap(block_group, cluster, &bitmaps, offset,
                                      bytes, min_bytes);
        if (ret)