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