linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: David Howells <dhowells@redhat.com>
To: linux-cachefs@redhat.com
Cc: dhowells@redhat.com, Trond Myklebust <trondmy@hammerspace.com>,
	Anna Schumaker <anna.schumaker@netapp.com>,
	Steve French <sfrench@samba.org>,
	Dominique Martinet <asmadeus@codewreck.org>,
	Jeff Layton <jlayton@kernel.org>,
	Matthew Wilcox <willy@infradead.org>,
	Alexander Viro <viro@zeniv.linux.org.uk>,
	Omar Sandoval <osandov@osandov.com>,
	JeffleXu <jefflexu@linux.alibaba.com>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org,
	linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org,
	v9fs-developer@lists.sourceforge.net,
	linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH v3 15/68] fscache: Provide and use cache methods to lookup/create/free a volume
Date: Thu, 16 Dec 2021 16:09:57 +0000	[thread overview]
Message-ID: <163967099771.1823006.1455197910571061835.stgit@warthog.procyon.org.uk> (raw)
In-Reply-To: <163967073889.1823006.12237147297060239168.stgit@warthog.procyon.org.uk>

Add cache methods to lookup, create and remove a volume.

Looking up or creating the volume requires the cache pinning for access;
freeing the volume requires the volume pinning for access.  The
->acquire_volume() method is used to ask the cache backend to lookup and,
if necessary, create a volume; the ->free_volume() method is used to free
the resources for a volume.

Signed-off-by: David Howells <dhowells@redhat.com>
cc: linux-cachefs@redhat.com
Link: https://lore.kernel.org/r/163819597821.215744.5225318658134989949.stgit@warthog.procyon.org.uk/ # v1
Link: https://lore.kernel.org/r/163906898645.143852.8537799955945956818.stgit@warthog.procyon.org.uk/ # v2
---

 fs/fscache/volume.c            |   89 +++++++++++++++++++++++++++++++++++++++-
 include/linux/fscache-cache.h  |    7 +++
 include/trace/events/fscache.h |   11 ++++-
 3 files changed, 103 insertions(+), 4 deletions(-)

diff --git a/fs/fscache/volume.c b/fs/fscache/volume.c
index 20497f0f10bb..e1a8e92a6adb 100644
--- a/fs/fscache/volume.c
+++ b/fs/fscache/volume.c
@@ -15,6 +15,8 @@ static struct hlist_bl_head fscache_volume_hash[1 << fscache_volume_hash_shift];
 static atomic_t fscache_volume_debug_id;
 static LIST_HEAD(fscache_volumes);
 
