Implement the helpers for the new write code in cachefiles.  There's now an
optional ->prepare_write() that allows the filesystem to set the parameters
for the next write, such as maximum size and maximum segment count, and an
->issue_write() that is called to initiate an (asynchronous) write
operation.

Signed-off-by: David Howells <dhowe...@redhat.com>
cc: Jeff Layton <jlay...@kernel.org>
cc: ne...@lists.linux.dev
cc: linux-erofs@lists.ozlabs.org
cc: linux-fsde...@vger.kernel.org
---
 fs/cachefiles/io.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 73 insertions(+)

diff --git a/fs/cachefiles/io.c b/fs/cachefiles/io.c
index 5ba5c7814fe4..437b24b0fd1c 100644
--- a/fs/cachefiles/io.c
+++ b/fs/cachefiles/io.c
@@ -622,6 +622,77 @@ static int cachefiles_prepare_write(struct 
netfs_cache_resources *cres,
        return ret;
 }
 
+static void cachefiles_prepare_write_subreq(struct netfs_io_subrequest *subreq)
+{
+       struct netfs_io_request *wreq = subreq->rreq;
+       struct netfs_cache_resources *cres = &wreq->cache_resources;
+
+       _enter("W=%x[%x] %llx", wreq->debug_id, subreq->debug_index, 
subreq->start);
+
+       subreq->max_len = ULONG_MAX;
+       subreq->max_nr_segs = BIO_MAX_VECS;
+
+       if (!cachefiles_cres_file(cres)) {
+               if (!fscache_wait_for_operation(cres, FSCACHE_WANT_WRITE))
+                       return netfs_prepare_write_failed(subreq);
+               if (!cachefiles_cres_file(cres))
+                       return netfs_prepare_write_failed(subreq);
+       }
+}
+
+static void cachefiles_issue_write(struct netfs_io_subrequest *subreq)
+{
+       struct netfs_io_request *wreq = subreq->rreq;
+       struct netfs_cache_resources *cres = &wreq->cache_resources;
+       struct cachefiles_object *object = cachefiles_cres_object(cres);
+       struct cachefiles_cache *cache = object->volume->cache;
+       const struct cred *saved_cred;
+       size_t off, pre, post, len = subreq->len;
+       loff_t start = subreq->start;
+       int ret;
+
+       _enter("W=%x[%x] %llx-%llx",
+              wreq->debug_id, subreq->debug_index, start, start + len - 1);
+
+       /* We need to start on the cache granularity boundary */
+       off = start & (CACHEFILES_DIO_BLOCK_SIZE - 1);
+       if (off) {
+               pre = CACHEFILES_DIO_BLOCK_SIZE - off;
+               if (pre >= len) {
+                       netfs_write_subrequest_terminated(subreq, len, false);
+                       return;
+               }
+               subreq->transferred += pre;
+               start += pre;
+               len -= pre;
+               iov_iter_advance(&subreq->io_iter, pre);
+       }
+
+       /* We also need to end on the cache granularity boundary */
+       post = len & (CACHEFILES_DIO_BLOCK_SIZE - 1);
+       if (post) {
+               len -= post;
+               if (len == 0) {
+                       netfs_write_subrequest_terminated(subreq, post, false);
+                       return;
+               }
+               iov_iter_truncate(&subreq->io_iter, len);
+       }
+
+       cachefiles_begin_secure(cache, &saved_cred);
+       ret = __cachefiles_prepare_write(object, cachefiles_cres_file(cres),
+                                        &start, &len, len, true);
+       cachefiles_end_secure(cache, saved_cred);
+       if (ret < 0) {
+               netfs_write_subrequest_terminated(subreq, ret, false);
+               return;
+       }
+
+       cachefiles_write(&subreq->rreq->cache_resources,
+                        subreq->start, &subreq->io_iter,
+                        netfs_write_subrequest_terminated, subreq);
+}
+
 /*
  * Clean up an operation.
  */
@@ -638,8 +709,10 @@ static const struct netfs_cache_ops 
cachefiles_netfs_cache_ops = {
        .end_operation          = cachefiles_end_operation,
        .read                   = cachefiles_read,
        .write                  = cachefiles_write,
+       .issue_write            = cachefiles_issue_write,
        .prepare_read           = cachefiles_prepare_read,
        .prepare_write          = cachefiles_prepare_write,
+       .prepare_write_subreq   = cachefiles_prepare_write_subreq,
        .prepare_ondemand_read  = cachefiles_prepare_ondemand_read,
        .query_occupancy        = cachefiles_query_occupancy,
 };

Reply via email to