Skip to content

Commit 29086a3

Browse files
Christoph Hellwigbrauner
authored andcommitted
iomap: rework REQ_FUA selection
The way how iomap_dio_can_use_fua and the caller is structured is a bit confusing, as the main guarding condition is hidden in the helper, and the secondary conditions are split between caller and callee. Refactor the code, so that iomap_dio_bio_iter itself tracks if a write might need metadata updates based on the iomap type and flags, and then have a condition based on that to use the FUA flag. Note that this also moves the REQ_OP_WRITE assignment to the end of the branch to improve readability a bit. Signed-off-by: Christoph Hellwig <hch@lst.de> Link: https://patch.msgid.link/20251113170633.1453259-4-hch@lst.de Signed-off-by: Christian Brauner <brauner@kernel.org>
1 parent ddb4873 commit 29086a3

1 file changed

Lines changed: 48 additions & 30 deletions

File tree

fs/iomap/direct-io.c

Lines changed: 48 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -287,23 +287,6 @@ static int iomap_dio_zero(const struct iomap_iter *iter, struct iomap_dio *dio,
287287
return 0;
288288
}
289289

290-
/*
291-
* Use a FUA write if we need datasync semantics and this is a pure data I/O
292-
* that doesn't require any metadata updates (including after I/O completion
293-
* such as unwritten extent conversion) and the underlying device either
294-
* doesn't have a volatile write cache or supports FUA.
295-
* This allows us to avoid cache flushes on I/O completion.
296-
*/
297-
static inline bool iomap_dio_can_use_fua(const struct iomap *iomap,
298-
struct iomap_dio *dio)
299-
{
300-
if (iomap->flags & (IOMAP_F_SHARED | IOMAP_F_DIRTY))
301-
return false;
302-
if (!(dio->flags & IOMAP_DIO_WRITE_THROUGH))
303-
return false;
304-
return !bdev_write_cache(iomap->bdev) || bdev_fua(iomap->bdev);
305-
}
306-
307290
static int iomap_dio_bio_iter(struct iomap_iter *iter, struct iomap_dio *dio)
308291
{
309292
const struct iomap *iomap = &iter->iomap;
@@ -332,7 +315,24 @@ static int iomap_dio_bio_iter(struct iomap_iter *iter, struct iomap_dio *dio)
332315
return -EINVAL;
333316

334317
if (dio->flags & IOMAP_DIO_WRITE) {
335-
bio_opf |= REQ_OP_WRITE;
318+
bool need_completion_work = true;
319+
320+
switch (iomap->type) {
321+
case IOMAP_MAPPED:
322+
/*
323+
* Directly mapped I/O does not inherently need to do
324+
* work at I/O completion time. But there are various
325+
* cases below where this will get set again.
326+
*/
327+
need_completion_work = false;
328+
break;
329+
case IOMAP_UNWRITTEN:
330+
dio->flags |= IOMAP_DIO_UNWRITTEN;
331+
need_zeroout = true;
332+
break;
333+
default:
334+
break;
335+
}
336336

337337
if (iomap->flags & IOMAP_F_ATOMIC_BIO) {
338338
/*
@@ -345,22 +345,40 @@ static int iomap_dio_bio_iter(struct iomap_iter *iter, struct iomap_dio *dio)
345345
bio_opf |= REQ_ATOMIC;
346346
}
347347

348-
if (iomap->type == IOMAP_UNWRITTEN) {
349-
dio->flags |= IOMAP_DIO_UNWRITTEN;
350-
need_zeroout = true;
351-
}
352-
353-
if (iomap->flags & IOMAP_F_SHARED)
348+
if (iomap->flags & IOMAP_F_SHARED) {
349+
/*
350+
* Unsharing of needs to update metadata at I/O
351+
* completion time.
352+
*/
353+
need_completion_work = true;
354354
dio->flags |= IOMAP_DIO_COW;
355+
}
355356

356-
if (iomap->flags & IOMAP_F_NEW)
357+
if (iomap->flags & IOMAP_F_NEW) {
358+
/*
359+
* Newly allocated blocks might need recording in
360+
* metadata at I/O completion time.
361+
*/
362+
need_completion_work = true;
357363
need_zeroout = true;
358-
else if (iomap->type == IOMAP_MAPPED &&
359-
iomap_dio_can_use_fua(iomap, dio))
360-
bio_opf |= REQ_FUA;
364+
}
361365

362-
if (!(bio_opf & REQ_FUA))
363-
dio->flags &= ~IOMAP_DIO_WRITE_THROUGH;
366+
/*
367+
* Use a FUA write if we need datasync semantics and this is a
368+
* pure overwrite that doesn't require any metadata updates.
369+
*
370+
* This allows us to avoid cache flushes on I/O completion.
371+
*/
372+
if (dio->flags & IOMAP_DIO_WRITE_THROUGH) {
373+
if (!need_completion_work &&
374+
!(iomap->flags & IOMAP_F_DIRTY) &&
375+
(!bdev_write_cache(iomap->bdev) ||
376+
bdev_fua(iomap->bdev)))
377+
bio_opf |= REQ_FUA;
378+
else
379+
dio->flags &= ~IOMAP_DIO_WRITE_THROUGH;
380+
}
381+
bio_opf |= REQ_OP_WRITE;
364382
} else {
365383
bio_opf |= REQ_OP_READ;
366384
}

0 commit comments

Comments
 (0)