summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-03-27 23:54:12 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-03-27 23:54:12 +0000
commitd3e71cb08747743fce908122bab08b479eb403a5 (patch)
treecbec6948fdbdee9af81cf3ecfb504070d2745d7b /kernel
parentfe7ff1706e323d0e5ed83972960a1ecc1ee538b3 (diff)
Merge with Linux 2.3.99-pre3.
Diffstat (limited to 'kernel')
-rw-r--r--kernel/Makefile5
-rw-r--r--kernel/ksyms.c21
-rw-r--r--kernel/ptrace.c4
-rw-r--r--kernel/sched.c7
-rw-r--r--kernel/signal.c94
-rw-r--r--kernel/sysctl.c69
6 files changed, 120 insertions, 80 deletions
diff --git a/kernel/Makefile b/kernel/Makefile
index bec392fca..2a4f548af 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -7,9 +7,6 @@
#
# Note 2! The CFLAGS definitions are now in the main makefile...
-.S.s:
- $(CPP) $(CPPFLAGS) -traditional $< -o $*.s
-
O_TARGET := kernel.o
O_OBJS = sched.o dma.o fork.o exec_domain.o panic.o printk.o sys.o \
module.o exit.o itimer.o info.o time.o softirq.o resource.o \
@@ -29,7 +26,7 @@ ifeq ($(CONFIG_MODULES),y)
OX_OBJS += ksyms.o
endif
-ifdef CONFIG_PM
+ifeq ($(CONFIG_PM),y)
OX_OBJS += pm.o
endif
diff --git a/kernel/ksyms.c b/kernel/ksyms.c
index a6748e70c..ad11eafea 100644
--- a/kernel/ksyms.c
+++ b/kernel/ksyms.c
@@ -207,6 +207,7 @@ EXPORT_SYMBOL(posix_unblock_lock);
EXPORT_SYMBOL(locks_mandatory_area);
EXPORT_SYMBOL(dput);
EXPORT_SYMBOL(is_root_busy);
+EXPORT_SYMBOL(have_submounts);
EXPORT_SYMBOL(prune_dcache);
EXPORT_SYMBOL(shrink_dcache_sb);
EXPORT_SYMBOL(shrink_dcache_parent);
@@ -324,12 +325,20 @@ EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax);
EXPORT_SYMBOL(proc_doulongvec_minmax);
/* interrupt handling */
+EXPORT_SYMBOL(add_timer);
+EXPORT_SYMBOL(del_timer);
EXPORT_SYMBOL(request_irq);
EXPORT_SYMBOL(free_irq);
+
+/* The notion of irq probe/assignment is foreign to S/390 */
+
+#if !defined(CONFIG_ARCH_S390)
EXPORT_SYMBOL(probe_irq_on);
EXPORT_SYMBOL(probe_irq_off);
-EXPORT_SYMBOL(add_timer);
-EXPORT_SYMBOL(del_timer);
+EXPORT_SYMBOL(autoirq_setup);
+EXPORT_SYMBOL(autoirq_report);
+#endif
+
#ifdef __SMP__
EXPORT_SYMBOL(del_timer_sync);
#endif
@@ -366,10 +375,6 @@ EXPORT_SYMBOL(lock_kiovec);
EXPORT_SYMBOL(unlock_kiovec);
EXPORT_SYMBOL(brw_kiovec);
-/* autoirq from drivers/net/auto_irq.c */
-EXPORT_SYMBOL(autoirq_setup);
-EXPORT_SYMBOL(autoirq_report);
-
/* dma handling */
EXPORT_SYMBOL(request_dma);
EXPORT_SYMBOL(free_dma);
@@ -439,8 +444,8 @@ EXPORT_SYMBOL(setup_arg_pages);
EXPORT_SYMBOL(copy_strings_kernel);
EXPORT_SYMBOL(do_execve);
EXPORT_SYMBOL(flush_old_exec);
-EXPORT_SYMBOL(open_dentry);
-EXPORT_SYMBOL(read_exec);
+EXPORT_SYMBOL(kernel_read);
+EXPORT_SYMBOL(open_exec);
/* Miscellaneous access points */
EXPORT_SYMBOL(si_meminfo);
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index c3f75124f..a87858804 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -44,9 +44,9 @@ repeat:
mapnr = pte_pagenr(*pgtable);
if (write && (!pte_write(*pgtable) || !pte_dirty(*pgtable)))
goto fault_in_page;
- if (mapnr >= max_mapnr)
- return 0;
page = mem_map + mapnr;
+ if ((mapnr >= max_mapnr) || PageReserved(page))
+ return 0;
flush_cache_page(vma, addr);
if (write) {
diff --git a/kernel/sched.c b/kernel/sched.c
index e1dbc62ba..c0ac80395 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -618,6 +618,11 @@ handle_softirq:
goto handle_softirq_back;
handle_tq_scheduler:
+ /*
+ * do not run the task queue with disabled interrupts,
+ * cli() wouldn't work on SMP
+ */
+ sti();
run_task_queue(&tq_scheduler);
goto tq_scheduler_back;
@@ -630,7 +635,7 @@ move_rr_last:
scheduling_in_interrupt:
printk("Scheduling in interrupt\n");
- *(int *)0 = 0;
+ BUG();
return;
}
diff --git a/kernel/signal.c b/kernel/signal.c
index 55017e2f6..0958af05c 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -90,7 +90,7 @@ flush_signal_handlers(struct task_struct *t)
* Dequeue a signal and return the element to the caller, which is
* expected to free it.
*
- * All callers of must be holding current->sigmask_lock.
+ * All callers must be holding current->sigmask_lock.
*/
int
@@ -149,19 +149,19 @@ printk("SIG dequeue (%s:%d): %d ", current->comm, current->pid,
kmem_cache_free(signal_queue_cachep,q);
atomic_dec(&nr_queued_signals);
- /* then see if this signal is still pending. */
- q = *pp;
- while (q) {
- if (q->info.si_signo == sig) {
- reset = 0;
- break;
- }
- q = q->next;
- }
+ /* Then see if this signal is still pending.
+ (Non rt signals may not be queued twice.)
+ */
+ if (sig >= SIGRTMIN)
+ for (q = *pp; q; q = q->next)
+ if (q->info.si_signo == sig) {
+ reset = 0;
+ break;
+ }
+
} else {
- /* Ok, it wasn't in the queue. It must have
- been sent either by a non-rt mechanism and
- we ran out of queue space. So zero out the
+ /* Ok, it wasn't in the queue. We must have
+ been out of queue space. So zero out the
info. */
info->si_signo = sig;
info->si_errno = 0;
@@ -170,9 +170,10 @@ printk("SIG dequeue (%s:%d): %d ", current->comm, current->pid,
info->si_uid = 0;
}
- if (reset)
+ if (reset) {
sigdelset(&current->signal, sig);
- recalc_sigpending(current);
+ recalc_sigpending(current);
+ }
/* XXX: Once POSIX.1b timers are in, if si_code == SI_TIMER,
we need to xchg out the timer overrun values. */
@@ -196,6 +197,43 @@ printk(" %d -> %d\n", signal_pending(current), sig);
}
/*
+ * Remove signal sig from queue and from t->signal.
+ * Returns 1 if sig was found in t->signal.
+ *
+ * All callers must be holding t->sigmask_lock.
+ */
+static int rm_sig_from_queue(int sig, struct task_struct *t)
+{
+ struct signal_queue *q, **pp;
+
+ if (sig >= SIGRTMIN) {
+ printk(KERN_CRIT "SIG: rm_sig_from_queue() doesn't support rt signals\n");
+ return 0;
+ }
+
+ if (!sigismember(&t->signal, sig))
+ return 0;
+
+ sigdelset(&t->signal, sig);
+
+ pp = &t->sigqueue;
+ q = t->sigqueue;
+
+ /* Find the one we're interested in ...
+ It may appear only once. */
+ for ( ; q ; pp = &q->next, q = q->next)
+ if (q->info.si_signo == sig)
+ break;
+ if (q) {
+ if ((*pp = q->next) == NULL)
+ t->sigqueue_tail = pp;
+ kmem_cache_free(signal_queue_cachep,q);
+ atomic_dec(&nr_queued_signals);
+ }
+ return 1;
+}
+
+/*
* Determine whether a signal should be posted or not.
*
* Signals with SIG_IGN can be ignored, except for the
@@ -273,18 +311,16 @@ printk("SIG queue (%s:%d): %d ", t->comm, t->pid, sig);
if (t->state == TASK_STOPPED)
wake_up_process(t);
t->exit_code = 0;
- sigdelsetmask(&t->signal, (sigmask(SIGSTOP)|sigmask(SIGTSTP)|
- sigmask(SIGTTOU)|sigmask(SIGTTIN)));
- /* Inflict this corner case with recalculations, not mainline */
- recalc_sigpending(t);
+ if (rm_sig_from_queue(SIGSTOP, t) || rm_sig_from_queue(SIGTSTP, t) ||
+ rm_sig_from_queue(SIGTTOU, t) || rm_sig_from_queue(SIGTTIN, t))
+ recalc_sigpending(t);
break;
case SIGSTOP: case SIGTSTP:
case SIGTTIN: case SIGTTOU:
/* If we're stopping again, cancel SIGCONT */
- sigdelset(&t->signal, SIGCONT);
- /* Inflict this corner case with recalculations, not mainline */
- recalc_sigpending(t);
+ if (rm_sig_from_queue(SIGCONT, t))
+ recalc_sigpending(t);
break;
}
@@ -338,8 +374,12 @@ printk("SIG queue (%s:%d): %d ", t->comm, t->pid, sig);
q->info = *info;
break;
}
- } else {
- /* Queue overflow, we have to abort. */
+ } else if (sig >= SIGRTMIN && info && (unsigned long)info != 1
+ && info->si_code < 0) {
+ /*
+ * Queue overflow, abort. We may abort if the signal was rt
+ * and sent by user using something other than kill().
+ */
ret = -EAGAIN;
goto out;
}
@@ -406,7 +446,7 @@ force_sig_info(int sig, struct siginfo *info, struct task_struct *t)
}
/*
- * kill_pg() sends a signal to a process group: this is what the tty
+ * kill_pg_info() sends a signal to a process group: this is what the tty
* control characters do (^C, ^Z etc)
*/
@@ -437,7 +477,7 @@ kill_pg_info(int sig, struct siginfo *info, pid_t pgrp)
}
/*
- * kill_sl() sends a signal to the session leader: this is used
+ * kill_sl_info() sends a signal to the session leader: this is used
* to send SIGHUP to the controlling process of a terminal when
* the connection is lost.
*/
@@ -484,7 +524,7 @@ kill_proc_info(int sig, struct siginfo *info, pid_t pid)
}
/*
- * kill_something() interprets pid in interesting ways just like kill(2).
+ * kill_something_info() interprets pid in interesting ways just like kill(2).
*
* POSIX specifies that kill(-1,sig) is unspecified, but what we have
* is probably wrong. Should make it like BSD or SYSV.
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 4e654fa3a..35883ed4c 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -14,6 +14,8 @@
* Added proc_doulongvec_minmax, 09/08/99, Carlos H. Bauer.
* Changed linked lists to use list.h instead of lists.h, 02/24/00, Bill
* Wendling.
+ * The list_for_each() macro wasn't appropriate for the sysctl loop.
+ * Removed it and replaced it with older style, 03/23/00, Bill Wendling
*/
#include <linux/config.h>
@@ -84,9 +86,9 @@ static int parse_table(int *, int, void *, size_t *, void *, size_t,
static int proc_doutsstring(ctl_table *table, int write, struct file *filp,
void *buffer, size_t *lenp);
-
static ctl_table root_table[];
-static LIST_HEAD(root_table_header);
+static struct ctl_table_header root_table_header =
+ { root_table, LIST_HEAD_INIT(root_table_header.ctl_entry) };
static ctl_table kern_table[];
static ctl_table vm_table[];
@@ -99,7 +101,6 @@ static ctl_table debug_table[];
static ctl_table dev_table[];
extern ctl_table random_table[];
-
/* /proc declarations: */
#ifdef CONFIG_PROC_FS
@@ -108,14 +109,12 @@ static ssize_t proc_readsys(struct file *, char *, size_t, loff_t *);
static ssize_t proc_writesys(struct file *, const char *, size_t, loff_t *);
static int proc_sys_permission(struct inode *, int);
-struct file_operations proc_sys_file_operations =
-{
+struct file_operations proc_sys_file_operations = {
read: proc_readsys,
write: proc_writesys,
};
-static struct inode_operations proc_sys_inode_operations =
-{
+static struct inode_operations proc_sys_inode_operations = {
permission: proc_sys_permission,
};
@@ -124,6 +123,7 @@ extern struct proc_dir_entry *proc_sys_root;
static void register_proc_table(ctl_table *, struct proc_dir_entry *);
static void unregister_proc_table(ctl_table *, struct proc_dir_entry *);
#endif
+
extern int inodes_stat[];
extern int dentry_stat[];
@@ -294,39 +294,33 @@ void __init sysctl_init(void)
register_proc_table(root_table, proc_sys_root);
init_irq_proc();
#endif
-
}
-int do_sysctl (int *name, int nlen,
- void *oldval, size_t *oldlenp,
+int do_sysctl(int *name, int nlen, void *oldval, size_t *oldlenp,
void *newval, size_t newlen)
{
- int error;
struct list_head *tmp;
- void *context;
-
+
if (nlen == 0 || nlen >= CTL_MAXNAME)
return -ENOTDIR;
-
- if (oldval)
- {
+ if (oldval) {
int old_len;
- if (!oldlenp)
- return -EFAULT;
- if(get_user(old_len, oldlenp))
+ if (!oldlenp || get_user(old_len, oldlenp))
return -EFAULT;
}
- list_for_each(tmp, &root_table_header) {
+ tmp = &root_table_header.ctl_entry;
+ do {
struct ctl_table_header *head =
list_entry(tmp, struct ctl_table_header, ctl_entry);
- context = NULL;
- error = parse_table(name, nlen, oldval, oldlenp,
- newval, newlen, head->ctl_table, &context);
+ void *context = NULL;
+ int error = parse_table(name, nlen, oldval, oldlenp,
+ newval, newlen, head->ctl_table,
+ &context);
if (context)
kfree(context);
if (error != -ENOTDIR)
return error;
- }
+ } while (tmp != &root_table_header.ctl_entry);
return -ENOTDIR;
}
@@ -335,7 +329,7 @@ extern asmlinkage long sys_sysctl(struct __sysctl_args *args)
struct __sysctl_args tmp;
int error;
- if(copy_from_user(&tmp, args, sizeof(tmp)))
+ if (copy_from_user(&tmp, args, sizeof(tmp)))
return -EFAULT;
lock_kernel();
@@ -345,9 +339,10 @@ extern asmlinkage long sys_sysctl(struct __sysctl_args *args)
return error;
}
-
-/* ctl_perm does NOT grant the superuser all rights automatically, because
- some sysctl variables are readonly even to root. */
+/*
+ * ctl_perm does NOT grant the superuser all rights automatically, because
+ * some sysctl variables are readonly even to root.
+ */
static int test_perm(int mode, int op)
{
@@ -370,17 +365,16 @@ static int parse_table(int *name, int nlen,
void *newval, size_t newlen,
ctl_table *table, void **context)
{
- int error;
repeat:
if (!nlen)
return -ENOTDIR;
for ( ; table->ctl_name; table++) {
int n;
- if(get_user(n,name))
+ if (get_user(n, name))
return -EFAULT;
- if (n == table->ctl_name ||
- table->ctl_name == CTL_ANY) {
+ if (n == table->ctl_name || table->ctl_name == CTL_ANY) {
+ int error;
if (table->child) {
if (ctl_perm(table, 001))
return -EPERM;
@@ -389,8 +383,8 @@ repeat:
table, name, nlen,
oldval, oldlenp,
newval, newlen, context);
- if (error)
- return error;
+ if (error)
+ return error;
}
name++;
nlen--;
@@ -465,9 +459,9 @@ struct ctl_table_header *register_sysctl_table(ctl_table * table,
tmp->ctl_table = table;
INIT_LIST_HEAD(&tmp->ctl_entry);
if (insert_at_head)
- list_add(&tmp->ctl_entry, &root_table_header);
+ list_add(&tmp->ctl_entry, &root_table_header.ctl_entry);
else
- list_add_tail(&tmp->ctl_entry, &root_table_header);
+ list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry);
#ifdef CONFIG_PROC_FS
register_proc_table(table, proc_sys_root);
#endif
@@ -694,6 +688,7 @@ static int proc_doutsstring(ctl_table *table, int write, struct file *filp,
#define OP_OR 2
#define OP_MAX 3
#define OP_MIN 4
+
static int do_proc_dointvec(ctl_table *table, int write, struct file *filp,
void *buffer, size_t *lenp, int conv, int op)
{
@@ -812,7 +807,6 @@ int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
(current->pid == 1) ? OP_SET : OP_AND);
}
-
int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
void *buffer, size_t *lenp)
{
@@ -911,7 +905,6 @@ int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
return 0;
}
-
/*
* an unsigned long function version
*/