|
@@ -2411,19 +2411,23 @@ out:
|
|
|
* Find the first task with tgid >= tgid
|
|
|
*
|
|
|
*/
|
|
|
-static struct task_struct *next_tgid(unsigned int tgid,
|
|
|
- struct pid_namespace *ns)
|
|
|
-{
|
|
|
+struct tgid_iter {
|
|
|
+ unsigned int tgid;
|
|
|
struct task_struct *task;
|
|
|
+};
|
|
|
+static struct tgid_iter next_tgid(struct pid_namespace *ns, struct tgid_iter iter)
|
|
|
+{
|
|
|
struct pid *pid;
|
|
|
|
|
|
+ if (iter.task)
|
|
|
+ put_task_struct(iter.task);
|
|
|
rcu_read_lock();
|
|
|
retry:
|
|
|
- task = NULL;
|
|
|
- pid = find_ge_pid(tgid, ns);
|
|
|
+ iter.task = NULL;
|
|
|
+ pid = find_ge_pid(iter.tgid, ns);
|
|
|
if (pid) {
|
|
|
- tgid = pid_nr_ns(pid, ns) + 1;
|
|
|
- task = pid_task(pid, PIDTYPE_PID);
|
|
|
+ iter.tgid = pid_nr_ns(pid, ns);
|
|
|
+ iter.task = pid_task(pid, PIDTYPE_PID);
|
|
|
/* What we to know is if the pid we have find is the
|
|
|
* pid of a thread_group_leader. Testing for task
|
|
|
* being a thread_group_leader is the obvious thing
|
|
@@ -2436,23 +2440,25 @@ retry:
|
|
|
* found doesn't happen to be a thread group leader.
|
|
|
* As we don't care in the case of readdir.
|
|
|
*/
|
|
|
- if (!task || !has_group_leader_pid(task))
|
|
|
+ if (!iter.task || !has_group_leader_pid(iter.task)) {
|
|
|
+ iter.tgid += 1;
|
|
|
goto retry;
|
|
|
- get_task_struct(task);
|
|
|
+ }
|
|
|
+ get_task_struct(iter.task);
|
|
|
}
|
|
|
rcu_read_unlock();
|
|
|
- return task;
|
|
|
+ return iter;
|
|
|
}
|
|
|
|
|
|
#define TGID_OFFSET (FIRST_PROCESS_ENTRY + ARRAY_SIZE(proc_base_stuff))
|
|
|
|
|
|
static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
|
|
|
- struct task_struct *task, int tgid)
|
|
|
+ struct tgid_iter iter)
|
|
|
{
|
|
|
char name[PROC_NUMBUF];
|
|
|
- int len = snprintf(name, sizeof(name), "%d", tgid);
|
|
|
+ int len = snprintf(name, sizeof(name), "%d", iter.tgid);
|
|
|
return proc_fill_cache(filp, dirent, filldir, name, len,
|
|
|
- proc_pid_instantiate, task, NULL);
|
|
|
+ proc_pid_instantiate, iter.task, NULL);
|
|
|
}
|
|
|
|
|
|
/* 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)
|
|
|
{
|
|
|
unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY;
|
|
|
struct task_struct *reaper = get_proc_task(filp->f_path.dentry->d_inode);
|
|
|
- struct task_struct *task;
|
|
|
- int tgid;
|
|
|
+ struct tgid_iter iter;
|
|
|
struct pid_namespace *ns;
|
|
|
|
|
|
if (!reaper)
|
|
@@ -2474,14 +2479,14 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
|
|
|
}
|
|
|
|
|
|
ns = filp->f_dentry->d_sb->s_fs_info;
|
|
|
- tgid = filp->f_pos - TGID_OFFSET;
|
|
|
- for (task = next_tgid(tgid, ns);
|
|
|
- task;
|
|
|
- put_task_struct(task), task = next_tgid(tgid + 1, ns)) {
|
|
|
- tgid = task_pid_nr_ns(task, ns);
|
|
|
- filp->f_pos = tgid + TGID_OFFSET;
|
|
|
- if (proc_pid_fill_cache(filp, dirent, filldir, task, tgid) < 0) {
|
|
|
- put_task_struct(task);
|
|
|
+ iter.task = NULL;
|
|
|
+ iter.tgid = filp->f_pos - TGID_OFFSET;
|
|
|
+ for (iter = next_tgid(ns, iter);
|
|
|
+ iter.task;
|
|
|
+ iter.tgid += 1, iter = next_tgid(ns, iter)) {
|
|
|
+ filp->f_pos = iter.tgid + TGID_OFFSET;
|
|
|
+ if (proc_pid_fill_cache(filp, dirent, filldir, iter) < 0) {
|
|
|
+ put_task_struct(iter.task);
|
|
|
goto out;
|
|
|
}
|
|
|
}
|