fscache: Procfile to display cookies
authorDavid Howells <dhowells@redhat.com>
Mon, 10 Feb 2020 10:00:22 +0000 (10:00 +0000)
committerDavid Howells <dhowells@redhat.com>
Fri, 27 Aug 2021 12:34:02 +0000 (13:34 +0100)
Add /proc/fs/fscache/cookies to display active cookies.

Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Jeff Layton <jlayton@redhat.com>
cc: linux-cachefs@redhat.com
Link: https://lore.kernel.org/r/158861211871.340223.7223853943667440807.stgit@warthog.procyon.org.uk/
Link: https://lore.kernel.org/r/159465771021.1376105.6933857529128238020.stgit@warthog.procyon.org.uk/
Link: https://lore.kernel.org/r/160588460994.3465195.16963417803501149328.stgit@warthog.procyon.org.uk/
Link: https://lore.kernel.org/r/162431194785.2908479.786917990782538164.stgit@warthog.procyon.org.uk/
fs/fscache/cookie.c
fs/fscache/internal.h
fs/fscache/proc.c
include/linux/fscache.h

index f2be98d2c64dd9fac0330beb057a0d321d11be6e..c7047544972b1f779f81897934ba3a8c4a3c324c 100644 (file)
@@ -19,6 +19,8 @@ static atomic_t fscache_object_debug_id = ATOMIC_INIT(0);
 
 #define fscache_cookie_hash_shift 15
 static struct hlist_bl_head fscache_cookie_hash[1 << fscache_cookie_hash_shift];
+static LIST_HEAD(fscache_cookies);
+static DEFINE_RWLOCK(fscache_cookies_lock);
 
 static int fscache_acquire_non_index_cookie(struct fscache_cookie *cookie,
                                            loff_t object_size);
