summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/.cvsignore1
-rw-r--r--kernel/Makefile5
-rw-r--r--kernel/acct.c11
-rw-r--r--kernel/exit.c5
-rw-r--r--kernel/fork.c22
-rw-r--r--kernel/ksyms.c23
-rw-r--r--kernel/module.c49
-rw-r--r--kernel/panic.c3
-rw-r--r--kernel/printk.c79
-rw-r--r--kernel/sched.c42
-rw-r--r--kernel/signal.c80
-rw-r--r--kernel/softirq.c6
-rw-r--r--kernel/sysctl.c30
-rw-r--r--kernel/time.c106
14 files changed, 274 insertions, 188 deletions
diff --git a/kernel/.cvsignore b/kernel/.cvsignore
index 4671378ae..857dd22e9 100644
--- a/kernel/.cvsignore
+++ b/kernel/.cvsignore
@@ -1 +1,2 @@
.depend
+.*.flags
diff --git a/kernel/Makefile b/kernel/Makefile
index a728719ef..ff908f68a 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -21,7 +21,6 @@ ifeq ($(CONFIG_MODULES),y)
OX_OBJS += ksyms.o
endif
-include $(TOPDIR)/Rules.make
+CFLAGS_sched.o := $(PROFILING) -fno-omit-frame-pointer
-sched.o: sched.c
- $(CC) $(CFLAGS) $(PROFILING) -fno-omit-frame-pointer -c $<
+include $(TOPDIR)/Rules.make
diff --git a/kernel/acct.c b/kernel/acct.c
index 27f99ff92..4229b9ebf 100644
--- a/kernel/acct.c
+++ b/kernel/acct.c
@@ -36,6 +36,7 @@
#include <linux/major.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
+#include <linux/file.h>
#include <asm/uaccess.h>
@@ -52,8 +53,6 @@
/*
* External references and all of the globals.
*/
-extern int close_fp(struct file *);
-
void acct_timeout(unsigned long);
static volatile int acct_active = 0;
@@ -129,7 +128,7 @@ asmlinkage int sys_acct(const char *name)
del_timer(&acct_timer);
acct_active = 0;
acct_needcheck = 0;
- close_fp(acct_file);
+ fput(acct_file);
}
error = 0;
goto out;
@@ -268,8 +267,8 @@ int acct_process(long exitcode)
/*
- * Fill the accounting struct with the needed info as recorded by the different
- * kernel functions.
+ * Fill the accounting struct with the needed info as recorded
+ * by the different kernel functions.
*/
memset((caddr_t)&ac, 0, sizeof(struct acct));
@@ -304,7 +303,7 @@ int acct_process(long exitcode)
}
vsize = vsize / 1024;
ac.ac_mem = encode_comp_t(vsize);
- ac.ac_io = encode_comp_t(current->io_usage);
+ ac.ac_io = encode_comp_t(0 /* current->io_usage */); /* %% */
ac.ac_rw = encode_comp_t(ac.ac_io / 1024);
ac.ac_minflt = encode_comp_t(current->min_flt);
ac.ac_majflt = encode_comp_t(current->maj_flt);
diff --git a/kernel/exit.c b/kernel/exit.c
index a01317af8..9824f5806 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -164,7 +164,7 @@ static inline void close_files(struct files_struct * files)
struct file * file = files->fd[i];
if (file) {
files->fd[i] = NULL;
- close_fp(file);
+ close_fp(file, files);
}
}
i++;
@@ -418,8 +418,7 @@ repeat:
if (ru != NULL)
getrusage(p, RUSAGE_BOTH, ru);
if (stat_addr)
- __put_user((p->exit_code << 8) | 0x7f,
- stat_addr);
+ __put_user((p->exit_code << 8) | 0x7f, stat_addr);
p->exit_code = 0;
retval = p->pid;
goto end_wait4;
diff --git a/kernel/fork.c b/kernel/fork.c
index 75430ddbc..38c98b0a8 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -211,7 +211,7 @@ static inline int dup_mmap(struct mm_struct * mm)
flush_cache_mm(current->mm);
pprev = &mm->mmap;
for (mpnt = current->mm->mmap ; mpnt ; mpnt = mpnt->vm_next) {
- struct dentry *dentry;
+ struct file *file;
retval = -ENOMEM;
tmp = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
@@ -220,12 +220,13 @@ static inline int dup_mmap(struct mm_struct * mm)
*tmp = *mpnt;
tmp->vm_flags &= ~VM_LOCKED;
tmp->vm_mm = mm;
+ mm->map_count++;
tmp->vm_next = NULL;
- dentry = tmp->vm_dentry;
- if (dentry) {
- dget(dentry);
+ file = tmp->vm_file;
+ if (file) {
+ file->f_count++;
if (tmp->vm_flags & VM_DENYWRITE)
- dentry->d_inode->i_writecount--;
+ file->f_dentry->d_inode->i_writecount--;
/* insert tmp into the share list, just after mpnt */
if((tmp->vm_next_share = mpnt->vm_next_share) != NULL)
@@ -272,6 +273,7 @@ struct mm_struct * mm_alloc(void)
*mm = *current->mm;
init_new_context(mm);
mm->count = 1;
+ mm->map_count = 0;
mm->def_flags = 0;
mm->mmap_sem = MUTEX;
/*
@@ -480,8 +482,14 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs)
p->times.tms_utime = p->times.tms_stime = 0;
p->times.tms_cutime = p->times.tms_cstime = 0;
#ifdef __SMP__
- p->has_cpu = 0;
- p->processor = NO_PROC_ID;
+ {
+ int i;
+ p->has_cpu = 0;
+ p->processor = NO_PROC_ID;
+ /* ?? should we just memset this ?? */
+ for(i = 0; i < smp_num_cpus; i++)
+ p->per_cpu_utime[i] = p->per_cpu_stime[i] = 0;
+ }
#endif
p->lock_depth = 0;
p->start_time = jiffies;
diff --git a/kernel/ksyms.c b/kernel/ksyms.c
index a66acd361..869e5e5bb 100644
--- a/kernel/ksyms.c
+++ b/kernel/ksyms.c
@@ -50,6 +50,7 @@
#include <linux/swap.h>
#include <linux/ctype.h>
#include <linux/file.h>
+#include <linux/console.h>
extern unsigned char aux_device_present, kbd_read_mask;
@@ -69,7 +70,7 @@ extern unsigned char aux_device_present, kbd_read_mask;
#endif
extern char *get_options(char *str, int *ints);
-extern void set_device_ro(int dev,int flag);
+extern void set_device_ro(kdev_t dev,int flag);
extern struct file_operations * get_blkfops(unsigned int);
extern int blkdev_release(struct inode * inode);
#if !defined(CONFIG_NFSD) && defined(CONFIG_NFSD_MODULE)
@@ -99,7 +100,6 @@ EXPORT_SYMBOL(kerneld_send);
EXPORT_SYMBOL(get_options);
#ifdef CONFIG_PCI
-/* PCI BIOS support */
EXPORT_SYMBOL(pcibios_present);
EXPORT_SYMBOL(pcibios_find_class);
EXPORT_SYMBOL(pcibios_find_device);
@@ -110,8 +110,6 @@ EXPORT_SYMBOL(pcibios_write_config_byte);
EXPORT_SYMBOL(pcibios_write_config_word);
EXPORT_SYMBOL(pcibios_write_config_dword);
EXPORT_SYMBOL(pcibios_strerror);
-EXPORT_SYMBOL(pci_strvendor);
-EXPORT_SYMBOL(pci_strdev);
#endif
/* process memory management */
@@ -119,6 +117,8 @@ EXPORT_SYMBOL(do_mmap);
EXPORT_SYMBOL(do_munmap);
EXPORT_SYMBOL(exit_mm);
EXPORT_SYMBOL(exit_files);
+EXPORT_SYMBOL(exit_fs);
+EXPORT_SYMBOL(exit_sighand);
/* internal kernel memory management */
EXPORT_SYMBOL(__get_free_pages);
@@ -143,6 +143,7 @@ EXPORT_SYMBOL(update_vm_cache);
EXPORT_SYMBOL(vmtruncate);
/* filesystem internal functions */
+EXPORT_SYMBOL(update_atime);
EXPORT_SYMBOL(get_super);
EXPORT_SYMBOL(getname);
EXPORT_SYMBOL(putname);
@@ -153,7 +154,6 @@ EXPORT_SYMBOL(__namei);
EXPORT_SYMBOL(lookup_dentry);
EXPORT_SYMBOL(open_namei);
EXPORT_SYMBOL(sys_close);
-EXPORT_SYMBOL(close_fp);
EXPORT_SYMBOL(d_alloc_root);
EXPORT_SYMBOL(d_delete);
EXPORT_SYMBOL(d_validate);
@@ -196,6 +196,7 @@ EXPORT_SYMBOL(posix_lock_file);
EXPORT_SYMBOL(posix_test_lock);
EXPORT_SYMBOL(posix_block_lock);
EXPORT_SYMBOL(posix_unblock_lock);
+EXPORT_SYMBOL(locks_remove_flock);
EXPORT_SYMBOL(dput);
EXPORT_SYMBOL(get_cached_page);
EXPORT_SYMBOL(put_cached_page);
@@ -203,6 +204,7 @@ EXPORT_SYMBOL(prune_dcache);
EXPORT_SYMBOL(shrink_dcache_sb);
EXPORT_SYMBOL(shrink_dcache_parent);
EXPORT_SYMBOL(find_inode_number);
+EXPORT_SYMBOL(is_subdir);
#if !defined(CONFIG_NFSD) && defined(CONFIG_NFSD_MODULE)
EXPORT_SYMBOL(do_nfsservctl);
@@ -238,9 +240,10 @@ EXPORT_SYMBOL(resetup_one_dev);
EXPORT_SYMBOL(unplug_device);
EXPORT_SYMBOL(make_request);
EXPORT_SYMBOL(tq_disk);
-EXPORT_SYMBOL(efind_buffer);
+EXPORT_SYMBOL(find_buffer);
EXPORT_SYMBOL(init_buffer);
EXPORT_SYMBOL(max_sectors);
+EXPORT_SYMBOL(max_readahead);
/* tty routines */
EXPORT_SYMBOL(tty_hangup);
@@ -321,8 +324,7 @@ EXPORT_SYMBOL(request_region);
EXPORT_SYMBOL(release_region);
/* process management */
-EXPORT_SYMBOL(wake_up);
-EXPORT_SYMBOL(wake_up_interruptible);
+EXPORT_SYMBOL(__wake_up);
EXPORT_SYMBOL(sleep_on);
EXPORT_SYMBOL(interruptible_sleep_on);
EXPORT_SYMBOL(schedule);
@@ -379,6 +381,7 @@ EXPORT_SYMBOL(read_ahead);
EXPORT_SYMBOL(get_hash_table);
EXPORT_SYMBOL(get_empty_inode);
EXPORT_SYMBOL(insert_inode_hash);
+EXPORT_SYMBOL(remove_inode_hash);
EXPORT_SYMBOL(make_bad_inode);
EXPORT_SYMBOL(is_bad_inode);
EXPORT_SYMBOL(event);
@@ -403,3 +406,7 @@ EXPORT_SYMBOL(disk_name); /* for md.c */
/* binfmt_aout */
EXPORT_SYMBOL(get_write_access);
EXPORT_SYMBOL(put_write_access);
+
+/* dynamic registering of consoles */
+EXPORT_SYMBOL(register_console);
+EXPORT_SYMBOL(unregister_console);
diff --git a/kernel/module.c b/kernel/module.c
index 83479fa03..efee5902e 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -54,7 +54,7 @@ struct module *module_list = &kernel_module;
static long get_mod_name(const char *user_name, char **buf);
static void put_mod_name(char *buf);
static struct module *find_module(const char *name);
-static void free_module(struct module *);
+static void free_module(struct module *, int tag_freed);
/*
@@ -305,17 +305,17 @@ sys_init_module(const char *name_user, struct module *mod_user)
for (i = 0, dep = mod->deps; i < mod->ndeps; ++i, ++dep) {
struct module *o, *d = dep->dep;
- /* Make sure the indicated dependancies are really modules. */
+ /* Make sure the indicated dependencies are really modules. */
if (d == mod) {
printk(KERN_ERR "init_module: self-referential "
- "dependancy in mod->deps.\n");
+ "dependency in mod->deps.\n");
goto err3;
}
for (o = module_list; o != &kernel_module; o = o->next)
if (o == d) goto found_dep;
- printk(KERN_ERR "init_module: found dependancy that is "
+ printk(KERN_ERR "init_module: found dependency that is "
"(no longer?) a module.\n");
goto err3;
@@ -363,6 +363,7 @@ sys_delete_module(const char *name_user)
struct module *mod, *next;
char *name;
long error = -EPERM;
+ int something_changed;
lock_kernel();
if (!suser())
@@ -386,25 +387,35 @@ sys_delete_module(const char *name_user)
if (mod->refs != NULL || __MOD_IN_USE(mod))
goto out;
- free_module(mod);
+ free_module(mod, 0);
error = 0;
goto out;
}
/* Do automatic reaping */
+restart:
+ something_changed = 0;
for (mod = module_list; mod != &kernel_module; mod = next) {
next = mod->next;
- if (mod->refs == NULL &&
- ((mod->flags
- & (MOD_AUTOCLEAN|MOD_RUNNING|MOD_DELETED|MOD_USED_ONCE))
- == (MOD_AUTOCLEAN|MOD_RUNNING|MOD_USED_ONCE)) &&
- !__MOD_IN_USE(mod)) {
- if (mod->flags & MOD_VISITED)
+ if (mod->refs == NULL
+ && (mod->flags & MOD_AUTOCLEAN)
+ && (mod->flags & MOD_RUNNING)
+ && !(mod->flags & MOD_DELETED)
+ && (mod->flags & MOD_USED_ONCE)
+ && !__MOD_IN_USE(mod)) {
+ if ((mod->flags & MOD_VISITED)
+ && !(mod->flags & MOD_JUST_FREED)) {
mod->flags &= ~MOD_VISITED;
- else
- free_module(mod);
+ } else {
+ free_module(mod, 1);
+ something_changed = 1;
+ }
}
}
+ if (something_changed)
+ goto restart;
+ for (mod = module_list; mod != &kernel_module; mod = mod->next)
+ mod->flags &= ~MOD_JUST_FREED;
error = 0;
out:
unlock_kernel();
@@ -764,7 +775,7 @@ find_module(const char *name)
*/
static void
-free_module(struct module *mod)
+free_module(struct module *mod, int tag_freed)
{
struct module_ref *dep;
unsigned i;
@@ -772,18 +783,22 @@ free_module(struct module *mod)
/* Let the module clean up. */
mod->flags |= MOD_DELETED;
- if (mod->flags & MOD_RUNNING) {
- mod->cleanup();
+ if (mod->flags & MOD_RUNNING)
+ {
+ if(mod->cleanup)
+ mod->cleanup();
mod->flags &= ~MOD_RUNNING;
}
- /* Remove the module from the dependancy lists. */
+ /* Remove the module from the dependency lists. */
for (i = 0, dep = mod->deps; i < mod->ndeps; ++i, ++dep) {
struct module_ref **pp;
for (pp = &dep->dep->refs; *pp != dep; pp = &(*pp)->next_ref)
continue;
*pp = dep->next_ref;
+ if (tag_freed && dep->dep->refs == NULL)
+ dep->dep->flags |= MOD_JUST_FREED;
}
/* And from the main module list. */
diff --git a/kernel/panic.c b/kernel/panic.c
index 255997676..bd106a9ec 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -17,6 +17,7 @@
#include <linux/reboot.h>
#include <linux/init.h>
#include <linux/sysrq.h>
+#include <linux/interrupt.h>
asmlinkage void sys_sync(void); /* it's really int */
extern void unblank_console(void);
@@ -41,6 +42,8 @@ NORET_TYPE void panic(const char * fmt, ...)
printk(KERN_EMERG "Kernel panic: %s\n",buf);
if (current == task[0])
printk(KERN_EMERG "In swapper task - not syncing\n");
+ else if (in_interrupt())
+ printk(KERN_EMERG "In interrupt handler - not syncing\n");
else
sys_sync();
diff --git a/kernel/printk.c b/kernel/printk.c
index 91bc771f2..afc178c5e 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -61,36 +61,49 @@ static int selected_console = 0;
*/
__initfunc(void console_setup(char *str, int *ints))
{
- char *s;
- int i;
struct console_cmdline *c;
+ char name[sizeof(c->name)];
+ char *s, *options;
+ int i, idx;
- for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
- ;
- if (i == MAX_CMDLINECONSOLES)
- return;
- c = &console_cmdline[i];
- selected_console = 1;
-
+ /*
+ * Decode str into name, index, options.
+ */
if (str[0] >= '0' && str[0] <= '9') {
- strcpy(c->name, "ttyS");
- strncpy(c->name + 4, str, sizeof(c->name) - 5);
+ strcpy(name, "ttyS");
+ strncpy(name + 4, str, sizeof(name) - 5);
} else
- strncpy(c->name, str, sizeof(c->name) - 1);
- if ((c->options = strchr(str, ',')) != NULL)
- *(c->options++) = 0;
+ strncpy(name, str, sizeof(name) - 1);
+ name[sizeof(name) - 1] = 0;
+ if ((options = strchr(str, ',')) != NULL)
+ *(options++) = 0;
#ifdef __sparc__
if (!strcmp(str, "ttya"))
- strcpy(c->name, "ttyS0");
+ strcpy(name, "ttyS0");
if (!strcmp(str, "ttyb"))
- strcpy(c->name, "ttyS1");
+ strcpy(name, "ttyS1");
#endif
-
- for(s = c->name; *s; s++)
+ for(s = name; *s; s++)
if (*s >= '0' && *s <= '9')
break;
- c->index = simple_strtoul(s, NULL, 10);
+ idx = simple_strtoul(s, NULL, 10);
*s = 0;
+
+ /*
+ * See if this tty is not yet registered, and
+ * if we have a slot free.
+ */
+ for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
+ if (strcmp(console_cmdline[i].name, name) == 0 &&
+ console_cmdline[i].index == idx)
+ return;
+ if (i == MAX_CMDLINECONSOLES)
+ return;
+ selected_console = 1;
+ c = &console_cmdline[i];
+ memcpy(c->name, name, sizeof(c->name));
+ c->options = options;
+ c->index = idx;
}
@@ -218,6 +231,7 @@ out:
return error;
}
+spinlock_t console_lock;
asmlinkage int printk(const char *fmt, ...)
{
@@ -228,8 +242,7 @@ asmlinkage int printk(const char *fmt, ...)
static signed char msg_level = -1;
long flags;
- __save_flags(flags);
- __cli();
+ spin_lock_irqsave(&console_lock, flags);
va_start(args, fmt);
i = vsprintf(buf + 3, fmt, args); /* hopefully i < sizeof(buf)-4 */
buf_end = buf + 3 + i;
@@ -277,7 +290,7 @@ asmlinkage int printk(const char *fmt, ...)
if (line_feed)
msg_level = -1;
}
- __restore_flags(flags);
+ spin_unlock_irqrestore(&console_lock, flags);
wake_up_interruptible(&log_wait);
return i;
}
@@ -324,6 +337,8 @@ void register_console(struct console * console)
* that registers here.
*/
if (selected_console == 0) {
+ if (console->index < 0)
+ console->index = 0;
if (console->setup == NULL ||
console->setup(console, NULL) == 0) {
console->flags |= CON_ENABLED | CON_FIRST;
@@ -392,6 +407,26 @@ void register_console(struct console * console)
}
}
+
+int unregister_console(struct console * console)
+{
+ struct console *a,*b;
+
+ if (console_drivers == console) {
+ console_drivers=console->next;
+ return (0);
+ }
+ for (a=console_drivers->next, b=console_drivers ;
+ a; b=a, a=b->next) {
+ if (a == console) {
+ b->next = a->next;
+ return 0;
+ }
+ }
+
+ return (1);
+}
+
/*
* Write a message to a certain tty, not just the console. This is used for
* messages that need to be redirected to a specific tty.
diff --git a/kernel/sched.c b/kernel/sched.c
index cfaea2116..f48f520ff 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -104,6 +104,8 @@ struct task_struct * task[NR_TASKS] = {&init_task, };
struct kernel_stat kstat = { 0 };
+void scheduling_functions_start_here(void) { }
+
static inline void add_to_runqueue(struct task_struct * p)
{
if (p->policy != SCHED_OTHER || p->counter > current->counter + 3)
@@ -142,7 +144,6 @@ static inline void move_last_runqueue(struct task_struct * p)
prev->next_run = p;
}
-#ifdef __SMP__
/*
* The tasklist_lock protects the linked list of processes.
*
@@ -156,8 +157,7 @@ static inline void move_last_runqueue(struct task_struct * p)
*/
rwlock_t tasklist_lock = RW_LOCK_UNLOCKED;
spinlock_t scheduler_lock = SPIN_LOCK_UNLOCKED;
-static spinlock_t runqueue_lock = SPIN_LOCK_UNLOCKED;
-#endif
+spinlock_t runqueue_lock = SPIN_LOCK_UNLOCKED;
/*
* Wake up a process. Put it on the run-queue if it's not
@@ -313,7 +313,7 @@ static inline void internal_add_timer(struct timer_list *timer)
}
}
-static spinlock_t timerlist_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t timerlist_lock = SPIN_LOCK_UNLOCKED;
void add_timer(struct timer_list *timer)
{
@@ -387,6 +387,8 @@ asmlinkage void schedule(void)
this_cpu = smp_processor_id();
if (local_irq_count[this_cpu])
goto scheduling_in_interrupt;
+ if (local_bh_count[this_cpu])
+ goto scheduling_in_interrupt;
release_kernel_lock(prev, this_cpu, lock_depth);
if (bh_active & bh_mask)
do_bottom_half();
@@ -505,27 +507,7 @@ rwlock_t waitqueue_lock = RW_LOCK_UNLOCKED;
* have to protect against interrupts), as the actual removal from the
* queue is handled by the process itself.
*/
-void wake_up(struct wait_queue **q)
-{
- struct wait_queue *next;
-
- read_lock(&waitqueue_lock);
- if (q && (next = *q)) {
- struct wait_queue *head;
-
- head = WAIT_QUEUE_HEAD(q);
- while (next != head) {
- struct task_struct *p = next->task;
- next = next->next;
- if ((p->state == TASK_UNINTERRUPTIBLE) ||
- (p->state == TASK_INTERRUPTIBLE))
- wake_up_process(p);
- }
- }
- read_unlock(&waitqueue_lock);
-}
-
-void wake_up_interruptible(struct wait_queue **q)
+void __wake_up(struct wait_queue **q, unsigned int mode)
{
struct wait_queue *next;
@@ -537,7 +519,7 @@ void wake_up_interruptible(struct wait_queue **q)
while (next != head) {
struct task_struct *p = next->task;
next = next->next;
- if (p->state == TASK_INTERRUPTIBLE)
+ if (p->state & mode)
wake_up_process(p);
}
}
@@ -678,6 +660,8 @@ void sleep_on(struct wait_queue **p)
__sleep_on(p,TASK_UNINTERRUPTIBLE);
}
+void scheduling_functions_end_here(void) { }
+
static inline void cascade_timers(struct timer_vec *tv)
{
/* cascade all the timers from tv up one level */
@@ -1027,8 +1011,10 @@ static inline void do_it_prof(struct task_struct * p, unsigned long ticks)
}
void update_one_process(struct task_struct *p,
- unsigned long ticks, unsigned long user, unsigned long system)
+ unsigned long ticks, unsigned long user, unsigned long system, int cpu)
{
+ p->per_cpu_utime[cpu] += user;
+ p->per_cpu_stime[cpu] += system;
do_process_times(p, user, system);
do_it_virt(p, user);
do_it_prof(p, ticks);
@@ -1054,7 +1040,7 @@ static void update_process_times(unsigned long ticks, unsigned long system)
kstat.cpu_user += user;
kstat.cpu_system += system;
}
- update_one_process(p, ticks, user, system);
+ update_one_process(p, ticks, user, system, 0);
#endif
}
diff --git a/kernel/signal.c b/kernel/signal.c
index 25168d989..53228eb31 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -583,23 +583,27 @@ EXPORT_SYMBOL(send_sig_info);
asmlinkage int
sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, size_t sigsetsize)
{
+ int error = -EINVAL;
sigset_t old_set, new_set;
/* XXX: Don't preclude handling different sized sigset_t's. */
if (sigsetsize != sizeof(sigset_t))
- return -EINVAL;
+ goto out;
if (set) {
+ error = -EFAULT;
if (copy_from_user(&new_set, set, sizeof(*set)))
- return -EFAULT;
+ goto out;
sigdelsetmask(&new_set, sigmask(SIGKILL)|sigmask(SIGSTOP));
spin_lock_irq(&current->sigmask_lock);
old_set = current->blocked;
+ error = 0;
switch (how) {
default:
- return -EINVAL;
+ error = -EINVAL;
+ break;
case SIG_BLOCK:
sigorsets(&new_set, &old_set, &new_set);
break;
@@ -613,47 +617,54 @@ sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, size_t sigsetsize)
current->blocked = new_set;
recalc_sigpending(current);
spin_unlock_irq(&current->sigmask_lock);
-
- if (oset) {
- if (copy_to_user(oset, &old_set, sizeof(*oset)))
- return -EFAULT;
- }
+ if (error)
+ goto out;
+ if (oset)
+ goto set_old;
} else if (oset) {
spin_lock_irq(&current->sigmask_lock);
old_set = current->blocked;
spin_unlock_irq(&current->sigmask_lock);
+ set_old:
+ error = -EFAULT;
if (copy_to_user(oset, &old_set, sizeof(*oset)))
- return -EFAULT;
+ goto out;
}
-
- return 0;
+ error = 0;
+out:
+ return error;
}
asmlinkage int
sys_rt_sigpending(sigset_t *set, size_t sigsetsize)
{
+ int error = -EINVAL;
sigset_t pending;
/* XXX: Don't preclude handling different sized sigset_t's. */
if (sigsetsize != sizeof(sigset_t))
- return -EINVAL;
+ goto out;
spin_lock_irq(&current->sigmask_lock);
sigandsets(&pending, &current->blocked, &current->signal);
spin_unlock_irq(&current->sigmask_lock);
- return copy_to_user(set, &pending, sizeof(*set));
+ error = -EFAULT;
+ if (!copy_to_user(set, &pending, sizeof(*set)))
+ error = 0;
+out:
+ return error;
}
asmlinkage int
sys_rt_sigtimedwait(const sigset_t *uthese, siginfo_t *uinfo,
const struct timespec *uts, size_t sigsetsize)
{
+ int ret, sig;
sigset_t these;
struct timespec ts;
siginfo_t info;
- int ret, sig;
/* XXX: Don't preclude handling different sized sigset_t's. */
if (sigsetsize != sizeof(sigset_t))
@@ -747,6 +758,7 @@ sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo)
Nor can they impersonate a kill(), which adds source info. */
if (info.si_code >= 0)
return -EPERM;
+ info.si_signo = sig;
/* POSIX.1b doesn't mention process groups. */
return kill_proc_info(sig, &info, pid);
@@ -825,19 +837,23 @@ do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact)
asmlinkage int
sys_sigprocmask(int how, old_sigset_t *set, old_sigset_t *oset)
{
+ int error;
old_sigset_t old_set, new_set;
if (set) {
+ error = -EFAULT;
if (copy_from_user(&new_set, set, sizeof(*set)))
- return -EFAULT;
+ goto out;
new_set &= ~(sigmask(SIGKILL)|sigmask(SIGSTOP));
spin_lock_irq(&current->sigmask_lock);
old_set = current->blocked.sig[0];
+ error = 0;
switch (how) {
default:
- return -EINVAL;
+ error = -EINVAL;
+ break;
case SIG_BLOCK:
sigaddsetmask(&current->blocked, new_set);
break;
@@ -845,36 +861,42 @@ sys_sigprocmask(int how, old_sigset_t *set, old_sigset_t *oset)
sigdelsetmask(&current->blocked, new_set);
break;
case SIG_SETMASK:
- siginitset(&current->blocked, new_set);
+ current->blocked.sig[0] = new_set;
break;
}
recalc_sigpending(current);
spin_unlock_irq(&current->sigmask_lock);
-
- if (oset) {
- if (copy_to_user(oset, &old_set, sizeof(*oset)))
- return -EFAULT;
- }
+ if (error)
+ goto out;
+ if (oset)
+ goto set_old;
} else if (oset) {
old_set = current->blocked.sig[0];
+ set_old:
+ error = -EFAULT;
if (copy_to_user(oset, &old_set, sizeof(*oset)))
- return -EFAULT;
+ goto out;
}
-
- return 0;
+ error = 0;
+out:
+ return error;
}
asmlinkage int
sys_sigpending(old_sigset_t *set)
{
+ int error;
old_sigset_t pending;
spin_lock_irq(&current->sigmask_lock);
pending = current->blocked.sig[0] & current->signal.sig[0];
spin_unlock_irq(&current->sigmask_lock);
- return copy_to_user(set, &pending, sizeof(*set));
+ error = -EFAULT;
+ if (!copy_to_user(set, &pending, sizeof(*set)))
+ error = 0;
+ return error;
}
asmlinkage int
@@ -882,11 +904,11 @@ sys_rt_sigaction(int sig, const struct sigaction *act, struct sigaction *oact,
size_t sigsetsize)
{
struct k_sigaction new_sa, old_sa;
- int ret;
+ int ret = -EINVAL;
/* XXX: Don't preclude handling different sized sigset_t's. */
if (sigsetsize != sizeof(sigset_t))
- return -EINVAL;
+ goto out;
if (act) {
if (copy_from_user(&new_sa.sa, act, sizeof(new_sa.sa)))
@@ -899,7 +921,7 @@ sys_rt_sigaction(int sig, const struct sigaction *act, struct sigaction *oact,
if (copy_to_user(oact, &old_sa.sa, sizeof(old_sa.sa)))
return -EFAULT;
}
-
+out:
return ret;
}
#endif
diff --git a/kernel/softirq.c b/kernel/softirq.c
index de398bcff..4bc5ee4b6 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -62,14 +62,14 @@ static inline void run_bottom_halves(void)
asmlinkage void do_bottom_half(void)
{
- if (softirq_trylock()) {
- int cpu = smp_processor_id();
+ int cpu = smp_processor_id();
+ if (softirq_trylock(cpu)) {
if (hardirq_trylock(cpu)) {
__sti();
run_bottom_halves();
hardirq_endlock(cpu);
}
- softirq_endlock();
+ softirq_endlock(cpu);
}
}
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 12abcefef..1b93ad7bd 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -160,12 +160,6 @@ static ctl_table kern_table[] = {
{KERN_REALROOTDEV, "real-root-dev", &real_root_dev, sizeof(int),
0644, NULL, &proc_dointvec},
#endif
-#ifdef CONFIG_ROOT_NFS
- {KERN_NFSRNAME, "nfs-root-name", nfs_root_name, NFS_ROOT_NAME_LEN,
- 0644, NULL, &proc_dostring, &sysctl_string },
- {KERN_NFSRADDRS, "nfs-root-addrs", nfs_root_addrs, NFS_ROOT_ADDRS_LEN,
- 0644, NULL, &proc_dostring, &sysctl_string },
-#endif
#ifdef CONFIG_BINFMT_JAVA
{KERN_JAVA_INTERPRETER, "java-interpreter", binfmt_java_interpreter,
64, 0644, NULL, &proc_dostring, &sysctl_string },
@@ -441,12 +435,16 @@ struct ctl_table_header *register_sysctl_table(ctl_table * table,
return tmp;
}
-void unregister_sysctl_table(struct ctl_table_header * table)
+/*
+ * Unlink and free a ctl_table.
+ */
+void unregister_sysctl_table(struct ctl_table_header * header)
{
- DLIST_DELETE(table, ctl_entry);
+ DLIST_DELETE(header, ctl_entry);
#ifdef CONFIG_PROC_FS
- unregister_proc_table(table->ctl_table, &proc_sys_root);
+ unregister_proc_table(header->ctl_table, &proc_sys_root);
#endif
+ kfree(header);
}
/*
@@ -463,18 +461,20 @@ static void register_proc_table(ctl_table * table, struct proc_dir_entry *root)
mode_t mode;
for (; table->ctl_name; table++) {
- de = 0;
/* Can't do anything without a proc name. */
if (!table->procname)
continue;
/* Maybe we can't do anything with it... */
- if (!table->proc_handler &&
- !table->child)
+ if (!table->proc_handler && !table->child) {
+ printk(KERN_WARNING "SYSCTL: Can't register %s\n",
+ table->procname);
continue;
+ }
len = strlen(table->procname);
mode = table->mode;
+ de = NULL;
if (table->proc_handler)
mode |= S_IFREG;
else {
@@ -501,6 +501,9 @@ static void register_proc_table(ctl_table * table, struct proc_dir_entry *root)
}
}
+/*
+ * Unregister a /proc sysctl table and any subdirectories.
+ */
static void unregister_proc_table(ctl_table * table, struct proc_dir_entry *root)
{
struct proc_dir_entry *de;
@@ -518,8 +521,9 @@ static void unregister_proc_table(ctl_table * table, struct proc_dir_entry *root
entries... */
if (!((de->mode & S_IFDIR) && de->subdir)) {
proc_unregister(root, de->low_ino);
+ table->de = NULL;
kfree(de);
- }
+ }
}
}
diff --git a/kernel/time.c b/kernel/time.c
index 7927c2aa1..e16a7a150 100644
--- a/kernel/time.c
+++ b/kernel/time.c
@@ -216,32 +216,24 @@ void (*hardpps_ptr)(struct timeval *) = (void (*)(struct timeval *))0;
/* adjtimex mainly allows reading (and writing, if superuser) of
* kernel time-keeping variables. used by xntpd.
*/
-asmlinkage int sys_adjtimex(struct timex *txc_p)
+int do_adjtimex(struct timex *txc)
{
long ltemp, mtemp, save_adjust;
- struct timex txc; /* Local copy of parameter */
-
- /* Copy the user data space into the kernel copy
- * structure. But bear in mind that the structures
- * may change
- */
- if(copy_from_user(&txc, txc_p, sizeof(struct timex)))
- return -EFAULT;
/* In order to modify anything, you gotta be super-user! */
- if (txc.modes && !suser())
+ if (txc->modes && !suser())
return -EPERM;
/* Now we validate the data before disabling interrupts */
- if (txc.modes != ADJ_OFFSET_SINGLESHOT && (txc.modes & ADJ_OFFSET))
+ if (txc->modes != ADJ_OFFSET_SINGLESHOT && (txc->modes & ADJ_OFFSET))
/* adjustment Offset limited to +- .512 seconds */
- if (txc.offset <= - MAXPHASE || txc.offset >= MAXPHASE )
+ if (txc->offset <= - MAXPHASE || txc->offset >= MAXPHASE )
return -EINVAL;
/* if the quartz is off by more than 10% something is VERY wrong ! */
- if (txc.modes & ADJ_TICK)
- if (txc.tick < 900000/HZ || txc.tick > 1100000/HZ)
+ if (txc->modes & ADJ_TICK)
+ if (txc->tick < 900000/HZ || txc->tick > 1100000/HZ)
return -EINVAL;
cli(); /* SMP: global cli() is enough protection. */
@@ -250,37 +242,37 @@ asmlinkage int sys_adjtimex(struct timex *txc_p)
save_adjust = time_adjust;
/* If there are input parameters, then process them */
- if (txc.modes)
+ if (txc->modes)
{
if (time_state == TIME_BAD)
time_state = TIME_OK;
- if (txc.modes & ADJ_STATUS)
- time_status = txc.status;
+ if (txc->modes & ADJ_STATUS)
+ time_status = txc->status;
- if (txc.modes & ADJ_FREQUENCY)
- time_freq = txc.freq;
+ if (txc->modes & ADJ_FREQUENCY)
+ time_freq = txc->freq;
- if (txc.modes & ADJ_MAXERROR)
- time_maxerror = txc.maxerror;
+ if (txc->modes & ADJ_MAXERROR)
+ time_maxerror = txc->maxerror;
- if (txc.modes & ADJ_ESTERROR)
- time_esterror = txc.esterror;
+ if (txc->modes & ADJ_ESTERROR)
+ time_esterror = txc->esterror;
- if (txc.modes & ADJ_TIMECONST)
- time_constant = txc.constant;
+ if (txc->modes & ADJ_TIMECONST)
+ time_constant = txc->constant;
- if (txc.modes & ADJ_OFFSET)
- if ((txc.modes == ADJ_OFFSET_SINGLESHOT)
+ if (txc->modes & ADJ_OFFSET)
+ if ((txc->modes == ADJ_OFFSET_SINGLESHOT)
|| !(time_status & STA_PLL))
{
- time_adjust = txc.offset;
+ time_adjust = txc->offset;
}
else if ((time_status & STA_PLL)||(time_status & STA_PPSTIME))
{
ltemp = (time_status & STA_PPSTIME &&
time_status & STA_PPSSIGNAL) ?
- pps_offset : txc.offset;
+ pps_offset : txc->offset;
/*
* Scale the phase adjustment and
@@ -335,30 +327,46 @@ asmlinkage int sys_adjtimex(struct timex *txc_p)
else if (time_freq < -time_tolerance)
time_freq = -time_tolerance;
} /* STA_PLL || STA_PPSTIME */
- if (txc.modes & ADJ_TICK)
- tick = txc.tick;
+ if (txc->modes & ADJ_TICK)
+ tick = txc->tick;
}
- txc.offset = save_adjust;
- txc.freq = time_freq;
- txc.maxerror = time_maxerror;
- txc.esterror = time_esterror;
- txc.status = time_status;
- txc.constant = time_constant;
- txc.precision = time_precision;
- txc.tolerance = time_tolerance;
- txc.time = xtime;
- txc.tick = tick;
- txc.ppsfreq = pps_freq;
- txc.jitter = pps_jitter;
- txc.shift = pps_shift;
- txc.stabil = pps_stabil;
- txc.jitcnt = pps_jitcnt;
- txc.calcnt = pps_calcnt;
- txc.errcnt = pps_errcnt;
- txc.stbcnt = pps_stbcnt;
+ txc->offset = save_adjust;
+ txc->freq = time_freq;
+ txc->maxerror = time_maxerror;
+ txc->esterror = time_esterror;
+ txc->status = time_status;
+ txc->constant = time_constant;
+ txc->precision = time_precision;
+ txc->tolerance = time_tolerance;
+ txc->time = xtime;
+ txc->tick = tick;
+ txc->ppsfreq = pps_freq;
+ txc->jitter = pps_jitter;
+ txc->shift = pps_shift;
+ txc->stabil = pps_stabil;
+ txc->jitcnt = pps_jitcnt;
+ txc->calcnt = pps_calcnt;
+ txc->errcnt = pps_errcnt;
+ txc->stbcnt = pps_stbcnt;
sti();
+ return 0;
+}
+
+asmlinkage int sys_adjtimex(struct timex *txc_p)
+{
+ struct timex txc; /* Local copy of parameter */
+ int ret;
+
+ /* Copy the user data space into the kernel copy
+ * structure. But bear in mind that the structures
+ * may change
+ */
+ if(copy_from_user(&txc, txc_p, sizeof(struct timex)))
+ return -EFAULT;
+ if ((ret = do_adjtimex(&txc)))
+ return ret;
return copy_to_user(txc_p, &txc, sizeof(struct timex)) ? -EFAULT : time_state;
}