diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/acct.c | 61 | ||||
-rw-r--r-- | kernel/exit.c | 3 | ||||
-rw-r--r-- | kernel/fork.c | 4 | ||||
-rw-r--r-- | kernel/kmod.c | 28 | ||||
-rw-r--r-- | kernel/ksyms.c | 5 | ||||
-rw-r--r-- | kernel/printk.c | 8 | ||||
-rw-r--r-- | kernel/sched.c | 21 | ||||
-rw-r--r-- | kernel/timer.c | 25 |
8 files changed, 91 insertions, 64 deletions
diff --git a/kernel/acct.c b/kernel/acct.c index eeab054d0..6eacd87b3 100644 --- a/kernel/acct.c +++ b/kernel/acct.c @@ -75,7 +75,7 @@ static volatile int acct_active; static volatile int acct_needcheck; static struct file *acct_file; static struct timer_list acct_timer; -static int do_acct_process(long, struct file *); +static void do_acct_process(long, struct file *); /* * Called whenever the timer says to check the free space. @@ -91,11 +91,14 @@ static void acct_timeout(unsigned long unused) static int check_free_space(struct file *file) { struct statfs sbuf; - int res = acct_active; + int res; int act; + lock_kernel(); + res = acct_active; if (!file || !acct_needcheck) - return res; + goto out; + unlock_kernel(); /* May block */ if (vfs_statfs(file->f_dentry->d_inode->i_sb, &sbuf)) @@ -112,8 +115,12 @@ static int check_free_space(struct file *file) * If some joker switched acct_file under us we'ld better be * silent and _not_ touch anything. */ - if (file != acct_file) - return act ? (act>0) : res; + lock_kernel(); + if (file != acct_file) { + if (act) + res = act>0; + goto out; + } if (acct_active) { if (act < 0) { @@ -131,7 +138,10 @@ static int check_free_space(struct file *file) acct_needcheck = 0; acct_timer.expires = jiffies + ACCT_TIMEOUT*HZ; add_timer(&acct_timer); - return acct_active; + res = acct_active; +out: + unlock_kernel(); + return res; } /* @@ -149,7 +159,6 @@ asmlinkage long sys_acct(const char *name) if (!capable(CAP_SYS_PACCT)) return -EPERM; - lock_kernel(); if (name) { tmp = getname(name); error = PTR_ERR(tmp); @@ -172,6 +181,7 @@ asmlinkage long sys_acct(const char *name) } error = 0; + lock_kernel(); if (acct_file) { old_acct = acct_file; del_timer(&acct_timer); @@ -183,18 +193,18 @@ asmlinkage long sys_acct(const char *name) acct_file = file; acct_needcheck = 0; acct_active = 1; - /* Its been deleted if it was used before so this is safe */ + /* It's been deleted if it was used before so this is safe */ init_timer(&acct_timer); acct_timer.function = acct_timeout; acct_timer.expires = jiffies + ACCT_TIMEOUT*HZ; add_timer(&acct_timer); } + unlock_kernel(); if (old_acct) { do_acct_process(0,old_acct); filp_close(old_acct, NULL); } out: - unlock_kernel(); return error; out_err: filp_close(file, NULL); @@ -203,8 +213,10 @@ out_err: void acct_auto_close(kdev_t dev) { + lock_kernel(); if (acct_file && acct_file->f_dentry->d_inode->i_dev == dev) - sys_acct((char *)NULL); + sys_acct(NULL); + unlock_kernel(); } /* @@ -256,26 +268,20 @@ static comp_t encode_comp_t(unsigned long value) */ /* - * do_acct_process does all actual work. + * do_acct_process does all actual work. Caller holds the reference to file. */ -static int do_acct_process(long exitcode, struct file *file) +static void do_acct_process(long exitcode, struct file *file) { struct acct ac; mm_segment_t fs; unsigned long vsize; - struct inode *inode; /* * First check to see if there is enough free_space to continue * the process accounting system. */ - if (!file) - return 0; - get_file(file); - if (!check_free_space(file)) { - fput(file); - return 0; - } + if (!check_free_space(file)) + return; /* * Fill the accounting struct with the needed info as recorded @@ -330,12 +336,9 @@ static int do_acct_process(long exitcode, struct file *file) */ fs = get_fs(); set_fs(KERNEL_DS); - inode = file->f_dentry->d_inode; file->f_op->write(file, (char *)&ac, sizeof(struct acct), &file->f_pos); set_fs(fs); - fput(file); - return 0; } /* @@ -343,7 +346,17 @@ static int do_acct_process(long exitcode, struct file *file) */ int acct_process(long exitcode) { - return do_acct_process(exitcode, acct_file); + struct file *file = NULL; + lock_kernel(); + if (acct_file) { + file = acct_file; + get_file(file); + unlock_kernel(); + do_acct_process(exitcode, acct_file); + fput(file); + } else + unlock_kernel(); + return 0; } #else diff --git a/kernel/exit.c b/kernel/exit.c index e912b75bc..536a6dd9c 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -217,6 +217,7 @@ void exit_files(struct task_struct *tsk) } static inline void __put_fs_struct(struct fs_struct *fs) { + /* No need to hold fs->lock if we are killing it */ if (atomic_dec_and_test(&fs->count)) { dput(fs->root); mntput(fs->rootmnt); @@ -437,11 +438,11 @@ NORET_TYPE void do_exit(long code) tsk->flags |= PF_EXITING; del_timer_sync(&tsk->real_timer); - lock_kernel(); fake_volatile: #ifdef CONFIG_BSD_PROCESS_ACCT acct_process(code); #endif + lock_kernel(); sem_exit(); __exit_mm(tsk); __exit_files(tsk); diff --git a/kernel/fork.c b/kernel/fork.c index b441988aa..b9cc831ec 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -425,9 +425,12 @@ fail_nomem: static inline struct fs_struct *__copy_fs_struct(struct fs_struct *old) { struct fs_struct *fs = kmalloc(sizeof(*old), GFP_KERNEL); + /* We don't need to lock fs - think why ;-) */ if (fs) { atomic_set(&fs->count, 1); + fs->lock = RW_LOCK_UNLOCKED; fs->umask = old->umask; + read_lock(&old->lock); fs->rootmnt = mntget(old->rootmnt); fs->root = dget(old->root); fs->pwdmnt = mntget(old->pwdmnt); @@ -439,6 +442,7 @@ static inline struct fs_struct *__copy_fs_struct(struct fs_struct *old) fs->altrootmnt = NULL; fs->altroot = NULL; } + read_unlock(&old->lock); } return fs; } diff --git a/kernel/kmod.c b/kernel/kmod.c index 5e8d825a4..2a78a9606 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -32,6 +32,8 @@ static inline void use_init_fs_context(void) { struct fs_struct *our_fs, *init_fs; + struct dentry *root, *pwd; + struct vfsmount *rootmnt, *pwdmnt; /* * Make modprobe's fs context be a copy of init's. @@ -49,23 +51,35 @@ use_init_fs_context(void) * We created the exec_modprobe thread without CLONE_FS, * so we can update the fields in our fs context freely. */ - lock_kernel(); - our_fs = current->fs; init_fs = init_task.fs; + read_lock(&init_fs->lock); + rootmnt = mntget(init_fs->rootmnt); + root = dget(init_fs->root); + pwdmnt = mntget(init_fs->pwdmnt); + pwd = dget(init_fs->pwd); + read_unlock(&init_fs->lock); + + /* FIXME - unsafe ->fs access */ + our_fs = current->fs; our_fs->umask = init_fs->umask; - set_fs_root(our_fs, init_fs->rootmnt, init_fs->root); - set_fs_pwd(our_fs, init_fs->pwdmnt, init_fs->pwd); + set_fs_root(our_fs, rootmnt, root); + set_fs_pwd(our_fs, pwdmnt, pwd); + write_lock(&our_fs->lock); if (our_fs->altroot) { struct vfsmount *mnt = our_fs->altrootmnt; struct dentry *dentry = our_fs->altroot; our_fs->altrootmnt = NULL; our_fs->altroot = NULL; + write_unlock(&our_fs->lock); dput(dentry); mntput(mnt); - } - - unlock_kernel(); + } else + write_unlock(&our_fs->lock); + dput(root); + mntput(rootmnt); + dput(pwd); + mntput(pwdmnt); } int exec_usermodehelper(char *program_path, char *argv[], char *envp[]) diff --git a/kernel/ksyms.c b/kernel/ksyms.c index 2189d87a4..5a1f457de 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -149,6 +149,7 @@ EXPORT_SYMBOL(__user_walk); EXPORT_SYMBOL(lookup_one); EXPORT_SYMBOL(lookup_hash); EXPORT_SYMBOL(sys_close); +EXPORT_SYMBOL(dcache_lock); EXPORT_SYMBOL(d_alloc_root); EXPORT_SYMBOL(d_delete); EXPORT_SYMBOL(d_validate); @@ -212,7 +213,7 @@ EXPORT_SYMBOL(posix_test_lock); EXPORT_SYMBOL(posix_block_lock); EXPORT_SYMBOL(posix_unblock_lock); EXPORT_SYMBOL(locks_mandatory_area); -EXPORT_SYMBOL(dput); +EXPORT_SYMBOL(__dput); EXPORT_SYMBOL(have_submounts); EXPORT_SYMBOL(d_find_alias); EXPORT_SYMBOL(d_prune_aliases); @@ -360,8 +361,6 @@ EXPORT_SYMBOL(mod_timer); EXPORT_SYMBOL(tq_timer); EXPORT_SYMBOL(tq_immediate); EXPORT_SYMBOL(tq_scheduler); -EXPORT_SYMBOL(timer_active); -EXPORT_SYMBOL(timer_table); #ifdef CONFIG_SMP /* Various random spinlocks we want to export */ diff --git a/kernel/printk.c b/kernel/printk.c index ca4b14ff9..ff6c727ab 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -471,6 +471,14 @@ int unregister_console(struct console * console) } } + /* If last console is removed, we re-enable picking the first + * one that gets registered. Without that, pmac early boot console + * would prevent fbcon from taking over. + */ + if (console_drivers == NULL) + preferred_console = -1; + + spin_unlock_irqrestore(&console_lock, flags); return res; } diff --git a/kernel/sched.c b/kernel/sched.c index fa30b0645..3b007e5e8 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1007,12 +1007,23 @@ asmlinkage long sys_sched_get_priority_min(int policy) asmlinkage long sys_sched_rr_get_interval(pid_t pid, struct timespec *interval) { struct timespec t; + struct task_struct *p; + int retval = -EINVAL; - t.tv_sec = 0; - t.tv_nsec = 150000; - if (copy_to_user(interval, &t, sizeof(struct timespec))) - return -EFAULT; - return 0; + if (pid < 0) + goto out_nounlock; + + retval = -ESRCH; + read_lock(&tasklist_lock); + p = find_process_by_pid(pid); + if (p) + jiffies_to_timespec(p->policy & SCHED_FIFO ? 0 : p->priority, + &t); + read_unlock(&tasklist_lock); + if (p) + retval = copy_to_user(interval, &t, sizeof(t)) ? -EFAULT : 0; +out_nounlock: + return retval; } static void show_task(struct task_struct * p) diff --git a/kernel/timer.c b/kernel/timer.c index 873fef479..1a0c2ba73 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -162,7 +162,7 @@ static inline void internal_add_timer(struct timer_list *timer) /* Initialize both explicitly - let's try to have them in the same cache line */ spinlock_t timerlist_lock = SPIN_LOCK_UNLOCKED; -volatile unsigned long timer_sequence = 0xfee1bad; +volatile struct timer_list *running_timer = NULL; void add_timer(struct timer_list *timer) { @@ -311,25 +311,6 @@ repeat: spin_unlock_irq(&timerlist_lock); } - -static inline void run_old_timers(void) -{ - struct timer_struct *tp; - unsigned long mask; - - for (mask = 1, tp = timer_table+0 ; mask ; tp++,mask += mask) { - if (mask > timer_active) - break; - if (!(mask & timer_active)) - continue; - if (time_after(tp->expires, jiffies)) - continue; - timer_active &= ~mask; - tp->fn(); - sti(); - } -} - spinlock_t tqueue_lock = SPIN_LOCK_UNLOCKED; void tqueue_bh(void) @@ -342,9 +323,6 @@ void immediate_bh(void) run_task_queue(&tq_immediate); } -unsigned long timer_active; -struct timer_struct timer_table[32]; - /* * this routine handles the overflow of the microsecond field * @@ -682,7 +660,6 @@ static inline void update_times(void) void timer_bh(void) { update_times(); - run_old_timers(); run_timer_list(); } |