diff options
author | Chris Mason <chris.mason@fusionio.com> | 2013-02-20 14:06:05 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@fusionio.com> | 2013-02-20 14:06:05 -0500 |
commit | e942f883bc6651d50be139477baf6fb0eed3d5bb (patch) | |
tree | e1d19783e9c8b42198a69c17c9719fb90f302847 /fs/btrfs/free-space-cache.c | |
parent | b2c6b3e0611c58fbeb6b9c0892b6249f7bdfaf6b (diff) | |
parent | 0e4e02636611dbf89a2f36320a32054f9936d6cb (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.c | 50 |
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 | ||
1467 | static struct btrfs_free_space * | 1467 | static struct btrfs_free_space * |
1468 | find_free_space(struct btrfs_free_space_ctl *ctl, u64 *offset, u64 *bytes) | 1468 | find_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, | |||
2125 | out: | 2157 | out: |
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 | ||