diff options
| author | Kirill Korotaev <kksx@mail.ru> | 2004-09-02 00:42:48 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-09-02 00:42:48 -0700 |
| commit | 37cbd41da09cb39c9896c04ed8baac7526bb9547 (patch) | |
| tree | c56359f143f02c3cf50996fb25a82fe896fae1ff /kernel | |
| parent | 3345ee71e2303c7c3d70de11d812306adc648865 (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.c | 6 | ||||
| -rw-r--r-- | kernel/exit.c | 26 | ||||
| -rw-r--r-- | kernel/fork.c | 5 | ||||
| -rw-r--r-- | kernel/pid.c | 88 | ||||
| -rw-r--r-- | kernel/signal.c | 12 | ||||
| -rw-r--r-- | kernel/sys.c | 16 |
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; } |
