diff --git a/src/lib/nfs/Connection.cxx b/src/lib/nfs/Connection.cxx
index 949ba7bf3..3c5ca5d09 100644
--- a/src/lib/nfs/Connection.cxx
+++ b/src/lib/nfs/Connection.cxx
@@ -91,14 +91,18 @@ NfsConnection::CancellableCallback::Read(nfs_context *ctx, struct nfsfh *fh,
 }
 
 inline void
-NfsConnection::CancellableCallback::CancelAndScheduleClose(struct nfsfh *fh) noexcept
+NfsConnection::CancellableCallback::CancelAndScheduleClose(struct nfsfh *fh,
+							   DisposablePointer &&_dispose_value) noexcept
 {
 	assert(connection.GetEventLoop().IsInside());
 	assert(!open);
 	assert(close_fh == nullptr);
+	assert(!dispose_value);
 	assert(fh != nullptr);
 
 	close_fh = fh;
+	dispose_value = std::move(_dispose_value);
+
 	Cancel();
 }
 
@@ -371,10 +375,11 @@ NfsConnection::Close(struct nfsfh *fh) noexcept
 }
 
 void
-NfsConnection::CancelAndClose(struct nfsfh *fh, NfsCallback &callback) noexcept
+NfsConnection::CancelAndClose(struct nfsfh *fh, DisposablePointer dispose_value,
+			      NfsCallback &callback) noexcept
 {
 	CancellableCallback &cancel = callbacks.Get(callback);
-	cancel.CancelAndScheduleClose(fh);
+	cancel.CancelAndScheduleClose(fh, std::move(dispose_value));
 }
 
 void
diff --git a/src/lib/nfs/Connection.hxx b/src/lib/nfs/Connection.hxx
index e01b1e206..3c2dbfbb3 100644
--- a/src/lib/nfs/Connection.hxx
+++ b/src/lib/nfs/Connection.hxx
@@ -7,6 +7,7 @@
 #include "event/SocketEvent.hxx"
 #include "event/CoarseTimerEvent.hxx"
 #include "event/DeferEvent.hxx"
+#include "util/DisposablePointer.hxx"
 #include "util/IntrusiveList.hxx"
 
 #include <cstdint>
@@ -41,6 +42,12 @@ class NfsConnection {
 		 */
 		struct nfsfh *close_fh;
 
+		/**
+		 * An arbitrary value that will be disposed of after
+		 * cancellation completes.
+		 */
+		DisposablePointer dispose_value;
+
 	public:
 		explicit CancellableCallback(NfsCallback &_callback,
 					     NfsConnection &_connection,
@@ -61,7 +68,8 @@ class NfsConnection {
 		 * Cancel the operation and schedule a call to
 		 * nfs_close_async() with the given file handle.
 		 */
-		void CancelAndScheduleClose(struct nfsfh *fh) noexcept;
+		void CancelAndScheduleClose(struct nfsfh *fh,
+					    DisposablePointer &&_dispose_value) noexcept;
 
 		/**
 		 * Called by NfsConnection::DestroyContext() right
@@ -226,8 +234,12 @@ public:
 	/**
 	 * Like Cancel(), but also close the specified NFS file
 	 * handle.
+	 *
+	 * @param dispose_value an arbitrary value that will be
+	 * disposed of after cancellation completes
 	 */
-	void CancelAndClose(struct nfsfh *fh, NfsCallback &callback) noexcept;
+	void CancelAndClose(struct nfsfh *fh, DisposablePointer dispose_value,
+			    NfsCallback &callback) noexcept;
 
 protected:
 	virtual void OnNfsConnectionError(std::exception_ptr e) noexcept = 0;
diff --git a/src/lib/nfs/FileReader.cxx b/src/lib/nfs/FileReader.cxx
index 466491630..8e33b1a3d 100644
--- a/src/lib/nfs/FileReader.cxx
+++ b/src/lib/nfs/FileReader.cxx
@@ -59,7 +59,7 @@ NfsFileReader::CancelOrClose() noexcept
 	else if (state > State::OPEN)
 		/* one async operation in progress: cancel it and
 		   defer the nfs_close_async() call */
-		connection->CancelAndClose(fh, *this);
+		connection->CancelAndClose(fh, {}, *this);
 	else if (state > State::MOUNT)
 		/* we don't have a file handle yet - just cancel the
 		   async operation */