18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* Global fscache object list maintainer and viewer 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) 2009 Red Hat, Inc. All Rights Reserved. 58c2ecf20Sopenharmony_ci * Written by David Howells (dhowells@redhat.com) 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#define FSCACHE_DEBUG_LEVEL COOKIE 98c2ecf20Sopenharmony_ci#include <linux/module.h> 108c2ecf20Sopenharmony_ci#include <linux/proc_fs.h> 118c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 128c2ecf20Sopenharmony_ci#include <linux/slab.h> 138c2ecf20Sopenharmony_ci#include <linux/key.h> 148c2ecf20Sopenharmony_ci#include <keys/user-type.h> 158c2ecf20Sopenharmony_ci#include "internal.h" 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_cistatic struct rb_root fscache_object_list; 188c2ecf20Sopenharmony_cistatic DEFINE_RWLOCK(fscache_object_list_lock); 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistruct fscache_objlist_data { 218c2ecf20Sopenharmony_ci unsigned long config; /* display configuration */ 228c2ecf20Sopenharmony_ci#define FSCACHE_OBJLIST_CONFIG_KEY 0x00000001 /* show object keys */ 238c2ecf20Sopenharmony_ci#define FSCACHE_OBJLIST_CONFIG_AUX 0x00000002 /* show object auxdata */ 248c2ecf20Sopenharmony_ci#define FSCACHE_OBJLIST_CONFIG_COOKIE 0x00000004 /* show objects with cookies */ 258c2ecf20Sopenharmony_ci#define FSCACHE_OBJLIST_CONFIG_NOCOOKIE 0x00000008 /* show objects without cookies */ 268c2ecf20Sopenharmony_ci#define FSCACHE_OBJLIST_CONFIG_BUSY 0x00000010 /* show busy objects */ 278c2ecf20Sopenharmony_ci#define FSCACHE_OBJLIST_CONFIG_IDLE 0x00000020 /* show idle objects */ 288c2ecf20Sopenharmony_ci#define FSCACHE_OBJLIST_CONFIG_PENDWR 0x00000040 /* show objects with pending writes */ 298c2ecf20Sopenharmony_ci#define FSCACHE_OBJLIST_CONFIG_NOPENDWR 0x00000080 /* show objects without pending writes */ 308c2ecf20Sopenharmony_ci#define FSCACHE_OBJLIST_CONFIG_READS 0x00000100 /* show objects with active reads */ 318c2ecf20Sopenharmony_ci#define FSCACHE_OBJLIST_CONFIG_NOREADS 0x00000200 /* show objects without active reads */ 328c2ecf20Sopenharmony_ci#define FSCACHE_OBJLIST_CONFIG_EVENTS 0x00000400 /* show objects with events */ 338c2ecf20Sopenharmony_ci#define FSCACHE_OBJLIST_CONFIG_NOEVENTS 0x00000800 /* show objects without no events */ 348c2ecf20Sopenharmony_ci#define FSCACHE_OBJLIST_CONFIG_WORK 0x00001000 /* show objects with work */ 358c2ecf20Sopenharmony_ci#define FSCACHE_OBJLIST_CONFIG_NOWORK 0x00002000 /* show objects without work */ 368c2ecf20Sopenharmony_ci}; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci/* 398c2ecf20Sopenharmony_ci * Add an object to the object list 408c2ecf20Sopenharmony_ci * - we use the address of the fscache_object structure as the key into the 418c2ecf20Sopenharmony_ci * tree 428c2ecf20Sopenharmony_ci */ 438c2ecf20Sopenharmony_civoid fscache_objlist_add(struct fscache_object *obj) 448c2ecf20Sopenharmony_ci{ 458c2ecf20Sopenharmony_ci struct fscache_object *xobj; 468c2ecf20Sopenharmony_ci struct rb_node **p = &fscache_object_list.rb_node, *parent = NULL; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci ASSERT(RB_EMPTY_NODE(&obj->objlist_link)); 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci write_lock(&fscache_object_list_lock); 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci while (*p) { 538c2ecf20Sopenharmony_ci parent = *p; 548c2ecf20Sopenharmony_ci xobj = rb_entry(parent, struct fscache_object, objlist_link); 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci if (obj < xobj) 578c2ecf20Sopenharmony_ci p = &(*p)->rb_left; 588c2ecf20Sopenharmony_ci else if (obj > xobj) 598c2ecf20Sopenharmony_ci p = &(*p)->rb_right; 608c2ecf20Sopenharmony_ci else 618c2ecf20Sopenharmony_ci BUG(); 628c2ecf20Sopenharmony_ci } 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci rb_link_node(&obj->objlist_link, parent, p); 658c2ecf20Sopenharmony_ci rb_insert_color(&obj->objlist_link, &fscache_object_list); 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci write_unlock(&fscache_object_list_lock); 688c2ecf20Sopenharmony_ci} 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci/* 718c2ecf20Sopenharmony_ci * Remove an object from the object list. 728c2ecf20Sopenharmony_ci */ 738c2ecf20Sopenharmony_civoid fscache_objlist_remove(struct fscache_object *obj) 748c2ecf20Sopenharmony_ci{ 758c2ecf20Sopenharmony_ci if (RB_EMPTY_NODE(&obj->objlist_link)) 768c2ecf20Sopenharmony_ci return; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci write_lock(&fscache_object_list_lock); 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci BUG_ON(RB_EMPTY_ROOT(&fscache_object_list)); 818c2ecf20Sopenharmony_ci rb_erase(&obj->objlist_link, &fscache_object_list); 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci write_unlock(&fscache_object_list_lock); 848c2ecf20Sopenharmony_ci} 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci/* 878c2ecf20Sopenharmony_ci * find the object in the tree on or after the specified index 888c2ecf20Sopenharmony_ci */ 898c2ecf20Sopenharmony_cistatic struct fscache_object *fscache_objlist_lookup(loff_t *_pos) 908c2ecf20Sopenharmony_ci{ 918c2ecf20Sopenharmony_ci struct fscache_object *pobj, *obj = NULL, *minobj = NULL; 928c2ecf20Sopenharmony_ci struct rb_node *p; 938c2ecf20Sopenharmony_ci unsigned long pos; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci if (*_pos >= (unsigned long) ERR_PTR(-ENOENT)) 968c2ecf20Sopenharmony_ci return NULL; 978c2ecf20Sopenharmony_ci pos = *_pos; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci /* banners (can't represent line 0 by pos 0 as that would involve 1008c2ecf20Sopenharmony_ci * returning a NULL pointer) */ 1018c2ecf20Sopenharmony_ci if (pos == 0) 1028c2ecf20Sopenharmony_ci return (struct fscache_object *)(long)++(*_pos); 1038c2ecf20Sopenharmony_ci if (pos < 3) 1048c2ecf20Sopenharmony_ci return (struct fscache_object *)pos; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci pobj = (struct fscache_object *)pos; 1078c2ecf20Sopenharmony_ci p = fscache_object_list.rb_node; 1088c2ecf20Sopenharmony_ci while (p) { 1098c2ecf20Sopenharmony_ci obj = rb_entry(p, struct fscache_object, objlist_link); 1108c2ecf20Sopenharmony_ci if (pobj < obj) { 1118c2ecf20Sopenharmony_ci if (!minobj || minobj > obj) 1128c2ecf20Sopenharmony_ci minobj = obj; 1138c2ecf20Sopenharmony_ci p = p->rb_left; 1148c2ecf20Sopenharmony_ci } else if (pobj > obj) { 1158c2ecf20Sopenharmony_ci p = p->rb_right; 1168c2ecf20Sopenharmony_ci } else { 1178c2ecf20Sopenharmony_ci minobj = obj; 1188c2ecf20Sopenharmony_ci break; 1198c2ecf20Sopenharmony_ci } 1208c2ecf20Sopenharmony_ci obj = NULL; 1218c2ecf20Sopenharmony_ci } 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci if (!minobj) 1248c2ecf20Sopenharmony_ci *_pos = (unsigned long) ERR_PTR(-ENOENT); 1258c2ecf20Sopenharmony_ci else if (minobj != obj) 1268c2ecf20Sopenharmony_ci *_pos = (unsigned long) minobj; 1278c2ecf20Sopenharmony_ci return minobj; 1288c2ecf20Sopenharmony_ci} 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci/* 1318c2ecf20Sopenharmony_ci * set up the iterator to start reading from the first line 1328c2ecf20Sopenharmony_ci */ 1338c2ecf20Sopenharmony_cistatic void *fscache_objlist_start(struct seq_file *m, loff_t *_pos) 1348c2ecf20Sopenharmony_ci __acquires(&fscache_object_list_lock) 1358c2ecf20Sopenharmony_ci{ 1368c2ecf20Sopenharmony_ci read_lock(&fscache_object_list_lock); 1378c2ecf20Sopenharmony_ci return fscache_objlist_lookup(_pos); 1388c2ecf20Sopenharmony_ci} 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci/* 1418c2ecf20Sopenharmony_ci * move to the next line 1428c2ecf20Sopenharmony_ci */ 1438c2ecf20Sopenharmony_cistatic void *fscache_objlist_next(struct seq_file *m, void *v, loff_t *_pos) 1448c2ecf20Sopenharmony_ci{ 1458c2ecf20Sopenharmony_ci (*_pos)++; 1468c2ecf20Sopenharmony_ci return fscache_objlist_lookup(_pos); 1478c2ecf20Sopenharmony_ci} 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci/* 1508c2ecf20Sopenharmony_ci * clean up after reading 1518c2ecf20Sopenharmony_ci */ 1528c2ecf20Sopenharmony_cistatic void fscache_objlist_stop(struct seq_file *m, void *v) 1538c2ecf20Sopenharmony_ci __releases(&fscache_object_list_lock) 1548c2ecf20Sopenharmony_ci{ 1558c2ecf20Sopenharmony_ci read_unlock(&fscache_object_list_lock); 1568c2ecf20Sopenharmony_ci} 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci/* 1598c2ecf20Sopenharmony_ci * display an object 1608c2ecf20Sopenharmony_ci */ 1618c2ecf20Sopenharmony_cistatic int fscache_objlist_show(struct seq_file *m, void *v) 1628c2ecf20Sopenharmony_ci{ 1638c2ecf20Sopenharmony_ci struct fscache_objlist_data *data = m->private; 1648c2ecf20Sopenharmony_ci struct fscache_object *obj = v; 1658c2ecf20Sopenharmony_ci struct fscache_cookie *cookie; 1668c2ecf20Sopenharmony_ci unsigned long config = data->config; 1678c2ecf20Sopenharmony_ci char _type[3], *type; 1688c2ecf20Sopenharmony_ci u8 *p; 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci if ((unsigned long) v == 1) { 1718c2ecf20Sopenharmony_ci seq_puts(m, "OBJECT PARENT STAT CHLDN OPS OOP IPR EX READS" 1728c2ecf20Sopenharmony_ci " EM EV FL S" 1738c2ecf20Sopenharmony_ci " | NETFS_COOKIE_DEF TY FL NETFS_DATA"); 1748c2ecf20Sopenharmony_ci if (config & (FSCACHE_OBJLIST_CONFIG_KEY | 1758c2ecf20Sopenharmony_ci FSCACHE_OBJLIST_CONFIG_AUX)) 1768c2ecf20Sopenharmony_ci seq_puts(m, " "); 1778c2ecf20Sopenharmony_ci if (config & FSCACHE_OBJLIST_CONFIG_KEY) 1788c2ecf20Sopenharmony_ci seq_puts(m, "OBJECT_KEY"); 1798c2ecf20Sopenharmony_ci if ((config & (FSCACHE_OBJLIST_CONFIG_KEY | 1808c2ecf20Sopenharmony_ci FSCACHE_OBJLIST_CONFIG_AUX)) == 1818c2ecf20Sopenharmony_ci (FSCACHE_OBJLIST_CONFIG_KEY | FSCACHE_OBJLIST_CONFIG_AUX)) 1828c2ecf20Sopenharmony_ci seq_puts(m, ", "); 1838c2ecf20Sopenharmony_ci if (config & FSCACHE_OBJLIST_CONFIG_AUX) 1848c2ecf20Sopenharmony_ci seq_puts(m, "AUX_DATA"); 1858c2ecf20Sopenharmony_ci seq_puts(m, "\n"); 1868c2ecf20Sopenharmony_ci return 0; 1878c2ecf20Sopenharmony_ci } 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci if ((unsigned long) v == 2) { 1908c2ecf20Sopenharmony_ci seq_puts(m, "======== ======== ==== ===== === === === == =====" 1918c2ecf20Sopenharmony_ci " == == == =" 1928c2ecf20Sopenharmony_ci " | ================ == == ================"); 1938c2ecf20Sopenharmony_ci if (config & (FSCACHE_OBJLIST_CONFIG_KEY | 1948c2ecf20Sopenharmony_ci FSCACHE_OBJLIST_CONFIG_AUX)) 1958c2ecf20Sopenharmony_ci seq_puts(m, " ================"); 1968c2ecf20Sopenharmony_ci seq_puts(m, "\n"); 1978c2ecf20Sopenharmony_ci return 0; 1988c2ecf20Sopenharmony_ci } 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci /* filter out any unwanted objects */ 2018c2ecf20Sopenharmony_ci#define FILTER(criterion, _yes, _no) \ 2028c2ecf20Sopenharmony_ci do { \ 2038c2ecf20Sopenharmony_ci unsigned long yes = FSCACHE_OBJLIST_CONFIG_##_yes; \ 2048c2ecf20Sopenharmony_ci unsigned long no = FSCACHE_OBJLIST_CONFIG_##_no; \ 2058c2ecf20Sopenharmony_ci if (criterion) { \ 2068c2ecf20Sopenharmony_ci if (!(config & yes)) \ 2078c2ecf20Sopenharmony_ci return 0; \ 2088c2ecf20Sopenharmony_ci } else { \ 2098c2ecf20Sopenharmony_ci if (!(config & no)) \ 2108c2ecf20Sopenharmony_ci return 0; \ 2118c2ecf20Sopenharmony_ci } \ 2128c2ecf20Sopenharmony_ci } while(0) 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci cookie = obj->cookie; 2158c2ecf20Sopenharmony_ci if (~config) { 2168c2ecf20Sopenharmony_ci FILTER(cookie->def, 2178c2ecf20Sopenharmony_ci COOKIE, NOCOOKIE); 2188c2ecf20Sopenharmony_ci FILTER(fscache_object_is_active(obj) || 2198c2ecf20Sopenharmony_ci obj->n_ops != 0 || 2208c2ecf20Sopenharmony_ci obj->n_obj_ops != 0 || 2218c2ecf20Sopenharmony_ci obj->flags || 2228c2ecf20Sopenharmony_ci !list_empty(&obj->dependents), 2238c2ecf20Sopenharmony_ci BUSY, IDLE); 2248c2ecf20Sopenharmony_ci FILTER(test_bit(FSCACHE_OBJECT_PENDING_WRITE, &obj->flags), 2258c2ecf20Sopenharmony_ci PENDWR, NOPENDWR); 2268c2ecf20Sopenharmony_ci FILTER(atomic_read(&obj->n_reads), 2278c2ecf20Sopenharmony_ci READS, NOREADS); 2288c2ecf20Sopenharmony_ci FILTER(obj->events & obj->event_mask, 2298c2ecf20Sopenharmony_ci EVENTS, NOEVENTS); 2308c2ecf20Sopenharmony_ci FILTER(work_busy(&obj->work), WORK, NOWORK); 2318c2ecf20Sopenharmony_ci } 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci seq_printf(m, 2348c2ecf20Sopenharmony_ci "%8x %8x %s %5u %3u %3u %3u %2u %5u %2lx %2lx %2lx %1x | ", 2358c2ecf20Sopenharmony_ci obj->debug_id, 2368c2ecf20Sopenharmony_ci obj->parent ? obj->parent->debug_id : -1, 2378c2ecf20Sopenharmony_ci obj->state->short_name, 2388c2ecf20Sopenharmony_ci obj->n_children, 2398c2ecf20Sopenharmony_ci obj->n_ops, 2408c2ecf20Sopenharmony_ci obj->n_obj_ops, 2418c2ecf20Sopenharmony_ci obj->n_in_progress, 2428c2ecf20Sopenharmony_ci obj->n_exclusive, 2438c2ecf20Sopenharmony_ci atomic_read(&obj->n_reads), 2448c2ecf20Sopenharmony_ci obj->event_mask, 2458c2ecf20Sopenharmony_ci obj->events, 2468c2ecf20Sopenharmony_ci obj->flags, 2478c2ecf20Sopenharmony_ci work_busy(&obj->work)); 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci if (fscache_use_cookie(obj)) { 2508c2ecf20Sopenharmony_ci uint16_t keylen = 0, auxlen = 0; 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci switch (cookie->type) { 2538c2ecf20Sopenharmony_ci case 0: 2548c2ecf20Sopenharmony_ci type = "IX"; 2558c2ecf20Sopenharmony_ci break; 2568c2ecf20Sopenharmony_ci case 1: 2578c2ecf20Sopenharmony_ci type = "DT"; 2588c2ecf20Sopenharmony_ci break; 2598c2ecf20Sopenharmony_ci default: 2608c2ecf20Sopenharmony_ci snprintf(_type, sizeof(_type), "%02u", 2618c2ecf20Sopenharmony_ci cookie->type); 2628c2ecf20Sopenharmony_ci type = _type; 2638c2ecf20Sopenharmony_ci break; 2648c2ecf20Sopenharmony_ci } 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci seq_printf(m, "%-16s %s %2lx %16p", 2678c2ecf20Sopenharmony_ci cookie->def->name, 2688c2ecf20Sopenharmony_ci type, 2698c2ecf20Sopenharmony_ci cookie->flags, 2708c2ecf20Sopenharmony_ci cookie->netfs_data); 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci if (config & FSCACHE_OBJLIST_CONFIG_KEY) 2738c2ecf20Sopenharmony_ci keylen = cookie->key_len; 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci if (config & FSCACHE_OBJLIST_CONFIG_AUX) 2768c2ecf20Sopenharmony_ci auxlen = cookie->aux_len; 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci if (keylen > 0 || auxlen > 0) { 2798c2ecf20Sopenharmony_ci seq_puts(m, " "); 2808c2ecf20Sopenharmony_ci p = keylen <= sizeof(cookie->inline_key) ? 2818c2ecf20Sopenharmony_ci cookie->inline_key : cookie->key; 2828c2ecf20Sopenharmony_ci for (; keylen > 0; keylen--) 2838c2ecf20Sopenharmony_ci seq_printf(m, "%02x", *p++); 2848c2ecf20Sopenharmony_ci if (auxlen > 0) { 2858c2ecf20Sopenharmony_ci if (config & FSCACHE_OBJLIST_CONFIG_KEY) 2868c2ecf20Sopenharmony_ci seq_puts(m, ", "); 2878c2ecf20Sopenharmony_ci p = auxlen <= sizeof(cookie->inline_aux) ? 2888c2ecf20Sopenharmony_ci cookie->inline_aux : cookie->aux; 2898c2ecf20Sopenharmony_ci for (; auxlen > 0; auxlen--) 2908c2ecf20Sopenharmony_ci seq_printf(m, "%02x", *p++); 2918c2ecf20Sopenharmony_ci } 2928c2ecf20Sopenharmony_ci } 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci seq_puts(m, "\n"); 2958c2ecf20Sopenharmony_ci fscache_unuse_cookie(obj); 2968c2ecf20Sopenharmony_ci } else { 2978c2ecf20Sopenharmony_ci seq_puts(m, "<no_netfs>\n"); 2988c2ecf20Sopenharmony_ci } 2998c2ecf20Sopenharmony_ci return 0; 3008c2ecf20Sopenharmony_ci} 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_cistatic const struct seq_operations fscache_objlist_ops = { 3038c2ecf20Sopenharmony_ci .start = fscache_objlist_start, 3048c2ecf20Sopenharmony_ci .stop = fscache_objlist_stop, 3058c2ecf20Sopenharmony_ci .next = fscache_objlist_next, 3068c2ecf20Sopenharmony_ci .show = fscache_objlist_show, 3078c2ecf20Sopenharmony_ci}; 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci/* 3108c2ecf20Sopenharmony_ci * get the configuration for filtering the list 3118c2ecf20Sopenharmony_ci */ 3128c2ecf20Sopenharmony_cistatic void fscache_objlist_config(struct fscache_objlist_data *data) 3138c2ecf20Sopenharmony_ci{ 3148c2ecf20Sopenharmony_ci#ifdef CONFIG_KEYS 3158c2ecf20Sopenharmony_ci const struct user_key_payload *confkey; 3168c2ecf20Sopenharmony_ci unsigned long config; 3178c2ecf20Sopenharmony_ci struct key *key; 3188c2ecf20Sopenharmony_ci const char *buf; 3198c2ecf20Sopenharmony_ci int len; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci key = request_key(&key_type_user, "fscache:objlist", NULL); 3228c2ecf20Sopenharmony_ci if (IS_ERR(key)) 3238c2ecf20Sopenharmony_ci goto no_config; 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci config = 0; 3268c2ecf20Sopenharmony_ci rcu_read_lock(); 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci confkey = user_key_payload_rcu(key); 3298c2ecf20Sopenharmony_ci if (!confkey) { 3308c2ecf20Sopenharmony_ci /* key was revoked */ 3318c2ecf20Sopenharmony_ci rcu_read_unlock(); 3328c2ecf20Sopenharmony_ci key_put(key); 3338c2ecf20Sopenharmony_ci goto no_config; 3348c2ecf20Sopenharmony_ci } 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci buf = confkey->data; 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci for (len = confkey->datalen - 1; len >= 0; len--) { 3398c2ecf20Sopenharmony_ci switch (buf[len]) { 3408c2ecf20Sopenharmony_ci case 'K': config |= FSCACHE_OBJLIST_CONFIG_KEY; break; 3418c2ecf20Sopenharmony_ci case 'A': config |= FSCACHE_OBJLIST_CONFIG_AUX; break; 3428c2ecf20Sopenharmony_ci case 'C': config |= FSCACHE_OBJLIST_CONFIG_COOKIE; break; 3438c2ecf20Sopenharmony_ci case 'c': config |= FSCACHE_OBJLIST_CONFIG_NOCOOKIE; break; 3448c2ecf20Sopenharmony_ci case 'B': config |= FSCACHE_OBJLIST_CONFIG_BUSY; break; 3458c2ecf20Sopenharmony_ci case 'b': config |= FSCACHE_OBJLIST_CONFIG_IDLE; break; 3468c2ecf20Sopenharmony_ci case 'W': config |= FSCACHE_OBJLIST_CONFIG_PENDWR; break; 3478c2ecf20Sopenharmony_ci case 'w': config |= FSCACHE_OBJLIST_CONFIG_NOPENDWR; break; 3488c2ecf20Sopenharmony_ci case 'R': config |= FSCACHE_OBJLIST_CONFIG_READS; break; 3498c2ecf20Sopenharmony_ci case 'r': config |= FSCACHE_OBJLIST_CONFIG_NOREADS; break; 3508c2ecf20Sopenharmony_ci case 'S': config |= FSCACHE_OBJLIST_CONFIG_WORK; break; 3518c2ecf20Sopenharmony_ci case 's': config |= FSCACHE_OBJLIST_CONFIG_NOWORK; break; 3528c2ecf20Sopenharmony_ci } 3538c2ecf20Sopenharmony_ci } 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci rcu_read_unlock(); 3568c2ecf20Sopenharmony_ci key_put(key); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci if (!(config & (FSCACHE_OBJLIST_CONFIG_COOKIE | FSCACHE_OBJLIST_CONFIG_NOCOOKIE))) 3598c2ecf20Sopenharmony_ci config |= FSCACHE_OBJLIST_CONFIG_COOKIE | FSCACHE_OBJLIST_CONFIG_NOCOOKIE; 3608c2ecf20Sopenharmony_ci if (!(config & (FSCACHE_OBJLIST_CONFIG_BUSY | FSCACHE_OBJLIST_CONFIG_IDLE))) 3618c2ecf20Sopenharmony_ci config |= FSCACHE_OBJLIST_CONFIG_BUSY | FSCACHE_OBJLIST_CONFIG_IDLE; 3628c2ecf20Sopenharmony_ci if (!(config & (FSCACHE_OBJLIST_CONFIG_PENDWR | FSCACHE_OBJLIST_CONFIG_NOPENDWR))) 3638c2ecf20Sopenharmony_ci config |= FSCACHE_OBJLIST_CONFIG_PENDWR | FSCACHE_OBJLIST_CONFIG_NOPENDWR; 3648c2ecf20Sopenharmony_ci if (!(config & (FSCACHE_OBJLIST_CONFIG_READS | FSCACHE_OBJLIST_CONFIG_NOREADS))) 3658c2ecf20Sopenharmony_ci config |= FSCACHE_OBJLIST_CONFIG_READS | FSCACHE_OBJLIST_CONFIG_NOREADS; 3668c2ecf20Sopenharmony_ci if (!(config & (FSCACHE_OBJLIST_CONFIG_EVENTS | FSCACHE_OBJLIST_CONFIG_NOEVENTS))) 3678c2ecf20Sopenharmony_ci config |= FSCACHE_OBJLIST_CONFIG_EVENTS | FSCACHE_OBJLIST_CONFIG_NOEVENTS; 3688c2ecf20Sopenharmony_ci if (!(config & (FSCACHE_OBJLIST_CONFIG_WORK | FSCACHE_OBJLIST_CONFIG_NOWORK))) 3698c2ecf20Sopenharmony_ci config |= FSCACHE_OBJLIST_CONFIG_WORK | FSCACHE_OBJLIST_CONFIG_NOWORK; 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci data->config = config; 3728c2ecf20Sopenharmony_ci return; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_cino_config: 3758c2ecf20Sopenharmony_ci#endif 3768c2ecf20Sopenharmony_ci data->config = ULONG_MAX; 3778c2ecf20Sopenharmony_ci} 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci/* 3808c2ecf20Sopenharmony_ci * open "/proc/fs/fscache/objects" to provide a list of active objects 3818c2ecf20Sopenharmony_ci * - can be configured by a user-defined key added to the caller's keyrings 3828c2ecf20Sopenharmony_ci */ 3838c2ecf20Sopenharmony_cistatic int fscache_objlist_open(struct inode *inode, struct file *file) 3848c2ecf20Sopenharmony_ci{ 3858c2ecf20Sopenharmony_ci struct fscache_objlist_data *data; 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci data = __seq_open_private(file, &fscache_objlist_ops, sizeof(*data)); 3888c2ecf20Sopenharmony_ci if (!data) 3898c2ecf20Sopenharmony_ci return -ENOMEM; 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci /* get the configuration key */ 3928c2ecf20Sopenharmony_ci fscache_objlist_config(data); 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci return 0; 3958c2ecf20Sopenharmony_ci} 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci/* 3988c2ecf20Sopenharmony_ci * clean up on close 3998c2ecf20Sopenharmony_ci */ 4008c2ecf20Sopenharmony_cistatic int fscache_objlist_release(struct inode *inode, struct file *file) 4018c2ecf20Sopenharmony_ci{ 4028c2ecf20Sopenharmony_ci struct seq_file *m = file->private_data; 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci kfree(m->private); 4058c2ecf20Sopenharmony_ci m->private = NULL; 4068c2ecf20Sopenharmony_ci return seq_release(inode, file); 4078c2ecf20Sopenharmony_ci} 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ciconst struct proc_ops fscache_objlist_proc_ops = { 4108c2ecf20Sopenharmony_ci .proc_open = fscache_objlist_open, 4118c2ecf20Sopenharmony_ci .proc_read = seq_read, 4128c2ecf20Sopenharmony_ci .proc_lseek = seq_lseek, 4138c2ecf20Sopenharmony_ci .proc_release = fscache_objlist_release, 4148c2ecf20Sopenharmony_ci}; 415