|
1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
2 | 2 | /* |
3 | 3 | * Copyright (C) 2010 Red Hat, Inc. |
4 | | - * Copyright (c) 2016-2021 Christoph Hellwig. |
| 4 | + * Copyright (c) 2016-2025 Christoph Hellwig. |
5 | 5 | */ |
6 | 6 | #include <linux/module.h> |
7 | 7 | #include <linux/compiler.h> |
|
12 | 12 | #include <linux/backing-dev.h> |
13 | 13 | #include <linux/uio.h> |
14 | 14 | #include <linux/task_io_accounting_ops.h> |
| 15 | +#include "internal.h" |
15 | 16 | #include "trace.h" |
16 | 17 |
|
17 | 18 | #include "../internal.h" |
|
20 | 21 | * Private flags for iomap_dio, must not overlap with the public ones in |
21 | 22 | * iomap.h: |
22 | 23 | */ |
| 24 | +#define IOMAP_DIO_NO_INVALIDATE (1U << 25) |
23 | 25 | #define IOMAP_DIO_CALLER_COMP (1U << 26) |
24 | 26 | #define IOMAP_DIO_INLINE_COMP (1U << 27) |
25 | 27 | #define IOMAP_DIO_WRITE_THROUGH (1U << 28) |
@@ -119,7 +121,8 @@ ssize_t iomap_dio_complete(struct iomap_dio *dio) |
119 | 121 | * ->end_io() when necessary, otherwise a racing buffer read would cache |
120 | 122 | * zeros from unwritten extents. |
121 | 123 | */ |
122 | | - if (!dio->error && dio->size && (dio->flags & IOMAP_DIO_WRITE)) |
| 124 | + if (!dio->error && dio->size && (dio->flags & IOMAP_DIO_WRITE) && |
| 125 | + !(dio->flags & IOMAP_DIO_NO_INVALIDATE)) |
123 | 126 | kiocb_invalidate_post_direct_write(iocb, dio->size); |
124 | 127 |
|
125 | 128 | inode_dio_end(file_inode(iocb->ki_filp)); |
@@ -241,6 +244,47 @@ void iomap_dio_bio_end_io(struct bio *bio) |
241 | 244 | } |
242 | 245 | EXPORT_SYMBOL_GPL(iomap_dio_bio_end_io); |
243 | 246 |
|
| 247 | +u32 iomap_finish_ioend_direct(struct iomap_ioend *ioend) |
| 248 | +{ |
| 249 | + struct iomap_dio *dio = ioend->io_bio.bi_private; |
| 250 | + bool should_dirty = (dio->flags & IOMAP_DIO_DIRTY); |
| 251 | + u32 vec_count = ioend->io_bio.bi_vcnt; |
| 252 | + |
| 253 | + if (ioend->io_error) |
| 254 | + iomap_dio_set_error(dio, ioend->io_error); |
| 255 | + |
| 256 | + if (atomic_dec_and_test(&dio->ref)) { |
| 257 | + /* |
| 258 | + * Try to avoid another context switch for the completion given |
| 259 | + * that we are already called from the ioend completion |
| 260 | + * workqueue, but never invalidate pages from this thread to |
| 261 | + * avoid deadlocks with buffered I/O completions. Tough luck if |
| 262 | + * you hit the tiny race with someone dirtying the range now |
| 263 | + * between this check and the actual completion. |
| 264 | + */ |
| 265 | + if (!dio->iocb->ki_filp->f_mapping->nrpages) { |
| 266 | + dio->flags |= IOMAP_DIO_INLINE_COMP; |
| 267 | + dio->flags |= IOMAP_DIO_NO_INVALIDATE; |
| 268 | + } |
| 269 | + dio->flags &= ~IOMAP_DIO_CALLER_COMP; |
| 270 | + iomap_dio_done(dio); |
| 271 | + } |
| 272 | + |
| 273 | + if (should_dirty) { |
| 274 | + bio_check_pages_dirty(&ioend->io_bio); |
| 275 | + } else { |
| 276 | + bio_release_pages(&ioend->io_bio, false); |
| 277 | + bio_put(&ioend->io_bio); |
| 278 | + } |
| 279 | + |
| 280 | + /* |
| 281 | + * Return the number of bvecs completed as even direct I/O completions |
| 282 | + * do significant per-folio work and we'll still want to give up the |
| 283 | + * CPU after a lot of completions. |
| 284 | + */ |
| 285 | + return vec_count; |
| 286 | +} |
| 287 | + |
244 | 288 | static int iomap_dio_zero(const struct iomap_iter *iter, struct iomap_dio *dio, |
245 | 289 | loff_t pos, unsigned len) |
246 | 290 | { |
|
0 commit comments