Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

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