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.
17 #include <linux/config.h>
18 #include <linux/malloc.h>
19 #include <linux/sysctl.h>
20 #include <linux/swapctl.h>
21 #include <linux/proc_fs.h>
22 #include <linux/ctype.h>
23 #include <linux/utsname.h>
24 #include <linux/capability.h>
25 #include <linux/smp_lock.h>
26 #include <linux/init.h>
27 #include <linux/sysrq.h>
28 #include <linux/highuid.h>
30 #include <asm/uaccess.h>
32 #ifdef CONFIG_ROOT_NFS
33 #include <linux/nfs_fs.h>
36 #if defined(CONFIG_SYSCTL)
38 /* External variables not in a header file. */
39 extern int panic_timeout
;
40 extern int console_loglevel
, C_A_D
;
41 extern int bdf_prm
[], bdflush_min
[], bdflush_max
[];
42 extern int sysctl_overcommit_memory
;
43 extern int max_threads
;
44 extern int nr_queued_signals
, max_queued_signals
;
46 /* this is needed for the proc_dointvec_minmax for overflow UID and GID */
47 static int maxolduid
= 65535;
48 static int minolduid
= 0;
51 extern char modprobe_path
[];
53 #ifdef CONFIG_CHR_DEV_SG
54 extern int sg_big_buff
;
57 extern size_t shm_ctlmax
;
58 extern int shm_ctlall
;
59 extern int shm_ctlmni
;
60 extern int msg_ctlmax
;
61 extern int msg_ctlmnb
;
62 extern int msg_ctlmni
;
63 extern int sem_ctls
[];
67 extern char reboot_command
[];
68 extern int stop_a_enabled
;
71 extern unsigned long htab_reclaim_on
, zero_paged_on
, powersave_nap
;
72 int proc_dol2crvec(ctl_table
*table
, int write
, struct file
*filp
,
73 void *buffer
, size_t *lenp
);
76 #ifdef CONFIG_BSD_PROCESS_ACCT
77 extern int acct_parm
[];
80 extern int pgt_cache_water
[];
82 static int parse_table(int *, int, void *, size_t *, void *, size_t,
83 ctl_table
*, void **);
84 static int proc_doutsstring(ctl_table
*table
, int write
, struct file
*filp
,
85 void *buffer
, size_t *lenp
);
88 static ctl_table root_table
[];
89 static struct ctl_table_header root_table_header
=
90 {root_table
, DNODE_SINGLE(&root_table_header
)};
92 static ctl_table kern_table
[];
93 static ctl_table vm_table
[];
95 extern ctl_table net_table
[];
97 static ctl_table proc_table
[];
98 static ctl_table fs_table
[];
99 static ctl_table debug_table
[];
100 static ctl_table dev_table
[];
101 extern ctl_table random_table
[];
104 /* /proc declarations: */
106 #ifdef CONFIG_PROC_FS
108 static ssize_t
proc_readsys(struct file
*, char *, size_t, loff_t
*);
109 static ssize_t
proc_writesys(struct file
*, const char *, size_t, loff_t
*);
110 static int proc_sys_permission(struct inode
*, int);
112 struct file_operations proc_sys_file_operations
=
115 proc_readsys
, /* read */
116 proc_writesys
, /* write */
121 NULL
, /* no special open code */
122 NULL
, /* no special flush code */
123 NULL
, /* no special release code */
124 NULL
/* can't fsync */
127 struct inode_operations proc_sys_inode_operations
=
129 &proc_sys_file_operations
,
140 NULL
, /* follow_link */
141 NULL
, /* get_block */
143 NULL
, /* writepage */
145 proc_sys_permission
, /* permission */
146 NULL
/* revalidate */
149 extern struct proc_dir_entry
*proc_sys_root
;
151 static void register_proc_table(ctl_table
*, struct proc_dir_entry
*);
152 static void unregister_proc_table(ctl_table
*, struct proc_dir_entry
*);
154 extern int inodes_stat
[];
155 extern int dentry_stat
[];
157 /* The default sysctl tables: */
159 static ctl_table root_table
[] = {
160 {CTL_KERN
, "kernel", NULL
, 0, 0555, kern_table
},
161 {CTL_VM
, "vm", NULL
, 0, 0555, vm_table
},
163 {CTL_NET
, "net", NULL
, 0, 0555, net_table
},
165 {CTL_PROC
, "proc", NULL
, 0, 0555, proc_table
},
166 {CTL_FS
, "fs", NULL
, 0, 0555, fs_table
},
167 {CTL_DEBUG
, "debug", NULL
, 0, 0555, debug_table
},
168 {CTL_DEV
, "dev", NULL
, 0, 0555, dev_table
},
172 static ctl_table kern_table
[] = {
173 {KERN_OSTYPE
, "ostype", system_utsname
.sysname
, 64,
174 0444, NULL
, &proc_doutsstring
, &sysctl_string
},
175 {KERN_OSRELEASE
, "osrelease", system_utsname
.release
, 64,
176 0444, NULL
, &proc_doutsstring
, &sysctl_string
},
177 {KERN_VERSION
, "version", system_utsname
.version
, 64,
178 0444, NULL
, &proc_doutsstring
, &sysctl_string
},
179 {KERN_NODENAME
, "hostname", system_utsname
.nodename
, 64,
180 0644, NULL
, &proc_doutsstring
, &sysctl_string
},
181 {KERN_DOMAINNAME
, "domainname", system_utsname
.domainname
, 64,
182 0644, NULL
, &proc_doutsstring
, &sysctl_string
},
183 {KERN_PANIC
, "panic", &panic_timeout
, sizeof(int),
184 0644, NULL
, &proc_dointvec
},
185 {KERN_CAP_BSET
, "cap-bound", &cap_bset
, sizeof(kernel_cap_t
),
186 0600, NULL
, &proc_dointvec_bset
},
187 #ifdef CONFIG_BLK_DEV_INITRD
188 {KERN_REALROOTDEV
, "real-root-dev", &real_root_dev
, sizeof(int),
189 0644, NULL
, &proc_dointvec
},
192 {KERN_SPARC_REBOOT
, "reboot-cmd", reboot_command
,
193 256, 0644, NULL
, &proc_dostring
, &sysctl_string
},
194 {KERN_SPARC_STOP_A
, "stop-a", &stop_a_enabled
, sizeof (int),
195 0644, NULL
, &proc_dointvec
},
198 {KERN_PPC_HTABRECLAIM
, "htab-reclaim", &htab_reclaim_on
, sizeof(int),
199 0644, NULL
, &proc_dointvec
},
200 {KERN_PPC_ZEROPAGED
, "zero-paged", &zero_paged_on
, sizeof(int),
201 0644, NULL
, &proc_dointvec
},
202 {KERN_PPC_POWERSAVE_NAP
, "powersave-nap", &powersave_nap
, sizeof(int),
203 0644, NULL
, &proc_dointvec
},
204 {KERN_PPC_L2CR
, "l2cr", NULL
, 0,
205 0644, NULL
, &proc_dol2crvec
},
207 {KERN_CTLALTDEL
, "ctrl-alt-del", &C_A_D
, sizeof(int),
208 0644, NULL
, &proc_dointvec
},
209 {KERN_PRINTK
, "printk", &console_loglevel
, 4*sizeof(int),
210 0644, NULL
, &proc_dointvec
},
212 {KERN_MODPROBE
, "modprobe", &modprobe_path
, 256,
213 0644, NULL
, &proc_dostring
, &sysctl_string
},
215 #ifdef CONFIG_CHR_DEV_SG
216 {KERN_SG_BIG_BUFF
, "sg-big-buff", &sg_big_buff
, sizeof (int),
217 0444, NULL
, &proc_dointvec
},
219 #ifdef CONFIG_BSD_PROCESS_ACCT
220 {KERN_ACCT
, "acct", &acct_parm
, 3*sizeof(int),
221 0644, NULL
, &proc_dointvec
},
223 {KERN_RTSIGNR
, "rtsig-nr", &nr_queued_signals
, sizeof(int),
224 0444, NULL
, &proc_dointvec
},
225 {KERN_RTSIGMAX
, "rtsig-max", &max_queued_signals
, sizeof(int),
226 0644, NULL
, &proc_dointvec
},
227 #ifdef CONFIG_SYSVIPC
228 {KERN_SHMMAX
, "shmmax", &shm_ctlmax
, sizeof (size_t),
229 0644, NULL
, &proc_doulongvec_minmax
},
230 {KERN_SHMALL
, "shmall", &shm_ctlall
, sizeof (int),
231 0644, NULL
, &proc_dointvec
},
232 {KERN_SHMMNI
, "shmmni", &shm_ctlmni
, sizeof (int),
233 0644, NULL
, &proc_dointvec
},
234 {KERN_MSGMAX
, "msgmax", &msg_ctlmax
, sizeof (int),
235 0644, NULL
, &proc_dointvec
},
236 {KERN_MSGMNI
, "msgmni", &msg_ctlmni
, sizeof (int),
237 0644, NULL
, &proc_dointvec
},
238 {KERN_MSGMNB
, "msgmnb", &msg_ctlmnb
, sizeof (int),
239 0644, NULL
, &proc_dointvec
},
240 {KERN_SEM
, "sem", &sem_ctls
, 4*sizeof (int),
241 0644, NULL
, &proc_dointvec
},
243 #ifdef CONFIG_MAGIC_SYSRQ
244 {KERN_SYSRQ
, "sysrq", &sysrq_enabled
, sizeof (int),
245 0644, NULL
, &proc_dointvec
},
247 {KERN_MAX_THREADS
, "threads-max", &max_threads
, sizeof(int),
248 0644, NULL
, &proc_dointvec
},
249 {KERN_RANDOM
, "random", NULL
, 0, 0555, random_table
},
250 {KERN_OVERFLOWUID
, "overflowuid", &overflowuid
, sizeof(int), 0644, NULL
,
251 &proc_dointvec_minmax
, &sysctl_intvec
, NULL
,
252 &minolduid
, &maxolduid
},
253 {KERN_OVERFLOWGID
, "overflowgid", &overflowgid
, sizeof(int), 0644, NULL
,
254 &proc_dointvec_minmax
, &sysctl_intvec
, NULL
,
255 &minolduid
, &maxolduid
},
259 static ctl_table vm_table
[] = {
260 {VM_FREEPG
, "freepages",
261 &freepages
, sizeof(freepages_t
), 0644, NULL
, &proc_dointvec
},
262 {VM_BDFLUSH
, "bdflush", &bdf_prm
, 9*sizeof(int), 0600, NULL
,
263 &proc_dointvec_minmax
, &sysctl_intvec
, NULL
,
264 &bdflush_min
, &bdflush_max
},
265 {VM_OVERCOMMIT_MEMORY
, "overcommit_memory", &sysctl_overcommit_memory
,
266 sizeof(sysctl_overcommit_memory
), 0644, NULL
, &proc_dointvec
},
267 {VM_BUFFERMEM
, "buffermem",
268 &buffer_mem
, sizeof(buffer_mem_t
), 0644, NULL
, &proc_dointvec
},
269 {VM_PAGECACHE
, "pagecache",
270 &page_cache
, sizeof(buffer_mem_t
), 0644, NULL
, &proc_dointvec
},
271 {VM_PAGERDAEMON
, "kswapd",
272 &pager_daemon
, sizeof(pager_daemon_t
), 0644, NULL
, &proc_dointvec
},
273 {VM_PGT_CACHE
, "pagetable_cache",
274 &pgt_cache_water
, 2*sizeof(int), 0600, NULL
, &proc_dointvec
},
275 {VM_PAGE_CLUSTER
, "page-cluster",
276 &page_cluster
, sizeof(int), 0600, NULL
, &proc_dointvec
},
280 static ctl_table proc_table
[] = {
284 static ctl_table fs_table
[] = {
285 {FS_NRINODE
, "inode-nr", &inodes_stat
, 2*sizeof(int),
286 0444, NULL
, &proc_dointvec
},
287 {FS_STATINODE
, "inode-state", &inodes_stat
, 7*sizeof(int),
288 0444, NULL
, &proc_dointvec
},
289 {FS_NRFILE
, "file-nr", &nr_files
, 3*sizeof(int),
290 0444, NULL
, &proc_dointvec
},
291 {FS_MAXFILE
, "file-max", &max_files
, sizeof(int),
292 0644, NULL
, &proc_dointvec
},
293 {FS_NRSUPER
, "super-nr", &nr_super_blocks
, sizeof(int),
294 0444, NULL
, &proc_dointvec
},
295 {FS_MAXSUPER
, "super-max", &max_super_blocks
, sizeof(int),
296 0644, NULL
, &proc_dointvec
},
297 {FS_NRDQUOT
, "dquot-nr", &nr_dquots
, 2*sizeof(int),
298 0444, NULL
, &proc_dointvec
},
299 {FS_MAXDQUOT
, "dquot-max", &max_dquots
, sizeof(int),
300 0644, NULL
, &proc_dointvec
},
301 {FS_DENTRY
, "dentry-state", &dentry_stat
, 6*sizeof(int),
302 0444, NULL
, &proc_dointvec
},
303 {FS_OVERFLOWUID
, "overflowuid", &fs_overflowuid
, sizeof(int), 0644, NULL
,
304 &proc_dointvec_minmax
, &sysctl_intvec
, NULL
,
305 &minolduid
, &maxolduid
},
306 {FS_OVERFLOWGID
, "overflowgid", &fs_overflowgid
, sizeof(int), 0644, NULL
,
307 &proc_dointvec_minmax
, &sysctl_intvec
, NULL
,
308 &minolduid
, &maxolduid
},
312 static ctl_table debug_table
[] = {
316 static ctl_table dev_table
[] = {
321 void __init
sysctl_init(void)
323 #ifdef CONFIG_PROC_FS
324 register_proc_table(root_table
, proc_sys_root
);
329 int do_sysctl (int *name
, int nlen
,
330 void *oldval
, size_t *oldlenp
,
331 void *newval
, size_t newlen
)
334 struct ctl_table_header
*tmp
;
337 if (nlen
== 0 || nlen
>= CTL_MAXNAME
)
345 if(get_user(old_len
, oldlenp
))
348 tmp
= &root_table_header
;
351 error
= parse_table(name
, nlen
, oldval
, oldlenp
,
352 newval
, newlen
, tmp
->ctl_table
, &context
);
355 if (error
!= -ENOTDIR
)
357 tmp
= tmp
->DLIST_NEXT(ctl_entry
);
358 } while (tmp
!= &root_table_header
);
362 extern asmlinkage
long sys_sysctl(struct __sysctl_args
*args
)
364 struct __sysctl_args tmp
;
367 if(copy_from_user(&tmp
, args
, sizeof(tmp
)))
371 error
= do_sysctl(tmp
.name
, tmp
.nlen
, tmp
.oldval
, tmp
.oldlenp
,
372 tmp
.newval
, tmp
.newlen
);
377 /* Like in_group_p, but testing against egid, not fsgid */
378 int in_egroup_p(gid_t grp
)
380 if (grp
!= current
->egid
) {
381 int i
= current
->ngroups
;
383 gid_t
*groups
= current
->groups
;
397 /* ctl_perm does NOT grant the superuser all rights automatically, because
398 some sysctl variables are readonly even to root. */
400 static int test_perm(int mode
, int op
)
404 else if (in_egroup_p(0))
406 if ((mode
& op
& 0007) == op
)
411 static inline int ctl_perm(ctl_table
*table
, int op
)
413 return test_perm(table
->mode
, op
);
416 static int parse_table(int *name
, int nlen
,
417 void *oldval
, size_t *oldlenp
,
418 void *newval
, size_t newlen
,
419 ctl_table
*table
, void **context
)
426 for ( ; table
->ctl_name
; table
++) {
430 if (n
== table
->ctl_name
||
431 table
->ctl_name
== CTL_ANY
) {
433 if (ctl_perm(table
, 001))
435 if (table
->strategy
) {
436 error
= table
->strategy(
439 newval
, newlen
, context
);
445 table
= table
->child
;
448 error
= do_sysctl_strategy(table
, name
, nlen
,
450 newval
, newlen
, context
);
457 /* Perform the actual read/write of a sysctl table entry. */
458 int do_sysctl_strategy (ctl_table
*table
,
460 void *oldval
, size_t *oldlenp
,
461 void *newval
, size_t newlen
, void **context
)
469 if (ctl_perm(table
, op
))
472 if (table
->strategy
) {
473 rc
= table
->strategy(table
, name
, nlen
, oldval
, oldlenp
,
474 newval
, newlen
, context
);
481 /* If there is no strategy routine, or if the strategy returns
482 * zero, proceed with automatic r/w */
483 if (table
->data
&& table
->maxlen
) {
484 if (oldval
&& oldlenp
) {
485 get_user(len
, oldlenp
);
487 if (len
> table
->maxlen
)
489 if(copy_to_user(oldval
, table
->data
, len
))
491 if(put_user(len
, oldlenp
))
495 if (newval
&& newlen
) {
497 if (len
> table
->maxlen
)
499 if(copy_from_user(table
->data
, newval
, len
))
506 struct ctl_table_header
*register_sysctl_table(ctl_table
* table
,
509 struct ctl_table_header
*tmp
;
510 tmp
= kmalloc(sizeof(*tmp
), GFP_KERNEL
);
513 *tmp
= ((struct ctl_table_header
) {table
, DNODE_NULL
});
515 DLIST_INSERT_AFTER(&root_table_header
, tmp
, ctl_entry
);
517 DLIST_INSERT_BEFORE(&root_table_header
, tmp
, ctl_entry
);
518 #ifdef CONFIG_PROC_FS
519 register_proc_table(table
, proc_sys_root
);
525 * Unlink and free a ctl_table.
527 void unregister_sysctl_table(struct ctl_table_header
* header
)
529 DLIST_DELETE(header
, ctl_entry
);
530 #ifdef CONFIG_PROC_FS
531 unregister_proc_table(header
->ctl_table
, proc_sys_root
);
540 #ifdef CONFIG_PROC_FS
542 /* Scan the sysctl entries in table and add them all into /proc */
543 static void register_proc_table(ctl_table
* table
, struct proc_dir_entry
*root
)
545 struct proc_dir_entry
*de
;
549 for (; table
->ctl_name
; table
++) {
550 /* Can't do anything without a proc name. */
551 if (!table
->procname
)
553 /* Maybe we can't do anything with it... */
554 if (!table
->proc_handler
&& !table
->child
) {
555 printk(KERN_WARNING
"SYSCTL: Can't register %s\n",
560 len
= strlen(table
->procname
);
564 if (table
->proc_handler
)
568 for (de
= root
->subdir
; de
; de
= de
->next
) {
569 if (proc_match(len
, table
->procname
, de
))
572 /* If the subdir exists already, de is non-NULL */
576 de
= create_proc_entry(table
->procname
, mode
, root
);
579 de
->data
= (void *) table
;
580 if (table
->proc_handler
)
581 de
->ops
= &proc_sys_inode_operations
;
585 if (de
->mode
& S_IFDIR
)
586 register_proc_table(table
->child
, de
);
591 * Unregister a /proc sysctl table and any subdirectories.
593 static void unregister_proc_table(ctl_table
* table
, struct proc_dir_entry
*root
)
595 struct proc_dir_entry
*de
;
596 for (; table
->ctl_name
; table
++) {
597 if (!(de
= table
->de
))
599 if (de
->mode
& S_IFDIR
) {
601 printk (KERN_ALERT
"Help - malformed sysctl tree on free\n");
604 unregister_proc_table(table
->child
, de
);
606 /* Don't unregister directories which still have entries.. */
611 /* Don't unregister proc entries that are still being used.. */
616 remove_proc_entry(table
->procname
, root
);
620 static ssize_t
do_rw_proc(int write
, struct file
* file
, char * buf
,
621 size_t count
, loff_t
*ppos
)
624 struct proc_dir_entry
*de
;
625 struct ctl_table
*table
;
629 de
= (struct proc_dir_entry
*) file
->f_dentry
->d_inode
->u
.generic_ip
;
630 if (!de
|| !de
->data
)
632 table
= (struct ctl_table
*) de
->data
;
633 if (!table
|| !table
->proc_handler
)
635 op
= (write
? 002 : 004);
636 if (ctl_perm(table
, op
))
642 * FIXME: we need to pass on ppos to the handler.
645 error
= (*table
->proc_handler
) (table
, write
, file
, buf
, &res
);
651 static ssize_t
proc_readsys(struct file
* file
, char * buf
,
652 size_t count
, loff_t
*ppos
)
654 return do_rw_proc(0, file
, buf
, count
, ppos
);
657 static ssize_t
proc_writesys(struct file
* file
, const char * buf
,
658 size_t count
, loff_t
*ppos
)
660 return do_rw_proc(1, file
, (char *) buf
, count
, ppos
);
663 static int proc_sys_permission(struct inode
*inode
, int op
)
665 return test_perm(inode
->i_mode
, op
);
668 int proc_dostring(ctl_table
*table
, int write
, struct file
*filp
,
669 void *buffer
, size_t *lenp
)
674 if (!table
->data
|| !table
->maxlen
|| !*lenp
||
675 (filp
->f_pos
&& !write
)) {
683 while (len
< *lenp
) {
686 if (c
== 0 || c
== '\n')
690 if (len
>= table
->maxlen
)
691 len
= table
->maxlen
-1;
692 if(copy_from_user(table
->data
, buffer
, len
))
694 ((char *) table
->data
)[len
] = 0;
695 filp
->f_pos
+= *lenp
;
697 len
= strlen(table
->data
);
698 if (len
> table
->maxlen
)
703 if(copy_to_user(buffer
, table
->data
, len
))
706 if(put_user('\n', ((char *) buffer
) + len
))
717 * Special case of dostring for the UTS structure. This has locks
718 * to observe. Should this be in kernel/sys.c ????
721 static int proc_doutsstring(ctl_table
*table
, int write
, struct file
*filp
,
722 void *buffer
, size_t *lenp
)
726 r
=proc_dostring(table
,write
,filp
,buffer
,lenp
);
736 static int do_proc_dointvec(ctl_table
*table
, int write
, struct file
*filp
,
737 void *buffer
, size_t *lenp
, int conv
, int op
)
739 int *i
, vleft
, first
=1, len
, left
, neg
, val
;
741 char buf
[TMPBUFLEN
], *p
;
743 if (!table
->data
|| !table
->maxlen
|| !*lenp
||
744 (filp
->f_pos
&& !write
)) {
749 i
= (int *) table
->data
;
750 vleft
= table
->maxlen
/ sizeof(int);
753 for (; left
&& vleft
--; i
++, first
=0) {
757 if(get_user(c
,(char *) buffer
))
768 if (len
> TMPBUFLEN
-1)
770 if(copy_from_user(buf
, buffer
, len
))
774 if (*p
== '-' && left
> 1) {
778 if (*p
< '0' || *p
> '9')
780 val
= simple_strtoul(p
, &p
, 0) * conv
;
782 if ((len
< left
) && *p
&& !isspace(*p
))
789 case OP_SET
: *i
= val
; break;
790 case OP_AND
: *i
&= val
; break;
791 case OP_OR
: *i
|= val
; break;
792 case OP_MAX
: if(*i
< val
)
795 case OP_MIN
: if(*i
> val
)
803 sprintf(p
, "%d", (*i
) / conv
);
807 if(copy_to_user(buffer
, buf
, len
))
814 if (!write
&& !first
&& left
) {
815 if(put_user('\n', (char *) buffer
))
833 filp
->f_pos
+= *lenp
;
837 int proc_dointvec(ctl_table
*table
, int write
, struct file
*filp
,
838 void *buffer
, size_t *lenp
)
840 return do_proc_dointvec(table
,write
,filp
,buffer
,lenp
,1,OP_SET
);
844 * init may raise the set.
847 int proc_dointvec_bset(ctl_table
*table
, int write
, struct file
*filp
,
848 void *buffer
, size_t *lenp
)
850 return do_proc_dointvec(table
,write
,filp
,buffer
,lenp
,1,
851 (current
->pid
== 1) ? OP_SET
: OP_AND
);
855 int proc_dointvec_minmax(ctl_table
*table
, int write
, struct file
*filp
,
856 void *buffer
, size_t *lenp
)
858 int *i
, *min
, *max
, vleft
, first
=1, len
, left
, neg
, val
;
860 char buf
[TMPBUFLEN
], *p
;
862 if (!table
->data
|| !table
->maxlen
|| !*lenp
||
863 (filp
->f_pos
&& !write
)) {
868 i
= (int *) table
->data
;
869 min
= (int *) table
->extra1
;
870 max
= (int *) table
->extra2
;
871 vleft
= table
->maxlen
/ sizeof(int);
874 for (; left
&& vleft
--; i
++, first
=0) {
878 if(get_user(c
, (char *) buffer
))
889 if (len
> TMPBUFLEN
-1)
891 if(copy_from_user(buf
, buffer
, len
))
895 if (*p
== '-' && left
> 1) {
899 if (*p
< '0' || *p
> '9')
901 val
= simple_strtoul(p
, &p
, 0);
903 if ((len
< left
) && *p
&& !isspace(*p
))
910 if (min
&& val
< *min
++)
912 if (max
&& val
> *max
++)
919 sprintf(p
, "%d", *i
);
923 if(copy_to_user(buffer
, buf
, len
))
930 if (!write
&& !first
&& left
) {
931 if(put_user('\n', (char *) buffer
))
949 filp
->f_pos
+= *lenp
;
955 * an unsigned long function version
958 static int do_proc_doulongvec_minmax(ctl_table
*table
, int write
,
960 void *buffer
, size_t *lenp
,
961 unsigned long convmul
,
962 unsigned long convdiv
)
965 unsigned long *i
, *min
, *max
, val
;
966 int vleft
, first
=1, len
, left
, neg
;
967 char buf
[TMPBUFLEN
], *p
;
969 if (!table
->data
|| !table
->maxlen
|| !*lenp
||
970 (filp
->f_pos
&& !write
)) {
975 i
= (unsigned long *) table
->data
;
976 min
= (unsigned long *) table
->extra1
;
977 max
= (unsigned long *) table
->extra2
;
978 vleft
= table
->maxlen
/ sizeof(unsigned long);
981 for (; left
&& vleft
--; i
++, first
=0) {
985 if(get_user(c
, (char *) buffer
))
996 if (len
> TMPBUFLEN
-1)
998 if(copy_from_user(buf
, buffer
, len
))
1002 if (*p
== '-' && left
> 1) {
1006 if (*p
< '0' || *p
> '9')
1008 val
= simple_strtoul(p
, &p
, 0) * convmul
/ convdiv
;
1010 if ((len
< left
) && *p
&& !isspace(*p
))
1019 if (min
&& val
< *min
++)
1021 if (max
&& val
> *max
++)
1028 sprintf(p
, "%lu", convdiv
* (*i
) / convmul
);
1032 if(copy_to_user(buffer
, buf
, len
))
1039 if (!write
&& !first
&& left
) {
1040 if(put_user('\n', (char *) buffer
))
1045 p
= (char *) buffer
;
1048 if(get_user(c
, p
++))
1058 filp
->f_pos
+= *lenp
;
1063 int proc_doulongvec_minmax(ctl_table
*table
, int write
, struct file
*filp
,
1064 void *buffer
, size_t *lenp
)
1066 return do_proc_doulongvec_minmax(table
, write
, filp
, buffer
, lenp
, 1l, 1l);
1069 int proc_doulongvec_ms_jiffies_minmax(ctl_table
*table
, int write
,
1071 void *buffer
, size_t *lenp
)
1073 return do_proc_doulongvec_minmax(table
, write
, filp
, buffer
,
1078 /* Like proc_dointvec, but converts seconds to jiffies */
1079 int proc_dointvec_jiffies(ctl_table
*table
, int write
, struct file
*filp
,
1080 void *buffer
, size_t *lenp
)
1082 return do_proc_dointvec(table
,write
,filp
,buffer
,lenp
,HZ
,OP_SET
);
1085 #else /* CONFIG_PROC_FS */
1087 int proc_dostring(ctl_table
*table
, int write
, struct file
*filp
,
1088 void *buffer
, size_t *lenp
)
1093 static int proc_doutsstring(ctl_table
*table
, int write
, struct file
*filp
,
1094 void *buffer
, size_t *lenp
)
1099 int proc_dointvec(ctl_table
*table
, int write
, struct file
*filp
,
1100 void *buffer
, size_t *lenp
)
1105 int proc_dointvec_bset(ctl_table
*table
, int write
, struct file
*filp
,
1106 void *buffer
, size_t *lenp
)
1111 int proc_dointvec_minmax(ctl_table
*table
, int write
, struct file
*filp
,
1112 void *buffer
, size_t *lenp
)
1117 int proc_dointvec_jiffies(ctl_table
*table
, int write
, struct file
*filp
,
1118 void *buffer
, size_t *lenp
)
1123 int proc_doulongvec_minmax(ctl_table
*table
, int write
, struct file
*filp
,
1124 void *buffer
, size_t *lenp
)
1129 int proc_doulongvec_ms_jiffies_minmax(ctl_table
*table
, int write
,
1131 void *buffer
, size_t *lenp
)
1137 #endif /* CONFIG_PROC_FS */
1141 * General sysctl support routines
1144 /* The generic string strategy routine: */
1145 int sysctl_string(ctl_table
*table
, int *name
, int nlen
,
1146 void *oldval
, size_t *oldlenp
,
1147 void *newval
, size_t newlen
, void **context
)
1151 if (!table
->data
|| !table
->maxlen
)
1154 if (oldval
&& oldlenp
) {
1155 if(get_user(len
, oldlenp
))
1158 l
= strlen(table
->data
);
1159 if (len
> l
) len
= l
;
1160 if (len
>= table
->maxlen
)
1161 len
= table
->maxlen
;
1162 if(copy_to_user(oldval
, table
->data
, len
))
1164 if(put_user(0, ((char *) oldval
) + len
))
1166 if(put_user(len
, oldlenp
))
1170 if (newval
&& newlen
) {
1172 if (len
> table
->maxlen
)
1173 len
= table
->maxlen
;
1174 if(copy_from_user(table
->data
, newval
, len
))
1176 if (len
== table
->maxlen
)
1178 ((char *) table
->data
)[len
] = 0;
1184 * This function makes sure that all of the integers in the vector
1185 * are between the minimum and maximum values given in the arrays
1186 * table->extra1 and table->extra2, respectively.
1188 int sysctl_intvec(ctl_table
*table
, int *name
, int nlen
,
1189 void *oldval
, size_t *oldlenp
,
1190 void *newval
, size_t newlen
, void **context
)
1192 int i
, length
, *vec
, *min
, *max
;
1194 if (newval
&& newlen
) {
1195 if (newlen
% sizeof(int) != 0)
1198 if (!table
->extra1
&& !table
->extra2
)
1201 if (newlen
> table
->maxlen
)
1202 newlen
= table
->maxlen
;
1203 length
= newlen
/ sizeof(int);
1205 vec
= (int *) newval
;
1206 min
= (int *) table
->extra1
;
1207 max
= (int *) table
->extra2
;
1209 for (i
= 0; i
< length
; i
++) {
1211 get_user(value
, vec
+ i
);
1212 if (min
&& value
< min
[i
])
1214 if (max
&& value
> max
[i
])
1221 /* Strategy function to convert jiffies to seconds */
1222 int sysctl_jiffies(ctl_table
*table
, int *name
, int nlen
,
1223 void *oldval
, size_t *oldlenp
,
1224 void *newval
, size_t newlen
, void **context
)
1229 if (get_user(olen
, oldlenp
))
1231 if (olen
!=sizeof(int))
1234 if (put_user(*(int *)(table
->data
) / HZ
, (int *)oldval
) ||
1235 (oldlenp
&& put_user(sizeof(int),oldlenp
)))
1238 if (newval
&& newlen
) {
1240 if (newlen
!= sizeof(int))
1242 if (get_user(new, (int *)newval
))
1244 *(int *)(table
->data
) = new*HZ
;
1250 void *oldval
, size_t *oldlenp
, void *newval
, size_t newlen
,
1251 int rdwr
, char *data
, size_t max
)
1253 int l
= strlen(data
) + 1;
1254 if (newval
&& !rdwr
)
1256 if (newval
&& newlen
>= max
)
1260 if(get_user(old_l
, oldlenp
))
1264 if(put_user(l
, oldlenp
) || copy_to_user(oldval
, data
, l
))
1268 if(copy_from_user(data
, newval
, newlen
))
1276 void *oldval
, size_t *oldlenp
, void *newval
, size_t newlen
,
1277 int rdwr
, int *data
)
1279 if (newval
&& !rdwr
)
1281 if (newval
&& newlen
!= sizeof(int))
1285 if(get_user(old_l
, oldlenp
))
1287 if (old_l
< sizeof(int))
1289 if(put_user(sizeof(int), oldlenp
)||copy_to_user(oldval
, data
, sizeof(int)))
1293 if(copy_from_user(data
, newval
, sizeof(int)))
1299 void *oldval
, size_t *oldlenp
, void *newval
, size_t newlen
,
1300 int rdwr
, void *data
, size_t len
)
1302 if (newval
&& !rdwr
)
1304 if (newval
&& newlen
!= len
)
1308 if(get_user(old_l
, oldlenp
))
1312 if(put_user(len
, oldlenp
) || copy_to_user(oldval
, data
, len
))
1316 if(copy_from_user(data
, newval
, len
))
1322 #else /* CONFIG_SYSCTL */
1325 extern asmlinkage
long sys_sysctl(struct __sysctl_args
*args
)
1330 int sysctl_string(ctl_table
*table
, int *name
, int nlen
,
1331 void *oldval
, size_t *oldlenp
,
1332 void *newval
, size_t newlen
, void **context
)
1337 int sysctl_intvec(ctl_table
*table
, int *name
, int nlen
,
1338 void *oldval
, size_t *oldlenp
,
1339 void *newval
, size_t newlen
, void **context
)
1344 int proc_dostring(ctl_table
*table
, int write
, struct file
*filp
,
1345 void *buffer
, size_t *lenp
)
1350 int proc_dointvec(ctl_table
*table
, int write
, struct file
*filp
,
1351 void *buffer
, size_t *lenp
)
1356 int proc_dointvec_bset(ctl_table
*table
, int write
, struct file
*filp
,
1357 void *buffer
, size_t *lenp
)
1362 int proc_dointvec_minmax(ctl_table
*table
, int write
, struct file
*filp
,
1363 void *buffer
, size_t *lenp
)
1368 int proc_dointvec_jiffies(ctl_table
*table
, int write
, struct file
*filp
,
1369 void *buffer
, size_t *lenp
)
1374 int proc_doulongvec_minmax(ctl_table
*table
, int write
, struct file
*filp
,
1375 void *buffer
, size_t *lenp
)
1380 int proc_doulongvec_ms_jiffies_minmax(ctl_table
*table
, int write
,
1382 void *buffer
, size_t *lenp
)
1387 struct ctl_table_header
* register_sysctl_table(ctl_table
* table
,
1393 void unregister_sysctl_table(struct ctl_table_header
* table
)
1397 #endif /* CONFIG_SYSCTL */