summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorKirill Korotaev <kksx@mail.ru>2004-09-02 00:42:48 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-09-02 00:42:48 -0700
commit37cbd41da09cb39c9896c04ed8baac7526bb9547 (patch)
treec56359f143f02c3cf50996fb25a82fe896fae1ff /kernel
parent3345ee71e2303c7c3d70de11d812306adc648865 (diff)
[PATCH] fixed pidhashing patch
This patch fixes strange and obscure pid implementation in current kernels: - it removes calling of put_task_struct() from detach_pid() under tasklist_lock. This allows to use blocking calls in security_task_free() hooks (in __put_task_struct()). - it saves some space = 5*5 ints = 100 bytes in task_struct - it's smaller and tidy, more straigthforward and doesn't use any knowledge about pids using and assignment. - it removes pid_links and pid_struct doesn't hold reference counters on task_struct. instead, new pid_structs and linked altogether and only one of them is inserted in hash_list. Signed-off-by: Kirill Korotaev (kksx@mail.ru) Signed-off-by: William Irwin <wli@holomorphy.com> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/capability.c6
-rw-r--r--kernel/exit.c26
-rw-r--r--kernel/fork.c5
-rw-r--r--kernel/pid.c88
-rw-r--r--kernel/signal.c12
-rw-r--r--kernel/sys.c16
6 files changed, 62 insertions, 91 deletions
diff --git a/kernel/capability.c b/kernel/capability.c
index 1c5c35718450..7e864e2ccf6a 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -89,14 +89,12 @@ static inline void cap_set_pg(int pgrp, kernel_cap_t *effective,
kernel_cap_t *permitted)
{
task_t *g, *target;
- struct list_head *l;
- struct pid *pid;
- for_each_task_pid(pgrp, PIDTYPE_PGID, g, l, pid) {
+ do_each_task_pid(pgrp, PIDTYPE_PGID, g) {
target = g;
while_each_thread(g, target)
security_capset_set(target, effective, inheritable, permitted);
- }
+ } while_each_task_pid(pgrp, PIDTYPE_PGID, g);
}
/*
diff --git a/kernel/exit.c b/kernel/exit.c
index 6e196d723d01..731b9ccd236b 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -124,16 +124,15 @@ void unhash_process(struct task_struct *p)
int session_of_pgrp(int pgrp)
{
struct task_struct *p;
- struct list_head *l;
- struct pid *pid;
int sid = -1;
read_lock(&tasklist_lock);
- for_each_task_pid(pgrp, PIDTYPE_PGID, p, l, pid)
+ do_each_task_pid(pgrp, PIDTYPE_PGID, p) {
if (p->signal->session > 0) {
sid = p->signal->session;
goto out;
}
+ } while_each_task_pid(pgrp, PIDTYPE_PGID, p);
p = find_task_by_pid(pgrp);
if (p)
sid = p->signal->session;
@@ -154,11 +153,9 @@ out:
static int will_become_orphaned_pgrp(int pgrp, task_t *ignored_task)
{
struct task_struct *p;
- struct list_head *l;
- struct pid *pid;
int ret = 1;
- for_each_task_pid(pgrp, PIDTYPE_PGID, p, l, pid) {
+ do_each_task_pid(pgrp, PIDTYPE_PGID, p) {
if (p == ignored_task
|| p->state >= TASK_ZOMBIE
|| p->real_parent->pid == 1)
@@ -168,7 +165,7 @@ static int will_become_orphaned_pgrp(int pgrp, task_t *ignored_task)
ret = 0;
break;
}
- }
+ } while_each_task_pid(pgrp, PIDTYPE_PGID, p);
return ret; /* (sighing) "Often!" */
}
@@ -187,10 +184,8 @@ static inline int has_stopped_jobs(int pgrp)
{
int retval = 0;
struct task_struct *p;
- struct list_head *l;
- struct pid *pid;
- for_each_task_pid(pgrp, PIDTYPE_PGID, p, l, pid) {
+ do_each_task_pid(pgrp, PIDTYPE_PGID, p) {
if (p->state != TASK_STOPPED)
continue;
@@ -206,7 +201,7 @@ static inline int has_stopped_jobs(int pgrp)
retval = 1;
break;
- }
+ } while_each_task_pid(pgrp, PIDTYPE_PGID, p);
return retval;
}
@@ -849,9 +844,6 @@ asmlinkage long sys_exit(int error_code)
task_t fastcall *next_thread(const task_t *p)
{
- const struct pid_link *link = p->pids + PIDTYPE_TGID;
- const struct list_head *tmp, *head = &link->pidptr->task_list;
-
#ifdef CONFIG_SMP
if (!p->sighand)
BUG();
@@ -859,11 +851,7 @@ task_t fastcall *next_thread(const task_t *p)
!rwlock_is_locked(&tasklist_lock))
BUG();
#endif
- tmp = link->pid_chain.next;
- if (tmp == head)
- tmp = head->next;
-
- return pid_task(tmp, PIDTYPE_TGID);
+ return pid_task(p->pids[PIDTYPE_TGID].pid_list.next, PIDTYPE_TGID);
}
EXPORT_SYMBOL(next_thread);
diff --git a/kernel/fork.c b/kernel/fork.c
index 9353b2e96700..78db8811c834 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1124,14 +1124,13 @@ static task_t *copy_process(unsigned long clone_flags,
__ptrace_link(p, current->parent);
attach_pid(p, PIDTYPE_PID, p->pid);
+ attach_pid(p, PIDTYPE_TGID, p->tgid);
if (thread_group_leader(p)) {
- attach_pid(p, PIDTYPE_TGID, p->tgid);
attach_pid(p, PIDTYPE_PGID, process_group(p));
attach_pid(p, PIDTYPE_SID, p->signal->session);
if (p->pid)
__get_cpu_var(process_counts)++;
- } else
- link_pid(p, p->pids + PIDTYPE_TGID, &p->group_leader->pids[PIDTYPE_TGID].pid);
+ }
nr_threads++;
write_unlock_irq(&tasklist_lock);
diff --git a/kernel/pid.c b/kernel/pid.c
index 8c9b7510174a..57527f0cda5e 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -146,74 +146,66 @@ failure:
return -1;
}
-fastcall struct pid *find_pid(enum pid_type type, int nr)
+struct pid * fastcall find_pid(enum pid_type type, int nr)
{
struct hlist_node *elem;
struct pid *pid;
hlist_for_each_entry(pid, elem,
- &pid_hash[type][pid_hashfn(nr)], hash_chain) {
+ &pid_hash[type][pid_hashfn(nr)], pid_chain) {
if (pid->nr == nr)
return pid;
}
return NULL;
}
-void fastcall link_pid(task_t *task, struct pid_link *link, struct pid *pid)
-{
- atomic_inc(&pid->count);
- list_add_tail(&link->pid_chain, &pid->task_list);
- link->pidptr = pid;
-}
-
int fastcall attach_pid(task_t *task, enum pid_type type, int nr)
{
- struct pid *pid = find_pid(type, nr);
-
- if (pid)
- atomic_inc(&pid->count);
- else {
- pid = &task->pids[type].pid;
- pid->nr = nr;
- atomic_set(&pid->count, 1);
- INIT_LIST_HEAD(&pid->task_list);
- pid->task = task;
- get_task_struct(task);
- hlist_add_head(&pid->hash_chain,
+ struct pid *pid, *task_pid;
+
+ task_pid = &task->pids[type];
+ pid = find_pid(type, nr);
+ if (pid == NULL) {
+ hlist_add_head(&task_pid->pid_chain,
&pid_hash[type][pid_hashfn(nr)]);
+ INIT_LIST_HEAD(&task_pid->pid_list);
+ } else {
+ INIT_HLIST_NODE(&task_pid->pid_chain);
+ list_add_tail(&task_pid->pid_list, &pid->pid_list);
}
- list_add_tail(&task->pids[type].pid_chain, &pid->task_list);
- task->pids[type].pidptr = pid;
+ task_pid->nr = nr;
return 0;
}
static inline int __detach_pid(task_t *task, enum pid_type type)
{
- struct pid_link *link = task->pids + type;
- struct pid *pid = link->pidptr;
+ struct pid *pid, *pid_next;
int nr;
- list_del(&link->pid_chain);
- if (!atomic_dec_and_test(&pid->count))
- return 0;
-
+ pid = &task->pids[type];
+ if (!hlist_unhashed(&pid->pid_chain)) {
+ hlist_del(&pid->pid_chain);
+ if (!list_empty(&pid->pid_list)) {
+ pid_next = list_entry(pid->pid_list.next,
+ struct pid, pid_list);
+ /* insert next pid from pid_list to hash */
+ hlist_add_head(&pid_next->pid_chain,
+ &pid_hash[type][pid_hashfn(pid_next->nr)]);
+ }
+ }
+ list_del(&pid->pid_list);
nr = pid->nr;
- hlist_del(&pid->hash_chain);
- put_task_struct(pid->task);
+ pid->nr = 0;
return nr;
}
-static void _detach_pid(task_t *task, enum pid_type type)
-{
- __detach_pid(task, type);
-}
-
void fastcall detach_pid(task_t *task, enum pid_type type)
{
- int nr = __detach_pid(task, type);
+ int nr;
+ nr = __detach_pid(task, type);
if (!nr)
return;
@@ -223,16 +215,18 @@ void fastcall detach_pid(task_t *task, enum pid_type type)
free_pidmap(nr);
}
-task_t *find_task_by_pid(int nr)
+task_t *find_task_by_pid_type(int type, int nr)
{
- struct pid *pid = find_pid(PIDTYPE_PID, nr);
+ struct pid *pid;
+ pid = find_pid(type, nr);
if (!pid)
return NULL;
- return pid_task(pid->task_list.next, PIDTYPE_PID);
+
+ return pid_task(&pid->pid_list, type);
}
-EXPORT_SYMBOL(find_task_by_pid);
+EXPORT_SYMBOL(find_task_by_pid_type);
/*
* This function switches the PIDs if a non-leader thread calls
@@ -241,13 +235,13 @@ EXPORT_SYMBOL(find_task_by_pid);
*/
void switch_exec_pids(task_t *leader, task_t *thread)
{
- _detach_pid(leader, PIDTYPE_PID);
- _detach_pid(leader, PIDTYPE_TGID);
- _detach_pid(leader, PIDTYPE_PGID);
- _detach_pid(leader, PIDTYPE_SID);
+ __detach_pid(leader, PIDTYPE_PID);
+ __detach_pid(leader, PIDTYPE_TGID);
+ __detach_pid(leader, PIDTYPE_PGID);
+ __detach_pid(leader, PIDTYPE_SID);
- _detach_pid(thread, PIDTYPE_PID);
- _detach_pid(thread, PIDTYPE_TGID);
+ __detach_pid(thread, PIDTYPE_PID);
+ __detach_pid(thread, PIDTYPE_TGID);
leader->pid = leader->tgid = thread->pid;
thread->pid = thread->tgid;
diff --git a/kernel/signal.c b/kernel/signal.c
index 2dec2c91ed6e..8b05f0b8c2dc 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1110,8 +1110,6 @@ int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
int __kill_pg_info(int sig, struct siginfo *info, pid_t pgrp)
{
struct task_struct *p;
- struct list_head *l;
- struct pid *pid;
int retval, success;
if (pgrp <= 0)
@@ -1119,11 +1117,11 @@ int __kill_pg_info(int sig, struct siginfo *info, pid_t pgrp)
success = 0;
retval = -ESRCH;
- for_each_task_pid(pgrp, PIDTYPE_PGID, p, l, pid) {
+ do_each_task_pid(pgrp, PIDTYPE_PGID, p) {
int err = group_send_sig_info(sig, info, p);
success |= !err;
retval = err;
- }
+ } while_each_task_pid(pgrp, PIDTYPE_PGID, p);
return success ? 0 : retval;
}
@@ -1150,8 +1148,6 @@ int
kill_sl_info(int sig, struct siginfo *info, pid_t sid)
{
int err, retval = -EINVAL;
- struct pid *pid;
- struct list_head *l;
struct task_struct *p;
if (sid <= 0)
@@ -1159,13 +1155,13 @@ kill_sl_info(int sig, struct siginfo *info, pid_t sid)
retval = -ESRCH;
read_lock(&tasklist_lock);
- for_each_task_pid(sid, PIDTYPE_SID, p, l, pid) {
+ do_each_task_pid(sid, PIDTYPE_SID, p) {
if (!p->signal->leader)
continue;
err = group_send_sig_info(sig, info, p);
if (retval)
retval = err;
- }
+ } while_each_task_pid(sid, PIDTYPE_SID, p);
read_unlock(&tasklist_lock);
out:
return retval;
diff --git a/kernel/sys.c b/kernel/sys.c
index de206f3df466..a4b29df201f6 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -310,8 +310,6 @@ asmlinkage long sys_setpriority(int which, int who, int niceval)
{
struct task_struct *g, *p;
struct user_struct *user;
- struct pid *pid;
- struct list_head *l;
int error = -EINVAL;
if (which > 2 || which < 0)
@@ -336,8 +334,9 @@ asmlinkage long sys_setpriority(int which, int who, int niceval)
case PRIO_PGRP:
if (!who)
who = process_group(current);
- for_each_task_pid(who, PIDTYPE_PGID, p, l, pid)
+ do_each_task_pid(who, PIDTYPE_PGID, p) {
error = set_one_prio(p, niceval, error);
+ } while_each_task_pid(who, PIDTYPE_PGID, p);
break;
case PRIO_USER:
if (!who)
@@ -371,8 +370,6 @@ out:
asmlinkage long sys_getpriority(int which, int who)
{
struct task_struct *g, *p;
- struct list_head *l;
- struct pid *pid;
struct user_struct *user;
long niceval, retval = -ESRCH;
@@ -394,11 +391,11 @@ asmlinkage long sys_getpriority(int which, int who)
case PRIO_PGRP:
if (!who)
who = process_group(current);
- for_each_task_pid(who, PIDTYPE_PGID, p, l, pid) {
+ do_each_task_pid(who, PIDTYPE_PGID, p) {
niceval = 20 - task_nice(p);
if (niceval > retval)
retval = niceval;
- }
+ } while_each_task_pid(who, PIDTYPE_PGID, p);
break;
case PRIO_USER:
if (!who)
@@ -1044,12 +1041,11 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
if (pgid != pid) {
struct task_struct *p;
- struct pid *pid;
- struct list_head *l;
- for_each_task_pid(pgid, PIDTYPE_PGID, p, l, pid)
+ do_each_task_pid(pgid, PIDTYPE_PGID, p) {
if (p->signal->session == current->signal->session)
goto ok_pgid;
+ } while_each_task_pid(pgid, PIDTYPE_PGID, p);
goto out;
}