@@ -65,6 +67,9 @@ void fscache_free_cookie(struct fscache_cookie *cookie)
 {
        if (cookie) {
                BUG_ON(!hlist_empty(&cookie->backing_objects));
+               write_lock(&fscache_cookies_lock);
+               list_del(&cookie->proc_link);
+               write_unlock(&fscache_cookies_lock);
                if (cookie->aux_len > sizeof(cookie->inline_aux))
                        kfree(cookie->aux);
                if (cookie->key_len > sizeof(cookie->inline_key))
@@ -192,6 +197,10 @@ struct fscache_cookie *fscache_alloc_cookie(
        /* radix tree insertion won't use the preallocation pool unless it's
         * told it may not wait */
        INIT_RADIX_TREE(&cookie->stores, GFP_NOFS & ~__GFP_DIRECT_RECLAIM);
+
+       write_lock(&fscache_cookies_lock);
+       list_add_tail(&cookie->proc_link, &fscache_cookies);
+       write_unlock(&fscache_cookies_lock);
        return cookie;
 
 nomem:
@@ -969,3 +978,97 @@ inconsistent:
        return -ESTALE;
 }
 EXPORT_SYMBOL(__fscache_check_consistency);
+
+/*
+ * Generate a list of extant cookies in /proc/fs/fscache/cookies
+ */
+static int fscache_cookies_seq_show(struct seq_file *m, void *v)
+{
+       struct fscache_cookie *cookie;
+       unsigned int keylen = 0, auxlen = 0;
+       char _type[3], *type;
+       u8 *p;
+
+       if (v == &fscache_cookies) {
+               seq_puts(m,
+                        "COOKIE   PARENT   USAGE CHILD ACT TY FL  DEF              NETFS_DATA\n"
+                        "======== ======== ===== ===== === == === ================ ==========\n"
+                        );
+               return 0;
+       }
+
+       cookie = list_entry(v, struct fscache_cookie, proc_link);
+
+       switch (cookie->type) {
+       case 0:
+               type = "IX";
+               break;
+       case 1:
+               type = "DT";
+               break;
+       default:
+               snprintf(_type, sizeof(_type), "%02u",
+                        cookie->type);
+               type = _type;
+               break;
+       }
+
+       seq_printf(m,
+                  "%08x %08x %5u %5u %3u %s %03lx %-16s %px",
+                  cookie->debug_id,
+                  cookie->parent ? cookie->parent->debug_id : 0,
+                  atomic_read(&cookie->usage),
+                  atomic_read(&cookie->n_children),
+                  atomic_read(&cookie->n_active),
+                  type,
+                  cookie->flags,
+                  cookie->def->name,
+                  cookie->netfs_data);
+
+       keylen = cookie->key_len;
+       auxlen = cookie->aux_len;
+
+       if (keylen > 0 || auxlen > 0) {
+               seq_puts(m, " ");
+               p = keylen <= sizeof(cookie->inline_key) ?
+                       cookie->inline_key : cookie->key;
+               for (; keylen > 0; keylen--)
+                       seq_printf(m, "%02x", *p++);
+               if (auxlen > 0) {
+                       seq_puts(m, ", ");
+                       p = auxlen <= sizeof(cookie->inline_aux) ?
+                               cookie->inline_aux : cookie->aux;
+                       for (; auxlen > 0; auxlen--)
+                               seq_printf(m, "%02x", *p++);
+               }
+       }
+
+       seq_puts(m, "\n");
+       return 0;
+}
+
+static void *fscache_cookies_seq_start(struct seq_file *m, loff_t *_pos)
+       __acquires(fscache_cookies_lock)
+{
+       read_lock(&fscache_cookies_lock);
+       return seq_list_start_head(&fscache_cookies, *_pos);
+}
+
+static void *fscache_cookies_seq_next(struct seq_file *m, void *v, loff_t *_pos)
+{
+       return seq_list_next(v, &fscache_cookies, _pos);
+}
+
+static void fscache_cookies_seq_stop(struct seq_file *m, void *v)
+       __releases(rcu)
+{
+       read_unlock(&fscache_cookies_lock);
+}
+
+
+const struct seq_operations fscache_cookies_seq_ops = {
+       .start  = fscache_cookies_seq_start,
+       .next   = fscache_cookies_seq_next,
+       .stop   = fscache_cookies_seq_stop,
+       .show   = fscache_cookies_seq_show,
+};
index c483863b740adee564f9df12022fa13c9848050a..207a6bc81ca994be363627082accbd5cc46032d3 100644 (file)
@@ -45,6 +45,7 @@ extern struct fscache_cache *fscache_select_cache_for_object(
  * cookie.c
  */
 extern struct kmem_cache *fscache_cookie_jar;
+extern const struct seq_operations fscache_cookies_seq_ops;
 
 extern void fscache_free_cookie(struct fscache_cookie *);
 extern struct fscache_cookie *fscache_alloc_cookie(struct fscache_cookie *,
index 90a7bc22f7e19e4ca115e67426c756d0423b06bb..da51fdfc864132f44f3e15b8e6fdc2bd3769ec5a 100644 (file)
@@ -21,6 +21,10 @@ int __init fscache_proc_init(void)
        if (!proc_mkdir("fs/fscache", NULL))
                goto error_dir;
 
+       if (!proc_create_seq("fs/fscache/cookies", S_IFREG | 0444, NULL,
+                            &fscache_cookies_seq_ops))
+               goto error_cookies;
+
 #ifdef CONFIG_FSCACHE_STATS
        if (!proc_create_single("fs/fscache/stats", S_IFREG | 0444, NULL,
                        fscache_stats_show))
@@ -53,6 +57,8 @@ error_histogram:
        remove_proc_entry("fs/fscache/stats", NULL);
 error_stats:
 #endif
+       remove_proc_entry("fs/fscache/cookies", NULL);
+error_cookies:
        remove_proc_entry("fs/fscache", NULL);
 error_dir:
        _leave(" = -ENOMEM");
@@ -73,5 +79,6 @@ void fscache_proc_cleanup(void)
 #ifdef CONFIG_FSCACHE_STATS
        remove_proc_entry("fs/fscache/stats", NULL);
 #endif
+       remove_proc_entry("fs/fscache/cookies", NULL);
        remove_proc_entry("fs/fscache", NULL);
 }
index ba58c427cf9a2a4ed737dca96effcda5851fab36..ea61e54a6bc572891bbb685901d50845fd0521ee 100644 (file)
@@ -133,6 +133,7 @@ struct fscache_cookie {
        const struct fscache_cookie_def *def;           /* definition */
        struct fscache_cookie           *parent;        /* parent of this entry */
        struct hlist_bl_node            hash_link;      /* Link in hash table */
+       struct list_head                proc_link;      /* Link in proc list */
        void                            *netfs_data;    /* back pointer to netfs */
        struct radix_tree_root          stores;         /* pages to be stored on this cookie */
 #define FSCACHE_COOKIE_PENDING_TAG     0               /* pages tag: pending write to cache */