#include <linux/slab.h>
 #include <linux/file.h>
 #include <linux/uio.h>
+#include <linux/bio.h>
 #include <linux/falloc.h>
 #include <linux/sched/mm.h>
 #include <trace/events/fscache.h>
        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.
  */
        .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,
 };