@@ -171,6 +171,48 @@ void fscache_put_cache(struct fscache_cache *cache,
}
EXPORT_SYMBOL(fscache_put_cache);
+/**
+ * fscache_add_cache - Declare a cache as being open for business
+ * @cache: The record describing the cache
+ * @ops: Table of cache operations to use
+ * @cache_priv: Private data for the cache record
+ *
+ * Add a cache to the system, making it available for netfs's to use.
+ *
+ * See Documentation/filesystems/caching/backend-api.rst for a complete
+ * description.
+ */
+int fscache_add_cache(struct fscache_cache *cache,
+ const struct fscache_cache_ops *ops,
+ void *cache_priv)
+{
+ int n_accesses;
+
+ _enter("{%s,%s}", ops->name, cache->name);
+
+ BUG_ON(fscache_cache_state(cache) != FSCACHE_CACHE_IS_PREPARING);
+
+ /* Get a ref on the cache cookie and keep its n_accesses counter raised
+ * by 1 to prevent wakeups from transitioning it to 0 until we're
+ * withdrawing caching services from it.
+ */
+ n_accesses = atomic_inc_return(&cache->n_accesses);
+ trace_fscache_access_cache(cache->debug_id, refcount_read(&cache->ref),
+ n_accesses, fscache_access_cache_pin);
+
+ down_write(&fscache_addremove_sem);
+
+ cache->ops = ops;
+ cache->cache_priv = cache_priv;
+ fscache_set_cache_state(cache, FSCACHE_CACHE_IS_ACTIVE);
+
+ up_write(&fscache_addremove_sem);
+ pr_notice("Cache \"%s\" added (type %s)\n", cache->name, ops->name);
+ _leave(" = 0 [%s]", cache->name);
+ return 0;
+}
+EXPORT_SYMBOL(fscache_add_cache);
+
/*
* Get an increment on a cache's access counter if the cache is live to prevent
* it from going away whilst we're accessing it.
@@ -208,6 +250,31 @@ void fscache_end_cache_access(struct fscache_cache *cache, enum fscache_access_t
wake_up_var(&cache->n_accesses);
}
+/**
+ * fscache_withdraw_cache - Withdraw a cache from the active service
+ * @cache: The cache cookie
+ *
+ * Begin the process of withdrawing a cache from service.
+ */
+void fscache_withdraw_cache(struct fscache_cache *cache)
+{
+ int n_accesses;
+
+ pr_notice("Withdrawing cache \"%s\" (%u objs)\n",
+ cache->name, atomic_read(&cache->object_count));
+
+ fscache_set_cache_state(cache, FSCACHE_CACHE_IS_WITHDRAWN);
+
+ /* Allow wakeups on dec-to-0 */
+ n_accesses = atomic_dec_return(&cache->n_accesses);
+ trace_fscache_access_cache(cache->debug_id, refcount_read(&cache->ref),
+ n_accesses, fscache_access_cache_unpin);
+
+ wait_var_event(&cache->n_accesses,
+ atomic_read(&cache->n_accesses) == 0);
+}
+EXPORT_SYMBOL(fscache_withdraw_cache);
+
#ifdef CONFIG_PROC_FS
static const char fscache_cache_states[NR__FSCACHE_CACHE_STATE] = "-PAEW";
@@ -17,6 +17,7 @@
#include <linux/fscache.h>
struct fscache_cache;
+struct fscache_cache_ops;
enum fscache_cache_trace;
enum fscache_cookie_trace;
enum fscache_access_trace;
@@ -34,6 +35,7 @@ enum fscache_cache_state {
* Cache cookie.
*/
struct fscache_cache {
+ const struct fscache_cache_ops *ops;
struct list_head cache_link; /* Link in cache list */
void *cache_priv; /* Private cache data (or NULL) */
refcount_t ref;
@@ -45,6 +47,14 @@ struct fscache_cache {
char *name;
};
+/*
+ * cache operations
+ */
+struct fscache_cache_ops {
+ /* name of cache provider */
+ const char *name;
+};
+
static inline enum fscache_cache_state fscache_cache_state(const struct fscache_cache *cache)
{
return smp_load_acquire(&cache->state);
@@ -74,8 +84,12 @@ static inline bool fscache_set_cache_state_maybe(struct fscache_cache *cache,
*/
extern struct rw_semaphore fscache_addremove_sem;
extern struct fscache_cache *fscache_acquire_cache(const char *name);
+extern int fscache_add_cache(struct fscache_cache *cache,
+ const struct fscache_cache_ops *ops,
+ void *cache_priv);
extern void fscache_put_cache(struct fscache_cache *cache,
enum fscache_cache_trace where);
+extern void fscache_withdraw_cache(struct fscache_cache *cache);
extern void fscache_end_volume_access(struct fscache_volume *volume,
enum fscache_access_trace why);
@@ -24,7 +24,9 @@ enum fscache_cache_trace {
fscache_cache_get_acquire,
fscache_cache_new_acquire,
fscache_cache_put_alloc_volume,
+ fscache_cache_put_cache,
fscache_cache_put_volume,
+ fscache_cache_put_withdraw,
};
enum fscache_volume_trace {
@@ -76,7 +78,9 @@ enum fscache_access_trace {
EM(fscache_cache_get_acquire, "GET acq ") \
EM(fscache_cache_new_acquire, "NEW acq ") \
EM(fscache_cache_put_alloc_volume, "PUT alvol") \
- E_(fscache_cache_put_volume, "PUT vol ")
+ EM(fscache_cache_put_cache, "PUT cache") \
+ EM(fscache_cache_put_volume, "PUT vol ") \
+ E_(fscache_cache_put_withdraw, "PUT withd")
#define fscache_volume_traces \
EM(fscache_volume_collision, "*COLLIDE*") \
Implement functions to allow the cache backend to add or remove a cache. Signed-off-by: David Howells <dhowells@redhat.com>cc: linux-cachefs@redhat.com --- fs/fscache/cache.c | 67 ++++++++++++++++++++++++++++++++++++++++ include/linux/fscache-cache.h | 14 ++++++++ include/trace/events/fscache.h | 6 +++- 3 files changed, 86 insertions(+), 1 deletion(-)