^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* Global fscache object list maintainer and viewer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2009 Red Hat, Inc. All Rights Reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Written by David Howells (dhowells@redhat.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #define FSCACHE_DEBUG_LEVEL COOKIE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/key.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <keys/user-type.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) static struct rb_root fscache_object_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) static DEFINE_RWLOCK(fscache_object_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) struct fscache_objlist_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) unsigned long config; /* display configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define FSCACHE_OBJLIST_CONFIG_KEY 0x00000001 /* show object keys */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define FSCACHE_OBJLIST_CONFIG_AUX 0x00000002 /* show object auxdata */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define FSCACHE_OBJLIST_CONFIG_COOKIE 0x00000004 /* show objects with cookies */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define FSCACHE_OBJLIST_CONFIG_NOCOOKIE 0x00000008 /* show objects without cookies */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define FSCACHE_OBJLIST_CONFIG_BUSY 0x00000010 /* show busy objects */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define FSCACHE_OBJLIST_CONFIG_IDLE 0x00000020 /* show idle objects */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define FSCACHE_OBJLIST_CONFIG_PENDWR 0x00000040 /* show objects with pending writes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define FSCACHE_OBJLIST_CONFIG_NOPENDWR 0x00000080 /* show objects without pending writes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define FSCACHE_OBJLIST_CONFIG_READS 0x00000100 /* show objects with active reads */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define FSCACHE_OBJLIST_CONFIG_NOREADS 0x00000200 /* show objects without active reads */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define FSCACHE_OBJLIST_CONFIG_EVENTS 0x00000400 /* show objects with events */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define FSCACHE_OBJLIST_CONFIG_NOEVENTS 0x00000800 /* show objects without no events */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define FSCACHE_OBJLIST_CONFIG_WORK 0x00001000 /* show objects with work */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define FSCACHE_OBJLIST_CONFIG_NOWORK 0x00002000 /* show objects without work */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * Add an object to the object list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * - we use the address of the fscache_object structure as the key into the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) void fscache_objlist_add(struct fscache_object *obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct fscache_object *xobj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct rb_node **p = &fscache_object_list.rb_node, *parent = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) ASSERT(RB_EMPTY_NODE(&obj->objlist_link));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) write_lock(&fscache_object_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) while (*p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) parent = *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) xobj = rb_entry(parent, struct fscache_object, objlist_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if (obj < xobj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) p = &(*p)->rb_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) else if (obj > xobj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) p = &(*p)->rb_right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) rb_link_node(&obj->objlist_link, parent, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) rb_insert_color(&obj->objlist_link, &fscache_object_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) write_unlock(&fscache_object_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * Remove an object from the object list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) void fscache_objlist_remove(struct fscache_object *obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (RB_EMPTY_NODE(&obj->objlist_link))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) write_lock(&fscache_object_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) BUG_ON(RB_EMPTY_ROOT(&fscache_object_list));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) rb_erase(&obj->objlist_link, &fscache_object_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) write_unlock(&fscache_object_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * find the object in the tree on or after the specified index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static struct fscache_object *fscache_objlist_lookup(loff_t *_pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct fscache_object *pobj, *obj = NULL, *minobj = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct rb_node *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) unsigned long pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (*_pos >= (unsigned long) ERR_PTR(-ENOENT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) pos = *_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /* banners (can't represent line 0 by pos 0 as that would involve
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * returning a NULL pointer) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (pos == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return (struct fscache_object *)(long)++(*_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (pos < 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return (struct fscache_object *)pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) pobj = (struct fscache_object *)pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) p = fscache_object_list.rb_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) while (p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) obj = rb_entry(p, struct fscache_object, objlist_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (pobj < obj) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (!minobj || minobj > obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) minobj = obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) p = p->rb_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) } else if (pobj > obj) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) p = p->rb_right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) minobj = obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) obj = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (!minobj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) *_pos = (unsigned long) ERR_PTR(-ENOENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) else if (minobj != obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) *_pos = (unsigned long) minobj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) return minobj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * set up the iterator to start reading from the first line
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static void *fscache_objlist_start(struct seq_file *m, loff_t *_pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) __acquires(&fscache_object_list_lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) read_lock(&fscache_object_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) return fscache_objlist_lookup(_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * move to the next line
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static void *fscache_objlist_next(struct seq_file *m, void *v, loff_t *_pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) (*_pos)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) return fscache_objlist_lookup(_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * clean up after reading
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static void fscache_objlist_stop(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) __releases(&fscache_object_list_lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) read_unlock(&fscache_object_list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * display an object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static int fscache_objlist_show(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) struct fscache_objlist_data *data = m->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) struct fscache_object *obj = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct fscache_cookie *cookie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) unsigned long config = data->config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) char _type[3], *type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) u8 *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) if ((unsigned long) v == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) seq_puts(m, "OBJECT PARENT STAT CHLDN OPS OOP IPR EX READS"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) " EM EV FL S"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) " | NETFS_COOKIE_DEF TY FL NETFS_DATA");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if (config & (FSCACHE_OBJLIST_CONFIG_KEY |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) FSCACHE_OBJLIST_CONFIG_AUX))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) seq_puts(m, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (config & FSCACHE_OBJLIST_CONFIG_KEY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) seq_puts(m, "OBJECT_KEY");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if ((config & (FSCACHE_OBJLIST_CONFIG_KEY |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) FSCACHE_OBJLIST_CONFIG_AUX)) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) (FSCACHE_OBJLIST_CONFIG_KEY | FSCACHE_OBJLIST_CONFIG_AUX))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) seq_puts(m, ", ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (config & FSCACHE_OBJLIST_CONFIG_AUX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) seq_puts(m, "AUX_DATA");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) seq_puts(m, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if ((unsigned long) v == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) seq_puts(m, "======== ======== ==== ===== === === === == ====="
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) " == == == ="
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) " | ================ == == ================");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (config & (FSCACHE_OBJLIST_CONFIG_KEY |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) FSCACHE_OBJLIST_CONFIG_AUX))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) seq_puts(m, " ================");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) seq_puts(m, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) /* filter out any unwanted objects */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) #define FILTER(criterion, _yes, _no) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) unsigned long yes = FSCACHE_OBJLIST_CONFIG_##_yes; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) unsigned long no = FSCACHE_OBJLIST_CONFIG_##_no; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (criterion) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (!(config & yes)) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return 0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) } else { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (!(config & no)) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) return 0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) } while(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) cookie = obj->cookie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if (~config) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) FILTER(cookie->def,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) COOKIE, NOCOOKIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) FILTER(fscache_object_is_active(obj) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) obj->n_ops != 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) obj->n_obj_ops != 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) obj->flags ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) !list_empty(&obj->dependents),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) BUSY, IDLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) FILTER(test_bit(FSCACHE_OBJECT_PENDING_WRITE, &obj->flags),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) PENDWR, NOPENDWR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) FILTER(atomic_read(&obj->n_reads),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) READS, NOREADS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) FILTER(obj->events & obj->event_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) EVENTS, NOEVENTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) FILTER(work_busy(&obj->work), WORK, NOWORK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) seq_printf(m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) "%8x %8x %s %5u %3u %3u %3u %2u %5u %2lx %2lx %2lx %1x | ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) obj->debug_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) obj->parent ? obj->parent->debug_id : -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) obj->state->short_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) obj->n_children,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) obj->n_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) obj->n_obj_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) obj->n_in_progress,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) obj->n_exclusive,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) atomic_read(&obj->n_reads),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) obj->event_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) obj->events,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) obj->flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) work_busy(&obj->work));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if (fscache_use_cookie(obj)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) uint16_t keylen = 0, auxlen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) switch (cookie->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) type = "IX";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) type = "DT";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) snprintf(_type, sizeof(_type), "%02u",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) cookie->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) type = _type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) seq_printf(m, "%-16s %s %2lx %16p",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) cookie->def->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) cookie->flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) cookie->netfs_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (config & FSCACHE_OBJLIST_CONFIG_KEY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) keylen = cookie->key_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (config & FSCACHE_OBJLIST_CONFIG_AUX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) auxlen = cookie->aux_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (keylen > 0 || auxlen > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) seq_puts(m, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) p = keylen <= sizeof(cookie->inline_key) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) cookie->inline_key : cookie->key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) for (; keylen > 0; keylen--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) seq_printf(m, "%02x", *p++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (auxlen > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (config & FSCACHE_OBJLIST_CONFIG_KEY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) seq_puts(m, ", ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) p = auxlen <= sizeof(cookie->inline_aux) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) cookie->inline_aux : cookie->aux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) for (; auxlen > 0; auxlen--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) seq_printf(m, "%02x", *p++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) seq_puts(m, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) fscache_unuse_cookie(obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) seq_puts(m, "<no_netfs>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) static const struct seq_operations fscache_objlist_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) .start = fscache_objlist_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) .stop = fscache_objlist_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) .next = fscache_objlist_next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) .show = fscache_objlist_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) * get the configuration for filtering the list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) static void fscache_objlist_config(struct fscache_objlist_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) #ifdef CONFIG_KEYS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) const struct user_key_payload *confkey;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) unsigned long config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) struct key *key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) const char *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) key = request_key(&key_type_user, "fscache:objlist", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) if (IS_ERR(key))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) goto no_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) config = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) confkey = user_key_payload_rcu(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (!confkey) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) /* key was revoked */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) key_put(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) goto no_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) buf = confkey->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) for (len = confkey->datalen - 1; len >= 0; len--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) switch (buf[len]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) case 'K': config |= FSCACHE_OBJLIST_CONFIG_KEY; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) case 'A': config |= FSCACHE_OBJLIST_CONFIG_AUX; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) case 'C': config |= FSCACHE_OBJLIST_CONFIG_COOKIE; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) case 'c': config |= FSCACHE_OBJLIST_CONFIG_NOCOOKIE; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) case 'B': config |= FSCACHE_OBJLIST_CONFIG_BUSY; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) case 'b': config |= FSCACHE_OBJLIST_CONFIG_IDLE; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) case 'W': config |= FSCACHE_OBJLIST_CONFIG_PENDWR; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) case 'w': config |= FSCACHE_OBJLIST_CONFIG_NOPENDWR; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) case 'R': config |= FSCACHE_OBJLIST_CONFIG_READS; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) case 'r': config |= FSCACHE_OBJLIST_CONFIG_NOREADS; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) case 'S': config |= FSCACHE_OBJLIST_CONFIG_WORK; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) case 's': config |= FSCACHE_OBJLIST_CONFIG_NOWORK; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) key_put(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (!(config & (FSCACHE_OBJLIST_CONFIG_COOKIE | FSCACHE_OBJLIST_CONFIG_NOCOOKIE)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) config |= FSCACHE_OBJLIST_CONFIG_COOKIE | FSCACHE_OBJLIST_CONFIG_NOCOOKIE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (!(config & (FSCACHE_OBJLIST_CONFIG_BUSY | FSCACHE_OBJLIST_CONFIG_IDLE)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) config |= FSCACHE_OBJLIST_CONFIG_BUSY | FSCACHE_OBJLIST_CONFIG_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (!(config & (FSCACHE_OBJLIST_CONFIG_PENDWR | FSCACHE_OBJLIST_CONFIG_NOPENDWR)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) config |= FSCACHE_OBJLIST_CONFIG_PENDWR | FSCACHE_OBJLIST_CONFIG_NOPENDWR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (!(config & (FSCACHE_OBJLIST_CONFIG_READS | FSCACHE_OBJLIST_CONFIG_NOREADS)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) config |= FSCACHE_OBJLIST_CONFIG_READS | FSCACHE_OBJLIST_CONFIG_NOREADS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) if (!(config & (FSCACHE_OBJLIST_CONFIG_EVENTS | FSCACHE_OBJLIST_CONFIG_NOEVENTS)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) config |= FSCACHE_OBJLIST_CONFIG_EVENTS | FSCACHE_OBJLIST_CONFIG_NOEVENTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (!(config & (FSCACHE_OBJLIST_CONFIG_WORK | FSCACHE_OBJLIST_CONFIG_NOWORK)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) config |= FSCACHE_OBJLIST_CONFIG_WORK | FSCACHE_OBJLIST_CONFIG_NOWORK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) data->config = config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) no_config:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) data->config = ULONG_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) * open "/proc/fs/fscache/objects" to provide a list of active objects
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) * - can be configured by a user-defined key added to the caller's keyrings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) static int fscache_objlist_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) struct fscache_objlist_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) data = __seq_open_private(file, &fscache_objlist_ops, sizeof(*data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) /* get the configuration key */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) fscache_objlist_config(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) * clean up on close
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) static int fscache_objlist_release(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) struct seq_file *m = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) kfree(m->private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) m->private = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) return seq_release(inode, file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) const struct proc_ops fscache_objlist_proc_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) .proc_open = fscache_objlist_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) .proc_read = seq_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) .proc_lseek = seq_lseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) .proc_release = fscache_objlist_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) };