diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-01-18 10:54:22 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:03:59 -0400 |
commit | e18e4809b10e6c9efb5fe10c1ddcb4ebb690d517 (patch) | |
tree | c8419f7fde6690cd352252af89295511650e3707 /fs/btrfs | |
parent | 04005cc7a1feef94237204566ccac38571af7991 (diff) |
Btrfs: Add mount -o ssd, which includes optimizations for seek free storage
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/ctree.h | 2 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 3 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 31 | ||||
-rw-r--r-- | fs/btrfs/super.c | 9 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 1 | ||||
-rw-r--r-- | fs/btrfs/tree-defrag.c | 3 |
6 files changed, 47 insertions, 2 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index fa65fe027e45..7a588ba2b747 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -351,6 +351,7 @@ struct btrfs_fs_info { | |||
351 | spinlock_t delalloc_lock; | 351 | spinlock_t delalloc_lock; |
352 | spinlock_t new_trans_lock; | 352 | spinlock_t new_trans_lock; |
353 | u64 delalloc_bytes; | 353 | u64 delalloc_bytes; |
354 | u64 last_alloc; | ||
354 | }; | 355 | }; |
355 | /* | 356 | /* |
356 | * in ram representation of the tree. extent_root is used for all allocations | 357 | * in ram representation of the tree. extent_root is used for all allocations |
@@ -444,6 +445,7 @@ struct btrfs_root { | |||
444 | #define BTRFS_MOUNT_NODATASUM (1 << 0) | 445 | #define BTRFS_MOUNT_NODATASUM (1 << 0) |
445 | #define BTRFS_MOUNT_NODATACOW (1 << 1) | 446 | #define BTRFS_MOUNT_NODATACOW (1 << 1) |
446 | #define BTRFS_MOUNT_NOBARRIER (1 << 2) | 447 | #define BTRFS_MOUNT_NOBARRIER (1 << 2) |
448 | #define BTRFS_MOUNT_SSD (1 << 3) | ||
447 | 449 | ||
448 | #define btrfs_clear_opt(o, opt) ((o) &= ~BTRFS_MOUNT_##opt) | 450 | #define btrfs_clear_opt(o, opt) ((o) &= ~BTRFS_MOUNT_##opt) |
449 | #define btrfs_set_opt(o, opt) ((o) |= BTRFS_MOUNT_##opt) | 451 | #define btrfs_set_opt(o, opt) ((o) |= BTRFS_MOUNT_##opt) |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 731a534f81f5..5d1f9bca2712 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -193,6 +193,7 @@ int csum_dirty_buffer(struct btrfs_root *root, struct page *page) | |||
193 | } | 193 | } |
194 | eb = alloc_extent_buffer(tree, start, len, page, GFP_NOFS); | 194 | eb = alloc_extent_buffer(tree, start, len, page, GFP_NOFS); |
195 | read_extent_buffer_pages(tree, eb, start + PAGE_CACHE_SIZE, 1); | 195 | read_extent_buffer_pages(tree, eb, start + PAGE_CACHE_SIZE, 1); |
196 | btrfs_clear_buffer_defrag(eb); | ||
196 | found_start = btrfs_header_bytenr(eb); | 197 | found_start = btrfs_header_bytenr(eb); |
197 | if (found_start != start) { | 198 | if (found_start != start) { |
198 | printk("warning: eb start incorrect %Lu buffer %Lu len %lu\n", | 199 | printk("warning: eb start incorrect %Lu buffer %Lu len %lu\n", |
@@ -676,6 +677,8 @@ struct btrfs_root *open_ctree(struct super_block *sb) | |||
676 | fs_info->do_barriers = 1; | 677 | fs_info->do_barriers = 1; |
677 | fs_info->closing = 0; | 678 | fs_info->closing = 0; |
678 | fs_info->total_pinned = 0; | 679 | fs_info->total_pinned = 0; |
680 | fs_info->last_alloc = 0; | ||
681 | |||
679 | #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18) | 682 | #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18) |
680 | INIT_WORK(&fs_info->trans_work, btrfs_transaction_cleaner, fs_info); | 683 | INIT_WORK(&fs_info->trans_work, btrfs_transaction_cleaner, fs_info); |
681 | #else | 684 | #else |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 2c569b4d59d4..b69a46691a96 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -1431,6 +1431,19 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans, | |||
1431 | data = BTRFS_BLOCK_GROUP_MIXED; | 1431 | data = BTRFS_BLOCK_GROUP_MIXED; |
1432 | } | 1432 | } |
1433 | 1433 | ||
1434 | /* for SSD, cluster allocations together as much as possible */ | ||
1435 | if (btrfs_test_opt(root, SSD)) { | ||
1436 | if (!data) { | ||
1437 | if (root->fs_info->last_alloc) | ||
1438 | hint_byte = root->fs_info->last_alloc; | ||
1439 | else { | ||
1440 | hint_byte = hint_byte & | ||
1441 | ~((u64)BTRFS_BLOCK_GROUP_SIZE - 1); | ||
1442 | empty_size += 16 * 1024 * 1024; | ||
1443 | } | ||
1444 | } | ||
1445 | } | ||
1446 | |||
1434 | search_end = min(search_end, | 1447 | search_end = min(search_end, |
1435 | btrfs_super_total_bytes(&info->super_copy)); | 1448 | btrfs_super_total_bytes(&info->super_copy)); |
1436 | if (hint_byte) { | 1449 | if (hint_byte) { |
@@ -1456,6 +1469,19 @@ check_failed: | |||
1456 | } | 1469 | } |
1457 | search_start = find_search_start(root, &block_group, search_start, | 1470 | search_start = find_search_start(root, &block_group, search_start, |
1458 | total_needed, data); | 1471 | total_needed, data); |
1472 | |||
1473 | if (!data && btrfs_test_opt(root, SSD) && info->last_alloc && | ||
1474 | search_start != info->last_alloc) { | ||
1475 | info->last_alloc = 0; | ||
1476 | if (!empty_size) { | ||
1477 | empty_size += 16 * 1024 * 1024; | ||
1478 | total_needed += empty_size; | ||
1479 | } | ||
1480 | search_start = find_search_start(root, &block_group, | ||
1481 | search_start, total_needed, | ||
1482 | data); | ||
1483 | } | ||
1484 | |||
1459 | search_start = stripe_align(root, search_start); | 1485 | search_start = stripe_align(root, search_start); |
1460 | cached_start = search_start; | 1486 | cached_start = search_start; |
1461 | btrfs_init_path(path); | 1487 | btrfs_init_path(path); |
@@ -1610,6 +1636,8 @@ enospc: | |||
1610 | error: | 1636 | error: |
1611 | btrfs_release_path(root, path); | 1637 | btrfs_release_path(root, path); |
1612 | btrfs_free_path(path); | 1638 | btrfs_free_path(path); |
1639 | if (btrfs_test_opt(root, SSD) && !ret && !data) | ||
1640 | info->last_alloc = ins->objectid + ins->offset; | ||
1613 | return ret; | 1641 | return ret; |
1614 | } | 1642 | } |
1615 | /* | 1643 | /* |
@@ -1778,7 +1806,8 @@ struct extent_buffer *__btrfs_alloc_free_block(struct btrfs_trans_handle *trans, | |||
1778 | buf->start, buf->start + buf->len - 1, | 1806 | buf->start, buf->start + buf->len - 1, |
1779 | EXTENT_CSUM, GFP_NOFS); | 1807 | EXTENT_CSUM, GFP_NOFS); |
1780 | buf->flags |= EXTENT_CSUM; | 1808 | buf->flags |= EXTENT_CSUM; |
1781 | btrfs_set_buffer_defrag(buf); | 1809 | if (!btrfs_test_opt(root, SSD)) |
1810 | btrfs_set_buffer_defrag(buf); | ||
1782 | trans->blocks_used++; | 1811 | trans->blocks_used++; |
1783 | return buf; | 1812 | return buf; |
1784 | } | 1813 | } |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index e506de3168bc..b6982f0133cf 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -64,7 +64,7 @@ static void btrfs_put_super (struct super_block * sb) | |||
64 | 64 | ||
65 | enum { | 65 | enum { |
66 | Opt_subvol, Opt_nodatasum, Opt_nodatacow, Opt_max_extent, | 66 | Opt_subvol, Opt_nodatasum, Opt_nodatacow, Opt_max_extent, |
67 | Opt_alloc_start, Opt_nobarrier, Opt_err, | 67 | Opt_alloc_start, Opt_nobarrier, Opt_ssd, Opt_err, |
68 | }; | 68 | }; |
69 | 69 | ||
70 | static match_table_t tokens = { | 70 | static match_table_t tokens = { |
@@ -74,6 +74,7 @@ static match_table_t tokens = { | |||
74 | {Opt_nobarrier, "nobarrier"}, | 74 | {Opt_nobarrier, "nobarrier"}, |
75 | {Opt_max_extent, "max_extent=%s"}, | 75 | {Opt_max_extent, "max_extent=%s"}, |
76 | {Opt_alloc_start, "alloc_start=%s"}, | 76 | {Opt_alloc_start, "alloc_start=%s"}, |
77 | {Opt_ssd, "ssd"}, | ||
77 | {Opt_err, NULL} | 78 | {Opt_err, NULL} |
78 | }; | 79 | }; |
79 | 80 | ||
@@ -149,6 +150,12 @@ static int parse_options (char * options, | |||
149 | btrfs_set_opt(info->mount_opt, NODATASUM); | 150 | btrfs_set_opt(info->mount_opt, NODATASUM); |
150 | } | 151 | } |
151 | break; | 152 | break; |
153 | case Opt_ssd: | ||
154 | if (info) { | ||
155 | printk("btrfs: use ssd allocation scheme\n"); | ||
156 | btrfs_set_opt(info->mount_opt, SSD); | ||
157 | } | ||
158 | break; | ||
152 | case Opt_nobarrier: | 159 | case Opt_nobarrier: |
153 | if (info) { | 160 | if (info) { |
154 | printk("btrfs: turning off barriers\n"); | 161 | printk("btrfs: turning off barriers\n"); |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index b6bbfc179c29..163c01a24498 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -57,6 +57,7 @@ static int join_transaction(struct btrfs_root *root) | |||
57 | BUG_ON(!cur_trans); | 57 | BUG_ON(!cur_trans); |
58 | root->fs_info->generation++; | 58 | root->fs_info->generation++; |
59 | root->fs_info->running_transaction = cur_trans; | 59 | root->fs_info->running_transaction = cur_trans; |
60 | root->fs_info->last_alloc = 0; | ||
60 | cur_trans->num_writers = 1; | 61 | cur_trans->num_writers = 1; |
61 | cur_trans->num_joined = 0; | 62 | cur_trans->num_joined = 0; |
62 | cur_trans->transid = root->fs_info->generation; | 63 | cur_trans->transid = root->fs_info->generation; |
diff --git a/fs/btrfs/tree-defrag.c b/fs/btrfs/tree-defrag.c index 5c58630dce03..5935cbd8f2b8 100644 --- a/fs/btrfs/tree-defrag.c +++ b/fs/btrfs/tree-defrag.c | |||
@@ -179,6 +179,9 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans, | |||
179 | if (root->ref_cows == 0 && !is_extent) | 179 | if (root->ref_cows == 0 && !is_extent) |
180 | goto out; | 180 | goto out; |
181 | 181 | ||
182 | if (btrfs_test_opt(root, SSD)) | ||
183 | goto out; | ||
184 | |||
182 | path = btrfs_alloc_path(); | 185 | path = btrfs_alloc_path(); |
183 | if (!path) | 186 | if (!path) |
184 | return -ENOMEM; | 187 | return -ENOMEM; |