diff options
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 63 |
1 files changed, 48 insertions, 15 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 844bb896f5ac..b8b2a3cbdbe1 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -115,6 +115,31 @@ static struct extent_map *create_io_em(struct inode *inode, u64 start, u64 len, | |||
115 | u64 ram_bytes, int compress_type, | 115 | u64 ram_bytes, int compress_type, |
116 | int type); | 116 | int type); |
117 | 117 | ||
118 | static void __endio_write_update_ordered(struct inode *inode, | ||
119 | const u64 offset, const u64 bytes, | ||
120 | const bool uptodate); | ||
121 | |||
122 | /* | ||
123 | * Cleanup all submitted ordered extents in specified range to handle errors | ||
124 | * from the fill_dellaloc() callback. | ||
125 | * | ||
126 | * NOTE: caller must ensure that when an error happens, it can not call | ||
127 | * extent_clear_unlock_delalloc() to clear both the bits EXTENT_DO_ACCOUNTING | ||
128 | * and EXTENT_DELALLOC simultaneously, because that causes the reserved metadata | ||
129 | * to be released, which we want to happen only when finishing the ordered | ||
130 | * extent (btrfs_finish_ordered_io()). Also note that the caller of the | ||
131 | * fill_delalloc() callback already does proper cleanup for the first page of | ||
132 | * the range, that is, it invokes the callback writepage_end_io_hook() for the | ||
133 | * range of the first page. | ||
134 | */ | ||
135 | static inline void btrfs_cleanup_ordered_extents(struct inode *inode, | ||
136 | const u64 offset, | ||
137 | const u64 bytes) | ||
138 | { | ||
139 | return __endio_write_update_ordered(inode, offset + PAGE_SIZE, | ||
140 | bytes - PAGE_SIZE, false); | ||
141 | } | ||
142 | |||
118 | static int btrfs_dirty_inode(struct inode *inode); | 143 | static int btrfs_dirty_inode(struct inode *inode); |
119 | 144 | ||
120 | #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS | 145 | #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS |
@@ -1536,6 +1561,8 @@ static int run_delalloc_range(struct inode *inode, struct page *locked_page, | |||
1536 | ret = cow_file_range_async(inode, locked_page, start, end, | 1561 | ret = cow_file_range_async(inode, locked_page, start, end, |
1537 | page_started, nr_written); | 1562 | page_started, nr_written); |
1538 | } | 1563 | } |
1564 | if (ret) | ||
1565 | btrfs_cleanup_ordered_extents(inode, start, end - start + 1); | ||
1539 | return ret; | 1566 | return ret; |
1540 | } | 1567 | } |
1541 | 1568 | ||
@@ -8154,17 +8181,26 @@ static void btrfs_endio_direct_read(struct bio *bio) | |||
8154 | bio_put(bio); | 8181 | bio_put(bio); |
8155 | } | 8182 | } |
8156 | 8183 | ||
8157 | static void btrfs_endio_direct_write_update_ordered(struct inode *inode, | 8184 | static void __endio_write_update_ordered(struct inode *inode, |
8158 | const u64 offset, | 8185 | const u64 offset, const u64 bytes, |
8159 | const u64 bytes, | 8186 | const bool uptodate) |
8160 | const int uptodate) | ||
8161 | { | 8187 | { |
8162 | struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); | 8188 | struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); |
8163 | struct btrfs_ordered_extent *ordered = NULL; | 8189 | struct btrfs_ordered_extent *ordered = NULL; |
8190 | struct btrfs_workqueue *wq; | ||
8191 | btrfs_work_func_t func; | ||
8164 | u64 ordered_offset = offset; | 8192 | u64 ordered_offset = offset; |
8165 | u64 ordered_bytes = bytes; | 8193 | u64 ordered_bytes = bytes; |
8166 | int ret; | 8194 | int ret; |
8167 | 8195 | ||
8196 | if (btrfs_is_free_space_inode(BTRFS_I(inode))) { | ||
8197 | wq = fs_info->endio_freespace_worker; | ||
8198 | func = btrfs_freespace_write_helper; | ||
8199 | } else { | ||
8200 | wq = fs_info->endio_write_workers; | ||
8201 | func = btrfs_endio_write_helper; | ||
8202 | } | ||
8203 | |||
8168 | again: | 8204 | again: |
8169 | ret = btrfs_dec_test_first_ordered_pending(inode, &ordered, | 8205 | ret = btrfs_dec_test_first_ordered_pending(inode, &ordered, |
8170 | &ordered_offset, | 8206 | &ordered_offset, |
@@ -8173,9 +8209,8 @@ again: | |||
8173 | if (!ret) | 8209 | if (!ret) |
8174 | goto out_test; | 8210 | goto out_test; |
8175 | 8211 | ||
8176 | btrfs_init_work(&ordered->work, btrfs_endio_write_helper, | 8212 | btrfs_init_work(&ordered->work, func, finish_ordered_fn, NULL, NULL); |
8177 | finish_ordered_fn, NULL, NULL); | 8213 | btrfs_queue_work(wq, &ordered->work); |
8178 | btrfs_queue_work(fs_info->endio_write_workers, &ordered->work); | ||
8179 | out_test: | 8214 | out_test: |
8180 | /* | 8215 | /* |
8181 | * our bio might span multiple ordered extents. If we haven't | 8216 | * our bio might span multiple ordered extents. If we haven't |
@@ -8193,10 +8228,8 @@ static void btrfs_endio_direct_write(struct bio *bio) | |||
8193 | struct btrfs_dio_private *dip = bio->bi_private; | 8228 | struct btrfs_dio_private *dip = bio->bi_private; |
8194 | struct bio *dio_bio = dip->dio_bio; | 8229 | struct bio *dio_bio = dip->dio_bio; |
8195 | 8230 | ||
8196 | btrfs_endio_direct_write_update_ordered(dip->inode, | 8231 | __endio_write_update_ordered(dip->inode, dip->logical_offset, |
8197 | dip->logical_offset, | 8232 | dip->bytes, !bio->bi_error); |
8198 | dip->bytes, | ||
8199 | !bio->bi_error); | ||
8200 | 8233 | ||
8201 | kfree(dip); | 8234 | kfree(dip); |
8202 | 8235 | ||
@@ -8557,10 +8590,10 @@ free_ordered: | |||
8557 | io_bio = NULL; | 8590 | io_bio = NULL; |
8558 | } else { | 8591 | } else { |
8559 | if (write) | 8592 | if (write) |
8560 | btrfs_endio_direct_write_update_ordered(inode, | 8593 | __endio_write_update_ordered(inode, |
8561 | file_offset, | 8594 | file_offset, |
8562 | dio_bio->bi_iter.bi_size, | 8595 | dio_bio->bi_iter.bi_size, |
8563 | 0); | 8596 | false); |
8564 | else | 8597 | else |
8565 | unlock_extent(&BTRFS_I(inode)->io_tree, file_offset, | 8598 | unlock_extent(&BTRFS_I(inode)->io_tree, file_offset, |
8566 | file_offset + dio_bio->bi_iter.bi_size - 1); | 8599 | file_offset + dio_bio->bi_iter.bi_size - 1); |
@@ -8695,11 +8728,11 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) | |||
8695 | */ | 8728 | */ |
8696 | if (dio_data.unsubmitted_oe_range_start < | 8729 | if (dio_data.unsubmitted_oe_range_start < |
8697 | dio_data.unsubmitted_oe_range_end) | 8730 | dio_data.unsubmitted_oe_range_end) |
8698 | btrfs_endio_direct_write_update_ordered(inode, | 8731 | __endio_write_update_ordered(inode, |
8699 | dio_data.unsubmitted_oe_range_start, | 8732 | dio_data.unsubmitted_oe_range_start, |
8700 | dio_data.unsubmitted_oe_range_end - | 8733 | dio_data.unsubmitted_oe_range_end - |
8701 | dio_data.unsubmitted_oe_range_start, | 8734 | dio_data.unsubmitted_oe_range_start, |
8702 | 0); | 8735 | false); |
8703 | } else if (ret >= 0 && (size_t)ret < count) | 8736 | } else if (ret >= 0 && (size_t)ret < count) |
8704 | btrfs_delalloc_release_space(inode, offset, | 8737 | btrfs_delalloc_release_space(inode, offset, |
8705 | count - (size_t)ret); | 8738 | count - (size_t)ret); |