+static void fscache_create_volume_work(struct work_struct *work);
+
 struct fscache_volume *fscache_get_volume(struct fscache_volume *volume,
 					  enum fscache_volume_trace where)
 {
@@ -213,7 +215,7 @@ static struct fscache_volume *fscache_alloc_volume(const char *volume_key,
 
 	volume->cache = cache;
 	INIT_LIST_HEAD(&volume->proc_link);
-	INIT_WORK(&volume->work, NULL /* PLACEHOLDER */);
+	INIT_WORK(&volume->work, fscache_create_volume_work);
 	refcount_set(&volume->ref, 1);
 	spin_lock_init(&volume->lock);
 
@@ -249,6 +251,58 @@ static struct fscache_volume *fscache_alloc_volume(const char *volume_key,
 	return NULL;
 }
 
+/*
+ * Create a volume's representation on disk.  Have a volume ref and a cache
+ * access we have to release.
+ */
+static void fscache_create_volume_work(struct work_struct *work)
+{
+	const struct fscache_cache_ops *ops;
+	struct fscache_volume *volume =
+		container_of(work, struct fscache_volume, work);
+
+	fscache_see_volume(volume, fscache_volume_see_create_work);
+
+	ops = volume->cache->ops;
+	if (ops->acquire_volume)
+		ops->acquire_volume(volume);
+	fscache_end_cache_access(volume->cache,
+				 fscache_access_acquire_volume_end);
+
+	clear_bit_unlock(FSCACHE_VOLUME_CREATING, &volume->flags);
+	wake_up_bit(&volume->flags, FSCACHE_VOLUME_CREATING);
+	fscache_put_volume(volume, fscache_volume_put_create_work);
+}
+
+/*
+ * Dispatch a worker thread to create a volume's representation on disk.
+ */
+void fscache_create_volume(struct fscache_volume *volume, bool wait)
+{
+	if (test_and_set_bit(FSCACHE_VOLUME_CREATING, &volume->flags))
+		goto maybe_wait;
+	if (volume->cache_priv)
+		goto no_wait; /* We raced */
+	if (!fscache_begin_cache_access(volume->cache,
+					fscache_access_acquire_volume))
+		goto no_wait;
+
+	fscache_get_volume(volume, fscache_volume_get_create_work);
+	if (!schedule_work(&volume->work))
+		fscache_put_volume(volume, fscache_volume_put_create_work);
+
+maybe_wait:
+	if (wait) {
+		fscache_see_volume(volume, fscache_volume_wait_create_work);
+		wait_on_bit(&volume->flags, FSCACHE_VOLUME_CREATING,
+			    TASK_UNINTERRUPTIBLE);
+	}
+	return;
+no_wait:
+	clear_bit_unlock(FSCACHE_VOLUME_CREATING, &volume->flags);
+	wake_up_bit(&volume->flags, FSCACHE_VOLUME_CREATING);
+}
+
 /*
  * Acquire a volume representation cookie and link it to a (proposed) cache.
  */
@@ -269,7 +323,7 @@ struct fscache_volume *__fscache_acquire_volume(const char *volume_key,
 		return ERR_PTR(-EBUSY);
 	}
 
-	// PLACEHOLDER: Create the volume if we have a cache available
+	fscache_create_volume(volume, false);
 	return volume;
 }
 EXPORT_SYMBOL(__fscache_acquire_volume);
@@ -316,7 +370,12 @@ static void fscache_free_volume(struct fscache_volume *volume)
 	struct fscache_cache *cache = volume->cache;
 
 	if (volume->cache_priv) {
-		// PLACEHOLDER: Detach any attached cache
+		__fscache_begin_volume_access(volume, NULL,
+					      fscache_access_relinquish_volume);
+		if (volume->cache_priv)
+			cache->ops->free_volume(volume);
+		fscache_end_volume_access(volume, NULL,
+					  fscache_access_relinquish_volume_end);
 	}
 
 	down_write(&fscache_addremove_sem);
@@ -369,6 +428,30 @@ void __fscache_relinquish_volume(struct fscache_volume *volume,
 }
 EXPORT_SYMBOL(__fscache_relinquish_volume);
 
+/**
+ * fscache_withdraw_volume - Withdraw a volume from being cached
+ * @volume: Volume cookie
+ *
+ * Withdraw a cache volume from service, waiting for all accesses to complete
+ * before returning.
+ */
+void fscache_withdraw_volume(struct fscache_volume *volume)
+{
+	int n_accesses;
+
+	_debug("withdraw V=%x", volume->debug_id);
+
+	/* Allow wakeups on dec-to-0 */
+	n_accesses = atomic_dec_return(&volume->n_accesses);
+	trace_fscache_access_volume(volume->debug_id, 0,
+				    refcount_read(&volume->ref),
+				    n_accesses, fscache_access_cache_unpin);
+
+	wait_var_event(&volume->n_accesses,
+		       atomic_read(&volume->n_accesses) == 0);
+}
+EXPORT_SYMBOL(fscache_withdraw_volume);
+
 #ifdef CONFIG_PROC_FS
 /*
  * Generate a list of volumes in /proc/fs/fscache/volumes
diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h
index f78add6e7823..a10b66ca3544 100644
--- a/include/linux/fscache-cache.h
+++ b/include/linux/fscache-cache.h
@@ -51,6 +51,12 @@ struct fscache_cache {
 struct fscache_cache_ops {
 	/* name of cache provider */
 	const char *name;
+
+	/* Acquire a volume */
+	void (*acquire_volume)(struct fscache_volume *volume);
+
+	/* Free the cache's data attached to a volume */
+	void (*free_volume)(struct fscache_volume *volume);
 };
 
 extern struct workqueue_struct *fscache_wq;
