cachefiles: Implement begin and end I/O operation
authorDavid Howells <dhowells@redhat.com>
Thu, 21 Oct 2021 10:05:53 +0000 (11:05 +0100)
committerDavid Howells <dhowells@redhat.com>
Fri, 7 Jan 2022 13:42:44 +0000 (13:42 +0000)
Implement the methods for beginning and ending an I/O operation.

When called to begin an I/O operation, we are guaranteed that the cookie
has reached a certain stage (we're called by fscache after it has done a
suitable wait).

If a file is available, we paste a ref over into the cache resources for
the I/O routines to use.  This means that the object can be invalidated
whilst the I/O is ongoing without the need to synchronise as the file
pointer in the object is replaced, but the file pointer in the cache
resources is unaffected.

Ending the operation just requires ditching any refs we have and dropping
the access guarantee that fscache got for us on the cookie.

Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
cc: linux-cachefs@redhat.com
Link: https://lore.kernel.org/r/163819645033.215744.2199344081658268312.stgit@warthog.procyon.org.uk/
Link: https://lore.kernel.org/r/163906951916.143852.9531384743995679857.stgit@warthog.procyon.org.uk/
Link: https://lore.kernel.org/r/163967161222.1823006.4461476204800357263.stgit@warthog.procyon.org.uk/
Link: https://lore.kernel.org/r/164021559030.640689.3684291785218094142.stgit@warthog.procyon.org.uk/
fs/cachefiles/Makefile
fs/cachefiles/interface.c
fs/cachefiles/internal.h
fs/cachefiles/io.c [new file with mode: 0644]
include/trace/events/fscache.h

index cb7a6bcf51eb1188cc1f752f642a1996c7049e28..16d811f1a2faed8fe08baf98db6dfe752ee81de0 100644 (file)
@@ -7,6 +7,7 @@ cachefiles-y := \
        cache.o \
        daemon.o \
        interface.o \
+       io.o \
        key.o \
        main.o \
        namei.o \
index e47c52c3407127e881f57e526d16151d91ba20ae..ad9d311413ff44f7ef2d4d57648b7b5ffc990d4a 100644 (file)
@@ -362,5 +362,6 @@ const struct fscache_cache_ops cachefiles_cache_ops = {
        .lookup_cookie          = cachefiles_lookup_cookie,
        .withdraw_cookie        = cachefiles_withdraw_cookie,
        .invalidate_cookie      = cachefiles_invalidate_cookie,
+       .begin_operation        = cachefiles_begin_operation,
        .prepare_to_write       = cachefiles_prepare_to_write,
 };
index d7aae04edc61b4b962c35f2538dce9c4d2badcfc..d5868f5514d3a6dc310c490d460649cf40f7bf93 100644 (file)
@@ -105,6 +105,18 @@ struct cachefiles_cache {
 
 #include <trace/events/cachefiles.h>
 
+static inline
+struct file *cachefiles_cres_file(struct netfs_cache_resources *cres)
+{
+       return cres->cache_priv2;
+}
+
+static inline
+struct cachefiles_object *cachefiles_cres_object(struct netfs_cache_resources *cres)
+{
+       return fscache_cres_cookie(cres)->cache_priv;
+}
+
 /*
  * note change of state for daemon
  */
@@ -177,6 +189,12 @@ extern struct cachefiles_object *cachefiles_grab_object(struct cachefiles_object
 extern void cachefiles_put_object(struct cachefiles_object *object,
                                  enum cachefiles_obj_ref_trace why);
 
+/*
+ * io.c
+ */
+extern bool cachefiles_begin_operation(struct netfs_cache_resources *cres,
+                                      enum fscache_want_state want_state);
+
 /*
  * key.c
  */
diff --git a/fs/cachefiles/io.c b/fs/cachefiles/io.c
new file mode 100644 (file)
index 0000000..adeb9a4
--- /dev/null
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* kiocb-using read/write
+ *
+ * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ */
+
+#include <linux/mount.h>
+#include <linux/slab.h>
+#include <linux/file.h>
+#include <linux/uio.h>
+#include <linux/falloc.h>
+#include <linux/sched/mm.h>
+#include <trace/events/fscache.h>
+#include "internal.h"
+
+/*
+ * Clean up an operation.
+ */
+static void cachefiles_end_operation(struct netfs_cache_resources *cres)
+{
+       struct file *file = cachefiles_cres_file(cres);
+
+       if (file)
+               fput(file);
+       fscache_end_cookie_access(fscache_cres_cookie(cres), fscache_access_io_end);
+}
+
+static const struct netfs_cache_ops cachefiles_netfs_cache_ops = {
+       .end_operation          = cachefiles_end_operation,
+};
+
+/*
+ * Open the cache file when beginning a cache operation.
+ */
+bool cachefiles_begin_operation(struct netfs_cache_resources *cres,
+                               enum fscache_want_state want_state)
+{
+       struct cachefiles_object *object = cachefiles_cres_object(cres);
+
+       if (!cachefiles_cres_file(cres)) {
+               cres->ops = &cachefiles_netfs_cache_ops;
+               if (object->file) {
+                       spin_lock(&object->lock);
+                       if (!cres->cache_priv2 && object->file)
+                               cres->cache_priv2 = get_file(object->file);
+                       spin_unlock(&object->lock);
+               }
+       }
+
+       if (!cachefiles_cres_file(cres) && want_state != FSCACHE_WANT_PARAMS) {
+               pr_err("failed to get cres->file\n");
+               return false;
+       }
+
+       return true;
+}
index d9d830296ec3d7bc51c7bd6ee3b326db8d9eb63a..1594aefadeac776b214e1d33ba73e23170daf973 100644 (file)
@@ -78,6 +78,7 @@ enum fscache_access_trace {
        fscache_access_cache_unpin,
        fscache_access_invalidate_cookie,
        fscache_access_invalidate_cookie_end,
+       fscache_access_io_end,
        fscache_access_io_not_live,
        fscache_access_io_read,
        fscache_access_io_resize,
@@ -152,6 +153,7 @@ enum fscache_access_trace {
        EM(fscache_access_cache_unpin,          "UNPIN cache  ")        \
        EM(fscache_access_invalidate_cookie,    "BEGIN inval  ")        \
        EM(fscache_access_invalidate_cookie_end,"END   inval  ")        \
+       EM(fscache_access_io_end,               "END   io     ")        \
        EM(fscache_access_io_not_live,          "END   io_notl")        \
        EM(fscache_access_io_read,              "BEGIN io_read")        \
        EM(fscache_access_io_resize,            "BEGIN io_resz")        \