aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/proc/base.c104
-rw-r--r--include/linux/pid.h1
-rw-r--r--include/linux/sched.h11
-rw-r--r--kernel/pid.c36
4 files changed, 83 insertions, 69 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 89c20d9d50bf..b18f3773dd43 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -2142,72 +2142,43 @@ out_no_task:
2142} 2142}
2143 2143
2144/* 2144/*
2145 * Find the first tgid to return to user space. 2145 * Find the first task with tgid >= tgid
2146 * 2146 *
2147 * Usually this is just whatever follows &init_task, but if the users
2148 * buffer was too small to hold the full list or there was a seek into
2149 * the middle of the directory we have more work to do.
2150 *
2151 * In the case of a short read we start with find_task_by_pid.
2152 *
2153 * In the case of a seek we start with &init_task and walk nr
2154 * threads past it.
2155 */ 2147 */
2156static struct task_struct *first_tgid(int tgid, unsigned int nr) 2148static struct task_struct *next_tgid(unsigned int tgid)
2157{ 2149{
2158 struct task_struct *pos; 2150 struct task_struct *task;
2159 rcu_read_lock(); 2151 struct pid *pid;
2160 if (tgid && nr) {
2161 pos = find_task_by_pid(tgid);
2162 if (pos && thread_group_leader(pos))
2163 goto found;
2164 }
2165 /* If nr exceeds the number of processes get out quickly */
2166 pos = NULL;
2167 if (nr && nr >= nr_processes())
2168 goto done;
2169
2170 /* If we haven't found our starting place yet start with
2171 * the init_task and walk nr tasks forward.
2172 */
2173 for (pos = next_task(&init_task); nr > 0; --nr) {
2174 pos = next_task(pos);
2175 if (pos == &init_task) {
2176 pos = NULL;
2177 goto done;
2178 }
2179 }
2180found:
2181 get_task_struct(pos);
2182done:
2183 rcu_read_unlock();
2184 return pos;
2185}
2186 2152
2187/*
2188 * Find the next task in the task list.
2189 * Return NULL if we loop or there is any error.
2190 *
2191 * The reference to the input task_struct is released.
2192 */
2193static struct task_struct *next_tgid(struct task_struct *start)
2194{
2195 struct task_struct *pos;
2196 rcu_read_lock(); 2153 rcu_read_lock();
2197 pos = start; 2154retry:
2198 if (pid_alive(start)) 2155 task = NULL;
2199 pos = next_task(start); 2156 pid = find_ge_pid(tgid);
2200 if (pid_alive(pos) && (pos != &init_task)) { 2157 if (pid) {
2201 get_task_struct(pos); 2158 tgid = pid->nr + 1;
2202 goto done; 2159 task = pid_task(pid, PIDTYPE_PID);
2160 /* What we to know is if the pid we have find is the
2161 * pid of a thread_group_leader. Testing for task
2162 * being a thread_group_leader is the obvious thing
2163 * todo but there is a window when it fails, due to
2164 * the pid transfer logic in de_thread.
2165 *
2166 * So we perform the straight forward test of seeing
2167 * if the pid we have found is the pid of a thread
2168 * group leader, and don't worry if the task we have
2169 * found doesn't happen to be a thread group leader.
2170 * As we don't care in the case of readdir.
2171 */
2172 if (!task || !has_group_leader_pid(task))
2173 goto retry;
2174 get_task_struct(task);
2203 } 2175 }
2204 pos = NULL;
2205done:
2206 rcu_read_unlock(); 2176 rcu_read_unlock();
2207 put_task_struct(start); 2177 return task;
2208 return pos;
2209} 2178}
2210 2179
2180#define TGID_OFFSET (FIRST_PROCESS_ENTRY + (1 /* /proc/self */))
2181
2211/* for the /proc/ directory itself, after non-process stuff has been done */ 2182/* for the /proc/ directory itself, after non-process stuff has been done */
2212int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) 2183int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
2213{ 2184{
@@ -2223,29 +2194,24 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
2223 filp->f_pos++; 2194 filp->f_pos++;
2224 nr++; 2195 nr++;
2225 } 2196 }
2226 nr -= 1;
2227 2197
2228 /* f_version caches the tgid value that the last readdir call couldn't 2198 tgid = filp->f_pos - TGID_OFFSET;
2229 * return. lseek aka telldir automagically resets f_version to 0. 2199 for (task = next_tgid(tgid);
2230 */
2231 tgid = filp->f_version;
2232 filp->f_version = 0;
2233 for (task = first_tgid(tgid, nr);
2234 task; 2200 task;
2235 task = next_tgid(task), filp->f_pos++) { 2201 put_task_struct(task), task = next_tgid(tgid + 1)) {
2236 int len; 2202 int len;
2237 ino_t ino; 2203 ino_t ino;
2238 tgid = task->pid; 2204 tgid = task->pid;
2205 filp->f_pos = tgid + TGID_OFFSET;
2239 len = snprintf(buf, sizeof(buf), "%d", tgid); 2206 len = snprintf(buf, sizeof(buf), "%d", tgid);
2240 ino = fake_ino(tgid, PROC_TGID_INO); 2207 ino = fake_ino(tgid, PROC_TGID_INO);
2241 if (filldir(dirent, buf, len, filp->f_pos, ino, DT_DIR) < 0) { 2208 if (filldir(dirent, buf, len, filp->f_pos, ino, DT_DIR) < 0) {
2242 /* returning this tgid failed, save it as the first
2243 * pid for the next readir call */
2244 filp->f_version = tgid;
2245 put_task_struct(task); 2209 put_task_struct(task);
2246 break; 2210 goto out;
2247 } 2211 }
2248 } 2212 }
2213 filp->f_pos = PID_MAX_LIMIT + TGID_OFFSET;
2214out:
2249 return 0; 2215 return 0;
2250} 2216}
2251 2217
diff --git a/include/linux/pid.h b/include/linux/pid.h
index 93da7e2d9f30..359121086de1 100644
--- a/include/linux/pid.h
+++ b/include/linux/pid.h
@@ -89,6 +89,7 @@ extern struct pid *FASTCALL(find_pid(int nr));
89 * Lookup a PID in the hash table, and return with it's count elevated. 89 * Lookup a PID in the hash table, and return with it's count elevated.
90 */ 90 */
91extern struct pid *find_get_pid(int nr); 91extern struct pid *find_get_pid(int nr);
92extern struct pid *find_ge_pid(int nr);
92 93
93extern struct pid *alloc_pid(void); 94extern struct pid *alloc_pid(void);
94extern void FASTCALL(free_pid(struct pid *pid)); 95extern void FASTCALL(free_pid(struct pid *pid));
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 7ef899c47c29..be658e33bd26 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1358,6 +1358,17 @@ extern void wait_task_inactive(struct task_struct * p);
1358/* de_thread depends on thread_group_leader not being a pid based check */ 1358/* de_thread depends on thread_group_leader not being a pid based check */
1359#define thread_group_leader(p) (p == p->group_leader) 1359#define thread_group_leader(p) (p == p->group_leader)
1360 1360
1361/* Do to the insanities of de_thread it is possible for a process
1362 * to have the pid of the thread group leader without actually being
1363 * the thread group leader. For iteration through the pids in proc
1364 * all we care about is that we have a task with the appropriate
1365 * pid, we don't actually care if we have the right task.
1366 */
1367static inline int has_group_leader_pid(struct task_struct *p)
1368{
1369 return p->pid == p->tgid;
1370}
1371
1361static inline struct task_struct *next_thread(const struct task_struct *p) 1372static inline struct task_struct *next_thread(const struct task_struct *p)
1362{ 1373{
1363 return list_entry(rcu_dereference(p->thread_group.next), 1374 return list_entry(rcu_dereference(p->thread_group.next),
diff --git a/kernel/pid.c b/kernel/pid.c
index 8387e8c68193..ed89a732432c 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -145,6 +145,23 @@ static int alloc_pidmap(void)
145 return -1; 145 return -1;
146} 146}
147 147
148static int next_pidmap(int last)
149{
150 int offset;
151 pidmap_t *map;
152
153 offset = (last + 1) & BITS_PER_PAGE_MASK;
154 map = &pidmap_array[(last + 1)/BITS_PER_PAGE];
155 for (; map < &pidmap_array[PIDMAP_ENTRIES]; map++, offset = 0) {
156 if (unlikely(!map->page))
157 continue;
158 offset = find_next_bit((map)->page, BITS_PER_PAGE, offset);
159 if (offset < BITS_PER_PAGE)
160 return mk_pid(map, offset);
161 }
162 return -1;
163}
164
148fastcall void put_pid(struct pid *pid) 165fastcall void put_pid(struct pid *pid)
149{ 166{
150 if (!pid) 167 if (!pid)
@@ -303,6 +320,25 @@ struct pid *find_get_pid(pid_t nr)
303} 320}
304 321
305/* 322/*
323 * Used by proc to find the first pid that is greater then or equal to nr.
324 *
325 * If there is a pid at nr this function is exactly the same as find_pid.
326 */
327struct pid *find_ge_pid(int nr)
328{
329 struct pid *pid;
330
331 do {
332 pid = find_pid(nr);
333 if (pid)
334 break;
335 nr = next_pidmap(nr);
336 } while (nr > 0);
337
338 return pid;
339}
340
341/*
306 * The pid hash table is scaled according to the amount of memory in the 342 * The pid hash table is scaled according to the amount of memory in the
307 * machine. From a minimum of 16 slots up to 4096 slots at one gigabyte or 343 * machine. From a minimum of 16 slots up to 4096 slots at one gigabyte or
308 * more. 344 * more.