1 /* 2 * linux/net/sunrpc/sysctl.c 3 * 4 * Sysctl interface to sunrpc module. 5 * 6 * I would prefer to register the sunrpc table below sys/net, but that's 7 * impossible at the moment. 8 */ 9 10 #include <linux/types.h> 11 #include <linux/linkage.h> 12 #include <linux/ctype.h> 13 #include <linux/fs.h> 14 #include <linux/sysctl.h> 15 #include <linux/module.h> 16 17 #include <asm/uaccess.h> 18 #include <linux/sunrpc/types.h> 19 #include <linux/sunrpc/sched.h> 20 #include <linux/sunrpc/stats.h> 21 22 /* 23 * Declare the debug flags here 24 */ 25 unsigned int rpc_debug; 26 unsigned int nfs_debug; 27 unsigned int nfsd_debug; 28 unsigned int nlm_debug; 29 30 #ifdef RPC_DEBUG 31 32 static struct ctl_table_header *sunrpc_table_header; 33 static ctl_table sunrpc_table[]; 34 35 void 36 rpc_register_sysctl(void) 37 { 38 if (!sunrpc_table_header) 39 sunrpc_table_header = register_sysctl_table(sunrpc_table); 40 } 41 42 void 43 rpc_unregister_sysctl(void) 44 { 45 if (sunrpc_table_header) { 46 unregister_sysctl_table(sunrpc_table_header); 47 sunrpc_table_header = NULL; 48 } 49 } 50 51 static int 52 proc_dodebug(ctl_table *table, int write, struct file *file, 53 void __user *buffer, size_t *lenp, loff_t *ppos) 54 { 55 char tmpbuf[20], c, *s; 56 char __user *p; 57 unsigned int value; 58 size_t left, len; 59 60 if ((*ppos && !write) || !*lenp) { 61 *lenp = 0; 62 return 0; 63 } 64 65 left = *lenp; 66 67 if (write) { 68 if (!access_ok(VERIFY_READ, buffer, left)) 69 return -EFAULT; 70 p = buffer; 71 while (left && __get_user(c, p) >= 0 && isspace(c)) 72 left--, p++; 73 if (!left) 74 goto done; 75 76 if (left > sizeof(tmpbuf) - 1) 77 return -EINVAL; 78 if (copy_from_user(tmpbuf, p, left)) 79 return -EFAULT; 80 tmpbuf[left] = '\0'; 81 82 for (s = tmpbuf, value = 0; '0' <= *s && *s <= '9'; s++, left--) 83 value = 10 * value + (*s - '0'); 84 if (*s && !isspace(*s)) 85 return -EINVAL; 86 while (left && isspace(*s)) 87 left--, s++; 88 *(unsigned int *) table->data = value; 89 /* Display the RPC tasks on writing to rpc_debug */ 90 if (table->ctl_name == CTL_RPCDEBUG) { 91 rpc_show_tasks(); 92 } 93 } else { 94 if (!access_ok(VERIFY_WRITE, buffer, left)) 95 return -EFAULT; 96 len = sprintf(tmpbuf, "%d", *(unsigned int *) table->data); 97 if (len > left) 98 len = left; 99 if (__copy_to_user(buffer, tmpbuf, len)) 100 return -EFAULT; 101 if ((left -= len) > 0) { 102 if (put_user('\n', (char __user *)buffer + len)) 103 return -EFAULT; 104 left--; 105 } 106 } 107 108 done: 109 *lenp -= left; 110 *ppos += *lenp; 111 return 0; 112 } 113 114 115 static ctl_table debug_table[] = { 116 { 117 .ctl_name = CTL_RPCDEBUG, 118 .procname = "rpc_debug", 119 .data = &rpc_debug, 120 .maxlen = sizeof(int), 121 .mode = 0644, 122 .proc_handler = &proc_dodebug 123 }, 124 { 125 .ctl_name = CTL_NFSDEBUG, 126 .procname = "nfs_debug", 127 .data = &nfs_debug, 128 .maxlen = sizeof(int), 129 .mode = 0644, 130 .proc_handler = &proc_dodebug 131 }, 132 { 133 .ctl_name = CTL_NFSDDEBUG, 134 .procname = "nfsd_debug", 135 .data = &nfsd_debug, 136 .maxlen = sizeof(int), 137 .mode = 0644, 138 .proc_handler = &proc_dodebug 139 }, 140 { 141 .ctl_name = CTL_NLMDEBUG, 142 .procname = "nlm_debug", 143 .data = &nlm_debug, 144 .maxlen = sizeof(int), 145 .mode = 0644, 146 .proc_handler = &proc_dodebug 147 }, 148 { .ctl_name = 0 } 149 }; 150 151 static ctl_table sunrpc_table[] = { 152 { 153 .ctl_name = CTL_SUNRPC, 154 .procname = "sunrpc", 155 .mode = 0555, 156 .child = debug_table 157 }, 158 { .ctl_name = 0 } 159 }; 160 161 #endif 162