3905df6f026f2d5b2ceb4561f51c42ccea1bc085
[linux-2.6.git] / kernel / sysctl.c
1 /*
2  * sysctl.c: General linux system control interface
3  *
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
12  *  Horn.
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
16  *  Wendling.
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
19  */
20
21 #include <linux/config.h>
22 #include <linux/module.h>
23 #include <linux/mm.h>
24 #include <linux/swap.h>
25 #include <linux/slab.h>
26 #include <linux/sysctl.h>
27 #include <linux/proc_fs.h>
28 #include <linux/ctype.h>
29 #include <linux/utsname.h>
30 #include <linux/capability.h>
31 #include <linux/smp_lock.h>
32 #include <linux/init.h>
33 #include <linux/kernel.h>
34 #include <linux/sysrq.h>
35 #include <linux/highuid.h>
36 #include <linux/writeback.h>
37 #include <linux/hugetlb.h>
38 #include <linux/security.h>
39 #include <linux/initrd.h>
40 #include <linux/times.h>
41 #include <linux/limits.h>
42 #include <linux/dcache.h>
43
44 #include <asm/uaccess.h>
45
46 #ifdef CONFIG_ROOT_NFS
47 #include <linux/nfs_fs.h>
48 #endif
49
50 #if defined(CONFIG_SYSCTL)
51
52 /* External variables not in a header file. */
53 extern int panic_timeout;
54 extern int C_A_D;
55 extern int sysctl_overcommit_memory;
56 extern int sysctl_overcommit_ratio;
57 extern int max_threads;
58 extern int sysrq_enabled;
59 extern int core_uses_pid;
60 extern char core_pattern[];
61 extern int cad_pid;
62 extern int pid_max;
63 extern int sysctl_lower_zone_protection;
64 extern int min_free_kbytes;
65 extern int printk_ratelimit_jiffies;
66 extern int printk_ratelimit_burst;
67
68 /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
69 static int maxolduid = 65535;
70 static int minolduid;
71
72 static int ngroups_max = NGROUPS_MAX;
73
74 #ifdef CONFIG_KMOD
75 extern char modprobe_path[];
76 #endif
77 #ifdef CONFIG_HOTPLUG
78 extern char hotplug_path[];
79 #endif
80 #ifdef CONFIG_CHR_DEV_SG
81 extern int sg_big_buff;
82 #endif
83 #ifdef CONFIG_SYSVIPC
84 extern size_t shm_ctlmax;
85 extern size_t shm_ctlall;
86 extern int shm_ctlmni;
87 extern int msg_ctlmax;
88 extern int msg_ctlmnb;
89 extern int msg_ctlmni;
90 extern int sem_ctls[];
91 #endif
92
93 #ifdef __sparc__
94 extern char reboot_command [];
95 extern int stop_a_enabled;
96 extern int scons_pwroff;
97 #endif
98
99 #ifdef __hppa__
100 extern int pwrsw_enabled;
101 extern int unaligned_enabled;
102 #endif
103
104 #ifdef CONFIG_ARCH_S390
105 #ifdef CONFIG_MATHEMU
106 extern int sysctl_ieee_emulation_warnings;
107 #endif
108 extern int sysctl_userprocess_debug;
109 #endif
110
111 extern int sysctl_hz_timer;
112
113 #if defined(CONFIG_PPC32) && defined(CONFIG_6xx)
114 extern unsigned long powersave_nap;
115 int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
116                   void __user *buffer, size_t *lenp, loff_t *ppos);
117 #endif
118
119 #ifdef CONFIG_BSD_PROCESS_ACCT
120 extern int acct_parm[];
121 #endif
122
123 static int parse_table(int __user *, int, void __user *, size_t __user *, void __user *, size_t,
124                        ctl_table *, void **);
125 static int proc_doutsstring(ctl_table *table, int write, struct file *filp,
126                   void __user *buffer, size_t *lenp, loff_t *ppos);
127
128 static ctl_table root_table[];
129 static struct ctl_table_header root_table_header =
130         { root_table, LIST_HEAD_INIT(root_table_header.ctl_entry) };
131
132 static ctl_table kern_table[];
133 static ctl_table vm_table[];
134 #ifdef CONFIG_NET
135 extern ctl_table net_table[];
136 #endif
137 static ctl_table proc_table[];
138 static ctl_table fs_table[];
139 static ctl_table debug_table[];
140 static ctl_table dev_table[];
141 extern ctl_table random_table[];
142 #ifdef CONFIG_UNIX98_PTYS
143 extern ctl_table pty_table[];
144 #endif
145
146 /* /proc declarations: */
147
148 #ifdef CONFIG_PROC_FS
149
150 static ssize_t proc_readsys(struct file *, char __user *, size_t, loff_t *);
151 static ssize_t proc_writesys(struct file *, const char __user *, size_t, loff_t *);
152 static int proc_opensys(struct inode *, struct file *);
153
154 struct file_operations proc_sys_file_operations = {
155         .open           = proc_opensys,
156         .read           = proc_readsys,
157         .write          = proc_writesys,
158 };
159
160 extern struct proc_dir_entry *proc_sys_root;
161
162 static void register_proc_table(ctl_table *, struct proc_dir_entry *);
163 static void unregister_proc_table(ctl_table *, struct proc_dir_entry *);
164 #endif
165
166 /* The default sysctl tables: */
167
168 static ctl_table root_table[] = {
169         {
170                 .ctl_name       = CTL_KERN,
171                 .procname       = "kernel",
172                 .mode           = 0555,
173                 .child          = kern_table,
174         },
175         {
176                 .ctl_name       = CTL_VM,
177                 .procname       = "vm",
178                 .mode           = 0555,
179                 .child          = vm_table,
180         },
181 #ifdef CONFIG_NET
182         {
183                 .ctl_name       = CTL_NET,
184                 .procname       = "net",
185                 .mode           = 0555,
186                 .child          = net_table,
187         },
188 #endif
189         {
190                 .ctl_name       = CTL_PROC,
191                 .procname       = "proc",
192                 .mode           = 0555,
193                 .child          = proc_table,
194         },
195         {
196                 .ctl_name       = CTL_FS,
197                 .procname       = "fs",
198                 .mode           = 0555,
199                 .child          = fs_table,
200         },
201         {
202                 .ctl_name       = CTL_DEBUG,
203                 .procname       = "debug",
204                 .mode           = 0555,
205                 .child          = debug_table,
206         },
207         {
208                 .ctl_name       = CTL_DEV,
209                 .procname       = "dev",
210                 .mode           = 0555,
211                 .child          = dev_table,
212         },
213         { .ctl_name = 0 }
214 };
215
216 static ctl_table kern_table[] = {
217         {
218                 .ctl_name       = KERN_OSTYPE,
219                 .procname       = "ostype",
220                 .data           = system_utsname.sysname,
221                 .maxlen         = sizeof(system_utsname.sysname),
222                 .mode           = 0444,
223                 .proc_handler   = &proc_doutsstring,
224                 .strategy       = &sysctl_string,
225         },
226         {
227                 .ctl_name       = KERN_OSRELEASE,
228                 .procname       = "osrelease",
229                 .data           = system_utsname.release,
230                 .maxlen         = sizeof(system_utsname.release),
231                 .mode           = 0444,
232                 .proc_handler   = &proc_doutsstring,
233                 .strategy       = &sysctl_string,
234         },
235         {
236                 .ctl_name       = KERN_VERSION,
237                 .procname       = "version",
238                 .data           = system_utsname.version,
239                 .maxlen         = sizeof(system_utsname.version),
240                 .mode           = 0444,
241                 .proc_handler   = &proc_doutsstring,
242                 .strategy       = &sysctl_string,
243         },
244         {
245                 .ctl_name       = KERN_NODENAME,
246                 .procname       = "hostname",
247                 .data           = system_utsname.nodename,
248                 .maxlen         = sizeof(system_utsname.nodename),
249                 .mode           = 0644,
250                 .proc_handler   = &proc_doutsstring,
251                 .strategy       = &sysctl_string,
252         },
253         {
254                 .ctl_name       = KERN_DOMAINNAME,
255                 .procname       = "domainname",
256                 .data           = system_utsname.domainname,
257                 .maxlen         = sizeof(system_utsname.domainname),
258                 .mode           = 0644,
259                 .proc_handler   = &proc_doutsstring,
260                 .strategy       = &sysctl_string,
261         },
262         {
263                 .ctl_name       = KERN_PANIC,
264                 .procname       = "panic",
265                 .data           = &panic_timeout,
266                 .maxlen         = sizeof(int),
267                 .mode           = 0644,
268                 .proc_handler   = &proc_dointvec,
269         },
270         {
271                 .ctl_name       = KERN_CORE_USES_PID,
272                 .procname       = "core_uses_pid",
273                 .data           = &core_uses_pid,
274                 .maxlen         = sizeof(int),
275                 .mode           = 0644,
276                 .proc_handler   = &proc_dointvec,
277         },
278         {
279                 .ctl_name       = KERN_CORE_PATTERN,
280                 .procname       = "core_pattern",
281                 .data           = core_pattern,
282                 .maxlen         = 64,
283                 .mode           = 0644,
284                 .proc_handler   = &proc_dostring,
285                 .strategy       = &sysctl_string,
286         },
287         {
288                 .ctl_name       = KERN_TAINTED,
289                 .procname       = "tainted",
290                 .data           = &tainted,
291                 .maxlen         = sizeof(int),
292                 .mode           = 0644,
293                 .proc_handler   = &proc_dointvec,
294         },
295         {
296                 .ctl_name       = KERN_CAP_BSET,
297                 .procname       = "cap-bound",
298                 .data           = &cap_bset,
299                 .maxlen         = sizeof(kernel_cap_t),
300                 .mode           = 0600,
301                 .proc_handler   = &proc_dointvec_bset,
302         },
303 #ifdef CONFIG_BLK_DEV_INITRD
304         {
305                 .ctl_name       = KERN_REALROOTDEV,
306                 .procname       = "real-root-dev",
307                 .data           = &real_root_dev,
308                 .maxlen         = sizeof(int),
309                 .mode           = 0644,
310                 .proc_handler   = &proc_dointvec,
311         },
312 #endif
313 #ifdef __sparc__
314         {
315                 .ctl_name       = KERN_SPARC_REBOOT,
316                 .procname       = "reboot-cmd",
317                 .data           = reboot_command,
318                 .maxlen         = 256,
319                 .mode           = 0644,
320                 .proc_handler   = &proc_dostring,
321                 .strategy       = &sysctl_string,
322         },
323         {
324                 .ctl_name       = KERN_SPARC_STOP_A,
325                 .procname       = "stop-a",
326                 .data           = &stop_a_enabled,
327                 .maxlen         = sizeof (int),
328                 .mode           = 0644,
329                 .proc_handler   = &proc_dointvec,
330         },
331         {
332                 .ctl_name       = KERN_SPARC_SCONS_PWROFF,
333                 .procname       = "scons-poweroff",
334                 .data           = &scons_pwroff,
335                 .maxlen         = sizeof (int),
336                 .mode           = 0644,
337                 .proc_handler   = &proc_dointvec,
338         },
339 #endif
340 #ifdef __hppa__
341         {
342                 .ctl_name       = KERN_HPPA_PWRSW,
343                 .procname       = "soft-power",
344                 .data           = &pwrsw_enabled,
345                 .maxlen         = sizeof (int),
346                 .mode           = 0644,
347                 .proc_handler   = &proc_dointvec,
348         },
349         {
350                 .ctl_name       = KERN_HPPA_UNALIGNED,
351                 .procname       = "unaligned-trap",
352                 .data           = &unaligned_enabled,
353                 .maxlen         = sizeof (int),
354                 .mode           = 0644,
355                 .proc_handler   = &proc_dointvec,
356         },
357 #endif
358 #if defined(CONFIG_PPC32) && defined(CONFIG_6xx)
359         {
360                 .ctl_name       = KERN_PPC_POWERSAVE_NAP,
361                 .procname       = "powersave-nap",
362                 .data           = &powersave_nap,
363                 .maxlen         = sizeof(int),
364                 .mode           = 0644,
365                 .proc_handler   = &proc_dointvec,
366         },
367         {
368                 .ctl_name       = KERN_PPC_L2CR,
369                 .procname       = "l2cr",
370                 .mode           = 0644,
371                 .proc_handler   = &proc_dol2crvec,
372         },
373 #endif
374         {
375                 .ctl_name       = KERN_CTLALTDEL,
376                 .procname       = "ctrl-alt-del",
377                 .data           = &C_A_D,
378                 .maxlen         = sizeof(int),
379                 .mode           = 0644,
380                 .proc_handler   = &proc_dointvec,
381         },
382         {
383                 .ctl_name       = KERN_PRINTK,
384                 .procname       = "printk",
385                 .data           = &console_loglevel,
386                 .maxlen         = 4*sizeof(int),
387                 .mode           = 0644,
388                 .proc_handler   = &proc_dointvec,
389         },
390 #ifdef CONFIG_KMOD
391         {
392                 .ctl_name       = KERN_MODPROBE,
393                 .procname       = "modprobe",
394                 .data           = &modprobe_path,
395                 .maxlen         = KMOD_PATH_LEN,
396                 .mode           = 0644,
397                 .proc_handler   = &proc_dostring,
398                 .strategy       = &sysctl_string,
399         },
400 #endif
401 #ifdef CONFIG_HOTPLUG
402         {
403                 .ctl_name       = KERN_HOTPLUG,
404                 .procname       = "hotplug",
405                 .data           = &hotplug_path,
406                 .maxlen         = KMOD_PATH_LEN,
407                 .mode           = 0644,
408                 .proc_handler   = &proc_dostring,
409                 .strategy       = &sysctl_string,
410         },
411 #endif
412 #ifdef CONFIG_CHR_DEV_SG
413         {
414                 .ctl_name       = KERN_SG_BIG_BUFF,
415                 .procname       = "sg-big-buff",
416                 .data           = &sg_big_buff,
417                 .maxlen         = sizeof (int),
418                 .mode           = 0444,
419                 .proc_handler   = &proc_dointvec,
420         },
421 #endif
422 #ifdef CONFIG_BSD_PROCESS_ACCT
423         {
424                 .ctl_name       = KERN_ACCT,
425                 .procname       = "acct",
426                 .data           = &acct_parm,
427                 .maxlen         = 3*sizeof(int),
428                 .mode           = 0644,
429                 .proc_handler   = &proc_dointvec,
430         },
431 #endif
432 #ifdef CONFIG_SYSVIPC
433         {
434                 .ctl_name       = KERN_SHMMAX,
435                 .procname       = "shmmax",
436                 .data           = &shm_ctlmax,
437                 .maxlen         = sizeof (size_t),
438                 .mode           = 0644,
439                 .proc_handler   = &proc_doulongvec_minmax,
440         },
441         {
442                 .ctl_name       = KERN_SHMALL,
443                 .procname       = "shmall",
444                 .data           = &shm_ctlall,
445                 .maxlen         = sizeof (size_t),
446                 .mode           = 0644,
447                 .proc_handler   = &proc_doulongvec_minmax,
448         },
449         {
450                 .ctl_name       = KERN_SHMMNI,
451                 .procname       = "shmmni",
452                 .data           = &shm_ctlmni,
453                 .maxlen         = sizeof (int),
454                 .mode           = 0644,
455                 .proc_handler   = &proc_dointvec,
456         },
457         {
458                 .ctl_name       = KERN_MSGMAX,
459                 .procname       = "msgmax",
460                 .data           = &msg_ctlmax,
461                 .maxlen         = sizeof (int),
462                 .mode           = 0644,
463                 .proc_handler   = &proc_dointvec,
464         },
465         {
466                 .ctl_name       = KERN_MSGMNI,
467                 .procname       = "msgmni",
468                 .data           = &msg_ctlmni,
469                 .maxlen         = sizeof (int),
470                 .mode           = 0644,
471                 .proc_handler   = &proc_dointvec,
472         },
473         {
474                 .ctl_name       = KERN_MSGMNB,
475                 .procname       =  "msgmnb",
476                 .data           = &msg_ctlmnb,
477                 .maxlen         = sizeof (int),
478                 .mode           = 0644,
479                 .proc_handler   = &proc_dointvec,
480         },
481         {
482                 .ctl_name       = KERN_SEM,
483                 .procname       = "sem",
484                 .data           = &sem_ctls,
485                 .maxlen         = 4*sizeof (int),
486                 .mode           = 0644,
487                 .proc_handler   = &proc_dointvec,
488         },
489 #endif
490 #ifdef CONFIG_MAGIC_SYSRQ
491         {
492                 .ctl_name       = KERN_SYSRQ,
493                 .procname       = "sysrq",
494                 .data           = &sysrq_enabled,
495                 .maxlen         = sizeof (int),
496                 .mode           = 0644,
497                 .proc_handler   = &proc_dointvec,
498         },
499 #endif
500         {
501                 .ctl_name       = KERN_CADPID,
502                 .procname       = "cad_pid",
503                 .data           = &cad_pid,
504                 .maxlen         = sizeof (int),
505                 .mode           = 0600,
506                 .proc_handler   = &proc_dointvec,
507         },
508         {
509                 .ctl_name       = KERN_MAX_THREADS,
510                 .procname       = "threads-max",
511                 .data           = &max_threads,
512                 .maxlen         = sizeof(int),
513                 .mode           = 0644,
514                 .proc_handler   = &proc_dointvec,
515         },
516         {
517                 .ctl_name       = KERN_RANDOM,
518                 .procname       = "random",
519                 .mode           = 0555,
520                 .child          = random_table,
521         },
522 #ifdef CONFIG_UNIX98_PTYS
523         {
524                 .ctl_name       = KERN_PTY,
525                 .procname       = "pty",
526                 .mode           = 0555,
527                 .child          = pty_table,
528         },
529 #endif
530         {
531                 .ctl_name       = KERN_OVERFLOWUID,
532                 .procname       = "overflowuid",
533                 .data           = &overflowuid,
534                 .maxlen         = sizeof(int),
535                 .mode           = 0644,
536                 .proc_handler   = &proc_dointvec_minmax,
537                 .strategy       = &sysctl_intvec,
538                 .extra1         = &minolduid,
539                 .extra2         = &maxolduid,
540         },
541         {
542                 .ctl_name       = KERN_OVERFLOWGID,
543                 .procname       = "overflowgid",
544                 .data           = &overflowgid,
545                 .maxlen         = sizeof(int),
546                 .mode           = 0644,
547                 .proc_handler   = &proc_dointvec_minmax,
548                 .strategy       = &sysctl_intvec,
549                 .extra1         = &minolduid,
550                 .extra2         = &maxolduid,
551         },
552 #ifdef CONFIG_ARCH_S390
553 #ifdef CONFIG_MATHEMU
554         {
555                 .ctl_name       = KERN_IEEE_EMULATION_WARNINGS,
556                 .procname       = "ieee_emulation_warnings",
557                 .data           = &sysctl_ieee_emulation_warnings,
558                 .maxlen         = sizeof(int),
559                 .mode           = 0644,
560                 .proc_handler   = &proc_dointvec,
561         },
562 #endif
563 #ifdef CONFIG_NO_IDLE_HZ
564         {
565                 .ctl_name       = KERN_HZ_TIMER,
566                 .procname       = "hz_timer",
567                 .data           = &sysctl_hz_timer,
568                 .maxlen         = sizeof(int),
569                 .mode           = 0644,
570                 .proc_handler   = &proc_dointvec,
571         },
572 #endif
573         {
574                 .ctl_name       = KERN_S390_USER_DEBUG_LOGGING,
575                 .procname       = "userprocess_debug",
576                 .data           = &sysctl_userprocess_debug,
577                 .maxlen         = sizeof(int),
578                 .mode           = 0644,
579                 .proc_handler   = &proc_dointvec,
580         },
581 #endif
582         {
583                 .ctl_name       = KERN_PIDMAX,
584                 .procname       = "pid_max",
585                 .data           = &pid_max,
586                 .maxlen         = sizeof (int),
587                 .mode           = 0644,
588                 .proc_handler   = &proc_dointvec,
589         },
590         {
591                 .ctl_name       = KERN_PANIC_ON_OOPS,
592                 .procname       = "panic_on_oops",
593                 .data           = &panic_on_oops,
594                 .maxlen         = sizeof(int),
595                 .mode           = 0644,
596                 .proc_handler   = &proc_dointvec,
597         },
598         {
599                 .ctl_name       = KERN_PRINTK_RATELIMIT,
600                 .procname       = "printk_ratelimit",
601                 .data           = &printk_ratelimit_jiffies,
602                 .maxlen         = sizeof(int),
603                 .mode           = 0644,
604                 .proc_handler   = &proc_dointvec_jiffies,
605                 .strategy       = &sysctl_jiffies,
606         },
607         {
608                 .ctl_name       = KERN_PRINTK_RATELIMIT_BURST,
609                 .procname       = "printk_ratelimit_burst",
610                 .data           = &printk_ratelimit_burst,
611                 .maxlen         = sizeof(int),
612                 .mode           = 0644,
613                 .proc_handler   = &proc_dointvec,
614         },
615         {
616                 .ctl_name       = KERN_NGROUPS_MAX,
617                 .procname       = "ngroups_max",
618                 .data           = &ngroups_max,
619                 .maxlen         = sizeof (int),
620                 .mode           = 0444,
621                 .proc_handler   = &proc_dointvec,
622         },
623         { .ctl_name = 0 }
624 };
625
626 /* Constants for minimum and maximum testing in vm_table.
627    We use these as one-element integer vectors. */
628 static int zero;
629 static int one_hundred = 100;
630
631
632 static ctl_table vm_table[] = {
633         {
634                 .ctl_name       = VM_OVERCOMMIT_MEMORY,
635                 .procname       = "overcommit_memory",
636                 .data           = &sysctl_overcommit_memory,
637                 .maxlen         = sizeof(sysctl_overcommit_memory),
638                 .mode           = 0644,
639                 .proc_handler   = &proc_dointvec,
640         },
641         {
642                 .ctl_name       = VM_OVERCOMMIT_RATIO,
643                 .procname       = "overcommit_ratio",
644                 .data           = &sysctl_overcommit_ratio,
645                 .maxlen         = sizeof(sysctl_overcommit_ratio),
646                 .mode           = 0644,
647                 .proc_handler   = &proc_dointvec,
648         },
649         {
650                 .ctl_name       = VM_PAGE_CLUSTER,
651                 .procname       = "page-cluster", 
652                 .data           = &page_cluster,
653                 .maxlen         = sizeof(int),
654                 .mode           = 0644,
655                 .proc_handler   = &proc_dointvec,
656         },
657         {
658                 .ctl_name       = VM_DIRTY_BACKGROUND,
659                 .procname       = "dirty_background_ratio",
660                 .data           = &dirty_background_ratio,
661                 .maxlen         = sizeof(dirty_background_ratio),
662                 .mode           = 0644,
663                 .proc_handler   = &proc_dointvec_minmax,
664                 .strategy       = &sysctl_intvec,
665                 .extra1         = &zero,
666                 .extra2         = &one_hundred,
667         },
668         {
669                 .ctl_name       = VM_DIRTY_RATIO,
670                 .procname       = "dirty_ratio",
671                 .data           = &vm_dirty_ratio,
672                 .maxlen         = sizeof(vm_dirty_ratio),
673                 .mode           = 0644,
674                 .proc_handler   = &proc_dointvec_minmax,
675                 .strategy       = &sysctl_intvec,
676                 .extra1         = &zero,
677                 .extra2         = &one_hundred,
678         },
679         {
680                 .ctl_name       = VM_DIRTY_WB_CS,
681                 .procname       = "dirty_writeback_centisecs",
682                 .data           = &dirty_writeback_centisecs,
683                 .maxlen         = sizeof(dirty_writeback_centisecs),
684                 .mode           = 0644,
685                 .proc_handler   = &dirty_writeback_centisecs_handler,
686         },
687         {
688                 .ctl_name       = VM_DIRTY_EXPIRE_CS,
689                 .procname       = "dirty_expire_centisecs",
690                 .data           = &dirty_expire_centisecs,
691                 .maxlen         = sizeof(dirty_expire_centisecs),
692                 .mode           = 0644,
693                 .proc_handler   = &proc_dointvec,
694         },
695         {
696                 .ctl_name       = VM_NR_PDFLUSH_THREADS,
697                 .procname       = "nr_pdflush_threads",
698                 .data           = &nr_pdflush_threads,
699                 .maxlen         = sizeof nr_pdflush_threads,
700                 .mode           = 0444 /* read-only*/,
701                 .proc_handler   = &proc_dointvec,
702         },
703         {
704                 .ctl_name       = VM_SWAPPINESS,
705                 .procname       = "swappiness",
706                 .data           = &vm_swappiness,
707                 .maxlen         = sizeof(vm_swappiness),
708                 .mode           = 0644,
709                 .proc_handler   = &proc_dointvec_minmax,
710                 .strategy       = &sysctl_intvec,
711                 .extra1         = &zero,
712                 .extra2         = &one_hundred,
713         },
714 #ifdef CONFIG_HUGETLB_PAGE
715          {
716                 .ctl_name       = VM_HUGETLB_PAGES,
717                 .procname       = "nr_hugepages",
718                 .data           = &max_huge_pages,
719                 .maxlen         = sizeof(unsigned long),
720                 .mode           = 0644,
721                 .proc_handler   = &hugetlb_sysctl_handler,
722                 .extra1         = (void *)&hugetlb_zero,
723                 .extra2         = (void *)&hugetlb_infinity,
724          },
725          {
726                 .ctl_name       = VM_HUGETLB_GROUP,
727                 .procname       = "hugetlb_shm_group",
728                 .data           = &sysctl_hugetlb_shm_group,
729                 .maxlen         = sizeof(gid_t),
730                 .mode           = 0644,
731                 .proc_handler   = &proc_dointvec,
732          },
733 #endif
734         {
735                 .ctl_name       = VM_LOWER_ZONE_PROTECTION,
736                 .procname       = "lower_zone_protection",
737                 .data           = &sysctl_lower_zone_protection,
738                 .maxlen         = sizeof(sysctl_lower_zone_protection),
739                 .mode           = 0644,
740                 .proc_handler   = &lower_zone_protection_sysctl_handler,
741                 .strategy       = &sysctl_intvec,
742                 .extra1         = &zero,
743         },
744         {
745                 .ctl_name       = VM_MIN_FREE_KBYTES,
746                 .procname       = "min_free_kbytes",
747                 .data           = &min_free_kbytes,
748                 .maxlen         = sizeof(min_free_kbytes),
749                 .mode           = 0644,
750                 .proc_handler   = &min_free_kbytes_sysctl_handler,
751                 .strategy       = &sysctl_intvec,
752                 .extra1         = &zero,
753         },
754         {
755                 .ctl_name       = VM_MAX_MAP_COUNT,
756                 .procname       = "max_map_count",
757                 .data           = &sysctl_max_map_count,
758                 .maxlen         = sizeof(sysctl_max_map_count),
759                 .mode           = 0644,
760                 .proc_handler   = &proc_dointvec
761         },
762         {
763                 .ctl_name       = VM_LAPTOP_MODE,
764                 .procname       = "laptop_mode",
765                 .data           = &laptop_mode,
766                 .maxlen         = sizeof(laptop_mode),
767                 .mode           = 0644,
768                 .proc_handler   = &proc_dointvec,
769                 .strategy       = &sysctl_intvec,
770                 .extra1         = &zero,
771         },
772         {
773                 .ctl_name       = VM_BLOCK_DUMP,
774                 .procname       = "block_dump",
775                 .data           = &block_dump,
776                 .maxlen         = sizeof(block_dump),
777                 .mode           = 0644,
778                 .proc_handler   = &proc_dointvec,
779                 .strategy       = &sysctl_intvec,
780                 .extra1         = &zero,
781         },
782         {
783                 .ctl_name       = VM_VFS_CACHE_PRESSURE,
784                 .procname       = "vfs_cache_pressure",
785                 .data           = &sysctl_vfs_cache_pressure,
786                 .maxlen         = sizeof(sysctl_vfs_cache_pressure),
787                 .mode           = 0644,
788                 .proc_handler   = &proc_dointvec,
789                 .strategy       = &sysctl_intvec,
790                 .extra1         = &zero,
791         },
792         { .ctl_name = 0 }
793 };
794
795 static ctl_table proc_table[] = {
796         { .ctl_name = 0 }
797 };
798
799 static ctl_table fs_table[] = {
800         {
801                 .ctl_name       = FS_NRINODE,
802                 .procname       = "inode-nr",
803                 .data           = &inodes_stat,
804                 .maxlen         = 2*sizeof(int),
805                 .mode           = 0444,
806                 .proc_handler   = &proc_dointvec,
807         },
808         {
809                 .ctl_name       = FS_STATINODE,
810                 .procname       = "inode-state",
811                 .data           = &inodes_stat,
812                 .maxlen         = 7*sizeof(int),
813                 .mode           = 0444,
814                 .proc_handler   = &proc_dointvec,
815         },
816         {
817                 .ctl_name       = FS_NRFILE,
818                 .procname       = "file-nr",
819                 .data           = &files_stat,
820                 .maxlen         = 3*sizeof(int),
821                 .mode           = 0444,
822                 .proc_handler   = &proc_dointvec,
823         },
824         {
825                 .ctl_name       = FS_MAXFILE,
826                 .procname       = "file-max",
827                 .data           = &files_stat.max_files,
828                 .maxlen         = sizeof(int),
829                 .mode           = 0644,
830                 .proc_handler   = &proc_dointvec,
831         },
832         {
833                 .ctl_name       = FS_DENTRY,
834                 .procname       = "dentry-state",
835                 .data           = &dentry_stat,
836                 .maxlen         = 6*sizeof(int),
837                 .mode           = 0444,
838                 .proc_handler   = &proc_dointvec,
839         },
840         {
841                 .ctl_name       = FS_OVERFLOWUID,
842                 .procname       = "overflowuid",
843                 .data           = &fs_overflowuid,
844                 .maxlen         = sizeof(int),
845                 .mode           = 0644,
846                 .proc_handler   = &proc_dointvec_minmax,
847                 .strategy       = &sysctl_intvec,
848                 .extra1         = &minolduid,
849                 .extra2         = &maxolduid,
850         },
851         {
852                 .ctl_name       = FS_OVERFLOWGID,
853                 .procname       = "overflowgid",
854                 .data           = &fs_overflowgid,
855                 .maxlen         = sizeof(int),
856                 .mode           = 0644,
857                 .proc_handler   = &proc_dointvec_minmax,
858                 .strategy       = &sysctl_intvec,
859                 .extra1         = &minolduid,
860                 .extra2         = &maxolduid,
861         },
862         {
863                 .ctl_name       = FS_LEASES,
864                 .procname       = "leases-enable",
865                 .data           = &leases_enable,
866                 .maxlen         = sizeof(int),
867                 .mode           = 0644,
868                 .proc_handler   = &proc_dointvec,
869         },
870         {
871                 .ctl_name       = FS_DIR_NOTIFY,
872                 .procname       = "dir-notify-enable",
873                 .data           = &dir_notify_enable,
874                 .maxlen         = sizeof(int),
875                 .mode           = 0644,
876                 .proc_handler   = &proc_dointvec,
877         },
878         {
879                 .ctl_name       = FS_LEASE_TIME,
880                 .procname       = "lease-break-time",
881                 .data           = &lease_break_time,
882                 .maxlen         = sizeof(int),
883                 .mode           = 0644,
884                 .proc_handler   = &proc_dointvec,
885         },
886         {
887                 .ctl_name       = FS_AIO_NR,
888                 .procname       = "aio-nr",
889                 .data           = &aio_nr,
890                 .maxlen         = sizeof(aio_nr),
891                 .mode           = 0444,
892                 .proc_handler   = &proc_dointvec,
893         },
894         {
895                 .ctl_name       = FS_AIO_MAX_NR,
896                 .procname       = "aio-max-nr",
897                 .data           = &aio_max_nr,
898                 .maxlen         = sizeof(aio_max_nr),
899                 .mode           = 0644,
900                 .proc_handler   = &proc_dointvec,
901         },
902         { .ctl_name = 0 }
903 };
904
905 static ctl_table debug_table[] = {
906         { .ctl_name = 0 }
907 };
908
909 static ctl_table dev_table[] = {
910         { .ctl_name = 0 }
911 };  
912
913 extern void init_irq_proc (void);
914
915 void __init sysctl_init(void)
916 {
917 #ifdef CONFIG_PROC_FS
918         register_proc_table(root_table, proc_sys_root);
919         init_irq_proc();
920 #endif
921 }
922
923 int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp,
924                void __user *newval, size_t newlen)
925 {
926         struct list_head *tmp;
927
928         if (nlen <= 0 || nlen >= CTL_MAXNAME)
929                 return -ENOTDIR;
930         if (oldval) {
931                 int old_len;
932                 if (!oldlenp || get_user(old_len, oldlenp))
933                         return -EFAULT;
934         }
935         tmp = &root_table_header.ctl_entry;
936         do {
937                 struct ctl_table_header *head =
938                         list_entry(tmp, struct ctl_table_header, ctl_entry);
939                 void *context = NULL;
940                 int error = parse_table(name, nlen, oldval, oldlenp, 
941                                         newval, newlen, head->ctl_table,
942                                         &context);
943                 if (context)
944                         kfree(context);
945                 if (error != -ENOTDIR)
946                         return error;
947                 tmp = tmp->next;
948         } while (tmp != &root_table_header.ctl_entry);
949         return -ENOTDIR;
950 }
951
952 asmlinkage long sys_sysctl(struct __sysctl_args __user *args)
953 {
954         struct __sysctl_args tmp;
955         int error;
956
957         if (copy_from_user(&tmp, args, sizeof(tmp)))
958                 return -EFAULT;
959
960         lock_kernel();
961         error = do_sysctl(tmp.name, tmp.nlen, tmp.oldval, tmp.oldlenp,
962                           tmp.newval, tmp.newlen);
963         unlock_kernel();
964         return error;
965 }
966
967 /*
968  * ctl_perm does NOT grant the superuser all rights automatically, because
969  * some sysctl variables are readonly even to root.
970  */
971
972 static int test_perm(int mode, int op)
973 {
974         if (!current->euid)
975                 mode >>= 6;
976         else if (in_egroup_p(0))
977                 mode >>= 3;
978         if ((mode & op & 0007) == op)
979                 return 0;
980         return -EACCES;
981 }
982
983 static inline int ctl_perm(ctl_table *table, int op)
984 {
985         int error;
986         error = security_sysctl(table, op);
987         if (error)
988                 return error;
989         return test_perm(table->mode, op);
990 }
991
992 static int parse_table(int __user *name, int nlen,
993                        void __user *oldval, size_t __user *oldlenp,
994                        void __user *newval, size_t newlen,
995                        ctl_table *table, void **context)
996 {
997         int n;
998 repeat:
999         if (!nlen)
1000                 return -ENOTDIR;
1001         if (get_user(n, name))
1002                 return -EFAULT;
1003         for ( ; table->ctl_name; table++) {
1004                 if (n == table->ctl_name || table->ctl_name == CTL_ANY) {
1005                         int error;
1006                         if (table->child) {
1007                                 if (ctl_perm(table, 001))
1008                                         return -EPERM;
1009                                 if (table->strategy) {
1010                                         error = table->strategy(
1011                                                 table, name, nlen,
1012                                                 oldval, oldlenp,
1013                                                 newval, newlen, context);
1014                                         if (error)
1015                                                 return error;
1016                                 }
1017                                 name++;
1018                                 nlen--;
1019                                 table = table->child;
1020                                 goto repeat;
1021                         }
1022                         error = do_sysctl_strategy(table, name, nlen,
1023                                                    oldval, oldlenp,
1024                                                    newval, newlen, context);
1025                         return error;
1026                 }
1027         }
1028         return -ENOTDIR;
1029 }
1030
1031 /* Perform the actual read/write of a sysctl table entry. */
1032 int do_sysctl_strategy (ctl_table *table, 
1033                         int __user *name, int nlen,
1034                         void __user *oldval, size_t __user *oldlenp,
1035                         void __user *newval, size_t newlen, void **context)
1036 {
1037         int op = 0, rc;
1038         size_t len;
1039
1040         if (oldval)
1041                 op |= 004;
1042         if (newval) 
1043                 op |= 002;
1044         if (ctl_perm(table, op))
1045                 return -EPERM;
1046
1047         if (table->strategy) {
1048                 rc = table->strategy(table, name, nlen, oldval, oldlenp,
1049                                      newval, newlen, context);
1050                 if (rc < 0)
1051                         return rc;
1052                 if (rc > 0)
1053                         return 0;
1054         }
1055
1056         /* If there is no strategy routine, or if the strategy returns
1057          * zero, proceed with automatic r/w */
1058         if (table->data && table->maxlen) {
1059                 if (oldval && oldlenp) {
1060                         if (get_user(len, oldlenp))
1061                                 return -EFAULT;
1062                         if (len) {
1063                                 if (len > table->maxlen)
1064                                         len = table->maxlen;
1065                                 if(copy_to_user(oldval, table->data, len))
1066                                         return -EFAULT;
1067                                 if(put_user(len, oldlenp))
1068                                         return -EFAULT;
1069                         }
1070                 }
1071                 if (newval && newlen) {
1072                         len = newlen;
1073                         if (len > table->maxlen)
1074                                 len = table->maxlen;
1075                         if(copy_from_user(table->data, newval, len))
1076                                 return -EFAULT;
1077                 }
1078         }
1079         return 0;
1080 }
1081
1082 /**
1083  * register_sysctl_table - register a sysctl hierarchy
1084  * @table: the top-level table structure
1085  * @insert_at_head: whether the entry should be inserted in front or at the end
1086  *
1087  * Register a sysctl table hierarchy. @table should be a filled in ctl_table
1088  * array. An entry with a ctl_name of 0 terminates the table. 
1089  *
1090  * The members of the &ctl_table structure are used as follows:
1091  *
1092  * ctl_name - This is the numeric sysctl value used by sysctl(2). The number
1093  *            must be unique within that level of sysctl
1094  *
1095  * procname - the name of the sysctl file under /proc/sys. Set to %NULL to not
1096  *            enter a sysctl file
1097  *
1098  * data - a pointer to data for use by proc_handler
1099  *
1100  * maxlen - the maximum size in bytes of the data
1101  *
1102  * mode - the file permissions for the /proc/sys file, and for sysctl(2)
1103  *
1104  * child - a pointer to the child sysctl table if this entry is a directory, or
1105  *         %NULL.
1106  *
1107  * proc_handler - the text handler routine (described below)
1108  *
1109  * strategy - the strategy routine (described below)
1110  *
1111  * de - for internal use by the sysctl routines
1112  *
1113  * extra1, extra2 - extra pointers usable by the proc handler routines
1114  *
1115  * Leaf nodes in the sysctl tree will be represented by a single file
1116  * under /proc; non-leaf nodes will be represented by directories.
1117  *
1118  * sysctl(2) can automatically manage read and write requests through
1119  * the sysctl table.  The data and maxlen fields of the ctl_table
1120  * struct enable minimal validation of the values being written to be
1121  * performed, and the mode field allows minimal authentication.
1122  *
1123  * More sophisticated management can be enabled by the provision of a
1124  * strategy routine with the table entry.  This will be called before
1125  * any automatic read or write of the data is performed.
1126  *
1127  * The strategy routine may return
1128  *
1129  * < 0 - Error occurred (error is passed to user process)
1130  *
1131  * 0   - OK - proceed with automatic read or write.
1132  *
1133  * > 0 - OK - read or write has been done by the strategy routine, so
1134  *       return immediately.
1135  *
1136  * There must be a proc_handler routine for any terminal nodes
1137  * mirrored under /proc/sys (non-terminals are handled by a built-in
1138  * directory handler).  Several default handlers are available to
1139  * cover common cases -
1140  *
1141  * proc_dostring(), proc_dointvec(), proc_dointvec_jiffies(),
1142  * proc_dointvec_userhz_jiffies(), proc_dointvec_minmax(), 
1143  * proc_doulongvec_ms_jiffies_minmax(), proc_doulongvec_minmax()
1144  *
1145  * It is the handler's job to read the input buffer from user memory
1146  * and process it. The handler should return 0 on success.
1147  *
1148  * This routine returns %NULL on a failure to register, and a pointer
1149  * to the table header on success.
1150  */
1151 struct ctl_table_header *register_sysctl_table(ctl_table * table, 
1152                                                int insert_at_head)
1153 {
1154         struct ctl_table_header *tmp;
1155         tmp = kmalloc(sizeof(struct ctl_table_header), GFP_KERNEL);
1156         if (!tmp)
1157                 return NULL;
1158         tmp->ctl_table = table;
1159         INIT_LIST_HEAD(&tmp->ctl_entry);
1160         if (insert_at_head)
1161                 list_add(&tmp->ctl_entry, &root_table_header.ctl_entry);
1162         else
1163                 list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry);
1164 #ifdef CONFIG_PROC_FS
1165         register_proc_table(table, proc_sys_root);
1166 #endif
1167         return tmp;
1168 }
1169
1170 /**
1171  * unregister_sysctl_table - unregister a sysctl table hierarchy
1172  * @header: the header returned from register_sysctl_table
1173  *
1174  * Unregisters the sysctl table and all children. proc entries may not
1175  * actually be removed until they are no longer used by anyone.
1176  */
1177 void unregister_sysctl_table(struct ctl_table_header * header)
1178 {
1179         list_del(&header->ctl_entry);
1180 #ifdef CONFIG_PROC_FS
1181         unregister_proc_table(header->ctl_table, proc_sys_root);
1182 #endif
1183         kfree(header);
1184 }
1185
1186 /*
1187  * /proc/sys support
1188  */
1189
1190 #ifdef CONFIG_PROC_FS
1191
1192 /* Scan the sysctl entries in table and add them all into /proc */
1193 static void register_proc_table(ctl_table * table, struct proc_dir_entry *root)
1194 {
1195         struct proc_dir_entry *de;
1196         int len;
1197         mode_t mode;
1198         
1199         for (; table->ctl_name; table++) {
1200                 /* Can't do anything without a proc name. */
1201                 if (!table->procname)
1202                         continue;
1203                 /* Maybe we can't do anything with it... */
1204                 if (!table->proc_handler && !table->child) {
1205                         printk(KERN_WARNING "SYSCTL: Can't register %s\n",
1206                                 table->procname);
1207                         continue;
1208                 }
1209
1210                 len = strlen(table->procname);
1211                 mode = table->mode;
1212
1213                 de = NULL;
1214                 if (table->proc_handler)
1215                         mode |= S_IFREG;
1216                 else {
1217                         mode |= S_IFDIR;
1218                         for (de = root->subdir; de; de = de->next) {
1219                                 if (proc_match(len, table->procname, de))
1220                                         break;
1221                         }
1222                         /* If the subdir exists already, de is non-NULL */
1223                 }
1224
1225                 if (!de) {
1226                         de = create_proc_entry(table->procname, mode, root);
1227                         if (!de)
1228                                 continue;
1229                         de->data = (void *) table;
1230                         if (table->proc_handler)
1231                                 de->proc_fops = &proc_sys_file_operations;
1232                 }
1233                 table->de = de;
1234                 if (de->mode & S_IFDIR)
1235                         register_proc_table(table->child, de);
1236         }
1237 }
1238
1239 /*
1240  * Unregister a /proc sysctl table and any subdirectories.
1241  */
1242 static void unregister_proc_table(ctl_table * table, struct proc_dir_entry *root)
1243 {
1244         struct proc_dir_entry *de;
1245         for (; table->ctl_name; table++) {
1246                 if (!(de = table->de))
1247                         continue;
1248                 if (de->mode & S_IFDIR) {
1249                         if (!table->child) {
1250                                 printk (KERN_ALERT "Help - malformed sysctl tree on free\n");
1251                                 continue;
1252                         }
1253                         unregister_proc_table(table->child, de);
1254
1255                         /* Don't unregister directories which still have entries.. */
1256                         if (de->subdir)
1257                                 continue;
1258                 }
1259
1260                 /* Don't unregister proc entries that are still being used.. */
1261                 if (atomic_read(&de->count))
1262                         continue;
1263
1264                 table->de = NULL;
1265                 remove_proc_entry(table->procname, root);
1266         }
1267 }
1268
1269 static ssize_t do_rw_proc(int write, struct file * file, char __user * buf,
1270                           size_t count, loff_t *ppos)
1271 {
1272         int op;
1273         struct proc_dir_entry *de;
1274         struct ctl_table *table;
1275         size_t res;
1276         ssize_t error;
1277         
1278         de = PDE(file->f_dentry->d_inode);
1279         if (!de || !de->data)
1280                 return -ENOTDIR;
1281         table = (struct ctl_table *) de->data;
1282         if (!table || !table->proc_handler)
1283                 return -ENOTDIR;
1284         op = (write ? 002 : 004);
1285         if (ctl_perm(table, op))
1286                 return -EPERM;
1287         
1288         res = count;
1289
1290         error = (*table->proc_handler) (table, write, file, buf, &res, ppos);
1291         if (error)
1292                 return error;
1293         return res;
1294 }
1295
1296 static int proc_opensys(struct inode *inode, struct file *file)
1297 {
1298         if (file->f_mode & FMODE_WRITE) {
1299                 /*
1300                  * sysctl entries that are not writable,
1301                  * are _NOT_ writable, capabilities or not.
1302                  */
1303                 if (!(inode->i_mode & S_IWUSR))
1304                         return -EPERM;
1305         }
1306
1307         return 0;
1308 }
1309
1310 static ssize_t proc_readsys(struct file * file, char __user * buf,
1311                             size_t count, loff_t *ppos)
1312 {
1313         return do_rw_proc(0, file, buf, count, ppos);
1314 }
1315
1316 static ssize_t proc_writesys(struct file * file, const char __user * buf,
1317                              size_t count, loff_t *ppos)
1318 {
1319         return do_rw_proc(1, file, (char __user *) buf, count, ppos);
1320 }
1321
1322 /**
1323  * proc_dostring - read a string sysctl
1324  * @table: the sysctl table
1325  * @write: %TRUE if this is a write to the sysctl file
1326  * @filp: the file structure
1327  * @buffer: the user buffer
1328  * @lenp: the size of the user buffer
1329  *
1330  * Reads/writes a string from/to the user buffer. If the kernel
1331  * buffer provided is not large enough to hold the string, the
1332  * string is truncated. The copied string is %NULL-terminated.
1333  * If the string is being read by the user process, it is copied
1334  * and a newline '\n' is added. It is truncated if the buffer is
1335  * not large enough.
1336  *
1337  * Returns 0 on success.
1338  */
1339 int proc_dostring(ctl_table *table, int write, struct file *filp,
1340                   void __user *buffer, size_t *lenp, loff_t *ppos)
1341 {
1342         size_t len;
1343         char __user *p;
1344         char c;
1345         
1346         if (!table->data || !table->maxlen || !*lenp ||
1347             (*ppos && !write)) {
1348                 *lenp = 0;
1349                 return 0;
1350         }
1351         
1352         if (write) {
1353                 len = 0;
1354                 p = buffer;
1355                 while (len < *lenp) {
1356                         if (get_user(c, p++))
1357                                 return -EFAULT;
1358                         if (c == 0 || c == '\n')
1359                                 break;
1360                         len++;
1361                 }
1362                 if (len >= table->maxlen)
1363                         len = table->maxlen-1;
1364                 if(copy_from_user(table->data, buffer, len))
1365                         return -EFAULT;
1366                 ((char *) table->data)[len] = 0;
1367                 *ppos += *lenp;
1368         } else {
1369                 len = strlen(table->data);
1370                 if (len > table->maxlen)
1371                         len = table->maxlen;
1372                 if (len > *lenp)
1373                         len = *lenp;
1374                 if (len)
1375                         if(copy_to_user(buffer, table->data, len))
1376                                 return -EFAULT;
1377                 if (len < *lenp) {
1378                         if(put_user('\n', ((char __user *) buffer) + len))
1379                                 return -EFAULT;
1380                         len++;
1381                 }
1382                 *lenp = len;
1383                 *ppos += len;
1384         }
1385         return 0;
1386 }
1387
1388 /*
1389  *      Special case of dostring for the UTS structure. This has locks
1390  *      to observe. Should this be in kernel/sys.c ????
1391  */
1392  
1393 static int proc_doutsstring(ctl_table *table, int write, struct file *filp,
1394                   void __user *buffer, size_t *lenp, loff_t *ppos)
1395 {
1396         int r;
1397
1398         if (!write) {
1399                 down_read(&uts_sem);
1400                 r=proc_dostring(table,0,filp,buffer,lenp, ppos);
1401                 up_read(&uts_sem);
1402         } else {
1403                 down_write(&uts_sem);
1404                 r=proc_dostring(table,1,filp,buffer,lenp, ppos);
1405                 up_write(&uts_sem);
1406         }
1407         return r;
1408 }
1409
1410 static int do_proc_dointvec_conv(int *negp, unsigned long *lvalp,
1411                                  int *valp,
1412                                  int write, void *data)
1413 {
1414         if (write) {
1415                 *valp = *negp ? -*lvalp : *lvalp;
1416         } else {
1417                 int val = *valp;
1418                 if (val < 0) {
1419                         *negp = -1;
1420                         *lvalp = (unsigned long)-val;
1421                 } else {
1422                         *negp = 0;
1423                         *lvalp = (unsigned long)val;
1424                 }
1425         }
1426         return 0;
1427 }
1428
1429 static int do_proc_dointvec(ctl_table *table, int write, struct file *filp,
1430                   void __user *buffer, size_t *lenp, loff_t *ppos,
1431                   int (*conv)(int *negp, unsigned long *lvalp, int *valp,
1432                               int write, void *data),
1433                   void *data)
1434 {
1435 #define TMPBUFLEN 21
1436         int *i, vleft, first=1, neg, val;
1437         unsigned long lval;
1438         size_t left, len;
1439         
1440         char buf[TMPBUFLEN], *p;
1441         char __user *s = buffer;
1442         
1443         if (!table->data || !table->maxlen || !*lenp ||
1444             (*ppos && !write)) {
1445                 *lenp = 0;
1446                 return 0;
1447         }
1448         
1449         i = (int *) table->data;
1450         vleft = table->maxlen / sizeof(*i);
1451         left = *lenp;
1452
1453         if (!conv)
1454                 conv = do_proc_dointvec_conv;
1455
1456         for (; left && vleft--; i++, first=0) {
1457                 if (write) {
1458                         while (left) {
1459                                 char c;
1460                                 if (get_user(c, s))
1461                                         return -EFAULT;
1462                                 if (!isspace(c))
1463                                         break;
1464                                 left--;
1465                                 s++;
1466                         }
1467                         if (!left)
1468                                 break;
1469                         neg = 0;
1470                         len = left;
1471                         if (len > sizeof(buf) - 1)
1472                                 len = sizeof(buf) - 1;
1473                         if (copy_from_user(buf, s, len))
1474                                 return -EFAULT;
1475                         buf[len] = 0;
1476                         p = buf;
1477                         if (*p == '-' && left > 1) {
1478                                 neg = 1;
1479                                 left--, p++;
1480                         }
1481                         if (*p < '0' || *p > '9')
1482                                 break;
1483
1484                         lval = simple_strtoul(p, &p, 0);
1485
1486                         len = p-buf;
1487                         if ((len < left) && *p && !isspace(*p))
1488                                 break;
1489                         if (neg)
1490                                 val = -val;
1491                         s += len;
1492                         left -= len;
1493
1494                         if (conv(&neg, &lval, i, 1, data))
1495                                 break;
1496                 } else {
1497                         p = buf;
1498                         if (!first)
1499                                 *p++ = '\t';
1500         
1501                         if (conv(&neg, &lval, i, 0, data))
1502                                 break;
1503
1504                         sprintf(p, "%s%lu", neg ? "-" : "", lval);
1505                         len = strlen(buf);
1506                         if (len > left)
1507                                 len = left;
1508                         if(copy_to_user(s, buf, len))
1509                                 return -EFAULT;
1510                         left -= len;
1511                         s += len;
1512                 }
1513         }
1514
1515         if (!write && !first && left) {
1516                 if(put_user('\n', s))
1517                         return -EFAULT;
1518                 left--, s++;
1519         }
1520         if (write) {
1521                 while (left) {
1522                         char c;
1523                         if (get_user(c, s++))
1524                                 return -EFAULT;
1525                         if (!isspace(c))
1526                                 break;
1527                         left--;
1528                 }
1529         }
1530         if (write && first)
1531                 return -EINVAL;
1532         *lenp -= left;
1533         *ppos += *lenp;
1534         return 0;
1535 #undef TMPBUFLEN
1536 }
1537
1538 /**
1539  * proc_dointvec - read a vector of integers
1540  * @table: the sysctl table
1541  * @write: %TRUE if this is a write to the sysctl file
1542  * @filp: the file structure
1543  * @buffer: the user buffer
1544  * @lenp: the size of the user buffer
1545  *
1546  * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
1547  * values from/to the user buffer, treated as an ASCII string. 
1548  *
1549  * Returns 0 on success.
1550  */
1551 int proc_dointvec(ctl_table *table, int write, struct file *filp,
1552                      void __user *buffer, size_t *lenp, loff_t *ppos)
1553 {
1554     return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
1555                             NULL,NULL);
1556 }
1557
1558 #define OP_SET  0
1559 #define OP_AND  1
1560 #define OP_OR   2
1561 #define OP_MAX  3
1562 #define OP_MIN  4
1563
1564 static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp,
1565                                       int *valp,
1566                                       int write, void *data)
1567 {
1568         int op = *(int *)data;
1569         if (write) {
1570                 int val = *negp ? -*lvalp : *lvalp;
1571                 switch(op) {
1572                 case OP_SET:    *valp = val; break;
1573                 case OP_AND:    *valp &= val; break;
1574                 case OP_OR:     *valp |= val; break;
1575                 case OP_MAX:    if(*valp < val)
1576                                         *valp = val;
1577                                 break;
1578                 case OP_MIN:    if(*valp > val)
1579                                 *valp = val;
1580                                 break;
1581                 }
1582         } else {
1583                 int val = *valp;
1584                 if (val < 0) {
1585                         *negp = -1;
1586                         *lvalp = (unsigned long)-val;
1587                 } else {
1588                         *negp = 0;
1589                         *lvalp = (unsigned long)val;
1590                 }
1591         }
1592         return 0;
1593 }
1594
1595 /*
1596  *      init may raise the set.
1597  */
1598  
1599 int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
1600                         void __user *buffer, size_t *lenp, loff_t *ppos)
1601 {
1602         int op;
1603
1604         if (!capable(CAP_SYS_MODULE)) {
1605                 return -EPERM;
1606         }
1607
1608         op = (current->pid == 1) ? OP_SET : OP_AND;
1609         return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
1610                                 do_proc_dointvec_bset_conv,&op);
1611 }
1612
1613 struct do_proc_dointvec_minmax_conv_param {
1614         int *min;
1615         int *max;
1616 };
1617
1618 static int do_proc_dointvec_minmax_conv(int *negp, unsigned long *lvalp, 
1619                                         int *valp, 
1620                                         int write, void *data)
1621 {
1622         struct do_proc_dointvec_minmax_conv_param *param = data;
1623         if (write) {
1624                 int val = *negp ? -*lvalp : *lvalp;
1625                 if ((param->min && *param->min > val) ||
1626                     (param->max && *param->max < val))
1627                         return -EINVAL;
1628                 *valp = val;
1629         } else {
1630                 int val = *valp;
1631                 if (val < 0) {
1632                         *negp = -1;
1633                         *lvalp = (unsigned long)-val;
1634                 } else {
1635                         *negp = 0;
1636                         *lvalp = (unsigned long)val;
1637                 }
1638         }
1639         return 0;
1640 }
1641
1642 /**
1643  * proc_dointvec_minmax - read a vector of integers with min/max values
1644  * @table: the sysctl table
1645  * @write: %TRUE if this is a write to the sysctl file
1646  * @filp: the file structure
1647  * @buffer: the user buffer
1648  * @lenp: the size of the user buffer
1649  *
1650  * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
1651  * values from/to the user buffer, treated as an ASCII string.
1652  *
1653  * This routine will ensure the values are within the range specified by
1654  * table->extra1 (min) and table->extra2 (max).
1655  *
1656  * Returns 0 on success.
1657  */
1658 int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
1659                   void __user *buffer, size_t *lenp, loff_t *ppos)
1660 {
1661         struct do_proc_dointvec_minmax_conv_param param = {
1662                 .min = (int *) table->extra1,
1663                 .max = (int *) table->extra2,
1664         };
1665         return do_proc_dointvec(table, write, filp, buffer, lenp, ppos,
1666                                 do_proc_dointvec_minmax_conv, &param);
1667 }
1668
1669 static int do_proc_doulongvec_minmax(ctl_table *table, int write,
1670                                      struct file *filp,
1671                                      void __user *buffer,
1672                                      size_t *lenp, loff_t *ppos,
1673                                      unsigned long convmul,
1674                                      unsigned long convdiv)
1675 {
1676 #define TMPBUFLEN 21
1677         unsigned long *i, *min, *max, val;
1678         int vleft, first=1, neg;
1679         size_t len, left;
1680         char buf[TMPBUFLEN], *p;
1681         char __user *s = buffer;
1682         
1683         if (!table->data || !table->maxlen || !*lenp ||
1684             (*ppos && !write)) {
1685                 *lenp = 0;
1686                 return 0;
1687         }
1688         
1689         i = (unsigned long *) table->data;
1690         min = (unsigned long *) table->extra1;
1691         max = (unsigned long *) table->extra2;
1692         vleft = table->maxlen / sizeof(unsigned long);
1693         left = *lenp;
1694         
1695         for (; left && vleft--; i++, min++, max++, first=0) {
1696                 if (write) {
1697                         while (left) {
1698                                 char c;
1699                                 if (get_user(c, s))
1700                                         return -EFAULT;
1701                                 if (!isspace(c))
1702                                         break;
1703                                 left--;
1704                                 s++;
1705                         }
1706                         if (!left)
1707                                 break;
1708                         neg = 0;
1709                         len = left;
1710                         if (len > TMPBUFLEN-1)
1711                                 len = TMPBUFLEN-1;
1712                         if (copy_from_user(buf, s, len))
1713                                 return -EFAULT;
1714                         buf[len] = 0;
1715                         p = buf;
1716                         if (*p == '-' && left > 1) {
1717                                 neg = 1;
1718                                 left--, p++;
1719                         }
1720                         if (*p < '0' || *p > '9')
1721                                 break;
1722                         val = simple_strtoul(p, &p, 0) * convmul / convdiv ;
1723                         len = p-buf;
1724                         if ((len < left) && *p && !isspace(*p))
1725                                 break;
1726                         if (neg)
1727                                 val = -val;
1728                         s += len;
1729                         left -= len;
1730
1731                         if(neg)
1732                                 continue;
1733                         if ((min && val < *min) || (max && val > *max))
1734                                 continue;
1735                         *i = val;
1736                 } else {
1737                         p = buf;
1738                         if (!first)
1739                                 *p++ = '\t';
1740                         sprintf(p, "%lu", convdiv * (*i) / convmul);
1741                         len = strlen(buf);
1742                         if (len > left)
1743                                 len = left;
1744                         if(copy_to_user(s, buf, len))
1745                                 return -EFAULT;
1746                         left -= len;
1747                         s += len;
1748                 }
1749         }
1750
1751         if (!write && !first && left) {
1752                 if(put_user('\n', s))
1753                         return -EFAULT;
1754                 left--, s++;
1755         }
1756         if (write) {
1757                 while (left) {
1758                         char c;
1759                         if (get_user(c, s++))
1760                                 return -EFAULT;
1761                         if (!isspace(c))
1762                                 break;
1763                         left--;
1764                 }
1765         }
1766         if (write && first)
1767                 return -EINVAL;
1768         *lenp -= left;
1769         *ppos += *lenp;
1770         return 0;
1771 #undef TMPBUFLEN
1772 }
1773
1774 /**
1775  * proc_doulongvec_minmax - read a vector of long integers with min/max values
1776  * @table: the sysctl table
1777  * @write: %TRUE if this is a write to the sysctl file
1778  * @filp: the file structure
1779  * @buffer: the user buffer
1780  * @lenp: the size of the user buffer
1781  *
1782  * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
1783  * values from/to the user buffer, treated as an ASCII string.
1784  *
1785  * This routine will ensure the values are within the range specified by
1786  * table->extra1 (min) and table->extra2 (max).
1787  *
1788  * Returns 0 on success.
1789  */
1790 int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
1791                            void __user *buffer, size_t *lenp, loff_t *ppos)
1792 {
1793     return do_proc_doulongvec_minmax(table, write, filp, buffer, lenp, ppos, 1l, 1l);
1794 }
1795
1796 /**
1797  * proc_doulongvec_ms_jiffies_minmax - read a vector of millisecond values with min/max values
1798  * @table: the sysctl table
1799  * @write: %TRUE if this is a write to the sysctl file
1800  * @filp: the file structure
1801  * @buffer: the user buffer
1802  * @lenp: the size of the user buffer
1803  *
1804  * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
1805  * values from/to the user buffer, treated as an ASCII string. The values
1806  * are treated as milliseconds, and converted to jiffies when they are stored.
1807  *
1808  * This routine will ensure the values are within the range specified by
1809  * table->extra1 (min) and table->extra2 (max).
1810  *
1811  * Returns 0 on success.
1812  */
1813 int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
1814                                       struct file *filp,
1815                                       void __user *buffer,
1816                                       size_t *lenp, loff_t *ppos)
1817 {
1818     return do_proc_doulongvec_minmax(table, write, filp, buffer,
1819                                      lenp, ppos, HZ, 1000l);
1820 }
1821
1822
1823 static int do_proc_dointvec_jiffies_conv(int *negp, unsigned long *lvalp,
1824                                          int *valp,
1825                                          int write, void *data)
1826 {
1827         if (write) {
1828                 *valp = *negp ? -(*lvalp*HZ) : (*lvalp*HZ);
1829         } else {
1830                 int val = *valp;
1831                 unsigned long lval;
1832                 if (val < 0) {
1833                         *negp = -1;
1834                         lval = (unsigned long)-val;
1835                 } else {
1836                         *negp = 0;
1837                         lval = (unsigned long)val;
1838                 }
1839                 *lvalp = lval / HZ;
1840         }
1841         return 0;
1842 }
1843
1844 static int do_proc_dointvec_userhz_jiffies_conv(int *negp, unsigned long *lvalp,
1845                                                 int *valp,
1846                                                 int write, void *data)
1847 {
1848         if (write) {
1849                 *valp = clock_t_to_jiffies(*negp ? -*lvalp : *lvalp);
1850         } else {
1851                 int val = *valp;
1852                 unsigned long lval;
1853                 if (val < 0) {
1854                         *negp = -1;
1855                         lval = (unsigned long)-val;
1856                 } else {
1857                         *negp = 0;
1858                         lval = (unsigned long)val;
1859                 }
1860                 *lvalp = jiffies_to_clock_t(lval);
1861         }
1862         return 0;
1863 }
1864
1865 /**
1866  * proc_dointvec_jiffies - read a vector of integers as seconds
1867  * @table: the sysctl table
1868  * @write: %TRUE if this is a write to the sysctl file
1869  * @filp: the file structure
1870  * @buffer: the user buffer
1871  * @lenp: the size of the user buffer
1872  *
1873  * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
1874  * values from/to the user buffer, treated as an ASCII string. 
1875  * The values read are assumed to be in seconds, and are converted into
1876  * jiffies.
1877  *
1878  * Returns 0 on success.
1879  */
1880 int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
1881                           void __user *buffer, size_t *lenp, loff_t *ppos)
1882 {
1883     return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
1884                             do_proc_dointvec_jiffies_conv,NULL);
1885 }
1886
1887 /**
1888  * proc_dointvec_userhz_jiffies - read a vector of integers as 1/USER_HZ seconds
1889  * @table: the sysctl table
1890  * @write: %TRUE if this is a write to the sysctl file
1891  * @filp: the file structure
1892  * @buffer: the user buffer
1893  * @lenp: the size of the user buffer
1894  *
1895  * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
1896  * values from/to the user buffer, treated as an ASCII string. 
1897  * The values read are assumed to be in 1/USER_HZ seconds, and 
1898  * are converted into jiffies.
1899  *
1900  * Returns 0 on success.
1901  */
1902 int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp,
1903                                  void __user *buffer, size_t *lenp, loff_t *ppos)
1904 {
1905     return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
1906                             do_proc_dointvec_userhz_jiffies_conv,NULL);
1907 }
1908
1909 #else /* CONFIG_PROC_FS */
1910
1911 int proc_dostring(ctl_table *table, int write, struct file *filp,
1912                   void __user *buffer, size_t *lenp, loff_t *ppos)
1913 {
1914         return -ENOSYS;
1915 }
1916
1917 static int proc_doutsstring(ctl_table *table, int write, struct file *filp,
1918                             void __user *buffer, size_t *lenp, loff_t *ppos)
1919 {
1920         return -ENOSYS;
1921 }
1922
1923 int proc_dointvec(ctl_table *table, int write, struct file *filp,
1924                   void __user *buffer, size_t *lenp, loff_t *ppos)
1925 {
1926         return -ENOSYS;
1927 }
1928
1929 int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
1930                         void __user *buffer, size_t *lenp, loff_t *ppos)
1931 {
1932         return -ENOSYS;
1933 }
1934
1935 int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
1936                     void __user *buffer, size_t *lenp, loff_t *ppos)
1937 {
1938         return -ENOSYS;
1939 }
1940
1941 int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
1942                     void __user *buffer, size_t *lenp, loff_t *ppos)
1943 {
1944         return -ENOSYS;
1945 }
1946
1947 int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp,
1948                     void __user *buffer, size_t *lenp, loff_t *ppos)
1949 {
1950         return -ENOSYS;
1951 }
1952
1953 int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
1954                     void __user *buffer, size_t *lenp, loff_t *ppos)
1955 {
1956         return -ENOSYS;
1957 }
1958
1959 int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
1960                                       struct file *filp,
1961                                       void __user *buffer,
1962                                       size_t *lenp, loff_t *ppos)
1963 {
1964     return -ENOSYS;
1965 }
1966
1967
1968 #endif /* CONFIG_PROC_FS */
1969
1970
1971 /*
1972  * General sysctl support routines 
1973  */
1974
1975 /* The generic string strategy routine: */
1976 int sysctl_string(ctl_table *table, int __user *name, int nlen,
1977                   void __user *oldval, size_t __user *oldlenp,
1978                   void __user *newval, size_t newlen, void **context)
1979 {
1980         size_t l, len;
1981         
1982         if (!table->data || !table->maxlen) 
1983                 return -ENOTDIR;
1984         
1985         if (oldval && oldlenp) {
1986                 if (get_user(len, oldlenp))
1987                         return -EFAULT;
1988                 if (len) {
1989                         l = strlen(table->data);
1990                         if (len > l) len = l;
1991                         if (len >= table->maxlen)
1992                                 len = table->maxlen;
1993                         if(copy_to_user(oldval, table->data, len))
1994                                 return -EFAULT;
1995                         if(put_user(0, ((char __user *) oldval) + len))
1996                                 return -EFAULT;
1997                         if(put_user(len, oldlenp))
1998                                 return -EFAULT;
1999                 }
2000         }
2001         if (newval && newlen) {
2002                 len = newlen;
2003                 if (len > table->maxlen)
2004                         len = table->maxlen;
2005                 if(copy_from_user(table->data, newval, len))
2006                         return -EFAULT;
2007                 if (len == table->maxlen)
2008                         len--;
2009                 ((char *) table->data)[len] = 0;
2010         }
2011         return 0;
2012 }
2013
2014 /*
2015  * This function makes sure that all of the integers in the vector
2016  * are between the minimum and maximum values given in the arrays
2017  * table->extra1 and table->extra2, respectively.
2018  */
2019 int sysctl_intvec(ctl_table *table, int __user *name, int nlen,
2020                 void __user *oldval, size_t __user *oldlenp,
2021                 void __user *newval, size_t newlen, void **context)
2022 {
2023
2024         if (newval && newlen) {
2025                 int __user *vec = (int __user *) newval;
2026                 int *min = (int *) table->extra1;
2027                 int *max = (int *) table->extra2;
2028                 size_t length;
2029                 int i;
2030
2031                 if (newlen % sizeof(int) != 0)
2032                         return -EINVAL;
2033
2034                 if (!table->extra1 && !table->extra2)
2035                         return 0;
2036
2037                 if (newlen > table->maxlen)
2038                         newlen = table->maxlen;
2039                 length = newlen / sizeof(int);
2040
2041                 for (i = 0; i < length; i++) {
2042                         int value;
2043                         if (get_user(value, vec + i))
2044                                 return -EFAULT;
2045                         if (min && value < min[i])
2046                                 return -EINVAL;
2047                         if (max && value > max[i])
2048                                 return -EINVAL;
2049                 }
2050         }
2051         return 0;
2052 }
2053
2054 /* Strategy function to convert jiffies to seconds */ 
2055 int sysctl_jiffies(ctl_table *table, int __user *name, int nlen,
2056                 void __user *oldval, size_t __user *oldlenp,
2057                 void __user *newval, size_t newlen, void **context)
2058 {
2059         if (oldval) {
2060                 size_t olen;
2061                 if (oldlenp) { 
2062                         if (get_user(olen, oldlenp))
2063                                 return -EFAULT;
2064                         if (olen!=sizeof(int))
2065                                 return -EINVAL; 
2066                 }
2067                 if (put_user(*(int *)(table->data)/HZ, (int __user *)oldval) ||
2068                     (oldlenp && put_user(sizeof(int),oldlenp)))
2069                         return -EFAULT;
2070         }
2071         if (newval && newlen) { 
2072                 int new;
2073                 if (newlen != sizeof(int))
2074                         return -EINVAL; 
2075                 if (get_user(new, (int __user *)newval))
2076                         return -EFAULT;
2077                 *(int *)(table->data) = new*HZ; 
2078         }
2079         return 1;
2080 }
2081
2082
2083 #else /* CONFIG_SYSCTL */
2084
2085
2086 asmlinkage long sys_sysctl(struct __sysctl_args __user *args)
2087 {
2088         return -ENOSYS;
2089 }
2090
2091 int sysctl_string(ctl_table *table, int __user *name, int nlen,
2092                   void __user *oldval, size_t __user *oldlenp,
2093                   void __user *newval, size_t newlen, void **context)
2094 {
2095         return -ENOSYS;
2096 }
2097
2098 int sysctl_intvec(ctl_table *table, int __user *name, int nlen,
2099                 void __user *oldval, size_t __user *oldlenp,
2100                 void __user *newval, size_t newlen, void **context)
2101 {
2102         return -ENOSYS;
2103 }
2104
2105 int sysctl_jiffies(ctl_table *table, int __user *name, int nlen,
2106                 void __user *oldval, size_t __user *oldlenp,
2107                 void __user *newval, size_t newlen, void **context)
2108 {
2109         return -ENOSYS;
2110 }
2111
2112 int proc_dostring(ctl_table *table, int write, struct file *filp,
2113                   void __user *buffer, size_t *lenp, loff_t *ppos)
2114 {
2115         return -ENOSYS;
2116 }
2117
2118 int proc_dointvec(ctl_table *table, int write, struct file *filp,
2119                   void __user *buffer, size_t *lenp, loff_t *ppos)
2120 {
2121         return -ENOSYS;
2122 }
2123
2124 int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
2125                         void __user *buffer, size_t *lenp, loff_t *ppos)
2126 {
2127         return -ENOSYS;
2128 }
2129
2130 int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
2131                     void __user *buffer, size_t *lenp, loff_t *ppos)
2132 {
2133         return -ENOSYS;
2134 }
2135
2136 int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
2137                           void __user *buffer, size_t *lenp, loff_t *ppos)
2138 {
2139         return -ENOSYS;
2140 }
2141
2142 int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp,
2143                           void __user *buffer, size_t *lenp, loff_t *ppos)
2144 {
2145         return -ENOSYS;
2146 }
2147
2148 int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
2149                     void __user *buffer, size_t *lenp, loff_t *ppos)
2150 {
2151         return -ENOSYS;
2152 }
2153
2154 int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
2155                                       struct file *filp,
2156                                       void __user *buffer,
2157                                       size_t *lenp, loff_t *ppos)
2158 {
2159     return -ENOSYS;
2160 }
2161
2162 struct ctl_table_header * register_sysctl_table(ctl_table * table, 
2163                                                 int insert_at_head)
2164 {
2165         return NULL;
2166 }
2167
2168 void unregister_sysctl_table(struct ctl_table_header * table)
2169 {
2170 }
2171
2172 #endif /* CONFIG_SYSCTL */
2173
2174 /*
2175  * No sense putting this after each symbol definition, twice,
2176  * exception granted :-)
2177  */
2178 EXPORT_SYMBOL(proc_dointvec);
2179 EXPORT_SYMBOL(proc_dointvec_jiffies);
2180 EXPORT_SYMBOL(proc_dointvec_minmax);
2181 EXPORT_SYMBOL(proc_dointvec_userhz_jiffies);
2182 EXPORT_SYMBOL(proc_dostring);
2183 EXPORT_SYMBOL(proc_doulongvec_minmax);
2184 EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax);
2185 EXPORT_SYMBOL(register_sysctl_table);
2186 EXPORT_SYMBOL(sysctl_intvec);
2187 EXPORT_SYMBOL(sysctl_jiffies);
2188 EXPORT_SYMBOL(sysctl_string);
2189 EXPORT_SYMBOL(unregister_sysctl_table);