diff options
Diffstat (limited to 'fs/proc')
-rw-r--r-- | fs/proc/array.c | 4 | ||||
-rw-r--r-- | fs/proc/base.c | 51 | ||||
-rw-r--r-- | fs/proc/generic.c | 37 | ||||
-rw-r--r-- | fs/proc/internal.h | 2 | ||||
-rw-r--r-- | fs/proc/root.c | 2 |
5 files changed, 32 insertions, 64 deletions
diff --git a/fs/proc/array.c b/fs/proc/array.c index eba339ecba27..65c62e1bfd6f 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c | |||
@@ -374,7 +374,9 @@ static cputime_t task_stime(struct task_struct *p) | |||
374 | stime = nsec_to_clock_t(p->se.sum_exec_runtime) - | 374 | stime = nsec_to_clock_t(p->se.sum_exec_runtime) - |
375 | cputime_to_clock_t(task_utime(p)); | 375 | cputime_to_clock_t(task_utime(p)); |
376 | 376 | ||
377 | p->prev_stime = max(p->prev_stime, clock_t_to_cputime(stime)); | 377 | if (stime >= 0) |
378 | p->prev_stime = max(p->prev_stime, clock_t_to_cputime(stime)); | ||
379 | |||
378 | return p->prev_stime; | 380 | return p->prev_stime; |
379 | } | 381 | } |
380 | #endif | 382 | #endif |
diff --git a/fs/proc/base.c b/fs/proc/base.c index a17c26859074..02a63ac04178 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -2411,19 +2411,23 @@ out: | |||
2411 | * Find the first task with tgid >= tgid | 2411 | * Find the first task with tgid >= tgid |
2412 | * | 2412 | * |
2413 | */ | 2413 | */ |
2414 | static struct task_struct *next_tgid(unsigned int tgid, | 2414 | struct tgid_iter { |
2415 | struct pid_namespace *ns) | 2415 | unsigned int tgid; |
2416 | { | ||
2417 | struct task_struct *task; | 2416 | struct task_struct *task; |
2417 | }; | ||
2418 | static struct tgid_iter next_tgid(struct pid_namespace *ns, struct tgid_iter iter) | ||
2419 | { | ||
2418 | struct pid *pid; | 2420 | struct pid *pid; |
2419 | 2421 | ||
2422 | if (iter.task) | ||
2423 | put_task_struct(iter.task); | ||
2420 | rcu_read_lock(); | 2424 | rcu_read_lock(); |
2421 | retry: | 2425 | retry: |
2422 | task = NULL; | 2426 | iter.task = NULL; |
2423 | pid = find_ge_pid(tgid, ns); | 2427 | pid = find_ge_pid(iter.tgid, ns); |
2424 | if (pid) { | 2428 | if (pid) { |
2425 | tgid = pid_nr_ns(pid, ns) + 1; | 2429 | iter.tgid = pid_nr_ns(pid, ns); |
2426 | task = pid_task(pid, PIDTYPE_PID); | 2430 | iter.task = pid_task(pid, PIDTYPE_PID); |
2427 | /* What we to know is if the pid we have find is the | 2431 | /* What we to know is if the pid we have find is the |
2428 | * pid of a thread_group_leader. Testing for task | 2432 | * pid of a thread_group_leader. Testing for task |
2429 | * being a thread_group_leader is the obvious thing | 2433 | * being a thread_group_leader is the obvious thing |
@@ -2436,23 +2440,25 @@ retry: | |||
2436 | * found doesn't happen to be a thread group leader. | 2440 | * found doesn't happen to be a thread group leader. |
2437 | * As we don't care in the case of readdir. | 2441 | * As we don't care in the case of readdir. |
2438 | */ | 2442 | */ |
2439 | if (!task || !has_group_leader_pid(task)) | 2443 | if (!iter.task || !has_group_leader_pid(iter.task)) { |
2444 | iter.tgid += 1; | ||
2440 | goto retry; | 2445 | goto retry; |
2441 | get_task_struct(task); | 2446 | } |
2447 | get_task_struct(iter.task); | ||
2442 | } | 2448 | } |
2443 | rcu_read_unlock(); | 2449 | rcu_read_unlock(); |
2444 | return task; | 2450 | return iter; |
2445 | } | 2451 | } |
2446 | 2452 | ||
2447 | #define TGID_OFFSET (FIRST_PROCESS_ENTRY + ARRAY_SIZE(proc_base_stuff)) | 2453 | #define TGID_OFFSET (FIRST_PROCESS_ENTRY + ARRAY_SIZE(proc_base_stuff)) |
2448 | 2454 | ||
2449 | static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | 2455 | static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldir, |
2450 | struct task_struct *task, int tgid) | 2456 | struct tgid_iter iter) |
2451 | { | 2457 | { |
2452 | char name[PROC_NUMBUF]; | 2458 | char name[PROC_NUMBUF]; |
2453 | int len = snprintf(name, sizeof(name), "%d", tgid); | 2459 | int len = snprintf(name, sizeof(name), "%d", iter.tgid); |
2454 | return proc_fill_cache(filp, dirent, filldir, name, len, | 2460 | return proc_fill_cache(filp, dirent, filldir, name, len, |
2455 | proc_pid_instantiate, task, NULL); | 2461 | proc_pid_instantiate, iter.task, NULL); |
2456 | } | 2462 | } |
2457 | 2463 | ||
2458 | /* for the /proc/ directory itself, after non-process stuff has been done */ | 2464 | /* for the /proc/ directory itself, after non-process stuff has been done */ |
@@ -2460,8 +2466,7 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
2460 | { | 2466 | { |
2461 | unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY; | 2467 | unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY; |
2462 | struct task_struct *reaper = get_proc_task(filp->f_path.dentry->d_inode); | 2468 | struct task_struct *reaper = get_proc_task(filp->f_path.dentry->d_inode); |
2463 | struct task_struct *task; | 2469 | struct tgid_iter iter; |
2464 | int tgid; | ||
2465 | struct pid_namespace *ns; | 2470 | struct pid_namespace *ns; |
2466 | 2471 | ||
2467 | if (!reaper) | 2472 | if (!reaper) |
@@ -2474,14 +2479,14 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
2474 | } | 2479 | } |
2475 | 2480 | ||
2476 | ns = filp->f_dentry->d_sb->s_fs_info; | 2481 | ns = filp->f_dentry->d_sb->s_fs_info; |
2477 | tgid = filp->f_pos - TGID_OFFSET; | 2482 | iter.task = NULL; |
2478 | for (task = next_tgid(tgid, ns); | 2483 | iter.tgid = filp->f_pos - TGID_OFFSET; |
2479 | task; | 2484 | for (iter = next_tgid(ns, iter); |
2480 | put_task_struct(task), task = next_tgid(tgid + 1, ns)) { | 2485 | iter.task; |
2481 | tgid = task_pid_nr_ns(task, ns); | 2486 | iter.tgid += 1, iter = next_tgid(ns, iter)) { |
2482 | filp->f_pos = tgid + TGID_OFFSET; | 2487 | filp->f_pos = iter.tgid + TGID_OFFSET; |
2483 | if (proc_pid_fill_cache(filp, dirent, filldir, task, tgid) < 0) { | 2488 | if (proc_pid_fill_cache(filp, dirent, filldir, iter) < 0) { |
2484 | put_task_struct(task); | 2489 | put_task_struct(iter.task); |
2485 | goto out; | 2490 | goto out; |
2486 | } | 2491 | } |
2487 | } | 2492 | } |
diff --git a/fs/proc/generic.c b/fs/proc/generic.c index c2b752341f89..5fccfe222a63 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c | |||
@@ -565,41 +565,6 @@ static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp | |||
565 | return 0; | 565 | return 0; |
566 | } | 566 | } |
567 | 567 | ||
568 | /* | ||
569 | * Kill an inode that got unregistered.. | ||
570 | */ | ||
571 | static void proc_kill_inodes(struct proc_dir_entry *de) | ||
572 | { | ||
573 | struct list_head *p; | ||
574 | struct super_block *sb; | ||
575 | |||
576 | /* | ||
577 | * Actually it's a partial revoke(). | ||
578 | */ | ||
579 | spin_lock(&sb_lock); | ||
580 | list_for_each_entry(sb, &proc_fs_type.fs_supers, s_instances) { | ||
581 | file_list_lock(); | ||
582 | list_for_each(p, &sb->s_files) { | ||
583 | struct file *filp = list_entry(p, struct file, | ||
584 | f_u.fu_list); | ||
585 | struct dentry *dentry = filp->f_path.dentry; | ||
586 | struct inode *inode; | ||
587 | const struct file_operations *fops; | ||
588 | |||
589 | if (dentry->d_op != &proc_dentry_operations) | ||
590 | continue; | ||
591 | inode = dentry->d_inode; | ||
592 | if (PDE(inode) != de) | ||
593 | continue; | ||
594 | fops = filp->f_op; | ||
595 | filp->f_op = NULL; | ||
596 | fops_put(fops); | ||
597 | } | ||
598 | file_list_unlock(); | ||
599 | } | ||
600 | spin_unlock(&sb_lock); | ||
601 | } | ||
602 | |||
603 | static struct proc_dir_entry *proc_create(struct proc_dir_entry **parent, | 568 | static struct proc_dir_entry *proc_create(struct proc_dir_entry **parent, |
604 | const char *name, | 569 | const char *name, |
605 | mode_t mode, | 570 | mode_t mode, |
@@ -774,8 +739,6 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent) | |||
774 | continue_removing: | 739 | continue_removing: |
775 | if (S_ISDIR(de->mode)) | 740 | if (S_ISDIR(de->mode)) |
776 | parent->nlink--; | 741 | parent->nlink--; |
777 | if (!S_ISREG(de->mode)) | ||
778 | proc_kill_inodes(de); | ||
779 | de->nlink = 0; | 742 | de->nlink = 0; |
780 | WARN_ON(de->subdir); | 743 | WARN_ON(de->subdir); |
781 | if (!atomic_read(&de->count)) | 744 | if (!atomic_read(&de->count)) |
diff --git a/fs/proc/internal.h b/fs/proc/internal.h index 1b2b6c6bb475..1820eb2ef762 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h | |||
@@ -78,5 +78,3 @@ static inline int proc_fd(struct inode *inode) | |||
78 | { | 78 | { |
79 | return PROC_I(inode)->fd; | 79 | return PROC_I(inode)->fd; |
80 | } | 80 | } |
81 | |||
82 | extern struct file_system_type proc_fs_type; | ||
diff --git a/fs/proc/root.c b/fs/proc/root.c index 1f86bb860e04..ec9cb3b6c93b 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c | |||
@@ -98,7 +98,7 @@ static void proc_kill_sb(struct super_block *sb) | |||
98 | put_pid_ns(ns); | 98 | put_pid_ns(ns); |
99 | } | 99 | } |
100 | 100 | ||
101 | struct file_system_type proc_fs_type = { | 101 | static struct file_system_type proc_fs_type = { |
102 | .name = "proc", | 102 | .name = "proc", |
103 | .get_sb = proc_get_sb, | 103 | .get_sb = proc_get_sb, |
104 | .kill_sb = proc_kill_sb, | 104 | .kill_sb = proc_kill_sb, |