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