mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	fscache: Implement cache registration
Implement a register of caches and provide functions to manage it.
Two functions are provided for the cache backend to use:
 (1) Acquire a cache cookie:
	struct fscache_cache *fscache_acquire_cache(const char *name)
     This gets the cache cookie for a cache of the specified name and moves
     it to the preparation state.  If a nameless cache cookie exists, that
     will be given this name and used.
 (2) Relinquish a cache cookie:
	void fscache_relinquish_cache(struct fscache_cache *cache);
     This relinquishes a cache cookie, cleans it and makes it available if
     it's still referenced by a network filesystem.
Note that network filesystems don't deal with cache cookies directly, but
rather go straight to the volume registration.
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/163819587157.215744.13523139317322503286.stgit@warthog.procyon.org.uk/ # v1
Link: https://lore.kernel.org/r/163906889665.143852.10378009165231294456.stgit@warthog.procyon.org.uk/ # v2
Link: https://lore.kernel.org/r/163967085081.1823006.2218944206363626210.stgit@warthog.procyon.org.uk/ # v3
Link: https://lore.kernel.org/r/164021494847.640689.10109692261640524343.stgit@warthog.procyon.org.uk/ # v4
			
			
This commit is contained in:
		
							parent
							
								
									e8a07c9d22
								
							
						
					
					
						commit
						9549332df4
					
				
					 6 changed files with 389 additions and 0 deletions
				
			
		| 
						 | 
					@ -4,6 +4,7 @@
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fscache-y := \
 | 
					fscache-y := \
 | 
				
			||||||
 | 
						cache.o \
 | 
				
			||||||
	main.o
 | 
						main.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fscache-$(CONFIG_PROC_FS) += proc.o
 | 
					fscache-$(CONFIG_PROC_FS) += proc.o
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										274
									
								
								fs/fscache/cache.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										274
									
								
								fs/fscache/cache.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,274 @@
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			||||||
 | 
					/* FS-Cache cache handling
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved.
 | 
				
			||||||
 | 
					 * Written by David Howells (dhowells@redhat.com)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define FSCACHE_DEBUG_LEVEL CACHE
 | 
				
			||||||
 | 
					#include <linux/export.h>
 | 
				
			||||||
 | 
					#include <linux/slab.h>
 | 
				
			||||||
 | 
					#include "internal.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static LIST_HEAD(fscache_caches);
 | 
				
			||||||
 | 
					DECLARE_RWSEM(fscache_addremove_sem);
 | 
				
			||||||
 | 
					EXPORT_SYMBOL(fscache_addremove_sem);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static atomic_t fscache_cache_debug_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Allocate a cache cookie.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static struct fscache_cache *fscache_alloc_cache(const char *name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct fscache_cache *cache;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cache = kzalloc(sizeof(*cache), GFP_KERNEL);
 | 
				
			||||||
 | 
						if (cache) {
 | 
				
			||||||
 | 
							if (name) {
 | 
				
			||||||
 | 
								cache->name = kstrdup(name, GFP_KERNEL);
 | 
				
			||||||
 | 
								if (!cache->name) {
 | 
				
			||||||
 | 
									kfree(cache);
 | 
				
			||||||
 | 
									return NULL;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							refcount_set(&cache->ref, 1);
 | 
				
			||||||
 | 
							INIT_LIST_HEAD(&cache->cache_link);
 | 
				
			||||||
 | 
							cache->debug_id = atomic_inc_return(&fscache_cache_debug_id);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return cache;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool fscache_get_cache_maybe(struct fscache_cache *cache,
 | 
				
			||||||
 | 
									    enum fscache_cache_trace where)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						bool success;
 | 
				
			||||||
 | 
						int ref;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						success = __refcount_inc_not_zero(&cache->ref, &ref);
 | 
				
			||||||
 | 
						if (success)
 | 
				
			||||||
 | 
							trace_fscache_cache(cache->debug_id, ref + 1, where);
 | 
				
			||||||
 | 
						return success;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Look up a cache cookie.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct fscache_cache *fscache_lookup_cache(const char *name, bool is_cache)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct fscache_cache *candidate, *cache, *unnamed = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* firstly check for the existence of the cache under read lock */
 | 
				
			||||||
 | 
						down_read(&fscache_addremove_sem);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list_for_each_entry(cache, &fscache_caches, cache_link) {
 | 
				
			||||||
 | 
							if (cache->name && name && strcmp(cache->name, name) == 0 &&
 | 
				
			||||||
 | 
							    fscache_get_cache_maybe(cache, fscache_cache_get_acquire))
 | 
				
			||||||
 | 
								goto got_cache_r;
 | 
				
			||||||
 | 
							if (!cache->name && !name &&
 | 
				
			||||||
 | 
							    fscache_get_cache_maybe(cache, fscache_cache_get_acquire))
 | 
				
			||||||
 | 
								goto got_cache_r;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!name) {
 | 
				
			||||||
 | 
							list_for_each_entry(cache, &fscache_caches, cache_link) {
 | 
				
			||||||
 | 
								if (cache->name &&
 | 
				
			||||||
 | 
								    fscache_get_cache_maybe(cache, fscache_cache_get_acquire))
 | 
				
			||||||
 | 
									goto got_cache_r;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						up_read(&fscache_addremove_sem);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* the cache does not exist - create a candidate */
 | 
				
			||||||
 | 
						candidate = fscache_alloc_cache(name);
 | 
				
			||||||
 | 
						if (!candidate)
 | 
				
			||||||
 | 
							return ERR_PTR(-ENOMEM);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* write lock, search again and add if still not present */
 | 
				
			||||||
 | 
						down_write(&fscache_addremove_sem);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list_for_each_entry(cache, &fscache_caches, cache_link) {
 | 
				
			||||||
 | 
							if (cache->name && name && strcmp(cache->name, name) == 0 &&
 | 
				
			||||||
 | 
							    fscache_get_cache_maybe(cache, fscache_cache_get_acquire))
 | 
				
			||||||
 | 
								goto got_cache_w;
 | 
				
			||||||
 | 
							if (!cache->name) {
 | 
				
			||||||
 | 
								unnamed = cache;
 | 
				
			||||||
 | 
								if (!name &&
 | 
				
			||||||
 | 
								    fscache_get_cache_maybe(cache, fscache_cache_get_acquire))
 | 
				
			||||||
 | 
									goto got_cache_w;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (unnamed && is_cache &&
 | 
				
			||||||
 | 
						    fscache_get_cache_maybe(unnamed, fscache_cache_get_acquire))
 | 
				
			||||||
 | 
							goto use_unnamed_cache;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!name) {
 | 
				
			||||||
 | 
							list_for_each_entry(cache, &fscache_caches, cache_link) {
 | 
				
			||||||
 | 
								if (cache->name &&
 | 
				
			||||||
 | 
								    fscache_get_cache_maybe(cache, fscache_cache_get_acquire))
 | 
				
			||||||
 | 
									goto got_cache_w;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list_add_tail(&candidate->cache_link, &fscache_caches);
 | 
				
			||||||
 | 
						trace_fscache_cache(candidate->debug_id,
 | 
				
			||||||
 | 
								    refcount_read(&candidate->ref),
 | 
				
			||||||
 | 
								    fscache_cache_new_acquire);
 | 
				
			||||||
 | 
						up_write(&fscache_addremove_sem);
 | 
				
			||||||
 | 
						return candidate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					got_cache_r:
 | 
				
			||||||
 | 
						up_read(&fscache_addremove_sem);
 | 
				
			||||||
 | 
						return cache;
 | 
				
			||||||
 | 
					use_unnamed_cache:
 | 
				
			||||||
 | 
						cache = unnamed;
 | 
				
			||||||
 | 
						cache->name = candidate->name;
 | 
				
			||||||
 | 
						candidate->name = NULL;
 | 
				
			||||||
 | 
					got_cache_w:
 | 
				
			||||||
 | 
						up_write(&fscache_addremove_sem);
 | 
				
			||||||
 | 
						kfree(candidate->name);
 | 
				
			||||||
 | 
						kfree(candidate);
 | 
				
			||||||
 | 
						return cache;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * fscache_acquire_cache - Acquire a cache-level cookie.
 | 
				
			||||||
 | 
					 * @name: The name of the cache.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Get a cookie to represent an actual cache.  If a name is given and there is
 | 
				
			||||||
 | 
					 * a nameless cache record available, this will acquire that and set its name,
 | 
				
			||||||
 | 
					 * directing all the volumes using it to this cache.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The cache will be switched over to the preparing state if not currently in
 | 
				
			||||||
 | 
					 * use, otherwise -EBUSY will be returned.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct fscache_cache *fscache_acquire_cache(const char *name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct fscache_cache *cache;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ASSERT(name);
 | 
				
			||||||
 | 
						cache = fscache_lookup_cache(name, true);
 | 
				
			||||||
 | 
						if (IS_ERR(cache))
 | 
				
			||||||
 | 
							return cache;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!fscache_set_cache_state_maybe(cache,
 | 
				
			||||||
 | 
										   FSCACHE_CACHE_IS_NOT_PRESENT,
 | 
				
			||||||
 | 
										   FSCACHE_CACHE_IS_PREPARING)) {
 | 
				
			||||||
 | 
							pr_warn("Cache tag %s in use\n", name);
 | 
				
			||||||
 | 
							fscache_put_cache(cache, fscache_cache_put_cache);
 | 
				
			||||||
 | 
							return ERR_PTR(-EBUSY);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return cache;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL(fscache_acquire_cache);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * fscache_put_cache - Release a cache-level cookie.
 | 
				
			||||||
 | 
					 * @cache: The cache cookie to be released
 | 
				
			||||||
 | 
					 * @where: An indication of where the release happened
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Release the caller's reference on a cache-level cookie.  The @where
 | 
				
			||||||
 | 
					 * indication should give information about the circumstances in which the call
 | 
				
			||||||
 | 
					 * occurs and will be logged through a tracepoint.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void fscache_put_cache(struct fscache_cache *cache,
 | 
				
			||||||
 | 
							       enum fscache_cache_trace where)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned int debug_id = cache->debug_id;
 | 
				
			||||||
 | 
						bool zero;
 | 
				
			||||||
 | 
						int ref;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (IS_ERR_OR_NULL(cache))
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						zero = __refcount_dec_and_test(&cache->ref, &ref);
 | 
				
			||||||
 | 
						trace_fscache_cache(debug_id, ref - 1, where);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (zero) {
 | 
				
			||||||
 | 
							down_write(&fscache_addremove_sem);
 | 
				
			||||||
 | 
							list_del_init(&cache->cache_link);
 | 
				
			||||||
 | 
							up_write(&fscache_addremove_sem);
 | 
				
			||||||
 | 
							kfree(cache->name);
 | 
				
			||||||
 | 
							kfree(cache);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * fscache_relinquish_cache - Reset cache state and release cookie
 | 
				
			||||||
 | 
					 * @cache: The cache cookie to be released
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Reset the state of a cache and release the caller's reference on a cache
 | 
				
			||||||
 | 
					 * cookie.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void fscache_relinquish_cache(struct fscache_cache *cache)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						enum fscache_cache_trace where =
 | 
				
			||||||
 | 
							(cache->state == FSCACHE_CACHE_IS_PREPARING) ?
 | 
				
			||||||
 | 
							fscache_cache_put_prep_failed :
 | 
				
			||||||
 | 
							fscache_cache_put_relinquish;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cache->cache_priv = NULL;
 | 
				
			||||||
 | 
						smp_store_release(&cache->state, FSCACHE_CACHE_IS_NOT_PRESENT);
 | 
				
			||||||
 | 
						fscache_put_cache(cache, where);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL(fscache_relinquish_cache);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_PROC_FS
 | 
				
			||||||
 | 
					static const char fscache_cache_states[NR__FSCACHE_CACHE_STATE] = "-PAEW";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Generate a list of caches in /proc/fs/fscache/caches
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int fscache_caches_seq_show(struct seq_file *m, void *v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct fscache_cache *cache;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (v == &fscache_caches) {
 | 
				
			||||||
 | 
							seq_puts(m,
 | 
				
			||||||
 | 
								 "CACHE    REF   VOLS  OBJS  ACCES S NAME\n"
 | 
				
			||||||
 | 
								 "======== ===== ===== ===== ===== = ===============\n"
 | 
				
			||||||
 | 
								 );
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cache = list_entry(v, struct fscache_cache, cache_link);
 | 
				
			||||||
 | 
						seq_printf(m,
 | 
				
			||||||
 | 
							   "%08x %5d %5d %5d %5d %c %s\n",
 | 
				
			||||||
 | 
							   cache->debug_id,
 | 
				
			||||||
 | 
							   refcount_read(&cache->ref),
 | 
				
			||||||
 | 
							   atomic_read(&cache->n_volumes),
 | 
				
			||||||
 | 
							   atomic_read(&cache->object_count),
 | 
				
			||||||
 | 
							   atomic_read(&cache->n_accesses),
 | 
				
			||||||
 | 
							   fscache_cache_states[cache->state],
 | 
				
			||||||
 | 
							   cache->name ?: "-");
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void *fscache_caches_seq_start(struct seq_file *m, loff_t *_pos)
 | 
				
			||||||
 | 
						__acquires(fscache_addremove_sem)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						down_read(&fscache_addremove_sem);
 | 
				
			||||||
 | 
						return seq_list_start_head(&fscache_caches, *_pos);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void *fscache_caches_seq_next(struct seq_file *m, void *v, loff_t *_pos)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return seq_list_next(v, &fscache_caches, _pos);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void fscache_caches_seq_stop(struct seq_file *m, void *v)
 | 
				
			||||||
 | 
						__releases(fscache_addremove_sem)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						up_read(&fscache_addremove_sem);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const struct seq_operations fscache_caches_seq_ops = {
 | 
				
			||||||
 | 
						.start  = fscache_caches_seq_start,
 | 
				
			||||||
 | 
						.next   = fscache_caches_seq_next,
 | 
				
			||||||
 | 
						.stop   = fscache_caches_seq_stop,
 | 
				
			||||||
 | 
						.show   = fscache_caches_seq_show,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					#endif /* CONFIG_PROC_FS */
 | 
				
			||||||
| 
						 | 
					@ -17,6 +17,39 @@
 | 
				
			||||||
#include <linux/sched.h>
 | 
					#include <linux/sched.h>
 | 
				
			||||||
#include <linux/seq_file.h>
 | 
					#include <linux/seq_file.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * cache.c
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#ifdef CONFIG_PROC_FS
 | 
				
			||||||
 | 
					extern const struct seq_operations fscache_caches_seq_ops;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					struct fscache_cache *fscache_lookup_cache(const char *name, bool is_cache);
 | 
				
			||||||
 | 
					void fscache_put_cache(struct fscache_cache *cache, enum fscache_cache_trace where);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline enum fscache_cache_state fscache_cache_state(const struct fscache_cache *cache)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return smp_load_acquire(&cache->state);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline bool fscache_cache_is_live(const struct fscache_cache *cache)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return fscache_cache_state(cache) == FSCACHE_CACHE_IS_ACTIVE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void fscache_set_cache_state(struct fscache_cache *cache,
 | 
				
			||||||
 | 
										   enum fscache_cache_state new_state)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						smp_store_release(&cache->state, new_state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline bool fscache_set_cache_state_maybe(struct fscache_cache *cache,
 | 
				
			||||||
 | 
											 enum fscache_cache_state old_state,
 | 
				
			||||||
 | 
											 enum fscache_cache_state new_state)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return try_cmpxchg_release(&cache->state, &old_state, new_state);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * main.c
 | 
					 * main.c
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,6 +19,10 @@ int __init fscache_proc_init(void)
 | 
				
			||||||
	if (!proc_mkdir("fs/fscache", NULL))
 | 
						if (!proc_mkdir("fs/fscache", NULL))
 | 
				
			||||||
		goto error_dir;
 | 
							goto error_dir;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!proc_create_seq("fs/fscache/caches", S_IFREG | 0444, NULL,
 | 
				
			||||||
 | 
								     &fscache_caches_seq_ops))
 | 
				
			||||||
 | 
							goto error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_FSCACHE_STATS
 | 
					#ifdef CONFIG_FSCACHE_STATS
 | 
				
			||||||
	if (!proc_create_single("fs/fscache/stats", S_IFREG | 0444, NULL,
 | 
						if (!proc_create_single("fs/fscache/stats", S_IFREG | 0444, NULL,
 | 
				
			||||||
				fscache_stats_show))
 | 
									fscache_stats_show))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,6 +16,40 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <linux/fscache.h>
 | 
					#include <linux/fscache.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum fscache_cache_trace;
 | 
				
			||||||
 | 
					enum fscache_access_trace;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum fscache_cache_state {
 | 
				
			||||||
 | 
						FSCACHE_CACHE_IS_NOT_PRESENT,	/* No cache is present for this name */
 | 
				
			||||||
 | 
						FSCACHE_CACHE_IS_PREPARING,	/* A cache is preparing to come live */
 | 
				
			||||||
 | 
						FSCACHE_CACHE_IS_ACTIVE,	/* Attached cache is active and can be used */
 | 
				
			||||||
 | 
						FSCACHE_CACHE_GOT_IOERROR,	/* Attached cache stopped on I/O error */
 | 
				
			||||||
 | 
						FSCACHE_CACHE_IS_WITHDRAWN,	/* Attached cache is being withdrawn */
 | 
				
			||||||
 | 
					#define NR__FSCACHE_CACHE_STATE (FSCACHE_CACHE_IS_WITHDRAWN + 1)
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Cache cookie.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct fscache_cache {
 | 
				
			||||||
 | 
						struct list_head	cache_link;	/* Link in cache list */
 | 
				
			||||||
 | 
						void			*cache_priv;	/* Private cache data (or NULL) */
 | 
				
			||||||
 | 
						refcount_t		ref;
 | 
				
			||||||
 | 
						atomic_t		n_volumes;	/* Number of active volumes; */
 | 
				
			||||||
 | 
						atomic_t		n_accesses;	/* Number of in-progress accesses on the cache */
 | 
				
			||||||
 | 
						atomic_t		object_count;	/* no. of live objects in this cache */
 | 
				
			||||||
 | 
						unsigned int		debug_id;
 | 
				
			||||||
 | 
						enum fscache_cache_state state;
 | 
				
			||||||
 | 
						char			*name;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern struct workqueue_struct *fscache_wq;
 | 
					extern struct workqueue_struct *fscache_wq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * out-of-line cache backend functions
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					extern struct rw_semaphore fscache_addremove_sem;
 | 
				
			||||||
 | 
					extern struct fscache_cache *fscache_acquire_cache(const char *name);
 | 
				
			||||||
 | 
					extern void fscache_relinquish_cache(struct fscache_cache *cache);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* _LINUX_FSCACHE_CACHE_H */
 | 
					#endif /* _LINUX_FSCACHE_CACHE_H */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,11 +19,27 @@
 | 
				
			||||||
#ifndef __FSCACHE_DECLARE_TRACE_ENUMS_ONCE_ONLY
 | 
					#ifndef __FSCACHE_DECLARE_TRACE_ENUMS_ONCE_ONLY
 | 
				
			||||||
#define __FSCACHE_DECLARE_TRACE_ENUMS_ONCE_ONLY
 | 
					#define __FSCACHE_DECLARE_TRACE_ENUMS_ONCE_ONLY
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum fscache_cache_trace {
 | 
				
			||||||
 | 
						fscache_cache_collision,
 | 
				
			||||||
 | 
						fscache_cache_get_acquire,
 | 
				
			||||||
 | 
						fscache_cache_new_acquire,
 | 
				
			||||||
 | 
						fscache_cache_put_cache,
 | 
				
			||||||
 | 
						fscache_cache_put_prep_failed,
 | 
				
			||||||
 | 
						fscache_cache_put_relinquish,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Declare tracing information enums and their string mappings for display.
 | 
					 * Declare tracing information enums and their string mappings for display.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					#define fscache_cache_traces						\
 | 
				
			||||||
 | 
						EM(fscache_cache_collision,		"*COLLIDE*")		\
 | 
				
			||||||
 | 
						EM(fscache_cache_get_acquire,		"GET acq  ")		\
 | 
				
			||||||
 | 
						EM(fscache_cache_new_acquire,		"NEW acq  ")		\
 | 
				
			||||||
 | 
						EM(fscache_cache_put_cache,		"PUT cache")		\
 | 
				
			||||||
 | 
						EM(fscache_cache_put_prep_failed,	"PUT pfail")		\
 | 
				
			||||||
 | 
						E_(fscache_cache_put_relinquish,	"PUT relnq")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Export enum symbols via userspace.
 | 
					 * Export enum symbols via userspace.
 | 
				
			||||||
| 
						 | 
					@ -33,6 +49,8 @@
 | 
				
			||||||
#define EM(a, b) TRACE_DEFINE_ENUM(a);
 | 
					#define EM(a, b) TRACE_DEFINE_ENUM(a);
 | 
				
			||||||
#define E_(a, b) TRACE_DEFINE_ENUM(a);
 | 
					#define E_(a, b) TRACE_DEFINE_ENUM(a);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fscache_cache_traces;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Now redefine the EM() and E_() macros to map the enums to the strings that
 | 
					 * Now redefine the EM() and E_() macros to map the enums to the strings that
 | 
				
			||||||
 * will be printed in the output.
 | 
					 * will be printed in the output.
 | 
				
			||||||
| 
						 | 
					@ -43,6 +61,31 @@
 | 
				
			||||||
#define E_(a, b)	{ a, b }
 | 
					#define E_(a, b)	{ a, b }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TRACE_EVENT(fscache_cache,
 | 
				
			||||||
 | 
						    TP_PROTO(unsigned int cache_debug_id,
 | 
				
			||||||
 | 
							     int usage,
 | 
				
			||||||
 | 
							     enum fscache_cache_trace where),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						    TP_ARGS(cache_debug_id, usage, where),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						    TP_STRUCT__entry(
 | 
				
			||||||
 | 
							    __field(unsigned int,		cache		)
 | 
				
			||||||
 | 
							    __field(int,			usage		)
 | 
				
			||||||
 | 
							    __field(enum fscache_cache_trace,	where		)
 | 
				
			||||||
 | 
								     ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						    TP_fast_assign(
 | 
				
			||||||
 | 
							    __entry->cache	= cache_debug_id;
 | 
				
			||||||
 | 
							    __entry->usage	= usage;
 | 
				
			||||||
 | 
							    __entry->where	= where;
 | 
				
			||||||
 | 
								   ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						    TP_printk("C=%08x %s r=%d",
 | 
				
			||||||
 | 
							      __entry->cache,
 | 
				
			||||||
 | 
							      __print_symbolic(__entry->where, fscache_cache_traces),
 | 
				
			||||||
 | 
							      __entry->usage)
 | 
				
			||||||
 | 
						    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* _TRACE_FSCACHE_H */
 | 
					#endif /* _TRACE_FSCACHE_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* This part must be outside protection */
 | 
					/* This part must be outside protection */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue