aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /fs/proc
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/array.c135
-rw-r--r--fs/proc/base.c121
-rw-r--r--fs/proc/generic.c60
-rw-r--r--fs/proc/inode.c32
-rw-r--r--fs/proc/internal.h10
-rw-r--r--fs/proc/kcore.c3
-rw-r--r--fs/proc/kmsg.c14
-rw-r--r--fs/proc/nommu.c1
-rw-r--r--fs/proc/page.c45
-rw-r--r--fs/proc/proc_devtree.c49
-rw-r--r--fs/proc/proc_net.c1
-rw-r--r--fs/proc/proc_sysctl.c4
-rw-r--r--fs/proc/root.c6
-rw-r--r--fs/proc/stat.c20
-rw-r--r--fs/proc/task_mmu.c155
-rw-r--r--fs/proc/task_nommu.c9
-rw-r--r--fs/proc/vmcore.c1
17 files changed, 325 insertions, 341 deletions
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 822c2d506518..885ab5513ac5 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -68,7 +68,6 @@
68#include <linux/hugetlb.h> 68#include <linux/hugetlb.h>
69#include <linux/pagemap.h> 69#include <linux/pagemap.h>
70#include <linux/swap.h> 70#include <linux/swap.h>
71#include <linux/slab.h>
72#include <linux/smp.h> 71#include <linux/smp.h>
73#include <linux/signal.h> 72#include <linux/signal.h>
74#include <linux/highmem.h> 73#include <linux/highmem.h>
@@ -82,7 +81,6 @@
82#include <linux/pid_namespace.h> 81#include <linux/pid_namespace.h>
83#include <linux/ptrace.h> 82#include <linux/ptrace.h>
84#include <linux/tracehook.h> 83#include <linux/tracehook.h>
85#include <linux/swapops.h>
86 84
87#include <asm/pgtable.h> 85#include <asm/pgtable.h>
88#include <asm/processor.h> 86#include <asm/processor.h>
@@ -134,13 +132,16 @@ static inline void task_name(struct seq_file *m, struct task_struct *p)
134 * simple bit tests. 132 * simple bit tests.
135 */ 133 */
136static const char *task_state_array[] = { 134static const char *task_state_array[] = {
137 "R (running)", /* 0 */ 135 "R (running)", /* 0 */
138 "S (sleeping)", /* 1 */ 136 "S (sleeping)", /* 1 */
139 "D (disk sleep)", /* 2 */ 137 "D (disk sleep)", /* 2 */
140 "T (stopped)", /* 4 */ 138 "T (stopped)", /* 4 */
141 "T (tracing stop)", /* 8 */ 139 "t (tracing stop)", /* 8 */
142 "Z (zombie)", /* 16 */ 140 "Z (zombie)", /* 16 */
143 "X (dead)" /* 32 */ 141 "X (dead)", /* 32 */
142 "x (dead)", /* 64 */
143 "K (wakekill)", /* 128 */
144 "W (waking)", /* 256 */
144}; 145};
145 146
146static inline const char *get_task_state(struct task_struct *tsk) 147static inline const char *get_task_state(struct task_struct *tsk)
@@ -148,6 +149,8 @@ static inline const char *get_task_state(struct task_struct *tsk)
148 unsigned int state = (tsk->state & TASK_REPORT) | tsk->exit_state; 149 unsigned int state = (tsk->state & TASK_REPORT) | tsk->exit_state;
149 const char **p = &task_state_array[0]; 150 const char **p = &task_state_array[0];
150 151
152 BUILD_BUG_ON(1 + ilog2(TASK_STATE_MAX) != ARRAY_SIZE(task_state_array));
153
151 while (state) { 154 while (state) {
152 p++; 155 p++;
153 state >>= 1; 156 state >>= 1;
@@ -265,8 +268,10 @@ static inline void task_sig(struct seq_file *m, struct task_struct *p)
265 blocked = p->blocked; 268 blocked = p->blocked;
266 collect_sigign_sigcatch(p, &ignored, &caught); 269 collect_sigign_sigcatch(p, &ignored, &caught);
267 num_threads = atomic_read(&p->signal->count); 270 num_threads = atomic_read(&p->signal->count);
271 rcu_read_lock(); /* FIXME: is this correct? */
268 qsize = atomic_read(&__task_cred(p)->user->sigpending); 272 qsize = atomic_read(&__task_cred(p)->user->sigpending);
269 qlim = p->signal->rlim[RLIMIT_SIGPENDING].rlim_cur; 273 rcu_read_unlock();
274 qlim = task_rlimit(p, RLIMIT_SIGPENDING);
270 unlock_task_sighand(p, &flags); 275 unlock_task_sighand(p, &flags);
271 } 276 }
272 277
@@ -322,93 +327,15 @@ static inline void task_context_switch_counts(struct seq_file *m,
322 p->nivcsw); 327 p->nivcsw);
323} 328}
324 329
325#ifdef CONFIG_MMU 330static void task_cpus_allowed(struct seq_file *m, struct task_struct *task)
326
327struct stack_stats {
328 struct vm_area_struct *vma;
329 unsigned long startpage;
330 unsigned long usage;
331};
332
333static int stack_usage_pte_range(pmd_t *pmd, unsigned long addr,
334 unsigned long end, struct mm_walk *walk)
335{
336 struct stack_stats *ss = walk->private;
337 struct vm_area_struct *vma = ss->vma;
338 pte_t *pte, ptent;
339 spinlock_t *ptl;
340 int ret = 0;
341
342 pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
343 for (; addr != end; pte++, addr += PAGE_SIZE) {
344 ptent = *pte;
345
346#ifdef CONFIG_STACK_GROWSUP
347 if (pte_present(ptent) || is_swap_pte(ptent))
348 ss->usage = addr - ss->startpage + PAGE_SIZE;
349#else
350 if (pte_present(ptent) || is_swap_pte(ptent)) {
351 ss->usage = ss->startpage - addr + PAGE_SIZE;
352 pte++;
353 ret = 1;
354 break;
355 }
356#endif
357 }
358 pte_unmap_unlock(pte - 1, ptl);
359 cond_resched();
360 return ret;
361}
362
363static inline unsigned long get_stack_usage_in_bytes(struct vm_area_struct *vma,
364 struct task_struct *task)
365{
366 struct stack_stats ss;
367 struct mm_walk stack_walk = {
368 .pmd_entry = stack_usage_pte_range,
369 .mm = vma->vm_mm,
370 .private = &ss,
371 };
372
373 if (!vma->vm_mm || is_vm_hugetlb_page(vma))
374 return 0;
375
376 ss.vma = vma;
377 ss.startpage = task->stack_start & PAGE_MASK;
378 ss.usage = 0;
379
380#ifdef CONFIG_STACK_GROWSUP
381 walk_page_range(KSTK_ESP(task) & PAGE_MASK, vma->vm_end,
382 &stack_walk);
383#else
384 walk_page_range(vma->vm_start, (KSTK_ESP(task) & PAGE_MASK) + PAGE_SIZE,
385 &stack_walk);
386#endif
387 return ss.usage;
388}
389
390static inline void task_show_stack_usage(struct seq_file *m,
391 struct task_struct *task)
392{
393 struct vm_area_struct *vma;
394 struct mm_struct *mm = get_task_mm(task);
395
396 if (mm) {
397 down_read(&mm->mmap_sem);
398 vma = find_vma(mm, task->stack_start);
399 if (vma)
400 seq_printf(m, "Stack usage:\t%lu kB\n",
401 get_stack_usage_in_bytes(vma, task) >> 10);
402
403 up_read(&mm->mmap_sem);
404 mmput(mm);
405 }
406}
407#else
408static void task_show_stack_usage(struct seq_file *m, struct task_struct *task)
409{ 331{
332 seq_printf(m, "Cpus_allowed:\t");
333 seq_cpumask(m, &task->cpus_allowed);
334 seq_printf(m, "\n");
335 seq_printf(m, "Cpus_allowed_list:\t");
336 seq_cpumask_list(m, &task->cpus_allowed);
337 seq_printf(m, "\n");
410} 338}
411#endif /* CONFIG_MMU */
412 339
413int proc_pid_status(struct seq_file *m, struct pid_namespace *ns, 340int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
414 struct pid *pid, struct task_struct *task) 341 struct pid *pid, struct task_struct *task)
@@ -424,12 +351,12 @@ int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
424 } 351 }
425 task_sig(m, task); 352 task_sig(m, task);
426 task_cap(m, task); 353 task_cap(m, task);
354 task_cpus_allowed(m, task);
427 cpuset_task_status_allowed(m, task); 355 cpuset_task_status_allowed(m, task);
428#if defined(CONFIG_S390) 356#if defined(CONFIG_S390)
429 task_show_regs(m, task); 357 task_show_regs(m, task);
430#endif 358#endif
431 task_context_switch_counts(m, task); 359 task_context_switch_counts(m, task);
432 task_show_stack_usage(m, task);
433 return 0; 360 return 0;
434} 361}
435 362
@@ -491,24 +418,21 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
491 cutime = sig->cutime; 418 cutime = sig->cutime;
492 cstime = sig->cstime; 419 cstime = sig->cstime;
493 cgtime = sig->cgtime; 420 cgtime = sig->cgtime;
494 rsslim = sig->rlim[RLIMIT_RSS].rlim_cur; 421 rsslim = ACCESS_ONCE(sig->rlim[RLIMIT_RSS].rlim_cur);
495 422
496 /* add up live thread stats at the group level */ 423 /* add up live thread stats at the group level */
497 if (whole) { 424 if (whole) {
498 struct task_cputime cputime;
499 struct task_struct *t = task; 425 struct task_struct *t = task;
500 do { 426 do {
501 min_flt += t->min_flt; 427 min_flt += t->min_flt;
502 maj_flt += t->maj_flt; 428 maj_flt += t->maj_flt;
503 gtime = cputime_add(gtime, task_gtime(t)); 429 gtime = cputime_add(gtime, t->gtime);
504 t = next_thread(t); 430 t = next_thread(t);
505 } while (t != task); 431 } while (t != task);
506 432
507 min_flt += sig->min_flt; 433 min_flt += sig->min_flt;
508 maj_flt += sig->maj_flt; 434 maj_flt += sig->maj_flt;
509 thread_group_cputime(task, &cputime); 435 thread_group_times(task, &utime, &stime);
510 utime = cputime.utime;
511 stime = cputime.stime;
512 gtime = cputime_add(gtime, sig->gtime); 436 gtime = cputime_add(gtime, sig->gtime);
513 } 437 }
514 438
@@ -524,9 +448,8 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
524 if (!whole) { 448 if (!whole) {
525 min_flt = task->min_flt; 449 min_flt = task->min_flt;
526 maj_flt = task->maj_flt; 450 maj_flt = task->maj_flt;
527 utime = task_utime(task); 451 task_times(task, &utime, &stime);
528 stime = task_stime(task); 452 gtime = task->gtime;
529 gtime = task_gtime(task);
530 } 453 }
531 454
532 /* scale priority and nice values from timeslices to -20..20 */ 455 /* scale priority and nice values from timeslices to -20..20 */
@@ -571,7 +494,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
571 rsslim, 494 rsslim,
572 mm ? mm->start_code : 0, 495 mm ? mm->start_code : 0,
573 mm ? mm->end_code : 0, 496 mm ? mm->end_code : 0,
574 (permitted && mm) ? task->stack_start : 0, 497 (permitted && mm) ? mm->start_stack : 0,
575 esp, 498 esp,
576 eip, 499 eip,
577 /* The signal information here is obsolete. 500 /* The signal information here is obsolete.
diff --git a/fs/proc/base.c b/fs/proc/base.c
index af643b5aefe8..8418fcc0a6ab 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -81,6 +81,7 @@
81#include <linux/elf.h> 81#include <linux/elf.h>
82#include <linux/pid_namespace.h> 82#include <linux/pid_namespace.h>
83#include <linux/fs_struct.h> 83#include <linux/fs_struct.h>
84#include <linux/slab.h>
84#include "internal.h" 85#include "internal.h"
85 86
86/* NOTE: 87/* NOTE:
@@ -442,12 +443,13 @@ static const struct file_operations proc_lstats_operations = {
442unsigned long badness(struct task_struct *p, unsigned long uptime); 443unsigned long badness(struct task_struct *p, unsigned long uptime);
443static int proc_oom_score(struct task_struct *task, char *buffer) 444static int proc_oom_score(struct task_struct *task, char *buffer)
444{ 445{
445 unsigned long points; 446 unsigned long points = 0;
446 struct timespec uptime; 447 struct timespec uptime;
447 448
448 do_posix_clock_monotonic_gettime(&uptime); 449 do_posix_clock_monotonic_gettime(&uptime);
449 read_lock(&tasklist_lock); 450 read_lock(&tasklist_lock);
450 points = badness(task->group_leader, uptime.tv_sec); 451 if (pid_alive(task))
452 points = badness(task, uptime.tv_sec);
451 read_unlock(&tasklist_lock); 453 read_unlock(&tasklist_lock);
452 return sprintf(buffer, "%lu\n", points); 454 return sprintf(buffer, "%lu\n", points);
453} 455}
@@ -647,17 +649,11 @@ static int mounts_release(struct inode *inode, struct file *file)
647static unsigned mounts_poll(struct file *file, poll_table *wait) 649static unsigned mounts_poll(struct file *file, poll_table *wait)
648{ 650{
649 struct proc_mounts *p = file->private_data; 651 struct proc_mounts *p = file->private_data;
650 struct mnt_namespace *ns = p->ns;
651 unsigned res = POLLIN | POLLRDNORM; 652 unsigned res = POLLIN | POLLRDNORM;
652 653
653 poll_wait(file, &ns->poll, wait); 654 poll_wait(file, &p->ns->poll, wait);
654 655 if (mnt_had_events(p))
655 spin_lock(&vfsmount_lock);
656 if (p->event != ns->event) {
657 p->event = ns->event;
658 res |= POLLERR | POLLPRI; 656 res |= POLLERR | POLLPRI;
659 }
660 spin_unlock(&vfsmount_lock);
661 657
662 return res; 658 return res;
663} 659}
@@ -1095,8 +1091,12 @@ static ssize_t proc_loginuid_write(struct file * file, const char __user * buf,
1095 if (!capable(CAP_AUDIT_CONTROL)) 1091 if (!capable(CAP_AUDIT_CONTROL))
1096 return -EPERM; 1092 return -EPERM;
1097 1093
1098 if (current != pid_task(proc_pid(inode), PIDTYPE_PID)) 1094 rcu_read_lock();
1095 if (current != pid_task(proc_pid(inode), PIDTYPE_PID)) {
1096 rcu_read_unlock();
1099 return -EPERM; 1097 return -EPERM;
1098 }
1099 rcu_read_unlock();
1100 1100
1101 if (count >= PAGE_SIZE) 1101 if (count >= PAGE_SIZE)
1102 count = PAGE_SIZE - 1; 1102 count = PAGE_SIZE - 1;
@@ -1265,6 +1265,72 @@ static const struct file_operations proc_pid_sched_operations = {
1265 1265
1266#endif 1266#endif
1267 1267
1268static ssize_t comm_write(struct file *file, const char __user *buf,
1269 size_t count, loff_t *offset)
1270{
1271 struct inode *inode = file->f_path.dentry->d_inode;
1272 struct task_struct *p;
1273 char buffer[TASK_COMM_LEN];
1274
1275 memset(buffer, 0, sizeof(buffer));
1276 if (count > sizeof(buffer) - 1)
1277 count = sizeof(buffer) - 1;
1278 if (copy_from_user(buffer, buf, count))
1279 return -EFAULT;
1280
1281 p = get_proc_task(inode);
1282 if (!p)
1283 return -ESRCH;
1284
1285 if (same_thread_group(current, p))
1286 set_task_comm(p, buffer);
1287 else
1288 count = -EINVAL;
1289
1290 put_task_struct(p);
1291
1292 return count;
1293}
1294
1295static int comm_show(struct seq_file *m, void *v)
1296{
1297 struct inode *inode = m->private;
1298 struct task_struct *p;
1299
1300 p = get_proc_task(inode);
1301 if (!p)
1302 return -ESRCH;
1303
1304 task_lock(p);
1305 seq_printf(m, "%s\n", p->comm);
1306 task_unlock(p);
1307
1308 put_task_struct(p);
1309
1310 return 0;
1311}
1312
1313static int comm_open(struct inode *inode, struct file *filp)
1314{
1315 int ret;
1316
1317 ret = single_open(filp, comm_show, NULL);
1318 if (!ret) {
1319 struct seq_file *m = filp->private_data;
1320
1321 m->private = inode;
1322 }
1323 return ret;
1324}
1325
1326static const struct file_operations proc_pid_set_comm_operations = {
1327 .open = comm_open,
1328 .read = seq_read,
1329 .write = comm_write,
1330 .llseek = seq_lseek,
1331 .release = single_release,
1332};
1333
1268/* 1334/*
1269 * We added or removed a vma mapping the executable. The vmas are only mapped 1335 * We added or removed a vma mapping the executable. The vmas are only mapped
1270 * during exec and are not mapped with the mmap system call. 1336 * during exec and are not mapped with the mmap system call.
@@ -1353,7 +1419,6 @@ static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
1353 goto out; 1419 goto out;
1354 1420
1355 error = PROC_I(inode)->op.proc_get_link(inode, &nd->path); 1421 error = PROC_I(inode)->op.proc_get_link(inode, &nd->path);
1356 nd->last_type = LAST_BIND;
1357out: 1422out:
1358 return ERR_PTR(error); 1423 return ERR_PTR(error);
1359} 1424}
@@ -2200,7 +2265,7 @@ static const struct inode_operations proc_attr_dir_inode_operations = {
2200 2265
2201#endif 2266#endif
2202 2267
2203#if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE) 2268#ifdef CONFIG_ELF_CORE
2204static ssize_t proc_coredump_filter_read(struct file *file, char __user *buf, 2269static ssize_t proc_coredump_filter_read(struct file *file, char __user *buf,
2205 size_t count, loff_t *ppos) 2270 size_t count, loff_t *ppos)
2206{ 2271{
@@ -2304,16 +2369,30 @@ static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
2304{ 2369{
2305 struct pid_namespace *ns = dentry->d_sb->s_fs_info; 2370 struct pid_namespace *ns = dentry->d_sb->s_fs_info;
2306 pid_t tgid = task_tgid_nr_ns(current, ns); 2371 pid_t tgid = task_tgid_nr_ns(current, ns);
2307 char tmp[PROC_NUMBUF]; 2372 char *name = ERR_PTR(-ENOENT);
2308 if (!tgid) 2373 if (tgid) {
2309 return ERR_PTR(-ENOENT); 2374 name = __getname();
2310 sprintf(tmp, "%d", task_tgid_nr_ns(current, ns)); 2375 if (!name)
2311 return ERR_PTR(vfs_follow_link(nd,tmp)); 2376 name = ERR_PTR(-ENOMEM);
2377 else
2378 sprintf(name, "%d", tgid);
2379 }
2380 nd_set_link(nd, name);
2381 return NULL;
2382}
2383
2384static void proc_self_put_link(struct dentry *dentry, struct nameidata *nd,
2385 void *cookie)
2386{
2387 char *s = nd_get_link(nd);
2388 if (!IS_ERR(s))
2389 __putname(s);
2312} 2390}
2313 2391
2314static const struct inode_operations proc_self_inode_operations = { 2392static const struct inode_operations proc_self_inode_operations = {
2315 .readlink = proc_self_readlink, 2393 .readlink = proc_self_readlink,
2316 .follow_link = proc_self_follow_link, 2394 .follow_link = proc_self_follow_link,
2395 .put_link = proc_self_put_link,
2317}; 2396};
2318 2397
2319/* 2398/*
@@ -2504,6 +2583,7 @@ static const struct pid_entry tgid_base_stuff[] = {
2504#ifdef CONFIG_SCHED_DEBUG 2583#ifdef CONFIG_SCHED_DEBUG
2505 REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), 2584 REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations),
2506#endif 2585#endif
2586 REG("comm", S_IRUGO|S_IWUSR, proc_pid_set_comm_operations),
2507#ifdef CONFIG_HAVE_ARCH_TRACEHOOK 2587#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
2508 INF("syscall", S_IRUSR, proc_pid_syscall), 2588 INF("syscall", S_IRUSR, proc_pid_syscall),
2509#endif 2589#endif
@@ -2556,7 +2636,7 @@ static const struct pid_entry tgid_base_stuff[] = {
2556#ifdef CONFIG_FAULT_INJECTION 2636#ifdef CONFIG_FAULT_INJECTION
2557 REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations), 2637 REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
2558#endif 2638#endif
2559#if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE) 2639#ifdef CONFIG_ELF_CORE
2560 REG("coredump_filter", S_IRUGO|S_IWUSR, proc_coredump_filter_operations), 2640 REG("coredump_filter", S_IRUGO|S_IWUSR, proc_coredump_filter_operations),
2561#endif 2641#endif
2562#ifdef CONFIG_TASK_IO_ACCOUNTING 2642#ifdef CONFIG_TASK_IO_ACCOUNTING
@@ -2829,7 +2909,7 @@ out_no_task:
2829 */ 2909 */
2830static const struct pid_entry tid_base_stuff[] = { 2910static const struct pid_entry tid_base_stuff[] = {
2831 DIR("fd", S_IRUSR|S_IXUSR, proc_fd_inode_operations, proc_fd_operations), 2911 DIR("fd", S_IRUSR|S_IXUSR, proc_fd_inode_operations, proc_fd_operations),
2832 DIR("fdinfo", S_IRUSR|S_IXUSR, proc_fdinfo_inode_operations, proc_fd_operations), 2912 DIR("fdinfo", S_IRUSR|S_IXUSR, proc_fdinfo_inode_operations, proc_fdinfo_operations),
2833 REG("environ", S_IRUSR, proc_environ_operations), 2913 REG("environ", S_IRUSR, proc_environ_operations),
2834 INF("auxv", S_IRUSR, proc_pid_auxv), 2914 INF("auxv", S_IRUSR, proc_pid_auxv),
2835 ONE("status", S_IRUGO, proc_pid_status), 2915 ONE("status", S_IRUGO, proc_pid_status),
@@ -2838,6 +2918,7 @@ static const struct pid_entry tid_base_stuff[] = {
2838#ifdef CONFIG_SCHED_DEBUG 2918#ifdef CONFIG_SCHED_DEBUG
2839 REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), 2919 REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations),
2840#endif 2920#endif
2921 REG("comm", S_IRUGO|S_IWUSR, proc_pid_set_comm_operations),
2841#ifdef CONFIG_HAVE_ARCH_TRACEHOOK 2922#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
2842 INF("syscall", S_IRUSR, proc_pid_syscall), 2923 INF("syscall", S_IRUSR, proc_pid_syscall),
2843#endif 2924#endif
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index fa678abc9db1..43c127490606 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -13,6 +13,7 @@
13#include <linux/proc_fs.h> 13#include <linux/proc_fs.h>
14#include <linux/stat.h> 14#include <linux/stat.h>
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/slab.h>
16#include <linux/mount.h> 17#include <linux/mount.h>
17#include <linux/init.h> 18#include <linux/init.h>
18#include <linux/idr.h> 19#include <linux/idr.h>
@@ -291,19 +292,17 @@ static const struct inode_operations proc_file_inode_operations = {
291 * returns the struct proc_dir_entry for "/proc/tty/driver", and 292 * returns the struct proc_dir_entry for "/proc/tty/driver", and
292 * returns "serial" in residual. 293 * returns "serial" in residual.
293 */ 294 */
294static int xlate_proc_name(const char *name, 295static int __xlate_proc_name(const char *name, struct proc_dir_entry **ret,
295 struct proc_dir_entry **ret, const char **residual) 296 const char **residual)
296{ 297{
297 const char *cp = name, *next; 298 const char *cp = name, *next;
298 struct proc_dir_entry *de; 299 struct proc_dir_entry *de;
299 int len; 300 int len;
300 int rtn = 0;
301 301
302 de = *ret; 302 de = *ret;
303 if (!de) 303 if (!de)
304 de = &proc_root; 304 de = &proc_root;
305 305
306 spin_lock(&proc_subdir_lock);
307 while (1) { 306 while (1) {
308 next = strchr(cp, '/'); 307 next = strchr(cp, '/');
309 if (!next) 308 if (!next)
@@ -315,16 +314,25 @@ static int xlate_proc_name(const char *name,
315 break; 314 break;
316 } 315 }
317 if (!de) { 316 if (!de) {
318 rtn = -ENOENT; 317 WARN(1, "name '%s'\n", name);
319 goto out; 318 return -ENOENT;
320 } 319 }
321 cp += len + 1; 320 cp += len + 1;
322 } 321 }
323 *residual = cp; 322 *residual = cp;
324 *ret = de; 323 *ret = de;
325out: 324 return 0;
325}
326
327static int xlate_proc_name(const char *name, struct proc_dir_entry **ret,
328 const char **residual)
329{
330 int rv;
331
332 spin_lock(&proc_subdir_lock);
333 rv = __xlate_proc_name(name, ret, residual);
326 spin_unlock(&proc_subdir_lock); 334 spin_unlock(&proc_subdir_lock);
327 return rtn; 335 return rv;
328} 336}
329 337
330static DEFINE_IDA(proc_inum_ida); 338static DEFINE_IDA(proc_inum_ida);
@@ -429,7 +437,7 @@ struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *dir,
429 unsigned int ino; 437 unsigned int ino;
430 438
431 ino = de->low_ino; 439 ino = de->low_ino;
432 de_get(de); 440 pde_get(de);
433 spin_unlock(&proc_subdir_lock); 441 spin_unlock(&proc_subdir_lock);
434 error = -EINVAL; 442 error = -EINVAL;
435 inode = proc_get_inode(dir->i_sb, ino, de); 443 inode = proc_get_inode(dir->i_sb, ino, de);
@@ -445,7 +453,7 @@ out_unlock:
445 return NULL; 453 return NULL;
446 } 454 }
447 if (de) 455 if (de)
448 de_put(de); 456 pde_put(de);
449 return ERR_PTR(error); 457 return ERR_PTR(error);
450} 458}
451 459
@@ -509,17 +517,17 @@ int proc_readdir_de(struct proc_dir_entry *de, struct file *filp, void *dirent,
509 struct proc_dir_entry *next; 517 struct proc_dir_entry *next;
510 518
511 /* filldir passes info to user space */ 519 /* filldir passes info to user space */
512 de_get(de); 520 pde_get(de);
513 spin_unlock(&proc_subdir_lock); 521 spin_unlock(&proc_subdir_lock);
514 if (filldir(dirent, de->name, de->namelen, filp->f_pos, 522 if (filldir(dirent, de->name, de->namelen, filp->f_pos,
515 de->low_ino, de->mode >> 12) < 0) { 523 de->low_ino, de->mode >> 12) < 0) {
516 de_put(de); 524 pde_put(de);
517 goto out; 525 goto out;
518 } 526 }
519 spin_lock(&proc_subdir_lock); 527 spin_lock(&proc_subdir_lock);
520 filp->f_pos++; 528 filp->f_pos++;
521 next = de->next; 529 next = de->next;
522 de_put(de); 530 pde_put(de);
523 de = next; 531 de = next;
524 } while (de); 532 } while (de);
525 spin_unlock(&proc_subdir_lock); 533 spin_unlock(&proc_subdir_lock);
@@ -662,6 +670,7 @@ struct proc_dir_entry *proc_symlink(const char *name,
662 } 670 }
663 return ent; 671 return ent;
664} 672}
673EXPORT_SYMBOL(proc_symlink);
665 674
666struct proc_dir_entry *proc_mkdir_mode(const char *name, mode_t mode, 675struct proc_dir_entry *proc_mkdir_mode(const char *name, mode_t mode,
667 struct proc_dir_entry *parent) 676 struct proc_dir_entry *parent)
@@ -700,6 +709,7 @@ struct proc_dir_entry *proc_mkdir(const char *name,
700{ 709{
701 return proc_mkdir_mode(name, S_IRUGO | S_IXUGO, parent); 710 return proc_mkdir_mode(name, S_IRUGO | S_IXUGO, parent);
702} 711}
712EXPORT_SYMBOL(proc_mkdir);
703 713
704struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode, 714struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
705 struct proc_dir_entry *parent) 715 struct proc_dir_entry *parent)
@@ -728,6 +738,7 @@ struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
728 } 738 }
729 return ent; 739 return ent;
730} 740}
741EXPORT_SYMBOL(create_proc_entry);
731 742
732struct proc_dir_entry *proc_create_data(const char *name, mode_t mode, 743struct proc_dir_entry *proc_create_data(const char *name, mode_t mode,
733 struct proc_dir_entry *parent, 744 struct proc_dir_entry *parent,
@@ -762,8 +773,9 @@ out_free:
762out: 773out:
763 return NULL; 774 return NULL;
764} 775}
776EXPORT_SYMBOL(proc_create_data);
765 777
766void free_proc_entry(struct proc_dir_entry *de) 778static void free_proc_entry(struct proc_dir_entry *de)
767{ 779{
768 unsigned int ino = de->low_ino; 780 unsigned int ino = de->low_ino;
769 781
@@ -777,6 +789,12 @@ void free_proc_entry(struct proc_dir_entry *de)
777 kfree(de); 789 kfree(de);
778} 790}
779 791
792void pde_put(struct proc_dir_entry *pde)
793{
794 if (atomic_dec_and_test(&pde->count))
795 free_proc_entry(pde);
796}
797
780/* 798/*
781 * Remove a /proc entry and free it if it's not currently in use. 799 * Remove a /proc entry and free it if it's not currently in use.
782 */ 800 */
@@ -787,11 +805,13 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
787 const char *fn = name; 805 const char *fn = name;
788 int len; 806 int len;
789 807
790 if (xlate_proc_name(name, &parent, &fn) != 0) 808 spin_lock(&proc_subdir_lock);
809 if (__xlate_proc_name(name, &parent, &fn) != 0) {
810 spin_unlock(&proc_subdir_lock);
791 return; 811 return;
812 }
792 len = strlen(fn); 813 len = strlen(fn);
793 814
794 spin_lock(&proc_subdir_lock);
795 for (p = &parent->subdir; *p; p=&(*p)->next ) { 815 for (p = &parent->subdir; *p; p=&(*p)->next ) {
796 if (proc_match(len, fn, *p)) { 816 if (proc_match(len, fn, *p)) {
797 de = *p; 817 de = *p;
@@ -801,8 +821,10 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
801 } 821 }
802 } 822 }
803 spin_unlock(&proc_subdir_lock); 823 spin_unlock(&proc_subdir_lock);
804 if (!de) 824 if (!de) {
825 WARN(1, "name '%s'\n", name);
805 return; 826 return;
827 }
806 828
807 spin_lock(&de->pde_unload_lock); 829 spin_lock(&de->pde_unload_lock);
808 /* 830 /*
@@ -845,6 +867,6 @@ continue_removing:
845 WARN(de->subdir, KERN_WARNING "%s: removing non-empty directory " 867 WARN(de->subdir, KERN_WARNING "%s: removing non-empty directory "
846 "'%s/%s', leaking at least '%s'\n", __func__, 868 "'%s/%s', leaking at least '%s'\n", __func__,
847 de->parent->name, de->name, de->subdir->name); 869 de->parent->name, de->name, de->subdir->name);
848 if (atomic_dec_and_test(&de->count)) 870 pde_put(de);
849 free_proc_entry(de);
850} 871}
872EXPORT_SYMBOL(remove_proc_entry);
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index d78ade305541..d35b23238fb1 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -18,35 +18,13 @@
18#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/smp_lock.h> 19#include <linux/smp_lock.h>
20#include <linux/sysctl.h> 20#include <linux/sysctl.h>
21#include <linux/slab.h>
21 22
22#include <asm/system.h> 23#include <asm/system.h>
23#include <asm/uaccess.h> 24#include <asm/uaccess.h>
24 25
25#include "internal.h" 26#include "internal.h"
26 27
27struct proc_dir_entry *de_get(struct proc_dir_entry *de)
28{
29 atomic_inc(&de->count);
30 return de;
31}
32
33/*
34 * Decrements the use count and checks for deferred deletion.
35 */
36void de_put(struct proc_dir_entry *de)
37{
38 if (!atomic_read(&de->count)) {
39 printk("de_put: entry %s already free!\n", de->name);
40 return;
41 }
42
43 if (atomic_dec_and_test(&de->count))
44 free_proc_entry(de);
45}
46
47/*
48 * Decrement the use count of the proc_dir_entry.
49 */
50static void proc_delete_inode(struct inode *inode) 28static void proc_delete_inode(struct inode *inode)
51{ 29{
52 struct proc_dir_entry *de; 30 struct proc_dir_entry *de;
@@ -59,7 +37,7 @@ static void proc_delete_inode(struct inode *inode)
59 /* Let go of any associated proc directory entry */ 37 /* Let go of any associated proc directory entry */
60 de = PROC_I(inode)->pde; 38 de = PROC_I(inode)->pde;
61 if (de) 39 if (de)
62 de_put(de); 40 pde_put(de);
63 if (PROC_I(inode)->sysctl) 41 if (PROC_I(inode)->sysctl)
64 sysctl_head_put(PROC_I(inode)->sysctl); 42 sysctl_head_put(PROC_I(inode)->sysctl);
65 clear_inode(inode); 43 clear_inode(inode);
@@ -480,7 +458,7 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino,
480 } 458 }
481 unlock_new_inode(inode); 459 unlock_new_inode(inode);
482 } else 460 } else
483 de_put(de); 461 pde_put(de);
484 return inode; 462 return inode;
485} 463}
486 464
@@ -495,7 +473,7 @@ int proc_fill_super(struct super_block *s)
495 s->s_op = &proc_sops; 473 s->s_op = &proc_sops;
496 s->s_time_gran = 1; 474 s->s_time_gran = 1;
497 475
498 de_get(&proc_root); 476 pde_get(&proc_root);
499 root_inode = proc_get_inode(s, PROC_ROOT_INO, &proc_root); 477 root_inode = proc_get_inode(s, PROC_ROOT_INO, &proc_root);
500 if (!root_inode) 478 if (!root_inode)
501 goto out_no_root; 479 goto out_no_root;
@@ -509,6 +487,6 @@ int proc_fill_super(struct super_block *s)
509out_no_root: 487out_no_root:
510 printk("proc_read_super: get root inode failed\n"); 488 printk("proc_read_super: get root inode failed\n");
511 iput(root_inode); 489 iput(root_inode);
512 de_put(&proc_root); 490 pde_put(&proc_root);
513 return -ENOMEM; 491 return -ENOMEM;
514} 492}
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 753ca37002c8..1f24a3eddd12 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -61,8 +61,6 @@ extern const struct file_operations proc_pagemap_operations;
61extern const struct file_operations proc_net_operations; 61extern const struct file_operations proc_net_operations;
62extern const struct inode_operations proc_net_inode_operations; 62extern const struct inode_operations proc_net_inode_operations;
63 63
64void free_proc_entry(struct proc_dir_entry *de);
65
66void proc_init_inodecache(void); 64void proc_init_inodecache(void);
67 65
68static inline struct pid *proc_pid(struct inode *inode) 66static inline struct pid *proc_pid(struct inode *inode)
@@ -101,8 +99,12 @@ unsigned long task_vsize(struct mm_struct *);
101int task_statm(struct mm_struct *, int *, int *, int *, int *); 99int task_statm(struct mm_struct *, int *, int *, int *, int *);
102void task_mem(struct seq_file *, struct mm_struct *); 100void task_mem(struct seq_file *, struct mm_struct *);
103 101
104struct proc_dir_entry *de_get(struct proc_dir_entry *de); 102static inline struct proc_dir_entry *pde_get(struct proc_dir_entry *pde)
105void de_put(struct proc_dir_entry *de); 103{
104 atomic_inc(&pde->count);
105 return pde;
106}
107void pde_put(struct proc_dir_entry *pde);
106 108
107extern struct vfsmount *proc_mnt; 109extern struct vfsmount *proc_mnt;
108int proc_fill_super(struct super_block *); 110int proc_fill_super(struct super_block *);
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
index a44a7897fd4d..19979a2ce272 100644
--- a/fs/proc/kcore.c
+++ b/fs/proc/kcore.c
@@ -19,6 +19,7 @@
19#include <linux/highmem.h> 19#include <linux/highmem.h>
20#include <linux/bootmem.h> 20#include <linux/bootmem.h>
21#include <linux/init.h> 21#include <linux/init.h>
22#include <linux/slab.h>
22#include <asm/uaccess.h> 23#include <asm/uaccess.h>
23#include <asm/io.h> 24#include <asm/io.h>
24#include <linux/list.h> 25#include <linux/list.h>
@@ -490,7 +491,7 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
490 } 491 }
491 read_unlock(&kclist_lock); 492 read_unlock(&kclist_lock);
492 493
493 if (m == NULL) { 494 if (&m->list == &kclist_head) {
494 if (clear_user(buffer, tsz)) 495 if (clear_user(buffer, tsz))
495 return -EFAULT; 496 return -EFAULT;
496 } else if (is_vmalloc_or_module_addr((void *)start)) { 497 } else if (is_vmalloc_or_module_addr((void *)start)) {
diff --git a/fs/proc/kmsg.c b/fs/proc/kmsg.c
index 7ca78346d3f0..cfe90a48a6e8 100644
--- a/fs/proc/kmsg.c
+++ b/fs/proc/kmsg.c
@@ -12,37 +12,37 @@
12#include <linux/poll.h> 12#include <linux/poll.h>
13#include <linux/proc_fs.h> 13#include <linux/proc_fs.h>
14#include <linux/fs.h> 14#include <linux/fs.h>
15#include <linux/syslog.h>
15 16
16#include <asm/uaccess.h> 17#include <asm/uaccess.h>
17#include <asm/io.h> 18#include <asm/io.h>
18 19
19extern wait_queue_head_t log_wait; 20extern wait_queue_head_t log_wait;
20 21
21extern int do_syslog(int type, char __user *bug, int count);
22
23static int kmsg_open(struct inode * inode, struct file * file) 22static int kmsg_open(struct inode * inode, struct file * file)
24{ 23{
25 return do_syslog(1,NULL,0); 24 return do_syslog(SYSLOG_ACTION_OPEN, NULL, 0, SYSLOG_FROM_FILE);
26} 25}
27 26
28static int kmsg_release(struct inode * inode, struct file * file) 27static int kmsg_release(struct inode * inode, struct file * file)
29{ 28{
30 (void) do_syslog(0,NULL,0); 29 (void) do_syslog(SYSLOG_ACTION_CLOSE, NULL, 0, SYSLOG_FROM_FILE);
31 return 0; 30 return 0;
32} 31}
33 32
34static ssize_t kmsg_read(struct file *file, char __user *buf, 33static ssize_t kmsg_read(struct file *file, char __user *buf,
35 size_t count, loff_t *ppos) 34 size_t count, loff_t *ppos)
36{ 35{
37 if ((file->f_flags & O_NONBLOCK) && !do_syslog(9, NULL, 0)) 36 if ((file->f_flags & O_NONBLOCK) &&
37 !do_syslog(SYSLOG_ACTION_SIZE_UNREAD, NULL, 0, SYSLOG_FROM_FILE))
38 return -EAGAIN; 38 return -EAGAIN;
39 return do_syslog(2, buf, count); 39 return do_syslog(SYSLOG_ACTION_READ, buf, count, SYSLOG_FROM_FILE);
40} 40}
41 41
42static unsigned int kmsg_poll(struct file *file, poll_table *wait) 42static unsigned int kmsg_poll(struct file *file, poll_table *wait)
43{ 43{
44 poll_wait(file, &log_wait, wait); 44 poll_wait(file, &log_wait, wait);
45 if (do_syslog(9, NULL, 0)) 45 if (do_syslog(SYSLOG_ACTION_SIZE_UNREAD, NULL, 0, SYSLOG_FROM_FILE))
46 return POLLIN | POLLRDNORM; 46 return POLLIN | POLLRDNORM;
47 return 0; 47 return 0;
48} 48}
diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c
index 9fe7d7ebe115..b1822dde55c2 100644
--- a/fs/proc/nommu.c
+++ b/fs/proc/nommu.c
@@ -21,7 +21,6 @@
21#include <linux/mmzone.h> 21#include <linux/mmzone.h>
22#include <linux/pagemap.h> 22#include <linux/pagemap.h>
23#include <linux/swap.h> 23#include <linux/swap.h>
24#include <linux/slab.h>
25#include <linux/smp.h> 24#include <linux/smp.h>
26#include <linux/seq_file.h> 25#include <linux/seq_file.h>
27#include <linux/hugetlb.h> 26#include <linux/hugetlb.h>
diff --git a/fs/proc/page.c b/fs/proc/page.c
index 5033ce0d254b..180cf5a0bd67 100644
--- a/fs/proc/page.c
+++ b/fs/proc/page.c
@@ -8,6 +8,7 @@
8#include <linux/proc_fs.h> 8#include <linux/proc_fs.h>
9#include <linux/seq_file.h> 9#include <linux/seq_file.h>
10#include <linux/hugetlb.h> 10#include <linux/hugetlb.h>
11#include <linux/kernel-page-flags.h>
11#include <asm/uaccess.h> 12#include <asm/uaccess.h>
12#include "internal.h" 13#include "internal.h"
13 14
@@ -71,52 +72,12 @@ static const struct file_operations proc_kpagecount_operations = {
71 * physical page flags. 72 * physical page flags.
72 */ 73 */
73 74
74/* These macros are used to decouple internal flags from exported ones */
75
76#define KPF_LOCKED 0
77#define KPF_ERROR 1
78#define KPF_REFERENCED 2
79#define KPF_UPTODATE 3
80#define KPF_DIRTY 4
81#define KPF_LRU 5
82#define KPF_ACTIVE 6
83#define KPF_SLAB 7
84#define KPF_WRITEBACK 8
85#define KPF_RECLAIM 9
86#define KPF_BUDDY 10
87
88/* 11-20: new additions in 2.6.31 */
89#define KPF_MMAP 11
90#define KPF_ANON 12
91#define KPF_SWAPCACHE 13
92#define KPF_SWAPBACKED 14
93#define KPF_COMPOUND_HEAD 15
94#define KPF_COMPOUND_TAIL 16
95#define KPF_HUGE 17
96#define KPF_UNEVICTABLE 18
97#define KPF_HWPOISON 19
98#define KPF_NOPAGE 20
99
100#define KPF_KSM 21
101
102/* kernel hacking assistances
103 * WARNING: subject to change, never rely on them!
104 */
105#define KPF_RESERVED 32
106#define KPF_MLOCKED 33
107#define KPF_MAPPEDTODISK 34
108#define KPF_PRIVATE 35
109#define KPF_PRIVATE_2 36
110#define KPF_OWNER_PRIVATE 37
111#define KPF_ARCH 38
112#define KPF_UNCACHED 39
113
114static inline u64 kpf_copy_bit(u64 kflags, int ubit, int kbit) 75static inline u64 kpf_copy_bit(u64 kflags, int ubit, int kbit)
115{ 76{
116 return ((kflags >> kbit) & 1) << ubit; 77 return ((kflags >> kbit) & 1) << ubit;
117} 78}
118 79
119static u64 get_uflags(struct page *page) 80u64 stable_page_flags(struct page *page)
120{ 81{
121 u64 k; 82 u64 k;
122 u64 u; 83 u64 u;
@@ -219,7 +180,7 @@ static ssize_t kpageflags_read(struct file *file, char __user *buf,
219 else 180 else
220 ppage = NULL; 181 ppage = NULL;
221 182
222 if (put_user(get_uflags(ppage), out)) { 183 if (put_user(stable_page_flags(ppage), out)) {
223 ret = -EFAULT; 184 ret = -EFAULT;
224 break; 185 break;
225 } 186 }
diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c
index 7ba79a54948c..ce94801f48ca 100644
--- a/fs/proc/proc_devtree.c
+++ b/fs/proc/proc_devtree.c
@@ -7,44 +7,50 @@
7#include <linux/init.h> 7#include <linux/init.h>
8#include <linux/time.h> 8#include <linux/time.h>
9#include <linux/proc_fs.h> 9#include <linux/proc_fs.h>
10#include <linux/seq_file.h>
10#include <linux/stat.h> 11#include <linux/stat.h>
11#include <linux/string.h> 12#include <linux/string.h>
13#include <linux/of.h>
14#include <linux/module.h>
15#include <linux/slab.h>
12#include <asm/prom.h> 16#include <asm/prom.h>
13#include <asm/uaccess.h> 17#include <asm/uaccess.h>
14#include "internal.h" 18#include "internal.h"
15 19
16#ifndef HAVE_ARCH_DEVTREE_FIXUPS
17static inline void set_node_proc_entry(struct device_node *np, 20static inline void set_node_proc_entry(struct device_node *np,
18 struct proc_dir_entry *de) 21 struct proc_dir_entry *de)
19{ 22{
20} 23#ifdef HAVE_ARCH_DEVTREE_FIXUPS
24 np->pde = de;
21#endif 25#endif
26}
22 27
23static struct proc_dir_entry *proc_device_tree; 28static struct proc_dir_entry *proc_device_tree;
24 29
25/* 30/*
26 * Supply data on a read from /proc/device-tree/node/property. 31 * Supply data on a read from /proc/device-tree/node/property.
27 */ 32 */
28static int property_read_proc(char *page, char **start, off_t off, 33static int property_proc_show(struct seq_file *m, void *v)
29 int count, int *eof, void *data)
30{ 34{
31 struct property *pp = data; 35 struct property *pp = m->private;
32 int n;
33 36
34 if (off >= pp->length) { 37 seq_write(m, pp->value, pp->length);
35 *eof = 1; 38 return 0;
36 return 0;
37 }
38 n = pp->length - off;
39 if (n > count)
40 n = count;
41 else
42 *eof = 1;
43 memcpy(page, (char *)pp->value + off, n);
44 *start = page;
45 return n;
46} 39}
47 40
41static int property_proc_open(struct inode *inode, struct file *file)
42{
43 return single_open(file, property_proc_show, PDE(inode)->data);
44}
45
46static const struct file_operations property_proc_fops = {
47 .owner = THIS_MODULE,
48 .open = property_proc_open,
49 .read = seq_read,
50 .llseek = seq_lseek,
51 .release = single_release,
52};
53
48/* 54/*
49 * For a node with a name like "gc@10", we make symlinks called "gc" 55 * For a node with a name like "gc@10", we make symlinks called "gc"
50 * and "@10" to it. 56 * and "@10" to it.
@@ -63,10 +69,9 @@ __proc_device_tree_add_prop(struct proc_dir_entry *de, struct property *pp,
63 * Unfortunately proc_register puts each new entry 69 * Unfortunately proc_register puts each new entry
64 * at the beginning of the list. So we rearrange them. 70 * at the beginning of the list. So we rearrange them.
65 */ 71 */
66 ent = create_proc_read_entry(name, 72 ent = proc_create_data(name,
67 strncmp(name, "security-", 9) 73 strncmp(name, "security-", 9) ? S_IRUGO : S_IRUSR,
68 ? S_IRUGO : S_IRUSR, de, 74 de, &property_proc_fops, pp);
69 property_read_proc, pp);
70 if (ent == NULL) 75 if (ent == NULL)
71 return NULL; 76 return NULL;
72 77
diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c
index 04d1270f1c38..9020ac15baaa 100644
--- a/fs/proc/proc_net.c
+++ b/fs/proc/proc_net.c
@@ -14,6 +14,7 @@
14#include <linux/time.h> 14#include <linux/time.h>
15#include <linux/proc_fs.h> 15#include <linux/proc_fs.h>
16#include <linux/stat.h> 16#include <linux/stat.h>
17#include <linux/slab.h>
17#include <linux/init.h> 18#include <linux/init.h>
18#include <linux/sched.h> 19#include <linux/sched.h>
19#include <linux/module.h> 20#include <linux/module.h>
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index f667e8aeabdf..6ff9981f0a18 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -48,7 +48,7 @@ out:
48static struct ctl_table *find_in_table(struct ctl_table *p, struct qstr *name) 48static struct ctl_table *find_in_table(struct ctl_table *p, struct qstr *name)
49{ 49{
50 int len; 50 int len;
51 for ( ; p->ctl_name || p->procname; p++) { 51 for ( ; p->procname; p++) {
52 52
53 if (!p->procname) 53 if (!p->procname)
54 continue; 54 continue;
@@ -218,7 +218,7 @@ static int scan(struct ctl_table_header *head, ctl_table *table,
218 void *dirent, filldir_t filldir) 218 void *dirent, filldir_t filldir)
219{ 219{
220 220
221 for (; table->ctl_name || table->procname; table++, (*pos)++) { 221 for (; table->procname; table++, (*pos)++) {
222 int res; 222 int res;
223 223
224 /* Can't do anything without a proc name */ 224 /* Can't do anything without a proc name */
diff --git a/fs/proc/root.c b/fs/proc/root.c
index b080b791d9e3..757c069f2a65 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -220,9 +220,3 @@ void pid_ns_release_proc(struct pid_namespace *ns)
220{ 220{
221 mntput(ns->proc_mnt); 221 mntput(ns->proc_mnt);
222} 222}
223
224EXPORT_SYMBOL(proc_symlink);
225EXPORT_SYMBOL(proc_mkdir);
226EXPORT_SYMBOL(create_proc_entry);
227EXPORT_SYMBOL(proc_create_data);
228EXPORT_SYMBOL(remove_proc_entry);
diff --git a/fs/proc/stat.c b/fs/proc/stat.c
index 7cc726c6d70a..bf31b03fc275 100644
--- a/fs/proc/stat.c
+++ b/fs/proc/stat.c
@@ -1,6 +1,5 @@
1#include <linux/cpumask.h> 1#include <linux/cpumask.h>
2#include <linux/fs.h> 2#include <linux/fs.h>
3#include <linux/gfp.h>
4#include <linux/init.h> 3#include <linux/init.h>
5#include <linux/interrupt.h> 4#include <linux/interrupt.h>
6#include <linux/kernel_stat.h> 5#include <linux/kernel_stat.h>
@@ -27,7 +26,7 @@ static int show_stat(struct seq_file *p, void *v)
27 int i, j; 26 int i, j;
28 unsigned long jif; 27 unsigned long jif;
29 cputime64_t user, nice, system, idle, iowait, irq, softirq, steal; 28 cputime64_t user, nice, system, idle, iowait, irq, softirq, steal;
30 cputime64_t guest; 29 cputime64_t guest, guest_nice;
31 u64 sum = 0; 30 u64 sum = 0;
32 u64 sum_softirq = 0; 31 u64 sum_softirq = 0;
33 unsigned int per_softirq_sums[NR_SOFTIRQS] = {0}; 32 unsigned int per_softirq_sums[NR_SOFTIRQS] = {0};
@@ -36,7 +35,7 @@ static int show_stat(struct seq_file *p, void *v)
36 35
37 user = nice = system = idle = iowait = 36 user = nice = system = idle = iowait =
38 irq = softirq = steal = cputime64_zero; 37 irq = softirq = steal = cputime64_zero;
39 guest = cputime64_zero; 38 guest = guest_nice = cputime64_zero;
40 getboottime(&boottime); 39 getboottime(&boottime);
41 jif = boottime.tv_sec; 40 jif = boottime.tv_sec;
42 41
@@ -51,6 +50,8 @@ static int show_stat(struct seq_file *p, void *v)
51 softirq = cputime64_add(softirq, kstat_cpu(i).cpustat.softirq); 50 softirq = cputime64_add(softirq, kstat_cpu(i).cpustat.softirq);
52 steal = cputime64_add(steal, kstat_cpu(i).cpustat.steal); 51 steal = cputime64_add(steal, kstat_cpu(i).cpustat.steal);
53 guest = cputime64_add(guest, kstat_cpu(i).cpustat.guest); 52 guest = cputime64_add(guest, kstat_cpu(i).cpustat.guest);
53 guest_nice = cputime64_add(guest_nice,
54 kstat_cpu(i).cpustat.guest_nice);
54 for_each_irq_nr(j) { 55 for_each_irq_nr(j) {
55 sum += kstat_irqs_cpu(j, i); 56 sum += kstat_irqs_cpu(j, i);
56 } 57 }
@@ -65,7 +66,8 @@ static int show_stat(struct seq_file *p, void *v)
65 } 66 }
66 sum += arch_irq_stat(); 67 sum += arch_irq_stat();
67 68
68 seq_printf(p, "cpu %llu %llu %llu %llu %llu %llu %llu %llu %llu\n", 69 seq_printf(p, "cpu %llu %llu %llu %llu %llu %llu %llu %llu %llu "
70 "%llu\n",
69 (unsigned long long)cputime64_to_clock_t(user), 71 (unsigned long long)cputime64_to_clock_t(user),
70 (unsigned long long)cputime64_to_clock_t(nice), 72 (unsigned long long)cputime64_to_clock_t(nice),
71 (unsigned long long)cputime64_to_clock_t(system), 73 (unsigned long long)cputime64_to_clock_t(system),
@@ -74,7 +76,8 @@ static int show_stat(struct seq_file *p, void *v)
74 (unsigned long long)cputime64_to_clock_t(irq), 76 (unsigned long long)cputime64_to_clock_t(irq),
75 (unsigned long long)cputime64_to_clock_t(softirq), 77 (unsigned long long)cputime64_to_clock_t(softirq),
76 (unsigned long long)cputime64_to_clock_t(steal), 78 (unsigned long long)cputime64_to_clock_t(steal),
77 (unsigned long long)cputime64_to_clock_t(guest)); 79 (unsigned long long)cputime64_to_clock_t(guest),
80 (unsigned long long)cputime64_to_clock_t(guest_nice));
78 for_each_online_cpu(i) { 81 for_each_online_cpu(i) {
79 82
80 /* Copy values here to work around gcc-2.95.3, gcc-2.96 */ 83 /* Copy values here to work around gcc-2.95.3, gcc-2.96 */
@@ -88,8 +91,10 @@ static int show_stat(struct seq_file *p, void *v)
88 softirq = kstat_cpu(i).cpustat.softirq; 91 softirq = kstat_cpu(i).cpustat.softirq;
89 steal = kstat_cpu(i).cpustat.steal; 92 steal = kstat_cpu(i).cpustat.steal;
90 guest = kstat_cpu(i).cpustat.guest; 93 guest = kstat_cpu(i).cpustat.guest;
94 guest_nice = kstat_cpu(i).cpustat.guest_nice;
91 seq_printf(p, 95 seq_printf(p,
92 "cpu%d %llu %llu %llu %llu %llu %llu %llu %llu %llu\n", 96 "cpu%d %llu %llu %llu %llu %llu %llu %llu %llu %llu "
97 "%llu\n",
93 i, 98 i,
94 (unsigned long long)cputime64_to_clock_t(user), 99 (unsigned long long)cputime64_to_clock_t(user),
95 (unsigned long long)cputime64_to_clock_t(nice), 100 (unsigned long long)cputime64_to_clock_t(nice),
@@ -99,7 +104,8 @@ static int show_stat(struct seq_file *p, void *v)
99 (unsigned long long)cputime64_to_clock_t(irq), 104 (unsigned long long)cputime64_to_clock_t(irq),
100 (unsigned long long)cputime64_to_clock_t(softirq), 105 (unsigned long long)cputime64_to_clock_t(softirq),
101 (unsigned long long)cputime64_to_clock_t(steal), 106 (unsigned long long)cputime64_to_clock_t(steal),
102 (unsigned long long)cputime64_to_clock_t(guest)); 107 (unsigned long long)cputime64_to_clock_t(guest),
108 (unsigned long long)cputime64_to_clock_t(guest_nice));
103 } 109 }
104 seq_printf(p, "intr %llu", (unsigned long long)sum); 110 seq_printf(p, "intr %llu", (unsigned long long)sum);
105 111
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 2a1bef9203c6..47f5b145f56e 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -4,6 +4,7 @@
4#include <linux/seq_file.h> 4#include <linux/seq_file.h>
5#include <linux/highmem.h> 5#include <linux/highmem.h>
6#include <linux/ptrace.h> 6#include <linux/ptrace.h>
7#include <linux/slab.h>
7#include <linux/pagemap.h> 8#include <linux/pagemap.h>
8#include <linux/mempolicy.h> 9#include <linux/mempolicy.h>
9#include <linux/swap.h> 10#include <linux/swap.h>
@@ -16,7 +17,7 @@
16 17
17void task_mem(struct seq_file *m, struct mm_struct *mm) 18void task_mem(struct seq_file *m, struct mm_struct *mm)
18{ 19{
19 unsigned long data, text, lib; 20 unsigned long data, text, lib, swap;
20 unsigned long hiwater_vm, total_vm, hiwater_rss, total_rss; 21 unsigned long hiwater_vm, total_vm, hiwater_rss, total_rss;
21 22
22 /* 23 /*
@@ -36,6 +37,7 @@ void task_mem(struct seq_file *m, struct mm_struct *mm)
36 data = mm->total_vm - mm->shared_vm - mm->stack_vm; 37 data = mm->total_vm - mm->shared_vm - mm->stack_vm;
37 text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK)) >> 10; 38 text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK)) >> 10;
38 lib = (mm->exec_vm << (PAGE_SHIFT-10)) - text; 39 lib = (mm->exec_vm << (PAGE_SHIFT-10)) - text;
40 swap = get_mm_counter(mm, MM_SWAPENTS);
39 seq_printf(m, 41 seq_printf(m,
40 "VmPeak:\t%8lu kB\n" 42 "VmPeak:\t%8lu kB\n"
41 "VmSize:\t%8lu kB\n" 43 "VmSize:\t%8lu kB\n"
@@ -46,7 +48,8 @@ void task_mem(struct seq_file *m, struct mm_struct *mm)
46 "VmStk:\t%8lu kB\n" 48 "VmStk:\t%8lu kB\n"
47 "VmExe:\t%8lu kB\n" 49 "VmExe:\t%8lu kB\n"
48 "VmLib:\t%8lu kB\n" 50 "VmLib:\t%8lu kB\n"
49 "VmPTE:\t%8lu kB\n", 51 "VmPTE:\t%8lu kB\n"
52 "VmSwap:\t%8lu kB\n",
50 hiwater_vm << (PAGE_SHIFT-10), 53 hiwater_vm << (PAGE_SHIFT-10),
51 (total_vm - mm->reserved_vm) << (PAGE_SHIFT-10), 54 (total_vm - mm->reserved_vm) << (PAGE_SHIFT-10),
52 mm->locked_vm << (PAGE_SHIFT-10), 55 mm->locked_vm << (PAGE_SHIFT-10),
@@ -54,7 +57,8 @@ void task_mem(struct seq_file *m, struct mm_struct *mm)
54 total_rss << (PAGE_SHIFT-10), 57 total_rss << (PAGE_SHIFT-10),
55 data << (PAGE_SHIFT-10), 58 data << (PAGE_SHIFT-10),
56 mm->stack_vm << (PAGE_SHIFT-10), text, lib, 59 mm->stack_vm << (PAGE_SHIFT-10), text, lib,
57 (PTRS_PER_PTE*sizeof(pte_t)*mm->nr_ptes) >> 10); 60 (PTRS_PER_PTE*sizeof(pte_t)*mm->nr_ptes) >> 10,
61 swap << (PAGE_SHIFT-10));
58} 62}
59 63
60unsigned long task_vsize(struct mm_struct *mm) 64unsigned long task_vsize(struct mm_struct *mm)
@@ -65,11 +69,11 @@ unsigned long task_vsize(struct mm_struct *mm)
65int task_statm(struct mm_struct *mm, int *shared, int *text, 69int task_statm(struct mm_struct *mm, int *shared, int *text,
66 int *data, int *resident) 70 int *data, int *resident)
67{ 71{
68 *shared = get_mm_counter(mm, file_rss); 72 *shared = get_mm_counter(mm, MM_FILEPAGES);
69 *text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK)) 73 *text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK))
70 >> PAGE_SHIFT; 74 >> PAGE_SHIFT;
71 *data = mm->total_vm - mm->shared_vm; 75 *data = mm->total_vm - mm->shared_vm;
72 *resident = *shared + get_mm_counter(mm, anon_rss); 76 *resident = *shared + get_mm_counter(mm, MM_ANONPAGES);
73 return mm->total_vm; 77 return mm->total_vm;
74} 78}
75 79
@@ -243,25 +247,6 @@ static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
243 } else if (vma->vm_start <= mm->start_stack && 247 } else if (vma->vm_start <= mm->start_stack &&
244 vma->vm_end >= mm->start_stack) { 248 vma->vm_end >= mm->start_stack) {
245 name = "[stack]"; 249 name = "[stack]";
246 } else {
247 unsigned long stack_start;
248 struct proc_maps_private *pmp;
249
250 pmp = m->private;
251 stack_start = pmp->task->stack_start;
252
253 if (vma->vm_start <= stack_start &&
254 vma->vm_end >= stack_start) {
255 pad_len_spaces(m, len);
256 seq_printf(m,
257 "[threadstack:%08lx]",
258#ifdef CONFIG_STACK_GROWSUP
259 vma->vm_end - stack_start
260#else
261 stack_start - vma->vm_start
262#endif
263 );
264 }
265 } 250 }
266 } else { 251 } else {
267 name = "[vdso]"; 252 name = "[vdso]";
@@ -361,12 +346,11 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
361 if (!pte_present(ptent)) 346 if (!pte_present(ptent))
362 continue; 347 continue;
363 348
364 mss->resident += PAGE_SIZE;
365
366 page = vm_normal_page(vma, addr, ptent); 349 page = vm_normal_page(vma, addr, ptent);
367 if (!page) 350 if (!page)
368 continue; 351 continue;
369 352
353 mss->resident += PAGE_SIZE;
370 /* Accumulate the size in pages that have been accessed. */ 354 /* Accumulate the size in pages that have been accessed. */
371 if (pte_young(ptent) || PageReferenced(page)) 355 if (pte_young(ptent) || PageReferenced(page))
372 mss->referenced += PAGE_SIZE; 356 mss->referenced += PAGE_SIZE;
@@ -404,6 +388,7 @@ static int show_smap(struct seq_file *m, void *v)
404 388
405 memset(&mss, 0, sizeof mss); 389 memset(&mss, 0, sizeof mss);
406 mss.vma = vma; 390 mss.vma = vma;
391 /* mmap_sem is held in m_start */
407 if (vma->vm_mm && !is_vm_hugetlb_page(vma)) 392 if (vma->vm_mm && !is_vm_hugetlb_page(vma))
408 walk_page_range(vma->vm_start, vma->vm_end, &smaps_walk); 393 walk_page_range(vma->vm_start, vma->vm_end, &smaps_walk);
409 394
@@ -550,7 +535,8 @@ const struct file_operations proc_clear_refs_operations = {
550}; 535};
551 536
552struct pagemapread { 537struct pagemapread {
553 u64 __user *out, *end; 538 int pos, len;
539 u64 *buffer;
554}; 540};
555 541
556#define PM_ENTRY_BYTES sizeof(u64) 542#define PM_ENTRY_BYTES sizeof(u64)
@@ -573,10 +559,8 @@ struct pagemapread {
573static int add_to_pagemap(unsigned long addr, u64 pfn, 559static int add_to_pagemap(unsigned long addr, u64 pfn,
574 struct pagemapread *pm) 560 struct pagemapread *pm)
575{ 561{
576 if (put_user(pfn, pm->out)) 562 pm->buffer[pm->pos++] = pfn;
577 return -EFAULT; 563 if (pm->pos >= pm->len)
578 pm->out++;
579 if (pm->out >= pm->end)
580 return PM_END_OF_BUFFER; 564 return PM_END_OF_BUFFER;
581 return 0; 565 return 0;
582} 566}
@@ -650,6 +634,37 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
650 return err; 634 return err;
651} 635}
652 636
637static u64 huge_pte_to_pagemap_entry(pte_t pte, int offset)
638{
639 u64 pme = 0;
640 if (pte_present(pte))
641 pme = PM_PFRAME(pte_pfn(pte) + offset)
642 | PM_PSHIFT(PAGE_SHIFT) | PM_PRESENT;
643 return pme;
644}
645
646/* This function walks within one hugetlb entry in the single call */
647static int pagemap_hugetlb_range(pte_t *pte, unsigned long hmask,
648 unsigned long addr, unsigned long end,
649 struct mm_walk *walk)
650{
651 struct pagemapread *pm = walk->private;
652 int err = 0;
653 u64 pfn;
654
655 for (; addr != end; addr += PAGE_SIZE) {
656 int offset = (addr & ~hmask) >> PAGE_SHIFT;
657 pfn = huge_pte_to_pagemap_entry(*pte, offset);
658 err = add_to_pagemap(addr, pfn, pm);
659 if (err)
660 return err;
661 }
662
663 cond_resched();
664
665 return err;
666}
667
653/* 668/*
654 * /proc/pid/pagemap - an array mapping virtual pages to pfns 669 * /proc/pid/pagemap - an array mapping virtual pages to pfns
655 * 670 *
@@ -674,21 +689,20 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
674 * determine which areas of memory are actually mapped and llseek to 689 * determine which areas of memory are actually mapped and llseek to
675 * skip over unmapped regions. 690 * skip over unmapped regions.
676 */ 691 */
692#define PAGEMAP_WALK_SIZE (PMD_SIZE)
677static ssize_t pagemap_read(struct file *file, char __user *buf, 693static ssize_t pagemap_read(struct file *file, char __user *buf,
678 size_t count, loff_t *ppos) 694 size_t count, loff_t *ppos)
679{ 695{
680 struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode); 696 struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
681 struct page **pages, *page;
682 unsigned long uaddr, uend;
683 struct mm_struct *mm; 697 struct mm_struct *mm;
684 struct pagemapread pm; 698 struct pagemapread pm;
685 int pagecount;
686 int ret = -ESRCH; 699 int ret = -ESRCH;
687 struct mm_walk pagemap_walk = {}; 700 struct mm_walk pagemap_walk = {};
688 unsigned long src; 701 unsigned long src;
689 unsigned long svpfn; 702 unsigned long svpfn;
690 unsigned long start_vaddr; 703 unsigned long start_vaddr;
691 unsigned long end_vaddr; 704 unsigned long end_vaddr;
705 int copied = 0;
692 706
693 if (!task) 707 if (!task)
694 goto out; 708 goto out;
@@ -711,37 +725,15 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
711 if (!mm) 725 if (!mm)
712 goto out_task; 726 goto out_task;
713 727
714 728 pm.len = PM_ENTRY_BYTES * (PAGEMAP_WALK_SIZE >> PAGE_SHIFT);
715 uaddr = (unsigned long)buf & PAGE_MASK; 729 pm.buffer = kmalloc(pm.len, GFP_TEMPORARY);
716 uend = (unsigned long)(buf + count);
717 pagecount = (PAGE_ALIGN(uend) - uaddr) / PAGE_SIZE;
718 ret = 0;
719 if (pagecount == 0)
720 goto out_mm;
721 pages = kcalloc(pagecount, sizeof(struct page *), GFP_KERNEL);
722 ret = -ENOMEM; 730 ret = -ENOMEM;
723 if (!pages) 731 if (!pm.buffer)
724 goto out_mm; 732 goto out_mm;
725 733
726 down_read(&current->mm->mmap_sem);
727 ret = get_user_pages(current, current->mm, uaddr, pagecount,
728 1, 0, pages, NULL);
729 up_read(&current->mm->mmap_sem);
730
731 if (ret < 0)
732 goto out_free;
733
734 if (ret != pagecount) {
735 pagecount = ret;
736 ret = -EFAULT;
737 goto out_pages;
738 }
739
740 pm.out = (u64 __user *)buf;
741 pm.end = (u64 __user *)(buf + count);
742
743 pagemap_walk.pmd_entry = pagemap_pte_range; 734 pagemap_walk.pmd_entry = pagemap_pte_range;
744 pagemap_walk.pte_hole = pagemap_pte_hole; 735 pagemap_walk.pte_hole = pagemap_pte_hole;
736 pagemap_walk.hugetlb_entry = pagemap_hugetlb_range;
745 pagemap_walk.mm = mm; 737 pagemap_walk.mm = mm;
746 pagemap_walk.private = &pm; 738 pagemap_walk.private = &pm;
747 739
@@ -760,23 +752,36 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
760 * user buffer is tracked in "pm", and the walk 752 * user buffer is tracked in "pm", and the walk
761 * will stop when we hit the end of the buffer. 753 * will stop when we hit the end of the buffer.
762 */ 754 */
763 ret = walk_page_range(start_vaddr, end_vaddr, &pagemap_walk); 755 ret = 0;
764 if (ret == PM_END_OF_BUFFER) 756 while (count && (start_vaddr < end_vaddr)) {
765 ret = 0; 757 int len;
766 /* don't need mmap_sem for these, but this looks cleaner */ 758 unsigned long end;
767 *ppos += (char __user *)pm.out - buf; 759
768 if (!ret) 760 pm.pos = 0;
769 ret = (char __user *)pm.out - buf; 761 end = start_vaddr + PAGEMAP_WALK_SIZE;
770 762 /* overflow ? */
771out_pages: 763 if (end < start_vaddr || end > end_vaddr)
772 for (; pagecount; pagecount--) { 764 end = end_vaddr;
773 page = pages[pagecount-1]; 765 down_read(&mm->mmap_sem);
774 if (!PageReserved(page)) 766 ret = walk_page_range(start_vaddr, end, &pagemap_walk);
775 SetPageDirty(page); 767 up_read(&mm->mmap_sem);
776 page_cache_release(page); 768 start_vaddr = end;
769
770 len = min(count, PM_ENTRY_BYTES * pm.pos);
771 if (copy_to_user(buf, pm.buffer, len)) {
772 ret = -EFAULT;
773 goto out_free;
774 }
775 copied += len;
776 buf += len;
777 count -= len;
777 } 778 }
779 *ppos += copied;
780 if (!ret || ret == PM_END_OF_BUFFER)
781 ret = copied;
782
778out_free: 783out_free:
779 kfree(pages); 784 kfree(pm.buffer);
780out_mm: 785out_mm:
781 mmput(mm); 786 mmput(mm);
782out_task: 787out_task:
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
index 8f5c05d3dbd3..46d4b5d72bd3 100644
--- a/fs/proc/task_nommu.c
+++ b/fs/proc/task_nommu.c
@@ -5,6 +5,7 @@
5#include <linux/fs_struct.h> 5#include <linux/fs_struct.h>
6#include <linux/mount.h> 6#include <linux/mount.h>
7#include <linux/ptrace.h> 7#include <linux/ptrace.h>
8#include <linux/slab.h>
8#include <linux/seq_file.h> 9#include <linux/seq_file.h>
9#include "internal.h" 10#include "internal.h"
10 11
@@ -110,9 +111,13 @@ int task_statm(struct mm_struct *mm, int *shared, int *text,
110 } 111 }
111 } 112 }
112 113
113 size += (*text = mm->end_code - mm->start_code); 114 *text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK))
114 size += (*data = mm->start_stack - mm->start_data); 115 >> PAGE_SHIFT;
116 *data = (PAGE_ALIGN(mm->start_stack) - (mm->start_data & PAGE_MASK))
117 >> PAGE_SHIFT;
115 up_read(&mm->mmap_sem); 118 up_read(&mm->mmap_sem);
119 size >>= PAGE_SHIFT;
120 size += *text + *data;
116 *resident = size; 121 *resident = size;
117 return size; 122 return size;
118} 123}
diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c
index 0872afa58d39..9fbc99ec799a 100644
--- a/fs/proc/vmcore.c
+++ b/fs/proc/vmcore.c
@@ -12,6 +12,7 @@
12#include <linux/user.h> 12#include <linux/user.h>
13#include <linux/elf.h> 13#include <linux/elf.h>
14#include <linux/elfcore.h> 14#include <linux/elfcore.h>
15#include <linux/slab.h>
15#include <linux/highmem.h> 16#include <linux/highmem.h>
16#include <linux/bootmem.h> 17#include <linux/bootmem.h>
17#include <linux/init.h> 18#include <linux/init.h>