diff options
-rw-r--r-- | fs/btrfs/disk-io.c | 22 | ||||
-rw-r--r-- | fs/btrfs/extent_io.c | 14 | ||||
-rw-r--r-- | fs/btrfs/extent_io.h | 1 |
3 files changed, 35 insertions, 2 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index dcaf55695e6f..aa02eab8c40b 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -46,6 +46,10 @@ | |||
46 | #include "check-integrity.h" | 46 | #include "check-integrity.h" |
47 | #include "rcu-string.h" | 47 | #include "rcu-string.h" |
48 | 48 | ||
49 | #ifdef CONFIG_X86 | ||
50 | #include <asm/cpufeature.h> | ||
51 | #endif | ||
52 | |||
49 | static struct extent_io_ops btree_extent_io_ops; | 53 | static struct extent_io_ops btree_extent_io_ops; |
50 | static void end_workqueue_fn(struct btrfs_work *work); | 54 | static void end_workqueue_fn(struct btrfs_work *work); |
51 | static void free_fs_root(struct btrfs_root *root); | 55 | static void free_fs_root(struct btrfs_root *root); |
@@ -859,10 +863,22 @@ static int __btree_submit_bio_done(struct inode *inode, int rw, struct bio *bio, | |||
859 | return btrfs_map_bio(BTRFS_I(inode)->root, rw, bio, mirror_num, 1); | 863 | return btrfs_map_bio(BTRFS_I(inode)->root, rw, bio, mirror_num, 1); |
860 | } | 864 | } |
861 | 865 | ||
866 | static int check_async_write(struct inode *inode, unsigned long bio_flags) | ||
867 | { | ||
868 | if (bio_flags & EXTENT_BIO_TREE_LOG) | ||
869 | return 0; | ||
870 | #ifdef CONFIG_X86 | ||
871 | if (cpu_has_xmm4_2) | ||
872 | return 0; | ||
873 | #endif | ||
874 | return 1; | ||
875 | } | ||
876 | |||
862 | static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, | 877 | static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, |
863 | int mirror_num, unsigned long bio_flags, | 878 | int mirror_num, unsigned long bio_flags, |
864 | u64 bio_offset) | 879 | u64 bio_offset) |
865 | { | 880 | { |
881 | int async = check_async_write(inode, bio_flags); | ||
866 | int ret; | 882 | int ret; |
867 | 883 | ||
868 | if (!(rw & REQ_WRITE)) { | 884 | if (!(rw & REQ_WRITE)) { |
@@ -877,6 +893,12 @@ static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, | |||
877 | return ret; | 893 | return ret; |
878 | return btrfs_map_bio(BTRFS_I(inode)->root, rw, bio, | 894 | return btrfs_map_bio(BTRFS_I(inode)->root, rw, bio, |
879 | mirror_num, 0); | 895 | mirror_num, 0); |
896 | } else if (!async) { | ||
897 | ret = btree_csum_one_bio(bio); | ||
898 | if (ret) | ||
899 | return ret; | ||
900 | return btrfs_map_bio(BTRFS_I(inode)->root, rw, bio, | ||
901 | mirror_num, 0); | ||
880 | } | 902 | } |
881 | 903 | ||
882 | /* | 904 | /* |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index a2c21570adf5..979fa0d6bfee 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -45,6 +45,7 @@ struct extent_page_data { | |||
45 | struct bio *bio; | 45 | struct bio *bio; |
46 | struct extent_io_tree *tree; | 46 | struct extent_io_tree *tree; |
47 | get_extent_t *get_extent; | 47 | get_extent_t *get_extent; |
48 | unsigned long bio_flags; | ||
48 | 49 | ||
49 | /* tells writepage not to lock the state bits for this range | 50 | /* tells writepage not to lock the state bits for this range |
50 | * it still does the unlocking | 51 | * it still does the unlocking |
@@ -3163,12 +3164,16 @@ static int write_one_eb(struct extent_buffer *eb, | |||
3163 | struct block_device *bdev = fs_info->fs_devices->latest_bdev; | 3164 | struct block_device *bdev = fs_info->fs_devices->latest_bdev; |
3164 | u64 offset = eb->start; | 3165 | u64 offset = eb->start; |
3165 | unsigned long i, num_pages; | 3166 | unsigned long i, num_pages; |
3167 | unsigned long bio_flags = 0; | ||
3166 | int rw = (epd->sync_io ? WRITE_SYNC : WRITE); | 3168 | int rw = (epd->sync_io ? WRITE_SYNC : WRITE); |
3167 | int ret = 0; | 3169 | int ret = 0; |
3168 | 3170 | ||
3169 | clear_bit(EXTENT_BUFFER_IOERR, &eb->bflags); | 3171 | clear_bit(EXTENT_BUFFER_IOERR, &eb->bflags); |
3170 | num_pages = num_extent_pages(eb->start, eb->len); | 3172 | num_pages = num_extent_pages(eb->start, eb->len); |
3171 | atomic_set(&eb->io_pages, num_pages); | 3173 | atomic_set(&eb->io_pages, num_pages); |
3174 | if (btrfs_header_owner(eb) == BTRFS_TREE_LOG_OBJECTID) | ||
3175 | bio_flags = EXTENT_BIO_TREE_LOG; | ||
3176 | |||
3172 | for (i = 0; i < num_pages; i++) { | 3177 | for (i = 0; i < num_pages; i++) { |
3173 | struct page *p = extent_buffer_page(eb, i); | 3178 | struct page *p = extent_buffer_page(eb, i); |
3174 | 3179 | ||
@@ -3177,7 +3182,8 @@ static int write_one_eb(struct extent_buffer *eb, | |||
3177 | ret = submit_extent_page(rw, eb->tree, p, offset >> 9, | 3182 | ret = submit_extent_page(rw, eb->tree, p, offset >> 9, |
3178 | PAGE_CACHE_SIZE, 0, bdev, &epd->bio, | 3183 | PAGE_CACHE_SIZE, 0, bdev, &epd->bio, |
3179 | -1, end_bio_extent_buffer_writepage, | 3184 | -1, end_bio_extent_buffer_writepage, |
3180 | 0, 0, 0); | 3185 | 0, epd->bio_flags, bio_flags); |
3186 | epd->bio_flags = bio_flags; | ||
3181 | if (ret) { | 3187 | if (ret) { |
3182 | set_bit(EXTENT_BUFFER_IOERR, &eb->bflags); | 3188 | set_bit(EXTENT_BUFFER_IOERR, &eb->bflags); |
3183 | SetPageError(p); | 3189 | SetPageError(p); |
@@ -3212,6 +3218,7 @@ int btree_write_cache_pages(struct address_space *mapping, | |||
3212 | .tree = tree, | 3218 | .tree = tree, |
3213 | .extent_locked = 0, | 3219 | .extent_locked = 0, |
3214 | .sync_io = wbc->sync_mode == WB_SYNC_ALL, | 3220 | .sync_io = wbc->sync_mode == WB_SYNC_ALL, |
3221 | .bio_flags = 0, | ||
3215 | }; | 3222 | }; |
3216 | int ret = 0; | 3223 | int ret = 0; |
3217 | int done = 0; | 3224 | int done = 0; |
@@ -3474,7 +3481,7 @@ static void flush_epd_write_bio(struct extent_page_data *epd) | |||
3474 | if (epd->sync_io) | 3481 | if (epd->sync_io) |
3475 | rw = WRITE_SYNC; | 3482 | rw = WRITE_SYNC; |
3476 | 3483 | ||
3477 | ret = submit_one_bio(rw, epd->bio, 0, 0); | 3484 | ret = submit_one_bio(rw, epd->bio, 0, epd->bio_flags); |
3478 | BUG_ON(ret < 0); /* -ENOMEM */ | 3485 | BUG_ON(ret < 0); /* -ENOMEM */ |
3479 | epd->bio = NULL; | 3486 | epd->bio = NULL; |
3480 | } | 3487 | } |
@@ -3497,6 +3504,7 @@ int extent_write_full_page(struct extent_io_tree *tree, struct page *page, | |||
3497 | .get_extent = get_extent, | 3504 | .get_extent = get_extent, |
3498 | .extent_locked = 0, | 3505 | .extent_locked = 0, |
3499 | .sync_io = wbc->sync_mode == WB_SYNC_ALL, | 3506 | .sync_io = wbc->sync_mode == WB_SYNC_ALL, |
3507 | .bio_flags = 0, | ||
3500 | }; | 3508 | }; |
3501 | 3509 | ||
3502 | ret = __extent_writepage(page, wbc, &epd); | 3510 | ret = __extent_writepage(page, wbc, &epd); |
@@ -3521,6 +3529,7 @@ int extent_write_locked_range(struct extent_io_tree *tree, struct inode *inode, | |||
3521 | .get_extent = get_extent, | 3529 | .get_extent = get_extent, |
3522 | .extent_locked = 1, | 3530 | .extent_locked = 1, |
3523 | .sync_io = mode == WB_SYNC_ALL, | 3531 | .sync_io = mode == WB_SYNC_ALL, |
3532 | .bio_flags = 0, | ||
3524 | }; | 3533 | }; |
3525 | struct writeback_control wbc_writepages = { | 3534 | struct writeback_control wbc_writepages = { |
3526 | .sync_mode = mode, | 3535 | .sync_mode = mode, |
@@ -3560,6 +3569,7 @@ int extent_writepages(struct extent_io_tree *tree, | |||
3560 | .get_extent = get_extent, | 3569 | .get_extent = get_extent, |
3561 | .extent_locked = 0, | 3570 | .extent_locked = 0, |
3562 | .sync_io = wbc->sync_mode == WB_SYNC_ALL, | 3571 | .sync_io = wbc->sync_mode == WB_SYNC_ALL, |
3572 | .bio_flags = 0, | ||
3563 | }; | 3573 | }; |
3564 | 3574 | ||
3565 | ret = extent_write_cache_pages(tree, mapping, wbc, | 3575 | ret = extent_write_cache_pages(tree, mapping, wbc, |
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index 512f8da041f1..a69dea219044 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h | |||
@@ -27,6 +27,7 @@ | |||
27 | * type for this bio | 27 | * type for this bio |
28 | */ | 28 | */ |
29 | #define EXTENT_BIO_COMPRESSED 1 | 29 | #define EXTENT_BIO_COMPRESSED 1 |
30 | #define EXTENT_BIO_TREE_LOG 2 | ||
30 | #define EXTENT_BIO_FLAG_SHIFT 16 | 31 | #define EXTENT_BIO_FLAG_SHIFT 16 |
31 | 32 | ||
32 | /* these are bit numbers for test/set bit */ | 33 | /* these are bit numbers for test/set bit */ |