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