Commit 4fbf4291 authored by David Howells's avatar David Howells

FS-Cache: Allow the current state of all objects to be dumped

Allow the current state of all fscache objects to be dumped by doing:

	cat /proc/fs/fscache/objects

By default, all objects and all fields will be shown.  This can be restricted
by adding a suitable key to one of the caller's keyrings (such as the session
keyring):

	keyctl add user fscache:objlist "<restrictions>" @s

The <restrictions> are:

	K	Show hexdump of object key (don't show if not given)
	A	Show hexdump of object aux data (don't show if not given)

And paired restrictions:

	C	Show objects that have a cookie
	c	Show objects that don't have a cookie
	B	Show objects that are busy
	b	Show objects that aren't busy
	W	Show objects that have pending writes
	w	Show objects that don't have pending writes
	R	Show objects that have outstanding reads
	r	Show objects that don't have outstanding reads
	S	Show objects that have slow work queued
	s	Show objects that don't have slow work queued

If neither side of a restriction pair is given, then both are implied.  For
example:

	keyctl add user fscache:objlist KB @s

shows objects that are busy, and lists their object keys, but does not dump
their auxiliary data.  It also implies "CcWwRrSs", but as 'B' is given, 'b' is
not implied.
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
parent 440f0aff
...@@ -299,6 +299,87 @@ proc files. ...@@ -299,6 +299,87 @@ proc files.
jiffy range covered, and the SECS field the equivalent number of seconds. jiffy range covered, and the SECS field the equivalent number of seconds.
===========
OBJECT LIST
===========
If CONFIG_FSCACHE_OBJECT_LIST is enabled, the FS-Cache facility will maintain a
list of all the objects currently allocated and allow them to be viewed
through:
/proc/fs/fscache/objects
This will look something like:
[root@andromeda ~]# head /proc/fs/fscache/objects
OBJECT PARENT STAT CHLDN OPS OOP IPR EX READS EM EV F S | NETFS_COOKIE_DEF TY FL NETFS_DATA OBJECT_KEY, AUX_DATA
======== ======== ==== ===== === === === == ===== == == = = | ================ == == ================ ================
17e4b 2 ACTV 0 0 0 0 0 0 7b 4 0 8 | NFS.fh DT 0 ffff88001dd82820 010006017edcf8bbc93b43298fdfbe71e50b57b13a172c0117f38472, e567634700000000000000000000000063f2404a000000000000000000000000c9030000000000000000000063f2404a
1693a 2 ACTV 0 0 0 0 0 0 7b 4 0 8 | NFS.fh DT 0 ffff88002db23380 010006017edcf8bbc93b43298fdfbe71e50b57b1e0162c01a2df0ea6, 420ebc4a000000000000000000000000420ebc4a0000000000000000000000000e1801000000000000000000420ebc4a
where the first set of columns before the '|' describe the object:
COLUMN DESCRIPTION
======= ===============================================================
OBJECT Object debugging ID (appears as OBJ%x in some debug messages)
PARENT Debugging ID of parent object
STAT Object state
CHLDN Number of child objects of this object
OPS Number of outstanding operations on this object
OOP Number of outstanding child object management operations
IPR
EX Number of outstanding exclusive operations
READS Number of outstanding read operations
EM Object's event mask
EV Events raised on this object
F Object flags
S Object slow-work work item flags
and the second set of columns describe the object's cookie, if present:
COLUMN DESCRIPTION
=============== =======================================================
NETFS_COOKIE_DEF Name of netfs cookie definition
TY Cookie type (IX - index, DT - data, hex - special)
FL Cookie flags
NETFS_DATA Netfs private data stored in the cookie
OBJECT_KEY Object key } 1 column, with separating comma
AUX_DATA Object aux data } presence may be configured
The data shown may be filtered by attaching the a key to an appropriate keyring
before viewing the file. Something like:
keyctl add user fscache:objlist <restrictions> @s
where <restrictions> are a selection of the following letters:
K Show hexdump of object key (don't show if not given)
A Show hexdump of object aux data (don't show if not given)
and the following paired letters:
C Show objects that have a cookie
c Show objects that don't have a cookie
B Show objects that are busy
b Show objects that aren't busy
W Show objects that have pending writes
w Show objects that don't have pending writes
R Show objects that have outstanding reads
r Show objects that don't have outstanding reads
S Show objects that have slow work queued
s Show objects that don't have slow work queued
If neither side of a letter pair is given, then both are implied. For example:
keyctl add user fscache:objlist KB @s
shows objects that are busy, and lists their object keys, but does not dump
their auxiliary data. It also implies "CcWwRrSs", but as 'B' is given, 'b' is
not implied.
By default all objects and all fields will be shown.
========= =========
DEBUGGING DEBUGGING
========= =========
......
...@@ -331,6 +331,7 @@ static void cachefiles_put_object(struct fscache_object *_object) ...@@ -331,6 +331,7 @@ static void cachefiles_put_object(struct fscache_object *_object)
} }
cache = object->fscache.cache; cache = object->fscache.cache;
fscache_object_destroy(&object->fscache);
kmem_cache_free(cachefiles_object_jar, object); kmem_cache_free(cachefiles_object_jar, object);
fscache_object_destroyed(cache); fscache_object_destroyed(cache);
} }
......
...@@ -333,7 +333,8 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op, ...@@ -333,7 +333,8 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op,
shift = PAGE_SHIFT - inode->i_sb->s_blocksize_bits; shift = PAGE_SHIFT - inode->i_sb->s_blocksize_bits;
op->op.flags = FSCACHE_OP_FAST; op->op.flags &= FSCACHE_OP_KEEP_FLAGS;
op->op.flags |= FSCACHE_OP_FAST;
op->op.processor = cachefiles_read_copier; op->op.processor = cachefiles_read_copier;
pagevec_init(&pagevec, 0); pagevec_init(&pagevec, 0);
...@@ -639,7 +640,8 @@ int cachefiles_read_or_alloc_pages(struct fscache_retrieval *op, ...@@ -639,7 +640,8 @@ int cachefiles_read_or_alloc_pages(struct fscache_retrieval *op,
pagevec_init(&pagevec, 0); pagevec_init(&pagevec, 0);
op->op.flags = FSCACHE_OP_FAST; op->op.flags &= FSCACHE_OP_KEEP_FLAGS;
op->op.flags |= FSCACHE_OP_FAST;
op->op.processor = cachefiles_read_copier; op->op.processor = cachefiles_read_copier;
INIT_LIST_HEAD(&backpages); INIT_LIST_HEAD(&backpages);
......
...@@ -54,3 +54,10 @@ config FSCACHE_DEBUG ...@@ -54,3 +54,10 @@ config FSCACHE_DEBUG
enabled by setting bits in /sys/modules/fscache/parameter/debug. enabled by setting bits in /sys/modules/fscache/parameter/debug.
See Documentation/filesystems/caching/fscache.txt for more information. See Documentation/filesystems/caching/fscache.txt for more information.
config FSCACHE_OBJECT_LIST
bool "Maintain global object list for debugging purposes"
depends on FSCACHE && PROC_FS
help
Maintain a global list of active fscache objects that can be
retrieved through /proc/fs/fscache/objects for debugging purposes
...@@ -15,5 +15,6 @@ fscache-y := \ ...@@ -15,5 +15,6 @@ fscache-y := \
fscache-$(CONFIG_PROC_FS) += proc.o fscache-$(CONFIG_PROC_FS) += proc.o
fscache-$(CONFIG_FSCACHE_STATS) += stats.o fscache-$(CONFIG_FSCACHE_STATS) += stats.o
fscache-$(CONFIG_FSCACHE_HISTOGRAM) += histogram.o fscache-$(CONFIG_FSCACHE_HISTOGRAM) += histogram.o
fscache-$(CONFIG_FSCACHE_OBJECT_LIST) += object-list.o
obj-$(CONFIG_FSCACHE) := fscache.o obj-$(CONFIG_FSCACHE) := fscache.o
...@@ -263,6 +263,7 @@ int fscache_add_cache(struct fscache_cache *cache, ...@@ -263,6 +263,7 @@ int fscache_add_cache(struct fscache_cache *cache,
spin_lock(&cache->object_list_lock); spin_lock(&cache->object_list_lock);
list_add_tail(&ifsdef->cache_link, &cache->object_list); list_add_tail(&ifsdef->cache_link, &cache->object_list);
spin_unlock(&cache->object_list_lock); spin_unlock(&cache->object_list_lock);
fscache_objlist_add(ifsdef);
/* add the cache's netfs definition index object to the top level index /* add the cache's netfs definition index object to the top level index
* cookie as a known backing object */ * cookie as a known backing object */
......
...@@ -349,6 +349,8 @@ static int fscache_attach_object(struct fscache_cookie *cookie, ...@@ -349,6 +349,8 @@ static int fscache_attach_object(struct fscache_cookie *cookie,
object->cookie = cookie; object->cookie = cookie;
atomic_inc(&cookie->usage); atomic_inc(&cookie->usage);
hlist_add_head(&object->cookie_link, &cookie->backing_objects); hlist_add_head(&object->cookie_link, &cookie->backing_objects);
fscache_objlist_add(object);
ret = 0; ret = 0;
cant_attach_object: cant_attach_object:
......
...@@ -88,10 +88,23 @@ extern int fscache_wait_bit_interruptible(void *); ...@@ -88,10 +88,23 @@ extern int fscache_wait_bit_interruptible(void *);
/* /*
* object.c * object.c
*/ */
extern const char fscache_object_states_short[FSCACHE_OBJECT__NSTATES][5];
extern void fscache_withdrawing_object(struct fscache_cache *, extern void fscache_withdrawing_object(struct fscache_cache *,
struct fscache_object *); struct fscache_object *);
extern void fscache_enqueue_object(struct fscache_object *); extern void fscache_enqueue_object(struct fscache_object *);
/*
* object-list.c
*/
#ifdef CONFIG_FSCACHE_OBJECT_LIST
extern const struct file_operations fscache_objlist_fops;
extern void fscache_objlist_add(struct fscache_object *);
#else
#define fscache_objlist_add(object) do {} while(0)
#endif
/* /*
* operation.c * operation.c
*/ */
......
This diff is collapsed.
...@@ -34,7 +34,7 @@ const char *fscache_object_states[FSCACHE_OBJECT__NSTATES] = { ...@@ -34,7 +34,7 @@ const char *fscache_object_states[FSCACHE_OBJECT__NSTATES] = {
}; };
EXPORT_SYMBOL(fscache_object_states); EXPORT_SYMBOL(fscache_object_states);
static const char fscache_object_states_short[FSCACHE_OBJECT__NSTATES][5] = { const char fscache_object_states_short[FSCACHE_OBJECT__NSTATES][5] = {
[FSCACHE_OBJECT_INIT] = "INIT", [FSCACHE_OBJECT_INIT] = "INIT",
[FSCACHE_OBJECT_LOOKING_UP] = "LOOK", [FSCACHE_OBJECT_LOOKING_UP] = "LOOK",
[FSCACHE_OBJECT_CREATING] = "CRTN", [FSCACHE_OBJECT_CREATING] = "CRTN",
......
...@@ -322,6 +322,9 @@ void fscache_put_operation(struct fscache_operation *op) ...@@ -322,6 +322,9 @@ void fscache_put_operation(struct fscache_operation *op)
object = op->object; object = op->object;
if (test_bit(FSCACHE_OP_DEC_READ_CNT, &op->flags))
atomic_dec(&object->n_reads);
/* now... we may get called with the object spinlock held, so we /* now... we may get called with the object spinlock held, so we
* complete the cleanup here only if we can immediately acquire the * complete the cleanup here only if we can immediately acquire the
* lock, and defer it otherwise */ * lock, and defer it otherwise */
......
...@@ -275,6 +275,9 @@ int __fscache_read_or_alloc_page(struct fscache_cookie *cookie, ...@@ -275,6 +275,9 @@ int __fscache_read_or_alloc_page(struct fscache_cookie *cookie,
ASSERTCMP(object->state, >, FSCACHE_OBJECT_LOOKING_UP); ASSERTCMP(object->state, >, FSCACHE_OBJECT_LOOKING_UP);
atomic_inc(&object->n_reads);
set_bit(FSCACHE_OP_DEC_READ_CNT, &op->op.flags);
if (fscache_submit_op(object, &op->op) < 0) if (fscache_submit_op(object, &op->op) < 0)
goto nobufs_unlock; goto nobufs_unlock;
spin_unlock(&cookie->lock); spin_unlock(&cookie->lock);
...@@ -386,6 +389,9 @@ int __fscache_read_or_alloc_pages(struct fscache_cookie *cookie, ...@@ -386,6 +389,9 @@ int __fscache_read_or_alloc_pages(struct fscache_cookie *cookie,
object = hlist_entry(cookie->backing_objects.first, object = hlist_entry(cookie->backing_objects.first,
struct fscache_object, cookie_link); struct fscache_object, cookie_link);
atomic_inc(&object->n_reads);
set_bit(FSCACHE_OP_DEC_READ_CNT, &op->op.flags);
if (fscache_submit_op(object, &op->op) < 0) if (fscache_submit_op(object, &op->op) < 0)
goto nobufs_unlock; goto nobufs_unlock;
spin_unlock(&cookie->lock); spin_unlock(&cookie->lock);
......
...@@ -37,10 +37,20 @@ int __init fscache_proc_init(void) ...@@ -37,10 +37,20 @@ int __init fscache_proc_init(void)
goto error_histogram; goto error_histogram;
#endif #endif
#ifdef CONFIG_FSCACHE_OBJECT_LIST
if (!proc_create("fs/fscache/objects", S_IFREG | 0444, NULL,
&fscache_objlist_fops))
goto error_objects;
#endif
_leave(" = 0"); _leave(" = 0");
return 0; return 0;
#ifdef CONFIG_FSCACHE_OBJECT_LIST
error_objects:
#endif
#ifdef CONFIG_FSCACHE_HISTOGRAM #ifdef CONFIG_FSCACHE_HISTOGRAM
remove_proc_entry("fs/fscache/histogram", NULL);
error_histogram: error_histogram:
#endif #endif
#ifdef CONFIG_FSCACHE_STATS #ifdef CONFIG_FSCACHE_STATS
...@@ -58,6 +68,9 @@ int __init fscache_proc_init(void) ...@@ -58,6 +68,9 @@ int __init fscache_proc_init(void)
*/ */
void fscache_proc_cleanup(void) void fscache_proc_cleanup(void)
{ {
#ifdef CONFIG_FSCACHE_OBJECT_LIST
remove_proc_entry("fs/fscache/objects", NULL);
#endif
#ifdef CONFIG_FSCACHE_HISTOGRAM #ifdef CONFIG_FSCACHE_HISTOGRAM
remove_proc_entry("fs/fscache/histogram", NULL); remove_proc_entry("fs/fscache/histogram", NULL);
#endif #endif
......
...@@ -91,6 +91,8 @@ struct fscache_operation { ...@@ -91,6 +91,8 @@ struct fscache_operation {
#define FSCACHE_OP_WAITING 4 /* cleared when op is woken */ #define FSCACHE_OP_WAITING 4 /* cleared when op is woken */
#define FSCACHE_OP_EXCLUSIVE 5 /* exclusive op, other ops must wait */ #define FSCACHE_OP_EXCLUSIVE 5 /* exclusive op, other ops must wait */
#define FSCACHE_OP_DEAD 6 /* op is now dead */ #define FSCACHE_OP_DEAD 6 /* op is now dead */
#define FSCACHE_OP_DEC_READ_CNT 7 /* decrement object->n_reads on destruction */
#define FSCACHE_OP_KEEP_FLAGS 0xc0 /* flags to keep when repurposing an op */
atomic_t usage; atomic_t usage;
unsigned debug_id; /* debugging ID */ unsigned debug_id; /* debugging ID */
...@@ -357,6 +359,7 @@ struct fscache_object { ...@@ -357,6 +359,7 @@ struct fscache_object {
int n_obj_ops; /* number of object ops outstanding on object */ int n_obj_ops; /* number of object ops outstanding on object */
int n_in_progress; /* number of ops in progress */ int n_in_progress; /* number of ops in progress */
int n_exclusive; /* number of exclusive ops queued */ int n_exclusive; /* number of exclusive ops queued */
atomic_t n_reads; /* number of read ops in progress */
spinlock_t lock; /* state and operations lock */ spinlock_t lock; /* state and operations lock */
unsigned long lookup_jif; /* time at which lookup started */ unsigned long lookup_jif; /* time at which lookup started */
...@@ -370,6 +373,7 @@ struct fscache_object { ...@@ -370,6 +373,7 @@ struct fscache_object {
#define FSCACHE_OBJECT_EV_RELEASE 4 /* T if netfs requested object release */ #define FSCACHE_OBJECT_EV_RELEASE 4 /* T if netfs requested object release */
#define FSCACHE_OBJECT_EV_RETIRE 5 /* T if netfs requested object retirement */ #define FSCACHE_OBJECT_EV_RETIRE 5 /* T if netfs requested object retirement */
#define FSCACHE_OBJECT_EV_WITHDRAW 6 /* T if cache requested object withdrawal */ #define FSCACHE_OBJECT_EV_WITHDRAW 6 /* T if cache requested object withdrawal */
#define FSCACHE_OBJECT_EVENTS_MASK 0x7f /* mask of all events*/
unsigned long flags; unsigned long flags;
#define FSCACHE_OBJECT_LOCK 0 /* T if object is busy being processed */ #define FSCACHE_OBJECT_LOCK 0 /* T if object is busy being processed */
...@@ -385,6 +389,9 @@ struct fscache_object { ...@@ -385,6 +389,9 @@ struct fscache_object {
struct list_head dependents; /* FIFO of dependent objects */ struct list_head dependents; /* FIFO of dependent objects */
struct list_head dep_link; /* link in parent's dependents list */ struct list_head dep_link; /* link in parent's dependents list */
struct list_head pending_ops; /* unstarted operations on this object */ struct list_head pending_ops; /* unstarted operations on this object */
#ifdef CONFIG_FSCACHE_OBJECT_LIST
struct rb_node objlist_link; /* link in global object list */
#endif
pgoff_t store_limit; /* current storage limit */ pgoff_t store_limit; /* current storage limit */
}; };
...@@ -434,6 +441,12 @@ void fscache_object_init(struct fscache_object *object, ...@@ -434,6 +441,12 @@ void fscache_object_init(struct fscache_object *object,
extern void fscache_object_lookup_negative(struct fscache_object *object); extern void fscache_object_lookup_negative(struct fscache_object *object);
extern void fscache_obtained_object(struct fscache_object *object); extern void fscache_obtained_object(struct fscache_object *object);
#ifdef CONFIG_FSCACHE_OBJECT_LIST
extern void fscache_object_destroy(struct fscache_object *object);
#else
#define fscache_object_destroy(object) do {} while(0)
#endif
/** /**
* fscache_object_destroyed - Note destruction of an object in a cache * fscache_object_destroyed - Note destruction of an object in a cache
* @cache: The cache from which the object came * @cache: The cache from which the object came
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment