File: /usr/src/linux/fs/proc/proc_misc.c

1     /*
2      *  linux/fs/proc/proc_misc.c
3      *
4      *  linux/fs/proc/array.c
5      *  Copyright (C) 1992  by Linus Torvalds
6      *  based on ideas by Darren Senn
7      *
8      *  This used to be the part of array.c. See the rest of history and credits
9      *  there. I took this into a separate file and switched the thing to generic
10      *  proc_file_inode_operations, leaving in array.c only per-process stuff.
11      *  Inumbers allocation made dynamic (via create_proc_entry()).  AV, May 1999.
12      *
13      * Changes:
14      * Fulton Green      :  Encapsulated position metric calculations.
15      *			<kernel@FultonGreen.com>
16      */
17     
18     #include <linux/types.h>
19     #include <linux/errno.h>
20     #include <linux/sched.h>
21     #include <linux/kernel.h>
22     #include <linux/kernel_stat.h>
23     #include <linux/tty.h>
24     #include <linux/string.h>
25     #include <linux/mman.h>
26     #include <linux/proc_fs.h>
27     #include <linux/ioport.h>
28     #include <linux/config.h>
29     #include <linux/mm.h>
30     #include <linux/pagemap.h>
31     #include <linux/swap.h>
32     #include <linux/slab.h>
33     #include <linux/smp.h>
34     #include <linux/signal.h>
35     #include <linux/module.h>
36     #include <linux/init.h>
37     #include <linux/smp_lock.h>
38     
39     #include <asm/uaccess.h>
40     #include <asm/pgtable.h>
41     #include <asm/io.h>
42     
43     
44     #define LOAD_INT(x) ((x) >> FSHIFT)
45     #define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
46     /*
47      * Warning: stuff below (imported functions) assumes that its output will fit
48      * into one page. For some of those functions it may be wrong. Moreover, we
49      * have a way to deal with that gracefully. Right now I used straightforward
50      * wrappers, but this needs further analysis wrt potential overflows.
51      */
52     extern int get_cpuinfo(char *);
53     extern int get_hardware_list(char *);
54     extern int get_stram_list(char *);
55     #ifdef CONFIG_DEBUG_MALLOC
56     extern int get_malloc(char * buffer);
57     #endif
58     #ifdef CONFIG_MODULES
59     extern int get_module_list(char *);
60     extern int get_ksyms_list(char *, char **, off_t, int);
61     #endif
62     extern int get_device_list(char *);
63     extern int get_partition_list(char *, char **, off_t, int);
64     extern int get_filesystem_list(char *);
65     extern int get_filesystem_info(char *);
66     extern int get_exec_domain_list(char *);
67     extern int get_irq_list(char *);
68     extern int get_dma_list(char *);
69     extern int get_locks_status (char *, char **, off_t, int);
70     extern int get_swaparea_info (char *);
71     #ifdef CONFIG_SGI_DS1286
72     extern int get_ds1286_status(char *);
73     #endif
74     
75     static int proc_calc_metrics(char *page, char **start, off_t off,
76     				 int count, int *eof, int len)
77     {
78     	if (len <= off+count) *eof = 1;
79     	*start = page + off;
80     	len -= off;
81     	if (len>count) len = count;
82     	if (len<0) len = 0;
83     	return len;
84     }
85     
86     static int loadavg_read_proc(char *page, char **start, off_t off,
87     				 int count, int *eof, void *data)
88     {
89     	int a, b, c;
90     	int len;
91     
92     	a = avenrun[0] + (FIXED_1/200);
93     	b = avenrun[1] + (FIXED_1/200);
94     	c = avenrun[2] + (FIXED_1/200);
95     	len = sprintf(page,"%d.%02d %d.%02d %d.%02d %d/%d %d\n",
96     		LOAD_INT(a), LOAD_FRAC(a),
97     		LOAD_INT(b), LOAD_FRAC(b),
98     		LOAD_INT(c), LOAD_FRAC(c),
99     		nr_running, nr_threads, last_pid);
100     	return proc_calc_metrics(page, start, off, count, eof, len);
101     }
102     
103     static int uptime_read_proc(char *page, char **start, off_t off,
104     				 int count, int *eof, void *data)
105     {
106     	unsigned long uptime;
107     	unsigned long idle;
108     	int len;
109     
110     	uptime = jiffies;
111     	idle = init_tasks[0]->times.tms_utime + init_tasks[0]->times.tms_stime;
112     
113     	/* The formula for the fraction parts really is ((t * 100) / HZ) % 100, but
114     	   that would overflow about every five days at HZ == 100.
115     	   Therefore the identity a = (a / b) * b + a % b is used so that it is
116     	   calculated as (((t / HZ) * 100) + ((t % HZ) * 100) / HZ) % 100.
117     	   The part in front of the '+' always evaluates as 0 (mod 100). All divisions
118     	   in the above formulas are truncating. For HZ being a power of 10, the
119     	   calculations simplify to the version in the #else part (if the printf
120     	   format is adapted to the same number of digits as zeroes in HZ.
121     	 */
122     #if HZ!=100
123     	len = sprintf(page,"%lu.%02lu %lu.%02lu\n",
124     		uptime / HZ,
125     		(((uptime % HZ) * 100) / HZ) % 100,
126     		idle / HZ,
127     		(((idle % HZ) * 100) / HZ) % 100);
128     #else
129     	len = sprintf(page,"%lu.%02lu %lu.%02lu\n",
130     		uptime / HZ,
131     		uptime % HZ,
132     		idle / HZ,
133     		idle % HZ);
134     #endif
135     	return proc_calc_metrics(page, start, off, count, eof, len);
136     }
137     
138     static int meminfo_read_proc(char *page, char **start, off_t off,
139     				 int count, int *eof, void *data)
140     {
141     	struct sysinfo i;
142     	int len;
143     
144     /*
145      * display in kilobytes.
146      */
147     #define K(x) ((x) << (PAGE_SHIFT - 10))
148     #define B(x) ((unsigned long long)(x) << PAGE_SHIFT)
149     	si_meminfo(&i);
150     	si_swapinfo(&i);
151     	len = sprintf(page, "        total:    used:    free:  shared: buffers:  cached:\n"
152     		"Mem:  %8Lu %8Lu %8Lu %8Lu %8Lu %8Lu\n"
153     		"Swap: %8Lu %8Lu %8Lu\n",
154     		B(i.totalram), B(i.totalram-i.freeram), B(i.freeram),
155     		B(i.sharedram), B(i.bufferram),
156     		B(atomic_read(&page_cache_size)), B(i.totalswap),
157     		B(i.totalswap-i.freeswap), B(i.freeswap));
158     	/*
159     	 * Tagged format, for easy grepping and expansion.
160     	 * The above will go away eventually, once the tools
161     	 * have been updated.
162     	 */
163     	len += sprintf(page+len,
164     		"MemTotal:     %8lu kB\n"
165     		"MemFree:      %8lu kB\n"
166     		"MemShared:    %8lu kB\n"
167     		"Buffers:      %8lu kB\n"
168     		"Cached:       %8lu kB\n"
169     		"SwapCached:   %8lu kB\n"
170     		"Active:       %8u kB\n"
171     		"Inactive:     %8u kB\n"
172     		"HighTotal:    %8lu kB\n"
173     		"HighFree:     %8lu kB\n"
174     		"LowTotal:     %8lu kB\n"
175     		"LowFree:      %8lu kB\n"
176     		"SwapTotal:    %8lu kB\n"
177     		"SwapFree:     %8lu kB\n",
178     		K(i.totalram),
179     		K(i.freeram),
180     		K(i.sharedram),
181     		K(i.bufferram),
182     		K(atomic_read(&page_cache_size) - swapper_space.nrpages),
183     		K(swapper_space.nrpages),
184     		K(nr_active_pages),
185     		K(nr_inactive_pages),
186     		K(i.totalhigh),
187     		K(i.freehigh),
188     		K(i.totalram-i.totalhigh),
189     		K(i.freeram-i.freehigh),
190     		K(i.totalswap),
191     		K(i.freeswap));
192     
193     	return proc_calc_metrics(page, start, off, count, eof, len);
194     #undef B
195     #undef K
196     }
197     
198     static int version_read_proc(char *page, char **start, off_t off,
199     				 int count, int *eof, void *data)
200     {
201     	extern char *linux_banner;
202     	int len;
203     
204     	strcpy(page, linux_banner);
205     	len = strlen(page);
206     	return proc_calc_metrics(page, start, off, count, eof, len);
207     }
208     
209     static int cpuinfo_read_proc(char *page, char **start, off_t off,
210     				 int count, int *eof, void *data)
211     {
212     	int len = get_cpuinfo(page);
213     	return proc_calc_metrics(page, start, off, count, eof, len);
214     }
215     
216     #ifdef CONFIG_PROC_HARDWARE
217     static int hardware_read_proc(char *page, char **start, off_t off,
218     				 int count, int *eof, void *data)
219     {
220     	int len = get_hardware_list(page);
221     	return proc_calc_metrics(page, start, off, count, eof, len);
222     }
223     #endif
224     
225     #ifdef CONFIG_STRAM_PROC
226     static int stram_read_proc(char *page, char **start, off_t off,
227     				 int count, int *eof, void *data)
228     {
229     	int len = get_stram_list(page);
230     	return proc_calc_metrics(page, start, off, count, eof, len);
231     }
232     #endif
233     
234     #ifdef CONFIG_DEBUG_MALLOC
235     static int malloc_read_proc(char *page, char **start, off_t off,
236     				 int count, int *eof, void *data)
237     {
238     	int len = get_malloc(page);
239     	return proc_calc_metrics(page, start, off, count, eof, len);
240     }
241     #endif
242     
243     #ifdef CONFIG_MODULES
244     static int modules_read_proc(char *page, char **start, off_t off,
245     				 int count, int *eof, void *data)
246     {
247     	int len = get_module_list(page);
248     	return proc_calc_metrics(page, start, off, count, eof, len);
249     }
250     
251     static int ksyms_read_proc(char *page, char **start, off_t off,
252     				 int count, int *eof, void *data)
253     {
254     	int len = get_ksyms_list(page, start, off, count);
255     	if (len < count) *eof = 1;
256     	return len;
257     }
258     #endif
259     
260     static int kstat_read_proc(char *page, char **start, off_t off,
261     				 int count, int *eof, void *data)
262     {
263     	int i, len;
264     	extern unsigned long total_forks;
265     	unsigned long jif = jiffies;
266     	unsigned int sum = 0, user = 0, nice = 0, system = 0;
267     	int major, disk;
268     
269     	for (i = 0 ; i < smp_num_cpus; i++) {
270     		int cpu = cpu_logical_map(i), j;
271     
272     		user += kstat.per_cpu_user[cpu];
273     		nice += kstat.per_cpu_nice[cpu];
274     		system += kstat.per_cpu_system[cpu];
275     #if !defined(CONFIG_ARCH_S390)
276     		for (j = 0 ; j < NR_IRQS ; j++)
277     			sum += kstat.irqs[cpu][j];
278     #endif
279     	}
280     
281     	len = sprintf(page, "cpu  %u %u %u %lu\n", user, nice, system,
282     		      jif * smp_num_cpus - (user + nice + system));
283     	for (i = 0 ; i < smp_num_cpus; i++)
284     		len += sprintf(page + len, "cpu%d %u %u %u %lu\n",
285     			i,
286     			kstat.per_cpu_user[cpu_logical_map(i)],
287     			kstat.per_cpu_nice[cpu_logical_map(i)],
288     			kstat.per_cpu_system[cpu_logical_map(i)],
289     			jif - (  kstat.per_cpu_user[cpu_logical_map(i)] 
290     				   + kstat.per_cpu_nice[cpu_logical_map(i)] 
291     				   + kstat.per_cpu_system[cpu_logical_map(i)]));
292     	len += sprintf(page + len,
293     		"page %u %u\n"
294     		"swap %u %u\n"
295     		"intr %u",
296     			kstat.pgpgin >> 1,
297     			kstat.pgpgout >> 1,
298     			kstat.pswpin,
299     			kstat.pswpout,
300     			sum
301     	);
302     #if !defined(CONFIG_ARCH_S390)
303     	for (i = 0 ; i < NR_IRQS ; i++)
304     		len += sprintf(page + len, " %u", kstat_irqs(i));
305     #endif
306     
307     	len += sprintf(page + len, "\ndisk_io: ");
308     
309     	for (major = 0; major < DK_MAX_MAJOR; major++) {
310     		for (disk = 0; disk < DK_MAX_DISK; disk++) {
311     			int active = kstat.dk_drive[major][disk] +
312     				kstat.dk_drive_rblk[major][disk] +
313     				kstat.dk_drive_wblk[major][disk];
314     			if (active)
315     				len += sprintf(page + len,
316     					"(%u,%u):(%u,%u,%u,%u,%u) ",
317     					major, disk,
318     					kstat.dk_drive[major][disk],
319     					kstat.dk_drive_rio[major][disk],
320     					kstat.dk_drive_rblk[major][disk],
321     					kstat.dk_drive_wio[major][disk],
322     					kstat.dk_drive_wblk[major][disk]
323     			);
324     		}
325     	}
326     
327     	len += sprintf(page + len,
328     		"\nctxt %u\n"
329     		"btime %lu\n"
330     		"processes %lu\n",
331     		kstat.context_swtch,
332     		xtime.tv_sec - jif / HZ,
333     		total_forks);
334     
335     	return proc_calc_metrics(page, start, off, count, eof, len);
336     }
337     
338     static int devices_read_proc(char *page, char **start, off_t off,
339     				 int count, int *eof, void *data)
340     {
341     	int len = get_device_list(page);
342     	return proc_calc_metrics(page, start, off, count, eof, len);
343     }
344     
345     static int partitions_read_proc(char *page, char **start, off_t off,
346     				 int count, int *eof, void *data)
347     {
348     	int len = get_partition_list(page, start, off, count);
349     	if (len < count) *eof = 1;
350     	return len;
351     }
352     
353     #if !defined(CONFIG_ARCH_S390)
354     static int interrupts_read_proc(char *page, char **start, off_t off,
355     				 int count, int *eof, void *data)
356     {
357     	int len = get_irq_list(page);
358     	return proc_calc_metrics(page, start, off, count, eof, len);
359     }
360     #endif
361     
362     static int filesystems_read_proc(char *page, char **start, off_t off,
363     				 int count, int *eof, void *data)
364     {
365     	int len = get_filesystem_list(page);
366     	return proc_calc_metrics(page, start, off, count, eof, len);
367     }
368     
369     static int dma_read_proc(char *page, char **start, off_t off,
370     				 int count, int *eof, void *data)
371     {
372     	int len = get_dma_list(page);
373     	return proc_calc_metrics(page, start, off, count, eof, len);
374     }
375     
376     static int ioports_read_proc(char *page, char **start, off_t off,
377     				 int count, int *eof, void *data)
378     {
379     	int len = get_ioport_list(page);
380     	return proc_calc_metrics(page, start, off, count, eof, len);
381     }
382     
383     static int cmdline_read_proc(char *page, char **start, off_t off,
384     				 int count, int *eof, void *data)
385     {
386     	extern char saved_command_line[];
387     	int len;
388     
389     	len = sprintf(page, "%s\n", saved_command_line);
390     	len = strlen(page);
391     	return proc_calc_metrics(page, start, off, count, eof, len);
392     }
393     
394     #ifdef CONFIG_SGI_DS1286
395     static int ds1286_read_proc(char *page, char **start, off_t off,
396     				 int count, int *eof, void *data)
397     {
398     	int len = get_ds1286_status(page);
399     	return proc_calc_metrics(page, start, off, count, eof, len);
400     }
401     #endif
402     
403     static int locks_read_proc(char *page, char **start, off_t off,
404     				 int count, int *eof, void *data)
405     {
406     	int len;
407     	lock_kernel();
408     	len = get_locks_status(page, start, off, count);
409     	unlock_kernel();
410     	if (len < count) *eof = 1;
411     	return len;
412     }
413     
414     static int mounts_read_proc(char *page, char **start, off_t off,
415     				 int count, int *eof, void *data)
416     {
417     	int len = get_filesystem_info(page);
418     	return proc_calc_metrics(page, start, off, count, eof, len);
419     }
420     
421     static int execdomains_read_proc(char *page, char **start, off_t off,
422     				 int count, int *eof, void *data)
423     {
424     	int len = get_exec_domain_list(page);
425     	return proc_calc_metrics(page, start, off, count, eof, len);
426     }
427     
428     static int swaps_read_proc(char *page, char **start, off_t off,
429     				 int count, int *eof, void *data)
430     {
431     	int len = get_swaparea_info(page);
432     	return proc_calc_metrics(page, start, off, count, eof, len);
433     }
434     
435     static int memory_read_proc(char *page, char **start, off_t off,
436     				 int count, int *eof, void *data)
437     {
438     	int len = get_mem_list(page);
439     	return proc_calc_metrics(page, start, off, count, eof, len);
440     }
441     
442     /*
443      * This function accesses profiling information. The returned data is
444      * binary: the sampling step and the actual contents of the profile
445      * buffer. Use of the program readprofile is recommended in order to
446      * get meaningful info out of these data.
447      */
448     static ssize_t read_profile(struct file *file, char *buf,
449     			    size_t count, loff_t *ppos)
450     {
451     	unsigned long p = *ppos;
452     	ssize_t read;
453     	char * pnt;
454     	unsigned int sample_step = 1 << prof_shift;
455     
456     	if (p >= (prof_len+1)*sizeof(unsigned int))
457     		return 0;
458     	if (count > (prof_len+1)*sizeof(unsigned int) - p)
459     		count = (prof_len+1)*sizeof(unsigned int) - p;
460     	read = 0;
461     
462     	while (p < sizeof(unsigned int) && count > 0) {
463     		put_user(*((char *)(&sample_step)+p),buf);
464     		buf++; p++; count--; read++;
465     	}
466     	pnt = (char *)prof_buffer + p - sizeof(unsigned int);
467     	copy_to_user(buf,(void *)pnt,count);
468     	read += count;
469     	*ppos += read;
470     	return read;
471     }
472     
473     /*
474      * Writing to /proc/profile resets the counters
475      *
476      * Writing a 'profiling multiplier' value into it also re-sets the profiling
477      * interrupt frequency, on architectures that support this.
478      */
479     static ssize_t write_profile(struct file * file, const char * buf,
480     			     size_t count, loff_t *ppos)
481     {
482     #ifdef CONFIG_SMP
483     	extern int setup_profiling_timer (unsigned int multiplier);
484     
485     	if (count==sizeof(int)) {
486     		unsigned int multiplier;
487     
488     		if (copy_from_user(&multiplier, buf, sizeof(int)))
489     			return -EFAULT;
490     
491     		if (setup_profiling_timer(multiplier))
492     			return -EINVAL;
493     	}
494     #endif
495     
496     	memset(prof_buffer, 0, prof_len * sizeof(*prof_buffer));
497     	return count;
498     }
499     
500     static struct file_operations proc_profile_operations = {
501     	read:		read_profile,
502     	write:		write_profile,
503     };
504     
505     struct proc_dir_entry *proc_root_kcore;
506     
507     void __init proc_misc_init(void)
508     {
509     	struct proc_dir_entry *entry;
510     	static struct {
511     		char *name;
512     		int (*read_proc)(char*,char**,off_t,int,int*,void*);
513     	} *p, simple_ones[] = {
514     		{"loadavg",     loadavg_read_proc},
515     		{"uptime",	uptime_read_proc},
516     		{"meminfo",	meminfo_read_proc},
517     		{"version",	version_read_proc},
518     		{"cpuinfo",	cpuinfo_read_proc},
519     #ifdef CONFIG_PROC_HARDWARE
520     		{"hardware",	hardware_read_proc},
521     #endif
522     #ifdef CONFIG_STRAM_PROC
523     		{"stram",	stram_read_proc},
524     #endif
525     #ifdef CONFIG_DEBUG_MALLOC
526     		{"malloc",	malloc_read_proc},
527     #endif
528     #ifdef CONFIG_MODULES
529     		{"modules",	modules_read_proc},
530     		{"ksyms",	ksyms_read_proc},
531     #endif
532     		{"stat",	kstat_read_proc},
533     		{"devices",	devices_read_proc},
534     		{"partitions",	partitions_read_proc},
535     #if !defined(CONFIG_ARCH_S390)
536     		{"interrupts",	interrupts_read_proc},
537     #endif
538     		{"filesystems",	filesystems_read_proc},
539     		{"dma",		dma_read_proc},
540     		{"ioports",	ioports_read_proc},
541     		{"cmdline",	cmdline_read_proc},
542     #ifdef CONFIG_SGI_DS1286
543     		{"rtc",		ds1286_read_proc},
544     #endif
545     		{"locks",	locks_read_proc},
546     		{"mounts",	mounts_read_proc},
547     		{"swaps",	swaps_read_proc},
548     		{"iomem",	memory_read_proc},
549     		{"execdomains",	execdomains_read_proc},
550     		{NULL,}
551     	};
552     	for (p = simple_ones; p->name; p++)
553     		create_proc_read_entry(p->name, 0, NULL, p->read_proc, NULL);
554     
555     	/* And now for trickier ones */
556     	entry = create_proc_entry("kmsg", S_IRUSR, &proc_root);
557     	if (entry)
558     		entry->proc_fops = &proc_kmsg_operations;
559     	proc_root_kcore = create_proc_entry("kcore", S_IRUSR, NULL);
560     	if (proc_root_kcore) {
561     		proc_root_kcore->proc_fops = &proc_kcore_operations;
562     		proc_root_kcore->size =
563     				(size_t)high_memory - PAGE_OFFSET + PAGE_SIZE;
564     	}
565     	if (prof_shift) {
566     		entry = create_proc_entry("profile", S_IWUSR | S_IRUGO, NULL);
567     		if (entry) {
568     			entry->proc_fops = &proc_profile_operations;
569     			entry->size = (1+prof_len) * sizeof(unsigned int);
570     		}
571     	}
572     #ifdef CONFIG_PPC32
573     	{
574     		extern struct file_operations ppc_htab_operations;
575     		entry = create_proc_entry("ppc_htab", S_IRUGO|S_IWUSR, NULL);
576     		if (entry)
577     			entry->proc_fops = &ppc_htab_operations;
578     	}
579     #endif
580     	entry = create_proc_read_entry("slabinfo", S_IWUSR | S_IRUGO, NULL,
581     				       slabinfo_read_proc, NULL);
582     	if (entry)
583     		entry->write_proc = slabinfo_write_proc;
584     }
585