aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/free-space-cache.c
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2009-07-13 21:29:25 -0400
committerChris Mason <chris.mason@oracle.com>2009-07-24 09:23:39 -0400
commit817d52f8dba26d0295c26035531c30ce5f1e3c3e (patch)
tree5230153e86323de48e7e1440352d1b74d2d9961d /fs/btrfs/free-space-cache.c
parent963030817060e4f109be1993b9ae8f81dbf5e11a (diff)
Btrfs: async block group caching
This patch moves the caching of the block group off to a kthread in order to allow people to allocate sooner. Instead of blocking up behind the caching mutex, we instead kick of the caching kthread, and then attempt to make an allocation. If we cannot, we wait on the block groups caching waitqueue, which the caching kthread will wake the waiting threads up everytime it finds 2 meg worth of space, and then again when its finished caching. This is how I tested the speedup from this mkfs the disk mount the disk fill the disk up with fs_mark unmount the disk mount the disk time touch /mnt/foo Without my changes this took 11 seconds on my box, with these changes it now takes 1 second. Another change thats been put in place is we lock the super mirror's in the pinned extent map in order to keep us from adding that stuff as free space when caching the block group. This doesn't really change anything else as far as the pinned extent map is concerned, since for actual pinned extents we use EXTENT_DIRTY, but it does mean that when we unmount we have to go in and unlock those extents to keep from leaking memory. I've also added a check where when we are reading block groups from disk, if the amount of space used == the size of the block group, we go ahead and mark the block group as cached. This drastically reduces the amount of time it takes to cache the block groups. Using the same test as above, except doing a dd to a file and then unmounting, it used to take 33 seconds to umount, now it takes 3 seconds. This version uses the commit_root in the caching kthread, and then keeps track of how many async caching threads are running at any given time so if one of the async threads is still running as we cross transactions we can wait until its finished before handling the pinned extents. Thank you, Signed-off-by: Josef Bacik <jbacik@redhat.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/free-space-cache.c')
-rw-r--r--fs/btrfs/free-space-cache.c42
1 files changed, 23 insertions, 19 deletions
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
index ab8cad8b46c9..af99b78b288e 100644
--- a/fs/btrfs/free-space-cache.c
+++ b/fs/btrfs/free-space-cache.c
@@ -238,6 +238,7 @@ static void unlink_free_space(struct btrfs_block_group_cache *block_group,
238{ 238{
239 rb_erase(&info->offset_index, &block_group->free_space_offset); 239 rb_erase(&info->offset_index, &block_group->free_space_offset);
240 block_group->free_extents--; 240 block_group->free_extents--;
241 block_group->free_space -= info->bytes;
241} 242}
242 243
243static int link_free_space(struct btrfs_block_group_cache *block_group, 244static int link_free_space(struct btrfs_block_group_cache *block_group,
@@ -251,6 +252,7 @@ static int link_free_space(struct btrfs_block_group_cache *block_group,
251 if (ret) 252 if (ret)
252 return ret; 253 return ret;
253 254
255 block_group->free_space += info->bytes;
254 block_group->free_extents++; 256 block_group->free_extents++;
255 return ret; 257 return ret;
256} 258}
@@ -285,36 +287,40 @@ static void recalculate_thresholds(struct btrfs_block_group_cache *block_group)
285 } 287 }
286} 288}
287 289
288static void bitmap_clear_bits(struct btrfs_free_space *info, u64 offset, u64 bytes, 290static void bitmap_clear_bits(struct btrfs_block_group_cache *block_group,
289 u64 sectorsize) 291 struct btrfs_free_space *info, u64 offset,
292 u64 bytes)
290{ 293{
291 unsigned long start, end; 294 unsigned long start, end;
292 unsigned long i; 295 unsigned long i;
293 296
294 start = offset_to_bit(info->offset, sectorsize, offset); 297 start = offset_to_bit(info->offset, block_group->sectorsize, offset);
295 end = start + bytes_to_bits(bytes, sectorsize); 298 end = start + bytes_to_bits(bytes, block_group->sectorsize);
296 BUG_ON(end > BITS_PER_BITMAP); 299 BUG_ON(end > BITS_PER_BITMAP);
297 300
298 for (i = start; i < end; i++) 301 for (i = start; i < end; i++)
299 clear_bit(i, info->bitmap); 302 clear_bit(i, info->bitmap);
300 303
301 info->bytes -= bytes; 304 info->bytes -= bytes;
305 block_group->free_space -= bytes;
302} 306}
303 307
304static void bitmap_set_bits(struct btrfs_free_space *info, u64 offset, u64 bytes, 308static void bitmap_set_bits(struct btrfs_block_group_cache *block_group,
305 u64 sectorsize) 309 struct btrfs_free_space *info, u64 offset,
310 u64 bytes)
306{ 311{
307 unsigned long start, end; 312 unsigned long start, end;
308 unsigned long i; 313 unsigned long i;
309 314
310 start = offset_to_bit(info->offset, sectorsize, offset); 315 start = offset_to_bit(info->offset, block_group->sectorsize, offset);
311 end = start + bytes_to_bits(bytes, sectorsize); 316 end = start + bytes_to_bits(bytes, block_group->sectorsize);
312 BUG_ON(end > BITS_PER_BITMAP); 317 BUG_ON(end > BITS_PER_BITMAP);
313 318
314 for (i = start; i < end; i++) 319 for (i = start; i < end; i++)
315 set_bit(i, info->bitmap); 320 set_bit(i, info->bitmap);
316 321
317 info->bytes += bytes; 322 info->bytes += bytes;
323 block_group->free_space += bytes;
318} 324}
319 325
320static int search_bitmap(struct btrfs_block_group_cache *block_group, 326static int search_bitmap(struct btrfs_block_group_cache *block_group,
@@ -414,13 +420,12 @@ again:
414 (u64)(BITS_PER_BITMAP * block_group->sectorsize) - 1; 420 (u64)(BITS_PER_BITMAP * block_group->sectorsize) - 1;
415 421
416 if (*offset > bitmap_info->offset && *offset + *bytes > end) { 422 if (*offset > bitmap_info->offset && *offset + *bytes > end) {
417 bitmap_clear_bits(bitmap_info, *offset, 423 bitmap_clear_bits(block_group, bitmap_info, *offset,
418 end - *offset + 1, block_group->sectorsize); 424 end - *offset + 1);
419 *bytes -= end - *offset + 1; 425 *bytes -= end - *offset + 1;
420 *offset = end + 1; 426 *offset = end + 1;
421 } else if (*offset >= bitmap_info->offset && *offset + *bytes <= end) { 427 } else if (*offset >= bitmap_info->offset && *offset + *bytes <= end) {
422 bitmap_clear_bits(bitmap_info, *offset, 428 bitmap_clear_bits(block_group, bitmap_info, *offset, *bytes);
423 *bytes, block_group->sectorsize);
424 *bytes = 0; 429 *bytes = 0;
425 } 430 }
426 431
@@ -495,14 +500,13 @@ again:
495 (u64)(BITS_PER_BITMAP * block_group->sectorsize); 500 (u64)(BITS_PER_BITMAP * block_group->sectorsize);
496 501
497 if (offset >= bitmap_info->offset && offset + bytes > end) { 502 if (offset >= bitmap_info->offset && offset + bytes > end) {
498 bitmap_set_bits(bitmap_info, offset, end - offset, 503 bitmap_set_bits(block_group, bitmap_info, offset,
499 block_group->sectorsize); 504 end - offset);
500 bytes -= end - offset; 505 bytes -= end - offset;
501 offset = end; 506 offset = end;
502 added = 0; 507 added = 0;
503 } else if (offset >= bitmap_info->offset && offset + bytes <= end) { 508 } else if (offset >= bitmap_info->offset && offset + bytes <= end) {
504 bitmap_set_bits(bitmap_info, offset, bytes, 509 bitmap_set_bits(block_group, bitmap_info, offset, bytes);
505 block_group->sectorsize);
506 bytes = 0; 510 bytes = 0;
507 } else { 511 } else {
508 BUG(); 512 BUG();
@@ -870,8 +874,7 @@ u64 btrfs_find_space_for_alloc(struct btrfs_block_group_cache *block_group,
870 874
871 ret = offset; 875 ret = offset;
872 if (entry->bitmap) { 876 if (entry->bitmap) {
873 bitmap_clear_bits(entry, offset, bytes, 877 bitmap_clear_bits(block_group, entry, offset, bytes);
874 block_group->sectorsize);
875 if (!entry->bytes) { 878 if (!entry->bytes) {
876 unlink_free_space(block_group, entry); 879 unlink_free_space(block_group, entry);
877 kfree(entry->bitmap); 880 kfree(entry->bitmap);
@@ -891,6 +894,7 @@ u64 btrfs_find_space_for_alloc(struct btrfs_block_group_cache *block_group,
891 894
892out: 895out:
893 spin_unlock(&block_group->tree_lock); 896 spin_unlock(&block_group->tree_lock);
897
894 return ret; 898 return ret;
895} 899}
896 900
@@ -967,7 +971,7 @@ static u64 btrfs_alloc_from_bitmap(struct btrfs_block_group_cache *block_group,
967 goto out; 971 goto out;
968 972
969 ret = search_start; 973 ret = search_start;
970 bitmap_clear_bits(entry, ret, bytes, block_group->sectorsize); 974 bitmap_clear_bits(block_group, entry, ret, bytes);
971out: 975out:
972 spin_unlock(&cluster->lock); 976 spin_unlock(&cluster->lock);
973 spin_unlock(&block_group->tree_lock); 977 spin_unlock(&block_group->tree_lock);