netfs, afs: Implement helpers for new write code
authorDavid Howells <dhowells@redhat.com>
Mon, 18 Mar 2024 20:25:53 +0000 (20:25 +0000)
committerDavid Howells <dhowells@redhat.com>
Wed, 1 May 2024 17:07:36 +0000 (18:07 +0100)
Implement the helpers for the new write code in afs.  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 <dhowells@redhat.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
cc: netfs@lists.linux.dev
cc: linux-fsdevel@vger.kernel.org

fs/afs/file.c
fs/afs/internal.h
fs/afs/write.c

index dfd8f60f5e1fdba3959b4fb0fbcfed5b8ff2a346..db9ebae84fa287bb83434ed1070d1b03e8833788 100644 (file)
@@ -400,6 +400,9 @@ const struct netfs_request_ops afs_req_ops = {
        .update_i_size          = afs_update_i_size,
        .invalidate_cache       = afs_netfs_invalidate_cache,
        .create_write_requests  = afs_create_write_requests,
+       .begin_writeback        = afs_begin_writeback,
+       .prepare_write          = afs_prepare_write,
+       .issue_write            = afs_issue_write,
 };
 
 static void afs_add_open_mmap(struct afs_vnode *vnode)
index b93aa026daa432b514a48e12bbdc5066d8d8429d..dcf0ae0323d3667de0c4a82f8768504b05379026 100644 (file)
@@ -1598,6 +1598,9 @@ extern int afs_check_volume_status(struct afs_volume *, struct afs_operation *);
 /*
  * write.c
  */
+void afs_prepare_write(struct netfs_io_subrequest *subreq);
+void afs_issue_write(struct netfs_io_subrequest *subreq);
+void afs_begin_writeback(struct netfs_io_request *wreq);
 extern int afs_writepages(struct address_space *, struct writeback_control *);
 extern int afs_fsync(struct file *, loff_t, loff_t, int);
 extern vm_fault_t afs_page_mkwrite(struct vm_fault *vmf);
index 1bc26466eb727bca70e4bedbf17f0f1908265711..34595f482718acd86a243561929765e2ba468015 100644 (file)
@@ -194,6 +194,60 @@ void afs_create_write_requests(struct netfs_io_request *wreq, loff_t start, size
                netfs_queue_write_request(subreq);
 }
 
+/*
+ * Writeback calls this when it finds a folio that needs uploading.  This isn't
+ * called if writeback only has copy-to-cache to deal with.
+ */
+void afs_begin_writeback(struct netfs_io_request *wreq)
+{
+       wreq->io_streams[0].avail = true;
+}
+
+/*
+ * Prepare a subrequest to write to the server.  This sets the max_len
+ * parameter.
+ */
+void afs_prepare_write(struct netfs_io_subrequest *subreq)
+{
+       //if (test_bit(NETFS_SREQ_RETRYING, &subreq->flags))
+       //      subreq->max_len = 512 * 1024;
+       //else
+       subreq->max_len = 256 * 1024 * 1024;
+}
+
+/*
+ * Issue a subrequest to write to the server.
+ */
+static void afs_issue_write_worker(struct work_struct *work)
+{
+       struct netfs_io_subrequest *subreq = container_of(work, struct netfs_io_subrequest, work);
+       struct afs_vnode *vnode = AFS_FS_I(subreq->rreq->inode);
+       ssize_t ret;
+
+       _enter("%x[%x],%zx",
+              subreq->rreq->debug_id, subreq->debug_index, subreq->io_iter.count);
+
+#if 0 // Error injection
+       if (subreq->debug_index == 3)
+               return netfs_write_subrequest_terminated(subreq, -ENOANO, false);
+
+       if (!test_bit(NETFS_SREQ_RETRYING, &subreq->flags)) {
+               set_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags);
+               return netfs_write_subrequest_terminated(subreq, -EAGAIN, false);
+       }
+#endif
+
+       ret = afs_store_data(vnode, &subreq->io_iter, subreq->start);
+       netfs_write_subrequest_terminated(subreq, ret < 0 ? ret : subreq->len, false);
+}
+
+void afs_issue_write(struct netfs_io_subrequest *subreq)
+{
+       subreq->work.func = afs_issue_write_worker;
+       if (!queue_work(system_unbound_wq, &subreq->work))
+               WARN_ON_ONCE(1);
+}
+
 /*
  * write some of the pending data back to the server
  */