@@ -65,6 +71,7 @@ extern int fscache_add_cache(struct fscache_cache *cache,
 			     const struct fscache_cache_ops *ops,
 			     void *cache_priv);
 extern void fscache_withdraw_cache(struct fscache_cache *cache);
+extern void fscache_withdraw_volume(struct fscache_volume *volume);
 
 extern void fscache_end_volume_access(struct fscache_volume *volume,
 				      struct fscache_cookie *cookie,
diff --git a/include/trace/events/fscache.h b/include/trace/events/fscache.h
index b1a962adfd16..1d576bd8112e 100644
--- a/include/trace/events/fscache.h
+++ b/include/trace/events/fscache.h
@@ -64,8 +64,12 @@ enum fscache_cookie_trace {
 };
 
 enum fscache_access_trace {
+	fscache_access_acquire_volume,
+	fscache_access_acquire_volume_end,
 	fscache_access_cache_pin,
 	fscache_access_cache_unpin,
+	fscache_access_relinquish_volume,
+	fscache_access_relinquish_volume_end,
 	fscache_access_unlive,
 };
 
@@ -96,7 +100,8 @@ enum fscache_access_trace {
 	EM(fscache_volume_put_hash_collision,	"PUT hcoll")		\
 	EM(fscache_volume_put_relinquish,	"PUT relnq")		\
 	EM(fscache_volume_see_create_work,	"SEE creat")		\
-	E_(fscache_volume_see_hash_wake,	"SEE hwake")
+	EM(fscache_volume_see_hash_wake,	"SEE hwake")		\
+	E_(fscache_volume_wait_create_work,	"WAIT crea")
 
 #define fscache_cookie_traces						\
 	EM(fscache_cookie_collision,		"*COLLIDE*")		\
@@ -115,8 +120,12 @@ enum fscache_access_trace {
 	E_(fscache_cookie_see_work,		"-   work ")
 
 #define fscache_access_traces		\
+	EM(fscache_access_acquire_volume,	"BEGIN acq_vol")	\
+	EM(fscache_access_acquire_volume_end,	"END   acq_vol")	\
 	EM(fscache_access_cache_pin,		"PIN   cache  ")	\
 	EM(fscache_access_cache_unpin,		"UNPIN cache  ")	\
+	EM(fscache_access_relinquish_volume,	"BEGIN rlq_vol")	\
+	EM(fscache_access_relinquish_volume_end,"END   rlq_vol")	\
 	E_(fscache_access_unlive,		"END   unlive ")
 
 /*



  parent reply	other threads:[~2021-12-16 16:10 UTC|newest]

Thread overview: 84+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-16 16:05 [PATCH v3 00/68] fscache, cachefiles: Rewrite David Howells
2021-12-16 16:05 ` [PATCH v3 01/68] fscache, cachefiles: Disable configuration David Howells
2021-12-16 16:06 ` [PATCH v3 02/68] cachefiles: Delete the cachefiles driver pending rewrite David Howells
2021-12-16 16:06 ` [PATCH v3 03/68] fscache: Remove the contents of the fscache driver, " David Howells
2021-12-16 16:06 ` [PATCH v3 04/68] netfs: Display the netfs inode number in the netfs_read tracepoint David Howells
2021-12-16 16:06 ` [PATCH v3 05/68] netfs: Pass a flag to ->prepare_write() to say if there's no alloc'd space David Howells
2021-12-16 16:06 ` [PATCH v3 06/68] fscache: Introduce new driver David Howells
2021-12-16 16:07 ` [PATCH v3 07/68] fscache: Implement a hash function David Howells
2021-12-16 16:07 ` [PATCH v3 08/68] fscache: Implement cache registration David Howells
2021-12-16 16:07 ` [PATCH v3 09/68] fscache: Implement volume registration David Howells
2021-12-16 16:08 ` [PATCH v3 10/68] fscache: Implement cookie registration David Howells
2021-12-16 16:08 ` [PATCH v3 11/68] fscache: Implement cache-level access helpers David Howells
2021-12-16 16:09 ` [PATCH v3 12/68] fscache: Implement volume-level " David Howells
2021-12-16 16:09 ` [PATCH v3 13/68] fscache: Implement cookie-level " David Howells
2021-12-16 16:09 ` [PATCH v3 14/68] fscache: Implement functions add/remove a cache David Howells
2021-12-16 16:09 ` David Howells [this message]
2021-12-16 16:10 ` [PATCH v3 16/68] fscache: Add a function for a cache backend to note an I/O error David Howells
2021-12-16 16:10 ` [PATCH v3 17/68] fscache: Implement simple cookie state machine David Howells
2021-12-17 19:07   ` Jeff Layton
2021-12-17 19:45   ` David Howells
2021-12-16 16:11 ` [PATCH v3 18/68] fscache: Implement cookie user counting and resource pinning David Howells
2021-12-17 19:42   ` Jeff Layton
2021-12-17 20:43   ` David Howells
2021-12-16 16:11 ` [PATCH v3 19/68] fscache: Implement cookie invalidation David Howells
2021-12-16 16:11 ` [PATCH v3 20/68] fscache: Provide a means to begin an operation David Howells
2021-12-16 16:11 ` [PATCH v3 21/68] fscache: Count data storage objects in a cache David Howells
2021-12-16 16:12 ` [PATCH v3 22/68] fscache: Provide read/write stat counters for the cache David Howells
2021-12-16 16:12 ` [PATCH v3 23/68] fscache: Provide a function to let the netfs update its coherency data David Howells
2021-12-16 16:13 ` [PATCH v3 24/68] netfs: Pass more information on how to deal with a hole in the cache David Howells
2021-12-16 16:13 ` [PATCH v3 25/68] fscache: Implement raw I/O interface David Howells
2021-12-16 16:13 ` [PATCH v3 26/68] fscache: Implement higher-level write " David Howells
2021-12-16 16:14 ` [PATCH v3 27/68] vfs, fscache: Implement pinning of cache usage for writeback David Howells
2021-12-16 16:14 ` [PATCH v3 28/68] fscache: Provide a function to note the release of a page David Howells
2021-12-16 16:14 ` [PATCH v3 29/68] fscache: Provide a function to resize a cookie David Howells
2021-12-16 16:15 ` [PATCH v3 30/68] cachefiles: Introduce rewritten driver David Howells
2021-12-16 16:15 ` [PATCH v3 31/68] cachefiles: Define structs David Howells
2021-12-16 16:15 ` [PATCH v3 32/68] cachefiles: Add some error injection support David Howells
2021-12-16 16:15 ` [PATCH v3 33/68] cachefiles: Add a couple of tracepoints for logging errors David Howells
2021-12-16 16:16 ` [PATCH v3 34/68] cachefiles: Add cache error reporting macro David Howells
2021-12-16 16:16 ` [PATCH v3 35/68] cachefiles: Add security derivation David Howells
2021-12-16 16:16 ` [PATCH v3 36/68] cachefiles: Register a miscdev and parse commands over it David Howells
2021-12-16 16:16 ` [PATCH v3 37/68] cachefiles: Provide a function to check how much space there is David Howells
2021-12-16 16:16 ` [PATCH v3 38/68] vfs, cachefiles: Mark a backing file in use with an inode flag David Howells
2021-12-16 16:16 ` [PATCH v3 39/68] cachefiles: Implement a function to get/create a directory in the cache David Howells
2021-12-16 16:17 ` [PATCH v3 40/68] cachefiles: Implement cache registration and withdrawal David Howells
2021-12-16 16:17 ` [PATCH v3 41/68] cachefiles: Implement volume support David Howells
2021-12-16 16:17 ` [PATCH v3 42/68] cachefiles: Add tracepoints for calls to the VFS David Howells
2021-12-16 16:18 ` [PATCH v3 43/68] cachefiles: Implement object lifecycle funcs David Howells
2021-12-16 16:18 ` [PATCH v3 44/68] cachefiles: Implement key to filename encoding David Howells
2021-12-16 16:18 ` [PATCH v3 45/68] cachefiles: Implement metadata/coherency data storage in xattrs David Howells
2021-12-16 16:19 ` [PATCH v3 46/68] cachefiles: Mark a backing file in use with an inode flag David Howells
2021-12-16 16:19 ` [PATCH v3 47/68] cachefiles: Implement culling daemon commands David Howells
2021-12-16 16:19 ` [PATCH v3 48/68] cachefiles: Implement backing file wrangling David Howells
2021-12-16 16:20 ` [PATCH v3 49/68] cachefiles: Implement begin and end I/O operation David Howells
2021-12-16 16:20 ` [PATCH v3 50/68] cachefiles: Implement cookie resize for truncate David Howells
2021-12-16 16:20 ` [PATCH v3 51/68] cachefiles: Implement the I/O routines David Howells
2021-12-16 16:20 ` [PATCH v3 52/68] fscache, cachefiles: Store the volume coherency data David Howells
2021-12-16 16:20 ` [PATCH v3 53/68] cachefiles: Allow cachefiles to actually function David Howells
2021-12-16 16:21 ` [PATCH v3 54/68] fscache, cachefiles: Display stats of no-space events David Howells
2021-12-16 16:21 ` [PATCH v3 55/68] fscache, cachefiles: Display stat of culling events David Howells
2021-12-16 16:21 ` [PATCH v3 56/68] afs: Handle len being extending over page end in write_begin/write_end David Howells
2021-12-16 16:31   ` Linus Torvalds
2021-12-16 19:28     ` Matthew Wilcox
2021-12-16 19:46       ` Linus Torvalds
2021-12-16 20:20         ` Matthew Wilcox
2021-12-16 21:17       ` David Howells
2021-12-16 16:47   ` David Howells
2021-12-16 16:22 ` [PATCH v3 57/68] afs: Fix afs_write_end() to handle len > page size David Howells
2021-12-16 16:27   ` Linus Torvalds
2021-12-16 16:22 ` [PATCH v3 58/68] afs: Convert afs to use the new fscache API David Howells
2021-12-16 16:22 ` [PATCH v3 59/68] afs: Copy local writes to the cache when writing to the server David Howells
2021-12-16 16:22 ` [PATCH v3 60/68] afs: Skip truncation on the server of data we haven't written yet David Howells
2021-12-16 16:23 ` [PATCH v3 61/68] 9p: Use fscache indexing rewrite and reenable caching David Howells
2021-12-16 16:23 ` [PATCH v3 62/68] 9p: Copy local writes to the cache when writing to the server David Howells
2021-12-16 16:23 ` [PATCH v3 63/68] nfs: Convert to new fscache volume/cookie API David Howells
2021-12-17 12:53   ` David Wysochanski
2021-12-17 13:21   ` David Howells
2021-12-17 13:35     ` David Wysochanski
2021-12-16 16:24 ` [PATCH v3 64/68] nfs: Implement cache I/O by accessing the cache directly David Howells
2021-12-16 16:24 ` [PATCH v3 65/68] cifs: Support fscache indexing rewrite (untested) David Howells
2021-12-16 16:24 ` [PATCH v3 66/68] ceph: conversion to new fscache API David Howells
2021-12-16 16:25 ` [PATCH v3 67/68] ceph: add fscache writeback support David Howells
2021-12-16 16:25 ` [PATCH v3 68/68] fscache: Rewrite documentation David Howells
2021-12-17 20:13 ` [PATCH v3 00/68] fscache, cachefiles: Rewrite Jeff Layton

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=163967099771.1823006.1455197910571061835.stgit@warthog.procyon.org.uk \
    --to=dhowells@redhat.com \
    --cc=anna.schumaker@netapp.com \
    --cc=asmadeus@codewreck.org \
    --cc=ceph-devel@vger.kernel.org \
    --cc=jefflexu@linux.alibaba.com \
    --cc=jlayton@kernel.org \
    --cc=linux-afs@lists.infradead.org \
    --cc=linux-cachefs@redhat.com \
    --cc=linux-cifs@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-nfs@vger.kernel.org \
    --cc=osandov@osandov.com \
    --cc=sfrench@samba.org \
    --cc=torvalds@linux-foundation.org \
    --cc=trondmy@hammerspace.com \
    --cc=v9fs-developer@lists.sourceforge.net \
    --cc=viro@zeniv.linux.org.uk \
    --cc=willy@infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).