aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/free-space-cache.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@fusionio.com>2013-02-20 14:06:05 -0500
committerChris Mason <chris.mason@fusionio.com>2013-02-20 14:06:05 -0500
commite942f883bc6651d50be139477baf6fb0eed3d5bb (patch)
treee1d19783e9c8b42198a69c17c9719fb90f302847 /fs/btrfs/free-space-cache.c
parentb2c6b3e0611c58fbeb6b9c0892b6249f7bdfaf6b (diff)
parent0e4e02636611dbf89a2f36320a32054f9936d6cb (diff)
Merge branch 'raid56-experimental' into for-linus-3.9
Signed-off-by: Chris Mason <chris.mason@fusionio.com> Conflicts: fs/btrfs/ctree.h fs/btrfs/extent-tree.c fs/btrfs/inode.c fs/btrfs/volumes.c
Diffstat (limited to 'fs/btrfs/free-space-cache.c')
-rw-r--r--fs/btrfs/free-space-cache.c50
1 files changed, 42 insertions, 8 deletions
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
index c8090f18c217..1f84fc09c1a8 100644
--- a/fs/btrfs/free-space-cache.c
+++ b/fs/btrfs/free-space-cache.c
@@ -1465,10 +1465,14 @@ static int search_bitmap(struct btrfs_free_space_ctl *ctl,
1465} 1465}
1466 1466
1467static struct btrfs_free_space * 1467static struct btrfs_free_space *
1468find_free_space(struct btrfs_free_space_ctl *ctl, u64 *offset, u64 *bytes) 1468find_free_space(struct btrfs_free_space_ctl *ctl, u64 *offset, u64 *bytes,
1469 unsigned long align)
1469{ 1470{
1470 struct btrfs_free_space *entry; 1471 struct btrfs_free_space *entry;
1471 struct rb_node *node; 1472 struct rb_node *node;
1473 u64 ctl_off;
1474 u64 tmp;
1475 u64 align_off;
1472 int ret; 1476 int ret;
1473 1477
1474 if (!ctl->free_space_offset.rb_node) 1478 if (!ctl->free_space_offset.rb_node)
@@ -1483,15 +1487,34 @@ find_free_space(struct btrfs_free_space_ctl *ctl, u64 *offset, u64 *bytes)
1483 if (entry->bytes < *bytes) 1487 if (entry->bytes < *bytes)
1484 continue; 1488 continue;
1485 1489
1490 /* make sure the space returned is big enough
1491 * to match our requested alignment
1492 */
1493 if (*bytes >= align) {
1494 ctl_off = entry->offset - ctl->start;
1495 tmp = ctl_off + align - 1;;
1496 do_div(tmp, align);
1497 tmp = tmp * align + ctl->start;
1498 align_off = tmp - entry->offset;
1499 } else {
1500 align_off = 0;
1501 tmp = entry->offset;
1502 }
1503
1504 if (entry->bytes < *bytes + align_off)
1505 continue;
1506
1486 if (entry->bitmap) { 1507 if (entry->bitmap) {
1487 ret = search_bitmap(ctl, entry, offset, bytes); 1508 ret = search_bitmap(ctl, entry, &tmp, bytes);
1488 if (!ret) 1509 if (!ret) {
1510 *offset = tmp;
1489 return entry; 1511 return entry;
1512 }
1490 continue; 1513 continue;
1491 } 1514 }
1492 1515
1493 *offset = entry->offset; 1516 *offset = tmp;
1494 *bytes = entry->bytes; 1517 *bytes = entry->bytes - align_off;
1495 return entry; 1518 return entry;
1496 } 1519 }
1497 1520
@@ -2101,9 +2124,12 @@ u64 btrfs_find_space_for_alloc(struct btrfs_block_group_cache *block_group,
2101 struct btrfs_free_space *entry = NULL; 2124 struct btrfs_free_space *entry = NULL;
2102 u64 bytes_search = bytes + empty_size; 2125 u64 bytes_search = bytes + empty_size;
2103 u64 ret = 0; 2126 u64 ret = 0;
2127 u64 align_gap = 0;
2128 u64 align_gap_len = 0;
2104 2129
2105 spin_lock(&ctl->tree_lock); 2130 spin_lock(&ctl->tree_lock);
2106 entry = find_free_space(ctl, &offset, &bytes_search); 2131 entry = find_free_space(ctl, &offset, &bytes_search,
2132 block_group->full_stripe_len);
2107 if (!entry) 2133 if (!entry)
2108 goto out; 2134 goto out;
2109 2135
@@ -2113,9 +2139,15 @@ u64 btrfs_find_space_for_alloc(struct btrfs_block_group_cache *block_group,
2113 if (!entry->bytes) 2139 if (!entry->bytes)
2114 free_bitmap(ctl, entry); 2140 free_bitmap(ctl, entry);
2115 } else { 2141 } else {
2142
2116 unlink_free_space(ctl, entry); 2143 unlink_free_space(ctl, entry);
2117 entry->offset += bytes; 2144 align_gap_len = offset - entry->offset;
2118 entry->bytes -= bytes; 2145 align_gap = entry->offset;
2146
2147 entry->offset = offset + bytes;
2148 WARN_ON(entry->bytes < bytes + align_gap_len);
2149
2150 entry->bytes -= bytes + align_gap_len;
2119 if (!entry->bytes) 2151 if (!entry->bytes)
2120 kmem_cache_free(btrfs_free_space_cachep, entry); 2152 kmem_cache_free(btrfs_free_space_cachep, entry);
2121 else 2153 else
@@ -2125,6 +2157,8 @@ u64 btrfs_find_space_for_alloc(struct btrfs_block_group_cache *block_group,
2125out: 2157out:
2126 spin_unlock(&ctl->tree_lock); 2158 spin_unlock(&ctl->tree_lock);
2127 2159
2160 if (align_gap_len)
2161 __btrfs_add_free_space(ctl, align_gap, align_gap_len);
2128 return ret; 2162 return ret;
2129} 2163}
2130 2164