2 * sysctl.c: General linux system control interface
4 * Begun 24 March 1995, Stephen Tweedie
5 * Added /proc support, Dec 1995
6 * Added bdflush entry and intvec min/max checking, 2/23/96, Tom Dyas.
7 * Added hooks for /proc/sys/net (minor, minor patch), 96/4/1, Mike Shaver.
8 * Added kernel/java-{interpreter,appletviewer}, 96/5/10, Mike Shaver.
9 * Dynamic registration fixes, Stephen Tweedie.
10 * Added kswapd-interval, ctrl-alt-del, printk stuff, 1/8/97, Chris Horn.
11 * Made sysctl support optional via CONFIG_SYSCTL, 1/10/97, Chris
13 * Added proc_doulongvec_ms_jiffies_minmax, 09/08/99, Carlos H. Bauer.
14 * Added proc_doulongvec_minmax, 09/08/99, Carlos H. Bauer.
15 * Changed linked lists to use list.h instead of lists.h, 02/24/00, Bill
17 * The list_for_each() macro wasn't appropriate for the sysctl loop.
18 * Removed it and replaced it with older style, 03/23/00, Bill Wendling
21 #include <linux/config.h>
22 #include <linux/malloc.h>
23 #include <linux/sysctl.h>
24 #include <linux/swapctl.h>
25 #include <linux/proc_fs.h>
26 #include <linux/ctype.h>
27 #include <linux/utsname.h>
28 #include <linux/capability.h>
29 #include <linux/smp_lock.h>
30 #include <linux/init.h>
31 #include <linux/sysrq.h>
32 #include <linux/highuid.h>
34 #include <asm/uaccess.h>
36 #ifdef CONFIG_ROOT_NFS
37 #include <linux/nfs_fs.h>
40 #if defined(CONFIG_SYSCTL)
42 /* External variables not in a header file. */
43 extern int panic_timeout
;
44 extern int console_loglevel
, C_A_D
;
45 extern int bdf_prm
[], bdflush_min
[], bdflush_max
[];
46 extern int sysctl_overcommit_memory
;
47 extern int max_threads
;
48 extern int nr_queued_signals
, max_queued_signals
;
49 extern int sysrq_enabled
;
51 /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
52 static int maxolduid
= 65535;
56 extern char modprobe_path
[];
58 extern char hotplug_path
[];
61 #ifdef CONFIG_CHR_DEV_SG
62 extern int sg_big_buff
;
65 extern size_t shm_ctlmax
;
66 extern int msg_ctlmax
;
67 extern int msg_ctlmnb
;
68 extern int msg_ctlmni
;
69 extern int sem_ctls
[];
73 extern char reboot_command
[];
74 extern int stop_a_enabled
;
77 extern unsigned long htab_reclaim_on
, zero_paged_on
, powersave_nap
;
78 int proc_dol2crvec(ctl_table
*table
, int write
, struct file
*filp
,
79 void *buffer
, size_t *lenp
);
82 #ifdef CONFIG_BSD_PROCESS_ACCT
83 extern int acct_parm
[];
86 extern int pgt_cache_water
[];
88 static int parse_table(int *, int, void *, size_t *, void *, size_t,
89 ctl_table
*, void **);
90 static int proc_doutsstring(ctl_table
*table
, int write
, struct file
*filp
,
91 void *buffer
, size_t *lenp
);
93 static ctl_table root_table
[];
94 static struct ctl_table_header root_table_header
=
95 { root_table
, LIST_HEAD_INIT(root_table_header
.ctl_entry
) };
97 static ctl_table kern_table
[];
98 static ctl_table vm_table
[];
100 extern ctl_table net_table
[];
102 static ctl_table proc_table
[];
103 static ctl_table fs_table
[];
104 static ctl_table debug_table
[];
105 static ctl_table dev_table
[];
106 extern ctl_table random_table
[];
108 /* /proc declarations: */
110 #ifdef CONFIG_PROC_FS
112 static ssize_t
proc_readsys(struct file
*, char *, size_t, loff_t
*);
113 static ssize_t
proc_writesys(struct file
*, const char *, size_t, loff_t
*);
114 static int proc_sys_permission(struct inode
*, int);
116 struct file_operations proc_sys_file_operations
= {
118 write
: proc_writesys
,
121 static struct inode_operations proc_sys_inode_operations
= {
122 permission
: proc_sys_permission
,
125 extern struct proc_dir_entry
*proc_sys_root
;
127 static void register_proc_table(ctl_table
*, struct proc_dir_entry
*);
128 static void unregister_proc_table(ctl_table
*, struct proc_dir_entry
*);
131 extern int inodes_stat
[];
132 extern int dentry_stat
[];
134 /* The default sysctl tables: */
136 static ctl_table root_table
[] = {
137 {CTL_KERN
, "kernel", NULL
, 0, 0555, kern_table
},
138 {CTL_VM
, "vm", NULL
, 0, 0555, vm_table
},
140 {CTL_NET
, "net", NULL
, 0, 0555, net_table
},
142 {CTL_PROC
, "proc", NULL
, 0, 0555, proc_table
},
143 {CTL_FS
, "fs", NULL
, 0, 0555, fs_table
},
144 {CTL_DEBUG
, "debug", NULL
, 0, 0555, debug_table
},
145 {CTL_DEV
, "dev", NULL
, 0, 0555, dev_table
},
149 static ctl_table kern_table
[] = {
150 {KERN_OSTYPE
, "ostype", system_utsname
.sysname
, 64,
151 0444, NULL
, &proc_doutsstring
, &sysctl_string
},
152 {KERN_OSRELEASE
, "osrelease", system_utsname
.release
, 64,
153 0444, NULL
, &proc_doutsstring
, &sysctl_string
},
154 {KERN_VERSION
, "version", system_utsname
.version
, 64,
155 0444, NULL
, &proc_doutsstring
, &sysctl_string
},
156 {KERN_NODENAME
, "hostname", system_utsname
.nodename
, 64,
157 0644, NULL
, &proc_doutsstring
, &sysctl_string
},
158 {KERN_DOMAINNAME
, "domainname", system_utsname
.domainname
, 64,
159 0644, NULL
, &proc_doutsstring
, &sysctl_string
},
160 {KERN_PANIC
, "panic", &panic_timeout
, sizeof(int),
161 0644, NULL
, &proc_dointvec
},
162 {KERN_CAP_BSET
, "cap-bound", &cap_bset
, sizeof(kernel_cap_t
),
163 0600, NULL
, &proc_dointvec_bset
},
164 #ifdef CONFIG_BLK_DEV_INITRD
165 {KERN_REALROOTDEV
, "real-root-dev", &real_root_dev
, sizeof(int),
166 0644, NULL
, &proc_dointvec
},
169 {KERN_SPARC_REBOOT
, "reboot-cmd", reboot_command
,
170 256, 0644, NULL
, &proc_dostring
, &sysctl_string
},
171 {KERN_SPARC_STOP_A
, "stop-a", &stop_a_enabled
, sizeof (int),
172 0644, NULL
, &proc_dointvec
},
175 {KERN_PPC_HTABRECLAIM
, "htab-reclaim", &htab_reclaim_on
, sizeof(int),
176 0644, NULL
, &proc_dointvec
},
177 {KERN_PPC_ZEROPAGED
, "zero-paged", &zero_paged_on
, sizeof(int),
178 0644, NULL
, &proc_dointvec
},
179 {KERN_PPC_POWERSAVE_NAP
, "powersave-nap", &powersave_nap
, sizeof(int),
180 0644, NULL
, &proc_dointvec
},
181 {KERN_PPC_L2CR
, "l2cr", NULL
, 0,
182 0644, NULL
, &proc_dol2crvec
},
184 {KERN_CTLALTDEL
, "ctrl-alt-del", &C_A_D
, sizeof(int),
185 0644, NULL
, &proc_dointvec
},
186 {KERN_PRINTK
, "printk", &console_loglevel
, 4*sizeof(int),
187 0644, NULL
, &proc_dointvec
},
189 {KERN_MODPROBE
, "modprobe", &modprobe_path
, 256,
190 0644, NULL
, &proc_dostring
, &sysctl_string
},
191 #ifdef CONFIG_HOTPLUG
192 {KERN_HOTPLUG
, "hotplug", &hotplug_path
, 256,
193 0644, NULL
, &proc_dostring
, &sysctl_string
},
196 #ifdef CONFIG_CHR_DEV_SG
197 {KERN_SG_BIG_BUFF
, "sg-big-buff", &sg_big_buff
, sizeof (int),
198 0444, NULL
, &proc_dointvec
},
200 #ifdef CONFIG_BSD_PROCESS_ACCT
201 {KERN_ACCT
, "acct", &acct_parm
, 3*sizeof(int),
202 0644, NULL
, &proc_dointvec
},
204 {KERN_RTSIGNR
, "rtsig-nr", &nr_queued_signals
, sizeof(int),
205 0444, NULL
, &proc_dointvec
},
206 {KERN_RTSIGMAX
, "rtsig-max", &max_queued_signals
, sizeof(int),
207 0644, NULL
, &proc_dointvec
},
208 #ifdef CONFIG_SYSVIPC
209 {KERN_SHMMAX
, "shmmax", &shm_ctlmax
, sizeof (size_t),
210 0644, NULL
, &proc_doulongvec_minmax
},
211 {KERN_MSGMAX
, "msgmax", &msg_ctlmax
, sizeof (int),
212 0644, NULL
, &proc_dointvec
},
213 {KERN_MSGMNI
, "msgmni", &msg_ctlmni
, sizeof (int),
214 0644, NULL
, &proc_dointvec
},
215 {KERN_MSGMNB
, "msgmnb", &msg_ctlmnb
, sizeof (int),
216 0644, NULL
, &proc_dointvec
},
217 {KERN_SEM
, "sem", &sem_ctls
, 4*sizeof (int),
218 0644, NULL
, &proc_dointvec
},
220 #ifdef CONFIG_MAGIC_SYSRQ
221 {KERN_SYSRQ
, "sysrq", &sysrq_enabled
, sizeof (int),
222 0644, NULL
, &proc_dointvec
},
224 {KERN_MAX_THREADS
, "threads-max", &max_threads
, sizeof(int),
225 0644, NULL
, &proc_dointvec
},
226 {KERN_RANDOM
, "random", NULL
, 0, 0555, random_table
},
227 {KERN_OVERFLOWUID
, "overflowuid", &overflowuid
, sizeof(int), 0644, NULL
,
228 &proc_dointvec_minmax
, &sysctl_intvec
, NULL
,
229 &minolduid
, &maxolduid
},
230 {KERN_OVERFLOWGID
, "overflowgid", &overflowgid
, sizeof(int), 0644, NULL
,
231 &proc_dointvec_minmax
, &sysctl_intvec
, NULL
,
232 &minolduid
, &maxolduid
},
236 static ctl_table vm_table
[] = {
237 {VM_FREEPG
, "freepages",
238 &freepages
, sizeof(freepages_t
), 0644, NULL
, &proc_dointvec
},
239 {VM_BDFLUSH
, "bdflush", &bdf_prm
, 9*sizeof(int), 0644, NULL
,
240 &proc_dointvec_minmax
, &sysctl_intvec
, NULL
,
241 &bdflush_min
, &bdflush_max
},
242 {VM_OVERCOMMIT_MEMORY
, "overcommit_memory", &sysctl_overcommit_memory
,
243 sizeof(sysctl_overcommit_memory
), 0644, NULL
, &proc_dointvec
},
244 {VM_BUFFERMEM
, "buffermem",
245 &buffer_mem
, sizeof(buffer_mem_t
), 0644, NULL
, &proc_dointvec
},
246 {VM_PAGECACHE
, "pagecache",
247 &page_cache
, sizeof(buffer_mem_t
), 0644, NULL
, &proc_dointvec
},
248 {VM_PAGERDAEMON
, "kswapd",
249 &pager_daemon
, sizeof(pager_daemon_t
), 0644, NULL
, &proc_dointvec
},
250 {VM_PGT_CACHE
, "pagetable_cache",
251 &pgt_cache_water
, 2*sizeof(int), 0644, NULL
, &proc_dointvec
},
252 {VM_PAGE_CLUSTER
, "page-cluster",
253 &page_cluster
, sizeof(int), 0644, NULL
, &proc_dointvec
},
257 static ctl_table proc_table
[] = {
261 static ctl_table fs_table
[] = {
262 {FS_NRINODE
, "inode-nr", &inodes_stat
, 2*sizeof(int),
263 0444, NULL
, &proc_dointvec
},
264 {FS_STATINODE
, "inode-state", &inodes_stat
, 7*sizeof(int),
265 0444, NULL
, &proc_dointvec
},
266 {FS_NRFILE
, "file-nr", &files_stat
, 3*sizeof(int),
267 0444, NULL
, &proc_dointvec
},
268 {FS_MAXFILE
, "file-max", &files_stat
.max_files
, sizeof(int),
269 0644, NULL
, &proc_dointvec
},
270 {FS_NRSUPER
, "super-nr", &nr_super_blocks
, sizeof(int),
271 0444, NULL
, &proc_dointvec
},
272 {FS_MAXSUPER
, "super-max", &max_super_blocks
, sizeof(int),
273 0644, NULL
, &proc_dointvec
},
274 {FS_NRDQUOT
, "dquot-nr", &nr_dquots
, 2*sizeof(int),
275 0444, NULL
, &proc_dointvec
},
276 {FS_MAXDQUOT
, "dquot-max", &max_dquots
, sizeof(int),
277 0644, NULL
, &proc_dointvec
},
278 {FS_DENTRY
, "dentry-state", &dentry_stat
, 6*sizeof(int),
279 0444, NULL
, &proc_dointvec
},
280 {FS_OVERFLOWUID
, "overflowuid", &fs_overflowuid
, sizeof(int), 0644, NULL
,
281 &proc_dointvec_minmax
, &sysctl_intvec
, NULL
,
282 &minolduid
, &maxolduid
},
283 {FS_OVERFLOWGID
, "overflowgid", &fs_overflowgid
, sizeof(int), 0644, NULL
,
284 &proc_dointvec_minmax
, &sysctl_intvec
, NULL
,
285 &minolduid
, &maxolduid
},
289 static ctl_table debug_table
[] = {
293 static ctl_table dev_table
[] = {
297 extern void init_irq_proc (void);
299 void __init
sysctl_init(void)
301 #ifdef CONFIG_PROC_FS
302 register_proc_table(root_table
, proc_sys_root
);
307 int do_sysctl(int *name
, int nlen
, void *oldval
, size_t *oldlenp
,
308 void *newval
, size_t newlen
)
310 struct list_head
*tmp
;
312 if (nlen
== 0 || nlen
>= CTL_MAXNAME
)
316 if (!oldlenp
|| get_user(old_len
, oldlenp
))
319 tmp
= &root_table_header
.ctl_entry
;
321 struct ctl_table_header
*head
=
322 list_entry(tmp
, struct ctl_table_header
, ctl_entry
);
323 void *context
= NULL
;
324 int error
= parse_table(name
, nlen
, oldval
, oldlenp
,
325 newval
, newlen
, head
->ctl_table
,
329 if (error
!= -ENOTDIR
)
332 } while (tmp
!= &root_table_header
.ctl_entry
);
336 extern asmlinkage
long sys_sysctl(struct __sysctl_args
*args
)
338 struct __sysctl_args tmp
;
341 if (copy_from_user(&tmp
, args
, sizeof(tmp
)))
345 error
= do_sysctl(tmp
.name
, tmp
.nlen
, tmp
.oldval
, tmp
.oldlenp
,
346 tmp
.newval
, tmp
.newlen
);
352 * ctl_perm does NOT grant the superuser all rights automatically, because
353 * some sysctl variables are readonly even to root.
356 static int test_perm(int mode
, int op
)
360 else if (in_egroup_p(0))
362 if ((mode
& op
& 0007) == op
)
367 static inline int ctl_perm(ctl_table
*table
, int op
)
369 return test_perm(table
->mode
, op
);
372 static int parse_table(int *name
, int nlen
,
373 void *oldval
, size_t *oldlenp
,
374 void *newval
, size_t newlen
,
375 ctl_table
*table
, void **context
)
381 if (get_user(n
, name
))
383 for ( ; table
->ctl_name
; table
++) {
384 if (n
== table
->ctl_name
|| table
->ctl_name
== CTL_ANY
) {
387 if (ctl_perm(table
, 001))
389 if (table
->strategy
) {
390 error
= table
->strategy(
393 newval
, newlen
, context
);
399 table
= table
->child
;
402 error
= do_sysctl_strategy(table
, name
, nlen
,
404 newval
, newlen
, context
);
411 /* Perform the actual read/write of a sysctl table entry. */
412 int do_sysctl_strategy (ctl_table
*table
,
414 void *oldval
, size_t *oldlenp
,
415 void *newval
, size_t newlen
, void **context
)
423 if (ctl_perm(table
, op
))
426 if (table
->strategy
) {
427 rc
= table
->strategy(table
, name
, nlen
, oldval
, oldlenp
,
428 newval
, newlen
, context
);
435 /* If there is no strategy routine, or if the strategy returns
436 * zero, proceed with automatic r/w */
437 if (table
->data
&& table
->maxlen
) {
438 if (oldval
&& oldlenp
) {
439 get_user(len
, oldlenp
);
441 if (len
> table
->maxlen
)
443 if(copy_to_user(oldval
, table
->data
, len
))
445 if(put_user(len
, oldlenp
))
449 if (newval
&& newlen
) {
451 if (len
> table
->maxlen
)
453 if(copy_from_user(table
->data
, newval
, len
))
460 struct ctl_table_header
*register_sysctl_table(ctl_table
* table
,
463 struct ctl_table_header
*tmp
;
464 tmp
= kmalloc(sizeof(struct ctl_table_header
), GFP_KERNEL
);
467 tmp
->ctl_table
= table
;
468 INIT_LIST_HEAD(&tmp
->ctl_entry
);
470 list_add(&tmp
->ctl_entry
, &root_table_header
.ctl_entry
);
472 list_add_tail(&tmp
->ctl_entry
, &root_table_header
.ctl_entry
);
473 #ifdef CONFIG_PROC_FS
474 register_proc_table(table
, proc_sys_root
);
480 * Unlink and free a ctl_table.
482 void unregister_sysctl_table(struct ctl_table_header
* header
)
484 list_del(&header
->ctl_entry
);
485 #ifdef CONFIG_PROC_FS
486 unregister_proc_table(header
->ctl_table
, proc_sys_root
);
495 #ifdef CONFIG_PROC_FS
497 /* Scan the sysctl entries in table and add them all into /proc */
498 static void register_proc_table(ctl_table
* table
, struct proc_dir_entry
*root
)
500 struct proc_dir_entry
*de
;
504 for (; table
->ctl_name
; table
++) {
505 /* Can't do anything without a proc name. */
506 if (!table
->procname
)
508 /* Maybe we can't do anything with it... */
509 if (!table
->proc_handler
&& !table
->child
) {
510 printk(KERN_WARNING
"SYSCTL: Can't register %s\n",
515 len
= strlen(table
->procname
);
519 if (table
->proc_handler
)
523 for (de
= root
->subdir
; de
; de
= de
->next
) {
524 if (proc_match(len
, table
->procname
, de
))
527 /* If the subdir exists already, de is non-NULL */
531 de
= create_proc_entry(table
->procname
, mode
, root
);
534 de
->data
= (void *) table
;
535 if (table
->proc_handler
) {
536 de
->proc_fops
= &proc_sys_file_operations
;
537 de
->proc_iops
= &proc_sys_inode_operations
;
541 if (de
->mode
& S_IFDIR
)
542 register_proc_table(table
->child
, de
);
547 * Unregister a /proc sysctl table and any subdirectories.
549 static void unregister_proc_table(ctl_table
* table
, struct proc_dir_entry
*root
)
551 struct proc_dir_entry
*de
;
552 for (; table
->ctl_name
; table
++) {
553 if (!(de
= table
->de
))
555 if (de
->mode
& S_IFDIR
) {
557 printk (KERN_ALERT
"Help - malformed sysctl tree on free\n");
560 unregister_proc_table(table
->child
, de
);
562 /* Don't unregister directories which still have entries.. */
567 /* Don't unregister proc entries that are still being used.. */
572 remove_proc_entry(table
->procname
, root
);
576 static ssize_t
do_rw_proc(int write
, struct file
* file
, char * buf
,
577 size_t count
, loff_t
*ppos
)
580 struct proc_dir_entry
*de
;
581 struct ctl_table
*table
;
585 de
= (struct proc_dir_entry
*) file
->f_dentry
->d_inode
->u
.generic_ip
;
586 if (!de
|| !de
->data
)
588 table
= (struct ctl_table
*) de
->data
;
589 if (!table
|| !table
->proc_handler
)
591 op
= (write
? 002 : 004);
592 if (ctl_perm(table
, op
))
598 * FIXME: we need to pass on ppos to the handler.
601 error
= (*table
->proc_handler
) (table
, write
, file
, buf
, &res
);
607 static ssize_t
proc_readsys(struct file
* file
, char * buf
,
608 size_t count
, loff_t
*ppos
)
610 return do_rw_proc(0, file
, buf
, count
, ppos
);
613 static ssize_t
proc_writesys(struct file
* file
, const char * buf
,
614 size_t count
, loff_t
*ppos
)
616 return do_rw_proc(1, file
, (char *) buf
, count
, ppos
);
619 static int proc_sys_permission(struct inode
*inode
, int op
)
621 return test_perm(inode
->i_mode
, op
);
624 int proc_dostring(ctl_table
*table
, int write
, struct file
*filp
,
625 void *buffer
, size_t *lenp
)
630 if (!table
->data
|| !table
->maxlen
|| !*lenp
||
631 (filp
->f_pos
&& !write
)) {
639 while (len
< *lenp
) {
642 if (c
== 0 || c
== '\n')
646 if (len
>= table
->maxlen
)
647 len
= table
->maxlen
-1;
648 if(copy_from_user(table
->data
, buffer
, len
))
650 ((char *) table
->data
)[len
] = 0;
651 filp
->f_pos
+= *lenp
;
653 len
= strlen(table
->data
);
654 if (len
> table
->maxlen
)
659 if(copy_to_user(buffer
, table
->data
, len
))
662 if(put_user('\n', ((char *) buffer
) + len
))
673 * Special case of dostring for the UTS structure. This has locks
674 * to observe. Should this be in kernel/sys.c ????
677 static int proc_doutsstring(ctl_table
*table
, int write
, struct file
*filp
,
678 void *buffer
, size_t *lenp
)
684 r
=proc_dostring(table
,0,filp
,buffer
,lenp
);
687 down_write(&uts_sem
);
688 r
=proc_dostring(table
,1,filp
,buffer
,lenp
);
700 static int do_proc_dointvec(ctl_table
*table
, int write
, struct file
*filp
,
701 void *buffer
, size_t *lenp
, int conv
, int op
)
703 int *i
, vleft
, first
=1, len
, left
, neg
, val
;
705 char buf
[TMPBUFLEN
], *p
;
707 if (!table
->data
|| !table
->maxlen
|| !*lenp
||
708 (filp
->f_pos
&& !write
)) {
713 i
= (int *) table
->data
;
714 vleft
= table
->maxlen
/ sizeof(int);
717 for (; left
&& vleft
--; i
++, first
=0) {
721 if(get_user(c
,(char *) buffer
))
732 if (len
> TMPBUFLEN
-1)
734 if(copy_from_user(buf
, buffer
, len
))
738 if (*p
== '-' && left
> 1) {
742 if (*p
< '0' || *p
> '9')
744 val
= simple_strtoul(p
, &p
, 0) * conv
;
746 if ((len
< left
) && *p
&& !isspace(*p
))
753 case OP_SET
: *i
= val
; break;
754 case OP_AND
: *i
&= val
; break;
755 case OP_OR
: *i
|= val
; break;
756 case OP_MAX
: if(*i
< val
)
759 case OP_MIN
: if(*i
> val
)
767 sprintf(p
, "%d", (*i
) / conv
);
771 if(copy_to_user(buffer
, buf
, len
))
778 if (!write
&& !first
&& left
) {
779 if(put_user('\n', (char *) buffer
))
797 filp
->f_pos
+= *lenp
;
801 int proc_dointvec(ctl_table
*table
, int write
, struct file
*filp
,
802 void *buffer
, size_t *lenp
)
804 return do_proc_dointvec(table
,write
,filp
,buffer
,lenp
,1,OP_SET
);
808 * init may raise the set.
811 int proc_dointvec_bset(ctl_table
*table
, int write
, struct file
*filp
,
812 void *buffer
, size_t *lenp
)
814 if (!capable(CAP_SYS_MODULE
)) {
817 return do_proc_dointvec(table
,write
,filp
,buffer
,lenp
,1,
818 (current
->pid
== 1) ? OP_SET
: OP_AND
);
821 int proc_dointvec_minmax(ctl_table
*table
, int write
, struct file
*filp
,
822 void *buffer
, size_t *lenp
)
824 int *i
, *min
, *max
, vleft
, first
=1, len
, left
, neg
, val
;
826 char buf
[TMPBUFLEN
], *p
;
828 if (!table
->data
|| !table
->maxlen
|| !*lenp
||
829 (filp
->f_pos
&& !write
)) {
834 i
= (int *) table
->data
;
835 min
= (int *) table
->extra1
;
836 max
= (int *) table
->extra2
;
837 vleft
= table
->maxlen
/ sizeof(int);
840 for (; left
&& vleft
--; i
++, first
=0) {
844 if(get_user(c
, (char *) buffer
))
855 if (len
> TMPBUFLEN
-1)
857 if(copy_from_user(buf
, buffer
, len
))
861 if (*p
== '-' && left
> 1) {
865 if (*p
< '0' || *p
> '9')
867 val
= simple_strtoul(p
, &p
, 0);
869 if ((len
< left
) && *p
&& !isspace(*p
))
876 if (min
&& val
< *min
++)
878 if (max
&& val
> *max
++)
885 sprintf(p
, "%d", *i
);
889 if(copy_to_user(buffer
, buf
, len
))
896 if (!write
&& !first
&& left
) {
897 if(put_user('\n', (char *) buffer
))
915 filp
->f_pos
+= *lenp
;
920 * an unsigned long function version
923 static int do_proc_doulongvec_minmax(ctl_table
*table
, int write
,
925 void *buffer
, size_t *lenp
,
926 unsigned long convmul
,
927 unsigned long convdiv
)
930 unsigned long *i
, *min
, *max
, val
;
931 int vleft
, first
=1, len
, left
, neg
;
932 char buf
[TMPBUFLEN
], *p
;
934 if (!table
->data
|| !table
->maxlen
|| !*lenp
||
935 (filp
->f_pos
&& !write
)) {
940 i
= (unsigned long *) table
->data
;
941 min
= (unsigned long *) table
->extra1
;
942 max
= (unsigned long *) table
->extra2
;
943 vleft
= table
->maxlen
/ sizeof(unsigned long);
946 for (; left
&& vleft
--; i
++, first
=0) {
950 if(get_user(c
, (char *) buffer
))
961 if (len
> TMPBUFLEN
-1)
963 if(copy_from_user(buf
, buffer
, len
))
967 if (*p
== '-' && left
> 1) {
971 if (*p
< '0' || *p
> '9')
973 val
= simple_strtoul(p
, &p
, 0) * convmul
/ convdiv
;
975 if ((len
< left
) && *p
&& !isspace(*p
))
984 if (min
&& val
< *min
++)
986 if (max
&& val
> *max
++)
993 sprintf(p
, "%lu", convdiv
* (*i
) / convmul
);
997 if(copy_to_user(buffer
, buf
, len
))
1004 if (!write
&& !first
&& left
) {
1005 if(put_user('\n', (char *) buffer
))
1010 p
= (char *) buffer
;
1013 if(get_user(c
, p
++))
1023 filp
->f_pos
+= *lenp
;
1028 int proc_doulongvec_minmax(ctl_table
*table
, int write
, struct file
*filp
,
1029 void *buffer
, size_t *lenp
)
1031 return do_proc_doulongvec_minmax(table
, write
, filp
, buffer
, lenp
, 1l, 1l);
1034 int proc_doulongvec_ms_jiffies_minmax(ctl_table
*table
, int write
,
1036 void *buffer
, size_t *lenp
)
1038 return do_proc_doulongvec_minmax(table
, write
, filp
, buffer
,
1043 /* Like proc_dointvec, but converts seconds to jiffies */
1044 int proc_dointvec_jiffies(ctl_table
*table
, int write
, struct file
*filp
,
1045 void *buffer
, size_t *lenp
)
1047 return do_proc_dointvec(table
,write
,filp
,buffer
,lenp
,HZ
,OP_SET
);
1050 #else /* CONFIG_PROC_FS */
1052 int proc_dostring(ctl_table
*table
, int write
, struct file
*filp
,
1053 void *buffer
, size_t *lenp
)
1058 static int proc_doutsstring(ctl_table
*table
, int write
, struct file
*filp
,
1059 void *buffer
, size_t *lenp
)
1064 int proc_dointvec(ctl_table
*table
, int write
, struct file
*filp
,
1065 void *buffer
, size_t *lenp
)
1070 int proc_dointvec_bset(ctl_table
*table
, int write
, struct file
*filp
,
1071 void *buffer
, size_t *lenp
)
1076 int proc_dointvec_minmax(ctl_table
*table
, int write
, struct file
*filp
,
1077 void *buffer
, size_t *lenp
)
1082 int proc_dointvec_jiffies(ctl_table
*table
, int write
, struct file
*filp
,
1083 void *buffer
, size_t *lenp
)
1088 int proc_doulongvec_minmax(ctl_table
*table
, int write
, struct file
*filp
,
1089 void *buffer
, size_t *lenp
)
1094 int proc_doulongvec_ms_jiffies_minmax(ctl_table
*table
, int write
,
1096 void *buffer
, size_t *lenp
)
1102 #endif /* CONFIG_PROC_FS */
1106 * General sysctl support routines
1109 /* The generic string strategy routine: */
1110 int sysctl_string(ctl_table
*table
, int *name
, int nlen
,
1111 void *oldval
, size_t *oldlenp
,
1112 void *newval
, size_t newlen
, void **context
)
1116 if (!table
->data
|| !table
->maxlen
)
1119 if (oldval
&& oldlenp
) {
1120 if(get_user(len
, oldlenp
))
1123 l
= strlen(table
->data
);
1124 if (len
> l
) len
= l
;
1125 if (len
>= table
->maxlen
)
1126 len
= table
->maxlen
;
1127 if(copy_to_user(oldval
, table
->data
, len
))
1129 if(put_user(0, ((char *) oldval
) + len
))
1131 if(put_user(len
, oldlenp
))
1135 if (newval
&& newlen
) {
1137 if (len
> table
->maxlen
)
1138 len
= table
->maxlen
;
1139 if(copy_from_user(table
->data
, newval
, len
))
1141 if (len
== table
->maxlen
)
1143 ((char *) table
->data
)[len
] = 0;
1149 * This function makes sure that all of the integers in the vector
1150 * are between the minimum and maximum values given in the arrays
1151 * table->extra1 and table->extra2, respectively.
1153 int sysctl_intvec(ctl_table
*table
, int *name
, int nlen
,
1154 void *oldval
, size_t *oldlenp
,
1155 void *newval
, size_t newlen
, void **context
)
1157 int i
, length
, *vec
, *min
, *max
;
1159 if (newval
&& newlen
) {
1160 if (newlen
% sizeof(int) != 0)
1163 if (!table
->extra1
&& !table
->extra2
)
1166 if (newlen
> table
->maxlen
)
1167 newlen
= table
->maxlen
;
1168 length
= newlen
/ sizeof(int);
1170 vec
= (int *) newval
;
1171 min
= (int *) table
->extra1
;
1172 max
= (int *) table
->extra2
;
1174 for (i
= 0; i
< length
; i
++) {
1176 get_user(value
, vec
+ i
);
1177 if (min
&& value
< min
[i
])
1179 if (max
&& value
> max
[i
])
1186 /* Strategy function to convert jiffies to seconds */
1187 int sysctl_jiffies(ctl_table
*table
, int *name
, int nlen
,
1188 void *oldval
, size_t *oldlenp
,
1189 void *newval
, size_t newlen
, void **context
)
1194 if (get_user(olen
, oldlenp
))
1196 if (olen
!=sizeof(int))
1199 if (put_user(*(int *)(table
->data
) / HZ
, (int *)oldval
) ||
1200 (oldlenp
&& put_user(sizeof(int),oldlenp
)))
1203 if (newval
&& newlen
) {
1205 if (newlen
!= sizeof(int))
1207 if (get_user(new, (int *)newval
))
1209 *(int *)(table
->data
) = new*HZ
;
1215 void *oldval
, size_t *oldlenp
, void *newval
, size_t newlen
,
1216 int rdwr
, char *data
, size_t max
)
1218 int l
= strlen(data
) + 1;
1219 if (newval
&& !rdwr
)
1221 if (newval
&& newlen
>= max
)
1225 if(get_user(old_l
, oldlenp
))
1229 if(put_user(l
, oldlenp
) || copy_to_user(oldval
, data
, l
))
1233 if(copy_from_user(data
, newval
, newlen
))
1241 void *oldval
, size_t *oldlenp
, void *newval
, size_t newlen
,
1242 int rdwr
, int *data
)
1244 if (newval
&& !rdwr
)
1246 if (newval
&& newlen
!= sizeof(int))
1250 if(get_user(old_l
, oldlenp
))
1252 if (old_l
< sizeof(int))
1254 if(put_user(sizeof(int), oldlenp
)||copy_to_user(oldval
, data
, sizeof(int)))
1258 if(copy_from_user(data
, newval
, sizeof(int)))
1264 void *oldval
, size_t *oldlenp
, void *newval
, size_t newlen
,
1265 int rdwr
, void *data
, size_t len
)
1267 if (newval
&& !rdwr
)
1269 if (newval
&& newlen
!= len
)
1273 if(get_user(old_l
, oldlenp
))
1277 if(put_user(len
, oldlenp
) || copy_to_user(oldval
, data
, len
))
1281 if(copy_from_user(data
, newval
, len
))
1287 #else /* CONFIG_SYSCTL */
1290 extern asmlinkage
long sys_sysctl(struct __sysctl_args
*args
)
1295 int sysctl_string(ctl_table
*table
, int *name
, int nlen
,
1296 void *oldval
, size_t *oldlenp
,
1297 void *newval
, size_t newlen
, void **context
)
1302 int sysctl_intvec(ctl_table
*table
, int *name
, int nlen
,
1303 void *oldval
, size_t *oldlenp
,
1304 void *newval
, size_t newlen
, void **context
)
1309 int proc_dostring(ctl_table
*table
, int write
, struct file
*filp
,
1310 void *buffer
, size_t *lenp
)
1315 int proc_dointvec(ctl_table
*table
, int write
, struct file
*filp
,
1316 void *buffer
, size_t *lenp
)
1321 int proc_dointvec_bset(ctl_table
*table
, int write
, struct file
*filp
,
1322 void *buffer
, size_t *lenp
)
1327 int proc_dointvec_minmax(ctl_table
*table
, int write
, struct file
*filp
,
1328 void *buffer
, size_t *lenp
)
1333 int proc_dointvec_jiffies(ctl_table
*table
, int write
, struct file
*filp
,
1334 void *buffer
, size_t *lenp
)
1339 int proc_doulongvec_minmax(ctl_table
*table
, int write
, struct file
*filp
,
1340 void *buffer
, size_t *lenp
)
1345 int proc_doulongvec_ms_jiffies_minmax(ctl_table
*table
, int write
,
1347 void *buffer
, size_t *lenp
)
1352 struct ctl_table_header
* register_sysctl_table(ctl_table
* table
,
1358 void unregister_sysctl_table(struct ctl_table_header
* table
)
1362 #endif /* CONFIG_SYSCTL */