diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-05-29 10:05:05 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-05-29 10:05:05 -0400 |
commit | 6715930654e06c4d2e66e718ea159079f71838f4 (patch) | |
tree | 6a0a19fb62f3e99cb5f6bf6c34ae541f7c30fb42 /kernel | |
parent | ea3f01f8afd3bc5daff915cc4ea5cc5ea9e7d427 (diff) | |
parent | e490517a039a99d692cb3a5561941b0a5f576172 (diff) |
Merge commit 'linus/master' into sched-fixes-for-linus
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/audit.c | 11 | ||||
-rw-r--r-- | kernel/audit_tree.c | 5 | ||||
-rw-r--r-- | kernel/cgroup.c | 2 | ||||
-rw-r--r-- | kernel/exit.c | 7 | ||||
-rw-r--r-- | kernel/fork.c | 130 | ||||
-rw-r--r-- | kernel/module.c | 18 | ||||
-rw-r--r-- | kernel/signal.c | 51 | ||||
-rw-r--r-- | kernel/stop_machine.c | 7 | ||||
-rw-r--r-- | kernel/sys.c | 6 | ||||
-rw-r--r-- | kernel/sysctl.c | 5 |
10 files changed, 85 insertions, 157 deletions
diff --git a/kernel/audit.c b/kernel/audit.c index b7d3709cc452..e8692a5748c2 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
@@ -572,16 +572,17 @@ void audit_send_reply(int pid, int seq, int type, int done, int multi, | |||
572 | 572 | ||
573 | skb = audit_make_reply(pid, seq, type, done, multi, payload, size); | 573 | skb = audit_make_reply(pid, seq, type, done, multi, payload, size); |
574 | if (!skb) | 574 | if (!skb) |
575 | return; | 575 | goto out; |
576 | 576 | ||
577 | reply->pid = pid; | 577 | reply->pid = pid; |
578 | reply->skb = skb; | 578 | reply->skb = skb; |
579 | 579 | ||
580 | tsk = kthread_run(audit_send_reply_thread, reply, "audit_send_reply"); | 580 | tsk = kthread_run(audit_send_reply_thread, reply, "audit_send_reply"); |
581 | if (IS_ERR(tsk)) { | 581 | if (!IS_ERR(tsk)) |
582 | kfree(reply); | 582 | return; |
583 | kfree_skb(skb); | 583 | kfree_skb(skb); |
584 | } | 584 | out: |
585 | kfree(reply); | ||
585 | } | 586 | } |
586 | 587 | ||
587 | /* | 588 | /* |
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 9ef5e0aacc3c..f7921a2ecf16 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c | |||
@@ -172,10 +172,9 @@ static void insert_hash(struct audit_chunk *chunk) | |||
172 | struct audit_chunk *audit_tree_lookup(const struct inode *inode) | 172 | struct audit_chunk *audit_tree_lookup(const struct inode *inode) |
173 | { | 173 | { |
174 | struct list_head *list = chunk_hash(inode); | 174 | struct list_head *list = chunk_hash(inode); |
175 | struct list_head *pos; | 175 | struct audit_chunk *p; |
176 | 176 | ||
177 | list_for_each_rcu(pos, list) { | 177 | list_for_each_entry_rcu(p, list, hash) { |
178 | struct audit_chunk *p = container_of(pos, struct audit_chunk, hash); | ||
179 | if (p->watch.inode == inode) { | 178 | if (p->watch.inode == inode) { |
180 | get_inotify_watch(&p->watch); | 179 | get_inotify_watch(&p->watch); |
181 | return p; | 180 | return p; |
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index fbc6fc8949b4..15ac0e1e4f4d 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -2903,7 +2903,7 @@ int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys) | |||
2903 | cg = tsk->cgroups; | 2903 | cg = tsk->cgroups; |
2904 | parent = task_cgroup(tsk, subsys->subsys_id); | 2904 | parent = task_cgroup(tsk, subsys->subsys_id); |
2905 | 2905 | ||
2906 | snprintf(nodename, MAX_CGROUP_TYPE_NAMELEN, "node_%d", tsk->pid); | 2906 | snprintf(nodename, MAX_CGROUP_TYPE_NAMELEN, "%d", tsk->pid); |
2907 | 2907 | ||
2908 | /* Pin the hierarchy */ | 2908 | /* Pin the hierarchy */ |
2909 | atomic_inc(&parent->root->sb->s_active); | 2909 | atomic_inc(&parent->root->sb->s_active); |
diff --git a/kernel/exit.c b/kernel/exit.c index 1510f78a0ffa..8f6185e69b69 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -126,6 +126,12 @@ static void __exit_signal(struct task_struct *tsk) | |||
126 | 126 | ||
127 | __unhash_process(tsk); | 127 | __unhash_process(tsk); |
128 | 128 | ||
129 | /* | ||
130 | * Do this under ->siglock, we can race with another thread | ||
131 | * doing sigqueue_free() if we have SIGQUEUE_PREALLOC signals. | ||
132 | */ | ||
133 | flush_sigqueue(&tsk->pending); | ||
134 | |||
129 | tsk->signal = NULL; | 135 | tsk->signal = NULL; |
130 | tsk->sighand = NULL; | 136 | tsk->sighand = NULL; |
131 | spin_unlock(&sighand->siglock); | 137 | spin_unlock(&sighand->siglock); |
@@ -133,7 +139,6 @@ static void __exit_signal(struct task_struct *tsk) | |||
133 | 139 | ||
134 | __cleanup_sighand(sighand); | 140 | __cleanup_sighand(sighand); |
135 | clear_tsk_thread_flag(tsk,TIF_SIGPENDING); | 141 | clear_tsk_thread_flag(tsk,TIF_SIGPENDING); |
136 | flush_sigqueue(&tsk->pending); | ||
137 | if (sig) { | 142 | if (sig) { |
138 | flush_sigqueue(&sig->shared_pending); | 143 | flush_sigqueue(&sig->shared_pending); |
139 | taskstats_tgid_free(sig); | 144 | taskstats_tgid_free(sig); |
diff --git a/kernel/fork.c b/kernel/fork.c index 933e60ebccae..19908b26cf80 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -660,136 +660,6 @@ static int copy_fs(unsigned long clone_flags, struct task_struct *tsk) | |||
660 | return 0; | 660 | return 0; |
661 | } | 661 | } |
662 | 662 | ||
663 | static int count_open_files(struct fdtable *fdt) | ||
664 | { | ||
665 | int size = fdt->max_fds; | ||
666 | int i; | ||
667 | |||
668 | /* Find the last open fd */ | ||
669 | for (i = size/(8*sizeof(long)); i > 0; ) { | ||
670 | if (fdt->open_fds->fds_bits[--i]) | ||
671 | break; | ||
672 | } | ||
673 | i = (i+1) * 8 * sizeof(long); | ||
674 | return i; | ||
675 | } | ||
676 | |||
677 | static struct files_struct *alloc_files(void) | ||
678 | { | ||
679 | struct files_struct *newf; | ||
680 | struct fdtable *fdt; | ||
681 | |||
682 | newf = kmem_cache_alloc(files_cachep, GFP_KERNEL); | ||
683 | if (!newf) | ||
684 | goto out; | ||
685 | |||
686 | atomic_set(&newf->count, 1); | ||
687 | |||
688 | spin_lock_init(&newf->file_lock); | ||
689 | newf->next_fd = 0; | ||
690 | fdt = &newf->fdtab; | ||
691 | fdt->max_fds = NR_OPEN_DEFAULT; | ||
692 | fdt->close_on_exec = (fd_set *)&newf->close_on_exec_init; | ||
693 | fdt->open_fds = (fd_set *)&newf->open_fds_init; | ||
694 | fdt->fd = &newf->fd_array[0]; | ||
695 | INIT_RCU_HEAD(&fdt->rcu); | ||
696 | fdt->next = NULL; | ||
697 | rcu_assign_pointer(newf->fdt, fdt); | ||
698 | out: | ||
699 | return newf; | ||
700 | } | ||
701 | |||
702 | /* | ||
703 | * Allocate a new files structure and copy contents from the | ||
704 | * passed in files structure. | ||
705 | * errorp will be valid only when the returned files_struct is NULL. | ||
706 | */ | ||
707 | static struct files_struct *dup_fd(struct files_struct *oldf, int *errorp) | ||
708 | { | ||
709 | struct files_struct *newf; | ||
710 | struct file **old_fds, **new_fds; | ||
711 | int open_files, size, i; | ||
712 | struct fdtable *old_fdt, *new_fdt; | ||
713 | |||
714 | *errorp = -ENOMEM; | ||
715 | newf = alloc_files(); | ||
716 | if (!newf) | ||
717 | goto out; | ||
718 | |||
719 | spin_lock(&oldf->file_lock); | ||
720 | old_fdt = files_fdtable(oldf); | ||
721 | new_fdt = files_fdtable(newf); | ||
722 | open_files = count_open_files(old_fdt); | ||
723 | |||
724 | /* | ||
725 | * Check whether we need to allocate a larger fd array and fd set. | ||
726 | * Note: we're not a clone task, so the open count won't change. | ||
727 | */ | ||
728 | if (open_files > new_fdt->max_fds) { | ||
729 | new_fdt->max_fds = 0; | ||
730 | spin_unlock(&oldf->file_lock); | ||
731 | spin_lock(&newf->file_lock); | ||
732 | *errorp = expand_files(newf, open_files-1); | ||
733 | spin_unlock(&newf->file_lock); | ||
734 | if (*errorp < 0) | ||
735 | goto out_release; | ||
736 | new_fdt = files_fdtable(newf); | ||
737 | /* | ||
738 | * Reacquire the oldf lock and a pointer to its fd table | ||
739 | * who knows it may have a new bigger fd table. We need | ||
740 | * the latest pointer. | ||
741 | */ | ||
742 | spin_lock(&oldf->file_lock); | ||
743 | old_fdt = files_fdtable(oldf); | ||
744 | } | ||
745 | |||
746 | old_fds = old_fdt->fd; | ||
747 | new_fds = new_fdt->fd; | ||
748 | |||
749 | memcpy(new_fdt->open_fds->fds_bits, | ||
750 | old_fdt->open_fds->fds_bits, open_files/8); | ||
751 | memcpy(new_fdt->close_on_exec->fds_bits, | ||
752 | old_fdt->close_on_exec->fds_bits, open_files/8); | ||
753 | |||
754 | for (i = open_files; i != 0; i--) { | ||
755 | struct file *f = *old_fds++; | ||
756 | if (f) { | ||
757 | get_file(f); | ||
758 | } else { | ||
759 | /* | ||
760 | * The fd may be claimed in the fd bitmap but not yet | ||
761 | * instantiated in the files array if a sibling thread | ||
762 | * is partway through open(). So make sure that this | ||
763 | * fd is available to the new process. | ||
764 | */ | ||
765 | FD_CLR(open_files - i, new_fdt->open_fds); | ||
766 | } | ||
767 | rcu_assign_pointer(*new_fds++, f); | ||
768 | } | ||
769 | spin_unlock(&oldf->file_lock); | ||
770 | |||
771 | /* compute the remainder to be cleared */ | ||
772 | size = (new_fdt->max_fds - open_files) * sizeof(struct file *); | ||
773 | |||
774 | /* This is long word aligned thus could use a optimized version */ | ||
775 | memset(new_fds, 0, size); | ||
776 | |||
777 | if (new_fdt->max_fds > open_files) { | ||
778 | int left = (new_fdt->max_fds-open_files)/8; | ||
779 | int start = open_files / (8 * sizeof(unsigned long)); | ||
780 | |||
781 | memset(&new_fdt->open_fds->fds_bits[start], 0, left); | ||
782 | memset(&new_fdt->close_on_exec->fds_bits[start], 0, left); | ||
783 | } | ||
784 | |||
785 | return newf; | ||
786 | |||
787 | out_release: | ||
788 | kmem_cache_free(files_cachep, newf); | ||
789 | out: | ||
790 | return NULL; | ||
791 | } | ||
792 | |||
793 | static int copy_files(unsigned long clone_flags, struct task_struct * tsk) | 663 | static int copy_files(unsigned long clone_flags, struct task_struct * tsk) |
794 | { | 664 | { |
795 | struct files_struct *oldf, *newf; | 665 | struct files_struct *oldf, *newf; |
diff --git a/kernel/module.c b/kernel/module.c index f5e9491ef7ac..5f80478b746d 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -1337,7 +1337,19 @@ out_unreg: | |||
1337 | kobject_put(&mod->mkobj.kobj); | 1337 | kobject_put(&mod->mkobj.kobj); |
1338 | return err; | 1338 | return err; |
1339 | } | 1339 | } |
1340 | #endif | 1340 | |
1341 | static void mod_sysfs_fini(struct module *mod) | ||
1342 | { | ||
1343 | kobject_put(&mod->mkobj.kobj); | ||
1344 | } | ||
1345 | |||
1346 | #else /* CONFIG_SYSFS */ | ||
1347 | |||
1348 | static void mod_sysfs_fini(struct module *mod) | ||
1349 | { | ||
1350 | } | ||
1351 | |||
1352 | #endif /* CONFIG_SYSFS */ | ||
1341 | 1353 | ||
1342 | static void mod_kobject_remove(struct module *mod) | 1354 | static void mod_kobject_remove(struct module *mod) |
1343 | { | 1355 | { |
@@ -1345,7 +1357,7 @@ static void mod_kobject_remove(struct module *mod) | |||
1345 | module_param_sysfs_remove(mod); | 1357 | module_param_sysfs_remove(mod); |
1346 | kobject_put(mod->mkobj.drivers_dir); | 1358 | kobject_put(mod->mkobj.drivers_dir); |
1347 | kobject_put(mod->holders_dir); | 1359 | kobject_put(mod->holders_dir); |
1348 | kobject_put(&mod->mkobj.kobj); | 1360 | mod_sysfs_fini(mod); |
1349 | } | 1361 | } |
1350 | 1362 | ||
1351 | /* | 1363 | /* |
@@ -1780,7 +1792,7 @@ static struct module *load_module(void __user *umod, | |||
1780 | 1792 | ||
1781 | /* Sanity checks against insmoding binaries or wrong arch, | 1793 | /* Sanity checks against insmoding binaries or wrong arch, |
1782 | weird elf version */ | 1794 | weird elf version */ |
1783 | if (memcmp(hdr->e_ident, ELFMAG, 4) != 0 | 1795 | if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0 |
1784 | || hdr->e_type != ET_REL | 1796 | || hdr->e_type != ET_REL |
1785 | || !elf_check_arch(hdr) | 1797 | || !elf_check_arch(hdr) |
1786 | || hdr->e_shentsize != sizeof(*sechdrs)) { | 1798 | || hdr->e_shentsize != sizeof(*sechdrs)) { |
diff --git a/kernel/signal.c b/kernel/signal.c index 72bb4f51f963..6c0958e52ea7 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -231,6 +231,40 @@ void flush_signals(struct task_struct *t) | |||
231 | spin_unlock_irqrestore(&t->sighand->siglock, flags); | 231 | spin_unlock_irqrestore(&t->sighand->siglock, flags); |
232 | } | 232 | } |
233 | 233 | ||
234 | static void __flush_itimer_signals(struct sigpending *pending) | ||
235 | { | ||
236 | sigset_t signal, retain; | ||
237 | struct sigqueue *q, *n; | ||
238 | |||
239 | signal = pending->signal; | ||
240 | sigemptyset(&retain); | ||
241 | |||
242 | list_for_each_entry_safe(q, n, &pending->list, list) { | ||
243 | int sig = q->info.si_signo; | ||
244 | |||
245 | if (likely(q->info.si_code != SI_TIMER)) { | ||
246 | sigaddset(&retain, sig); | ||
247 | } else { | ||
248 | sigdelset(&signal, sig); | ||
249 | list_del_init(&q->list); | ||
250 | __sigqueue_free(q); | ||
251 | } | ||
252 | } | ||
253 | |||
254 | sigorsets(&pending->signal, &signal, &retain); | ||
255 | } | ||
256 | |||
257 | void flush_itimer_signals(void) | ||
258 | { | ||
259 | struct task_struct *tsk = current; | ||
260 | unsigned long flags; | ||
261 | |||
262 | spin_lock_irqsave(&tsk->sighand->siglock, flags); | ||
263 | __flush_itimer_signals(&tsk->pending); | ||
264 | __flush_itimer_signals(&tsk->signal->shared_pending); | ||
265 | spin_unlock_irqrestore(&tsk->sighand->siglock, flags); | ||
266 | } | ||
267 | |||
234 | void ignore_signals(struct task_struct *t) | 268 | void ignore_signals(struct task_struct *t) |
235 | { | 269 | { |
236 | int i; | 270 | int i; |
@@ -1240,17 +1274,22 @@ void sigqueue_free(struct sigqueue *q) | |||
1240 | 1274 | ||
1241 | BUG_ON(!(q->flags & SIGQUEUE_PREALLOC)); | 1275 | BUG_ON(!(q->flags & SIGQUEUE_PREALLOC)); |
1242 | /* | 1276 | /* |
1243 | * If the signal is still pending remove it from the | 1277 | * We must hold ->siglock while testing q->list |
1244 | * pending queue. We must hold ->siglock while testing | 1278 | * to serialize with collect_signal() or with |
1245 | * q->list to serialize with collect_signal(). | 1279 | * __exit_signal()->flush_sigqueue(). |
1246 | */ | 1280 | */ |
1247 | spin_lock_irqsave(lock, flags); | 1281 | spin_lock_irqsave(lock, flags); |
1282 | q->flags &= ~SIGQUEUE_PREALLOC; | ||
1283 | /* | ||
1284 | * If it is queued it will be freed when dequeued, | ||
1285 | * like the "regular" sigqueue. | ||
1286 | */ | ||
1248 | if (!list_empty(&q->list)) | 1287 | if (!list_empty(&q->list)) |
1249 | list_del_init(&q->list); | 1288 | q = NULL; |
1250 | spin_unlock_irqrestore(lock, flags); | 1289 | spin_unlock_irqrestore(lock, flags); |
1251 | 1290 | ||
1252 | q->flags &= ~SIGQUEUE_PREALLOC; | 1291 | if (q) |
1253 | __sigqueue_free(q); | 1292 | __sigqueue_free(q); |
1254 | } | 1293 | } |
1255 | 1294 | ||
1256 | int send_sigqueue(struct sigqueue *q, struct task_struct *t, int group) | 1295 | int send_sigqueue(struct sigqueue *q, struct task_struct *t, int group) |
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c index 0101aeef7ed7..b7350bbfb076 100644 --- a/kernel/stop_machine.c +++ b/kernel/stop_machine.c | |||
@@ -62,8 +62,7 @@ static int stopmachine(void *cpu) | |||
62 | * help our sisters onto their CPUs. */ | 62 | * help our sisters onto their CPUs. */ |
63 | if (!prepared && !irqs_disabled) | 63 | if (!prepared && !irqs_disabled) |
64 | yield(); | 64 | yield(); |
65 | else | 65 | cpu_relax(); |
66 | cpu_relax(); | ||
67 | } | 66 | } |
68 | 67 | ||
69 | /* Ack: we are exiting. */ | 68 | /* Ack: we are exiting. */ |
@@ -106,8 +105,10 @@ static int stop_machine(void) | |||
106 | } | 105 | } |
107 | 106 | ||
108 | /* Wait for them all to come to life. */ | 107 | /* Wait for them all to come to life. */ |
109 | while (atomic_read(&stopmachine_thread_ack) != stopmachine_num_threads) | 108 | while (atomic_read(&stopmachine_thread_ack) != stopmachine_num_threads) { |
110 | yield(); | 109 | yield(); |
110 | cpu_relax(); | ||
111 | } | ||
111 | 112 | ||
112 | /* If some failed, kill them all. */ | 113 | /* If some failed, kill them all. */ |
113 | if (ret < 0) { | 114 | if (ret < 0) { |
diff --git a/kernel/sys.c b/kernel/sys.c index 895d2d4c9493..14e97282eb6c 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
@@ -1652,7 +1652,7 @@ asmlinkage long sys_umask(int mask) | |||
1652 | asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, | 1652 | asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, |
1653 | unsigned long arg4, unsigned long arg5) | 1653 | unsigned long arg4, unsigned long arg5) |
1654 | { | 1654 | { |
1655 | long uninitialized_var(error); | 1655 | long error = 0; |
1656 | 1656 | ||
1657 | if (security_task_prctl(option, arg2, arg3, arg4, arg5, &error)) | 1657 | if (security_task_prctl(option, arg2, arg3, arg4, arg5, &error)) |
1658 | return error; | 1658 | return error; |
@@ -1701,9 +1701,7 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, | |||
1701 | error = PR_TIMING_STATISTICAL; | 1701 | error = PR_TIMING_STATISTICAL; |
1702 | break; | 1702 | break; |
1703 | case PR_SET_TIMING: | 1703 | case PR_SET_TIMING: |
1704 | if (arg2 == PR_TIMING_STATISTICAL) | 1704 | if (arg2 != PR_TIMING_STATISTICAL) |
1705 | error = 0; | ||
1706 | else | ||
1707 | error = -EINVAL; | 1705 | error = -EINVAL; |
1708 | break; | 1706 | break; |
1709 | 1707 | ||
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index d7ffdc59816a..29116652dca8 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
@@ -81,6 +81,7 @@ extern int compat_log; | |||
81 | extern int maps_protect; | 81 | extern int maps_protect; |
82 | extern int sysctl_stat_interval; | 82 | extern int sysctl_stat_interval; |
83 | extern int latencytop_enabled; | 83 | extern int latencytop_enabled; |
84 | extern int sysctl_nr_open_min, sysctl_nr_open_max; | ||
84 | 85 | ||
85 | /* Constants used for minimum and maximum */ | 86 | /* Constants used for minimum and maximum */ |
86 | #if defined(CONFIG_DETECT_SOFTLOCKUP) || defined(CONFIG_HIGHMEM) | 87 | #if defined(CONFIG_DETECT_SOFTLOCKUP) || defined(CONFIG_HIGHMEM) |
@@ -1190,7 +1191,9 @@ static struct ctl_table fs_table[] = { | |||
1190 | .data = &sysctl_nr_open, | 1191 | .data = &sysctl_nr_open, |
1191 | .maxlen = sizeof(int), | 1192 | .maxlen = sizeof(int), |
1192 | .mode = 0644, | 1193 | .mode = 0644, |
1193 | .proc_handler = &proc_dointvec, | 1194 | .proc_handler = &proc_dointvec_minmax, |
1195 | .extra1 = &sysctl_nr_open_min, | ||
1196 | .extra2 = &sysctl_nr_open_max, | ||
1194 | }, | 1197 | }, |
1195 | { | 1198 | { |
1196 | .ctl_name = FS_DENTRY, | 1199 | .ctl_name = FS_DENTRY, |