Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v5.10-rc2 192 lines 3.6 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * linux/net/sunrpc/sysctl.c 4 * 5 * Sysctl interface to sunrpc module. 6 * 7 * I would prefer to register the sunrpc table below sys/net, but that's 8 * impossible at the moment. 9 */ 10 11#include <linux/types.h> 12#include <linux/linkage.h> 13#include <linux/ctype.h> 14#include <linux/fs.h> 15#include <linux/sysctl.h> 16#include <linux/module.h> 17 18#include <linux/uaccess.h> 19#include <linux/sunrpc/types.h> 20#include <linux/sunrpc/sched.h> 21#include <linux/sunrpc/stats.h> 22#include <linux/sunrpc/svc_xprt.h> 23 24#include "netns.h" 25 26/* 27 * Declare the debug flags here 28 */ 29unsigned int rpc_debug; 30EXPORT_SYMBOL_GPL(rpc_debug); 31 32unsigned int nfs_debug; 33EXPORT_SYMBOL_GPL(nfs_debug); 34 35unsigned int nfsd_debug; 36EXPORT_SYMBOL_GPL(nfsd_debug); 37 38unsigned int nlm_debug; 39EXPORT_SYMBOL_GPL(nlm_debug); 40 41#if IS_ENABLED(CONFIG_SUNRPC_DEBUG) 42 43static struct ctl_table_header *sunrpc_table_header; 44static struct ctl_table sunrpc_table[]; 45 46void 47rpc_register_sysctl(void) 48{ 49 if (!sunrpc_table_header) 50 sunrpc_table_header = register_sysctl_table(sunrpc_table); 51} 52 53void 54rpc_unregister_sysctl(void) 55{ 56 if (sunrpc_table_header) { 57 unregister_sysctl_table(sunrpc_table_header); 58 sunrpc_table_header = NULL; 59 } 60} 61 62static int proc_do_xprt(struct ctl_table *table, int write, 63 void *buffer, size_t *lenp, loff_t *ppos) 64{ 65 char tmpbuf[256]; 66 size_t len; 67 68 if ((*ppos && !write) || !*lenp) { 69 *lenp = 0; 70 return 0; 71 } 72 len = svc_print_xprts(tmpbuf, sizeof(tmpbuf)); 73 *lenp = memory_read_from_buffer(buffer, *lenp, ppos, tmpbuf, len); 74 75 if (*lenp < 0) { 76 *lenp = 0; 77 return -EINVAL; 78 } 79 return 0; 80} 81 82static int 83proc_dodebug(struct ctl_table *table, int write, void *buffer, size_t *lenp, 84 loff_t *ppos) 85{ 86 char tmpbuf[20], *s = NULL; 87 char *p; 88 unsigned int value; 89 size_t left, len; 90 91 if ((*ppos && !write) || !*lenp) { 92 *lenp = 0; 93 return 0; 94 } 95 96 left = *lenp; 97 98 if (write) { 99 p = buffer; 100 while (left && isspace(*p)) { 101 left--; 102 p++; 103 } 104 if (!left) 105 goto done; 106 107 if (left > sizeof(tmpbuf) - 1) 108 return -EINVAL; 109 memcpy(tmpbuf, p, left); 110 tmpbuf[left] = '\0'; 111 112 value = simple_strtol(tmpbuf, &s, 0); 113 if (s) { 114 left -= (s - tmpbuf); 115 if (left && !isspace(*s)) 116 return -EINVAL; 117 while (left && isspace(*s)) { 118 left--; 119 s++; 120 } 121 } else 122 left = 0; 123 *(unsigned int *) table->data = value; 124 /* Display the RPC tasks on writing to rpc_debug */ 125 if (strcmp(table->procname, "rpc_debug") == 0) 126 rpc_show_tasks(&init_net); 127 } else { 128 len = sprintf(tmpbuf, "0x%04x", *(unsigned int *) table->data); 129 if (len > left) 130 len = left; 131 memcpy(buffer, tmpbuf, len); 132 if ((left -= len) > 0) { 133 *((char *)buffer + len) = '\n'; 134 left--; 135 } 136 } 137 138done: 139 *lenp -= left; 140 *ppos += *lenp; 141 return 0; 142} 143 144 145static struct ctl_table debug_table[] = { 146 { 147 .procname = "rpc_debug", 148 .data = &rpc_debug, 149 .maxlen = sizeof(int), 150 .mode = 0644, 151 .proc_handler = proc_dodebug 152 }, 153 { 154 .procname = "nfs_debug", 155 .data = &nfs_debug, 156 .maxlen = sizeof(int), 157 .mode = 0644, 158 .proc_handler = proc_dodebug 159 }, 160 { 161 .procname = "nfsd_debug", 162 .data = &nfsd_debug, 163 .maxlen = sizeof(int), 164 .mode = 0644, 165 .proc_handler = proc_dodebug 166 }, 167 { 168 .procname = "nlm_debug", 169 .data = &nlm_debug, 170 .maxlen = sizeof(int), 171 .mode = 0644, 172 .proc_handler = proc_dodebug 173 }, 174 { 175 .procname = "transports", 176 .maxlen = 256, 177 .mode = 0444, 178 .proc_handler = proc_do_xprt, 179 }, 180 { } 181}; 182 183static struct ctl_table sunrpc_table[] = { 184 { 185 .procname = "sunrpc", 186 .mode = 0555, 187 .child = debug_table 188 }, 189 { } 190}; 191 192#endif