From: Darrick J. Wong <djwong@xxxxxxxxxx> There's no point in caching iomaps when we're initiating a disk write to an unwritten region -- we'll just replace the mapping in the ioend. Save ourselves a bit of overhead by screening for that. Signed-off-by: "Darrick J. Wong" <djwong@xxxxxxxxxx> --- misc/fuse2fs.c | 24 +++++++++++++++++++++++- misc/fuse4fs.c | 24 +++++++++++++++++++++++- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/misc/fuse2fs.c b/misc/fuse2fs.c index da384b10bc6bc5..1b44b836484b14 100644 --- a/misc/fuse2fs.c +++ b/misc/fuse2fs.c @@ -5833,6 +5833,28 @@ static int fuse2fs_iomap_begin_write(struct fuse2fs *ff, ext2_ino_t ino, return 0; } +static inline int fuse2fs_should_cache_iomap(struct fuse2fs *ff, + uint32_t opflags, + const struct fuse_file_iomap *map) +{ + if (!ff->iomap_cache) + return 0; + + /* + * Don't cache small unwritten extents that are being written to the + * device because the overhead of keeping the cache updated will tank + * performance. + */ + if ((opflags & (FUSE_IOMAP_OP_WRITE | FUSE_IOMAP_OP_DIRECT)) == 0) + return 1; + if (map->type != FUSE_IOMAP_TYPE_UNWRITTEN) + return 1; + if (map->length >= FUSE2FS_FSB_TO_B(ff, 16)) + return 1; + + return 0; +} + static int op_iomap_begin(const char *path, uint64_t nodeid, uint64_t attr_ino, off_t pos, uint64_t count, uint32_t opflags, struct fuse_file_iomap *read, @@ -5905,7 +5927,7 @@ static int op_iomap_begin(const char *path, uint64_t nodeid, uint64_t attr_ino, * Cache the mapping in the kernel so that we can reuse them for * subsequent IO. */ - if (ff->iomap_cache) { + if (fuse2fs_should_cache_iomap(ff, opflags, read)) { ret = fuse_fs_iomap_upsert(nodeid, attr_ino, read, NULL); if (ret) { ret = translate_error(fs, attr_ino, -ret); diff --git a/misc/fuse4fs.c b/misc/fuse4fs.c index a2601b5ca94970..df8da745fcd7c7 100644 --- a/misc/fuse4fs.c +++ b/misc/fuse4fs.c @@ -6159,6 +6159,28 @@ static int fuse4fs_iomap_begin_write(struct fuse4fs *ff, ext2_ino_t ino, return 0; } +static inline int fuse4fs_should_cache_iomap(struct fuse4fs *ff, + uint32_t opflags, + const struct fuse_file_iomap *map) +{ + if (!ff->iomap_cache) + return 0; + + /* + * Don't cache small unwritten extents that are being written to the + * device because the overhead of keeping the cache updated will tank + * performance. + */ + if ((opflags & (FUSE_IOMAP_OP_WRITE | FUSE_IOMAP_OP_DIRECT)) == 0) + return 1; + if (map->type != FUSE_IOMAP_TYPE_UNWRITTEN) + return 1; + if (map->length >= FUSE4FS_FSB_TO_B(ff, 16)) + return 1; + + return 0; +} + static void op_iomap_begin(fuse_req_t req, fuse_ino_t fino, uint64_t dontcare, off_t pos, uint64_t count, uint32_t opflags) { @@ -6229,7 +6251,7 @@ static void op_iomap_begin(fuse_req_t req, fuse_ino_t fino, uint64_t dontcare, * Cache the mapping in the kernel so that we can reuse them for * subsequent IO. */ - if (ff->iomap_cache) { + if (fuse4fs_should_cache_iomap(ff, opflags, &read)) { ret = fuse_lowlevel_notify_iomap_upsert(ff->fuse, fino, ino, &read, NULL); if (ret) {