From 734c115ad3023c8b712bdc0c3f6ab6dc42b20176 Mon Sep 17 00:00:00 2001 From: Matej Kenda Date: Fri, 12 Jun 2026 11:06:57 +0200 Subject: [PATCH] fix: data loss on writes larger than the tape block size _unified_insert_new_request copies at most one cache block (the tape block size) but returned the full requested count, so the append loop in unified_write advanced past data that was never stored. Writes larger than the block size silently lost everything after the first block while reporting success. Latent with libfuse 2, which caps requests at 128 KiB, below the default 512 KiB block; reachable today through the I/O scheduler API and triggered by FUSE 3 request sizes. Return the number of bytes actually stored. A regression test (multi-block single writes of random data, content verified) accompanies the integration test suite. Fixes #591 --- src/iosched/unified.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/iosched/unified.c b/src/iosched/unified.c index f492e12f..71f9dcc1 100644 --- a/src/iosched/unified.c +++ b/src/iosched/unified.c @@ -1790,7 +1790,11 @@ ssize_t _unified_insert_new_request(const char *buf, off_t offset, size_t count, if (new_req->offset + new_req->count > dpr->file_size) dpr->file_size = new_req->offset + new_req->count; - return (ssize_t)count; + /* Only copy_count bytes were stored (one cache block at most); the + * caller's append loop must advance by that, not the full count, or + * everything past the first block of a larger-than-blocksize write is + * silently dropped. */ + return (ssize_t)copy_count; } /**