diff options
Diffstat (limited to 'patches/boot_time_opt/0110-fs-ext4-fsync-optimize-double-fsync-a-bunch.patch')
| -rw-r--r-- | patches/boot_time_opt/0110-fs-ext4-fsync-optimize-double-fsync-a-bunch.patch | 158 |
1 files changed, 0 insertions, 158 deletions
diff --git a/patches/boot_time_opt/0110-fs-ext4-fsync-optimize-double-fsync-a-bunch.patch b/patches/boot_time_opt/0110-fs-ext4-fsync-optimize-double-fsync-a-bunch.patch deleted file mode 100644 index b115a5b..0000000 --- a/patches/boot_time_opt/0110-fs-ext4-fsync-optimize-double-fsync-a-bunch.patch +++ /dev/null | |||
| @@ -1,158 +0,0 @@ | |||
| 1 | From 5e6c814b3ab74e9abbdd836a224c5ceb7246b44e Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Arjan van de Ven <arjan@linux.intel.com> | ||
| 3 | Date: Sat, 9 Apr 2016 22:41:37 +0000 | ||
| 4 | Subject: [PATCH 110/126] fs: ext4: fsync: optimize double-fsync() a bunch | ||
| 5 | |||
| 6 | There are cases where EXT4 is a bit too conservative sending barriers down to | ||
| 7 | the disk; there are cases where the transaction in progress is not the one | ||
| 8 | that sent the barrier (in other words: the fsync is for a file for which the | ||
| 9 | IO happened more time ago and all data was already sent to the disk). | ||
| 10 | |||
| 11 | For that case, a more performing tradeoff can be made on SSD devices (which | ||
| 12 | have the ability to flush their dram caches in a hurry on a power fail event) | ||
| 13 | where the barrier gets sent to the disk, but we don't need to wait for the | ||
| 14 | barrier to complete. Any consecutive IO will block on the barrier correctly. | ||
| 15 | --- | ||
| 16 | block/bio.c | 19 +++++++++++++++++++ | ||
| 17 | block/blk-flush.c | 40 ++++++++++++++++++++++++++++++++++++++++ | ||
| 18 | fs/ext4/fsync.c | 6 +++++- | ||
| 19 | include/linux/bio.h | 1 + | ||
| 20 | include/linux/blkdev.h | 5 +++++ | ||
| 21 | 5 files changed, 70 insertions(+), 1 deletion(-) | ||
| 22 | |||
| 23 | diff --git a/block/bio.c b/block/bio.c | ||
| 24 | index 101c2a9b5481..8f9f6e9febe0 100644 | ||
| 25 | --- a/block/bio.c | ||
| 26 | +++ b/block/bio.c | ||
| 27 | @@ -956,6 +956,25 @@ int submit_bio_wait(struct bio *bio) | ||
| 28 | } | ||
| 29 | EXPORT_SYMBOL(submit_bio_wait); | ||
| 30 | |||
| 31 | +static void submit_bio_nowait_endio(struct bio *bio) | ||
| 32 | +{ | ||
| 33 | + bio_put(bio); | ||
| 34 | +} | ||
| 35 | + | ||
| 36 | +/** | ||
| 37 | + * submit_bio_nowait - submit a bio for fire-and-forge for fire-and-forget | ||
| 38 | + * @bio: The &struct bio which describes the I/O | ||
| 39 | + * | ||
| 40 | + * Simple wrapper around submit_bio() that takes care of bio_put() on completion | ||
| 41 | + */ | ||
| 42 | +void submit_bio_nowait(struct bio *bio) | ||
| 43 | +{ | ||
| 44 | + bio->bi_end_io = submit_bio_nowait_endio; | ||
| 45 | + bio->bi_opf |= REQ_SYNC; | ||
| 46 | + submit_bio(bio); | ||
| 47 | +} | ||
| 48 | +EXPORT_SYMBOL(submit_bio_nowait); | ||
| 49 | + | ||
| 50 | /** | ||
| 51 | * bio_advance - increment/complete a bio by some number of bytes | ||
| 52 | * @bio: bio to advance | ||
| 53 | diff --git a/block/blk-flush.c b/block/blk-flush.c | ||
| 54 | index 4938bec8cfef..020f2c75343a 100644 | ||
| 55 | --- a/block/blk-flush.c | ||
| 56 | +++ b/block/blk-flush.c | ||
| 57 | @@ -543,6 +543,46 @@ int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask, | ||
| 58 | } | ||
| 59 | EXPORT_SYMBOL(blkdev_issue_flush); | ||
| 60 | |||
| 61 | +/** | ||
| 62 | + * blkdev_issue_flush_nowait - queue a flush | ||
| 63 | + * @bdev: blockdev to issue flush for | ||
| 64 | + * @gfp_mask: memory allocation flags (for bio_alloc) | ||
| 65 | + * | ||
| 66 | + * Description: | ||
| 67 | + * Issue a flush for the block device in question. Caller can supply | ||
| 68 | + * room for storing the error offset in case of a flush error, if they | ||
| 69 | + * wish to. If WAIT flag is not passed then caller may check only what | ||
| 70 | + * request was pushed in some internal queue for later handling. | ||
| 71 | + */ | ||
| 72 | +void blkdev_issue_flush_nowait(struct block_device *bdev, gfp_t gfp_mask) | ||
| 73 | +{ | ||
| 74 | + struct request_queue *q; | ||
| 75 | + struct bio *bio; | ||
| 76 | + | ||
| 77 | + if (bdev->bd_disk == NULL) | ||
| 78 | + return; | ||
| 79 | + | ||
| 80 | + q = bdev_get_queue(bdev); | ||
| 81 | + if (!q) | ||
| 82 | + return; | ||
| 83 | + | ||
| 84 | + /* | ||
| 85 | + * some block devices may not have their queue correctly set up here | ||
| 86 | + * (e.g. loop device without a backing file) and so issuing a flush | ||
| 87 | + * here will panic. Ensure there is a request function before issuing | ||
| 88 | + * the flush. | ||
| 89 | + */ | ||
| 90 | + if (!q->make_request_fn) | ||
| 91 | + return; | ||
| 92 | + | ||
| 93 | + bio = bio_alloc(gfp_mask, 0); | ||
| 94 | + bio_set_dev(bio, bdev); | ||
| 95 | + bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH; | ||
| 96 | + | ||
| 97 | + submit_bio_nowait(bio); | ||
| 98 | +} | ||
| 99 | +EXPORT_SYMBOL(blkdev_issue_flush_nowait); | ||
| 100 | + | ||
| 101 | struct blk_flush_queue *blk_alloc_flush_queue(struct request_queue *q, | ||
| 102 | int node, int cmd_size) | ||
| 103 | { | ||
| 104 | diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c | ||
| 105 | index 26a7fe5c4fd3..2708b292ddca 100644 | ||
| 106 | --- a/fs/ext4/fsync.c | ||
| 107 | +++ b/fs/ext4/fsync.c | ||
| 108 | @@ -154,7 +154,11 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | ||
| 109 | ret = jbd2_complete_transaction(journal, commit_tid); | ||
| 110 | if (needs_barrier) { | ||
| 111 | issue_flush: | ||
| 112 | - err = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL); | ||
| 113 | + err = 0; | ||
| 114 | + if (!blk_queue_nonrot(bdev_get_queue(inode->i_sb->s_bdev))) | ||
| 115 | + err = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL); | ||
| 116 | + else | ||
| 117 | + blkdev_issue_flush_nowait(inode->i_sb->s_bdev, GFP_KERNEL); | ||
| 118 | if (!ret) | ||
| 119 | ret = err; | ||
| 120 | } | ||
| 121 | diff --git a/include/linux/bio.h b/include/linux/bio.h | ||
| 122 | index 275c91c99516..4ddfa9e10301 100644 | ||
| 123 | --- a/include/linux/bio.h | ||
| 124 | +++ b/include/linux/bio.h | ||
| 125 | @@ -448,6 +448,7 @@ struct request_queue; | ||
| 126 | extern int bio_phys_segments(struct request_queue *, struct bio *); | ||
| 127 | |||
| 128 | extern int submit_bio_wait(struct bio *bio); | ||
| 129 | +extern void submit_bio_nowait(struct bio *bio); | ||
| 130 | extern void bio_advance(struct bio *, unsigned); | ||
| 131 | |||
| 132 | extern void bio_init(struct bio *bio, struct bio_vec *table, | ||
| 133 | diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h | ||
| 134 | index 8da66379f7ea..c48565cc84fb 100644 | ||
| 135 | --- a/include/linux/blkdev.h | ||
| 136 | +++ b/include/linux/blkdev.h | ||
| 137 | @@ -1336,6 +1336,7 @@ static inline struct request *blk_map_queue_find_tag(struct blk_queue_tag *bqt, | ||
| 138 | } | ||
| 139 | |||
| 140 | extern int blkdev_issue_flush(struct block_device *, gfp_t, sector_t *); | ||
| 141 | +extern void blkdev_issue_flush_nowait(struct block_device *, gfp_t); | ||
| 142 | extern int blkdev_issue_write_same(struct block_device *bdev, sector_t sector, | ||
| 143 | sector_t nr_sects, gfp_t gfp_mask, struct page *page); | ||
| 144 | |||
| 145 | @@ -2001,6 +2002,10 @@ static inline int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask, | ||
| 146 | return 0; | ||
| 147 | } | ||
| 148 | |||
| 149 | +static inline void blkdev_issue_flush_nowait(struct block_device *bdev, gfp_t gfp_mask) | ||
| 150 | +{ | ||
| 151 | +} | ||
| 152 | + | ||
| 153 | #endif /* CONFIG_BLOCK */ | ||
| 154 | |||
| 155 | #endif | ||
| 156 | -- | ||
| 157 | 2.15.0 | ||
| 158 | |||
