diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/.cvsignore | 1 | ||||
-rw-r--r-- | kernel/Makefile | 5 | ||||
-rw-r--r-- | kernel/acct.c | 11 | ||||
-rw-r--r-- | kernel/exit.c | 5 | ||||
-rw-r--r-- | kernel/fork.c | 22 | ||||
-rw-r--r-- | kernel/ksyms.c | 23 | ||||
-rw-r--r-- | kernel/module.c | 49 | ||||
-rw-r--r-- | kernel/panic.c | 3 | ||||
-rw-r--r-- | kernel/printk.c | 79 | ||||
-rw-r--r-- | kernel/sched.c | 42 | ||||
-rw-r--r-- | kernel/signal.c | 80 | ||||
-rw-r--r-- | kernel/softirq.c | 6 | ||||
-rw-r--r-- | kernel/sysctl.c | 30 | ||||
-rw-r--r-- | kernel/time.c | 106 |
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(¤t->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(¤t->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(¤t->sigmask_lock); old_set = current->blocked; spin_unlock_irq(¤t->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(¤t->sigmask_lock); sigandsets(&pending, ¤t->blocked, ¤t->signal); spin_unlock_irq(¤t->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(¤t->sigmask_lock); old_set = current->blocked.sig[0]; + error = 0; switch (how) { default: - return -EINVAL; + error = -EINVAL; + break; case SIG_BLOCK: sigaddsetmask(¤t->blocked, new_set); break; @@ -845,36 +861,42 @@ sys_sigprocmask(int how, old_sigset_t *set, old_sigset_t *oset) sigdelsetmask(¤t->blocked, new_set); break; case SIG_SETMASK: - siginitset(¤t->blocked, new_set); + current->blocked.sig[0] = new_set; break; } recalc_sigpending(current); spin_unlock_irq(¤t->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(¤t->sigmask_lock); pending = current->blocked.sig[0] & current->signal.sig[0]; spin_unlock_irq(¤t->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; } |