diff --git a/src/io/uring/CancellableOperation.hxx b/src/io/uring/CancellableOperation.hxx
index 02fb8f097..9c6b81813 100644
--- a/src/io/uring/CancellableOperation.hxx
+++ b/src/io/uring/CancellableOperation.hxx
@@ -48,14 +48,19 @@ public:
 		new_operation.cancellable = this;
 	}
 
-	void OnUringCompletion(int res) noexcept {
+	void OnUringCompletion(int res, bool more) noexcept {
 		if (operation == nullptr)
 			return;
 
 		assert(operation->cancellable == this);
-		operation->cancellable = nullptr;
 
-		std::exchange(operation, nullptr)->OnUringCompletion(res);
+		if (more) {
+			operation->OnUringCompletion(res);
+		} else {
+			operation->cancellable = nullptr;
+
+			std::exchange(operation, nullptr)->OnUringCompletion(res);
+		}
 	}
 };
 
diff --git a/src/io/uring/Queue.cxx b/src/io/uring/Queue.cxx
index 2ce9f220e..066797354 100644
--- a/src/io/uring/Queue.cxx
+++ b/src/io/uring/Queue.cxx
@@ -57,9 +57,12 @@ Queue::DispatchOneCompletion(struct io_uring_cqe &cqe) noexcept
 	void *data = io_uring_cqe_get_data(&cqe);
 	if (data != nullptr) {
 		auto *c = (CancellableOperation *)data;
-		c->OnUringCompletion(cqe.res);
-		c->unlink();
-		delete c;
+		const bool more = cqe.flags & IORING_CQE_F_MORE;
+		c->OnUringCompletion(cqe.res, more);
+		if (!more) {
+			c->unlink();
+			delete c;
+		}
 	}
 
 	ring.SeenCompletion(cqe);