Commit 63f5d27a authored by Linus Torvalds's avatar Linus Torvalds

pre-2.1.130-3

There's a new pre-patch for people who want to test these things out: I'll
probably make a real 2.1.130 soon just to make sure all the silly problems
in 2.1.129 are left behind (ie the UP flu in particular that people are
still discussing even though there's a known cure).

The pre-patch fixes a rather serious problem with wall-clock itimer
functions, that admittedly was very very hard to trigger in real life (the
only reason we found it was due to the diligent help from John Taves that
saw sporadic problems under some very specific circumstances - thanks
John).

It also fixes a very silly NFS path revalidation issue: when we
revalidated a cached NFS path component, we didn't update the revalidation
time, so we ended up doing a lookup over the wire every time after the
first time - essentially making the dcache useless for path component
caching of NFS. If you use NFS heavily, you _will_ notice this change (it
also fixes some rather ugly uses of dentries and inodes in the NFS code
where we didn't update the counter so the inode wasn't guaranteed to even
be there any more!).

Also, thanks to Richard Gooch &co, who found the rather nasty race
condition when a kernel thread was started from an init-region. The
trivial fix was to not have the kernel thread function be inlined, but
while fixing it was trivial, it wasn't trivial to notice in the first
place. Good debugging.

And the UP flu is obviously fixed here (as it was in earlier pre-patches
and in various other patches floating around).

                        Linus
parent 2eec9bc7
...@@ -39,6 +39,7 @@ EXPORT_SYMBOL(local_bh_count); ...@@ -39,6 +39,7 @@ EXPORT_SYMBOL(local_bh_count);
EXPORT_SYMBOL(local_irq_count); EXPORT_SYMBOL(local_irq_count);
EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(enable_irq);
EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL(disable_irq);
EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL_NOVERS(__down_failed); EXPORT_SYMBOL_NOVERS(__down_failed);
EXPORT_SYMBOL_NOVERS(__down_failed_interruptible); EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
......
...@@ -507,7 +507,7 @@ void release_segments(struct mm_struct *mm) ...@@ -507,7 +507,7 @@ void release_segments(struct mm_struct *mm)
/* /*
* Create a kernel thread * Create a kernel thread
*/ */
pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
{ {
long retval; long retval;
......
...@@ -227,6 +227,7 @@ ...@@ -227,6 +227,7 @@
static const char *version = "depca.c:v0.5 1998/11/14 davies@maniac.ultranet.com\n"; static const char *version = "depca.c:v0.5 1998/11/14 davies@maniac.ultranet.com\n";
#include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
......
1998-11-21 a sun <asun@hecate.darksunrising.blah>
* hfs_sysdep.h, hfs_fs.h: added hfs_from_utc/to_utc to deal with
date differences on hfs formatted media.
NOTE: hfs extended keeps everything in utc, so we'll need to deal
with that when appropriate.
1998-11-12 a sun <asun@hecate.darksunrising.blah> 1998-11-12 a sun <asun@hecate.darksunrising.blah>
* extent.c (shrink_fork): added some lock_bitmap/unlock_bitmap's * extent.c (shrink_fork): added some lock_bitmap/unlock_bitmap's
......
...@@ -17,6 +17,20 @@ ...@@ -17,6 +17,20 @@
/*================ File-local functions ================*/ /*================ File-local functions ================*/
/* btree locking functions */
static inline void hfs_btree_lock(struct hfs_btree *tree)
{
while (tree->lock)
hfs_sleep_on(&tree->wait);
tree->lock = 1;
}
static inline void hfs_btree_unlock(struct hfs_btree *tree)
{
tree->lock = 0;
hfs_wake_up(&tree->wait);
}
/* /*
* binsert_nonfull() * binsert_nonfull()
* *
...@@ -512,15 +526,11 @@ int hfs_binsert(struct hfs_btree *tree, const struct hfs_bkey *key, ...@@ -512,15 +526,11 @@ int hfs_binsert(struct hfs_btree *tree, const struct hfs_bkey *key,
/* make certain we have enough nodes to proceed */ /* make certain we have enough nodes to proceed */
if ((tree->bthFree - tree->reserved) < reserve) { if ((tree->bthFree - tree->reserved) < reserve) {
hfs_brec_relse(&brec, NULL); hfs_brec_relse(&brec, NULL);
while (tree->lock) { hfs_btree_lock(tree);
hfs_sleep_on(&tree->wait);
}
tree->lock = 1;
if ((tree->bthFree - tree->reserved) < reserve) { if ((tree->bthFree - tree->reserved) < reserve) {
hfs_btree_extend(tree); hfs_btree_extend(tree);
} }
tree->lock = 0; hfs_btree_unlock(tree);
hfs_wake_up(&tree->wait);
if ((tree->bthFree - tree->reserved) < reserve) { if ((tree->bthFree - tree->reserved) < reserve) {
return -ENOSPC; return -ENOSPC;
} else { } else {
......
...@@ -371,6 +371,15 @@ nfs_free_dircache(void) ...@@ -371,6 +371,15 @@ nfs_free_dircache(void)
nfs_invalidate_dircache_sb(NULL); nfs_invalidate_dircache_sb(NULL);
} }
/*
* Whenever an NFS operation succeeds, we know that the dentry
* is valid, so we update the revalidation timestamp.
*/
static inline void nfs_renew_times(struct dentry * dentry)
{
dentry->d_time = jiffies;
}
#define NFS_REVALIDATE_INTERVAL (5*HZ) #define NFS_REVALIDATE_INTERVAL (5*HZ)
/* /*
* This is called every time the dcache has a lookup hit, * This is called every time the dcache has a lookup hit,
...@@ -427,6 +436,9 @@ parent->d_name.name, dentry->d_name.name); ...@@ -427,6 +436,9 @@ parent->d_name.name, dentry->d_name.name);
if (memcmp(dentry->d_fsdata, &fhandle, sizeof(struct nfs_fh))) if (memcmp(dentry->d_fsdata, &fhandle, sizeof(struct nfs_fh)))
goto out_bad; goto out_bad;
/* Ok, remeber that we successfully checked it.. */
nfs_renew_times(dentry);
out_valid: out_valid:
return 1; return 1;
out_bad: out_bad:
...@@ -514,15 +526,6 @@ static void show_dentry(struct list_head * dlist) ...@@ -514,15 +526,6 @@ static void show_dentry(struct list_head * dlist)
} }
#endif #endif
/*
* Whenever an NFS operation succeeds, we know that the dentry
* is valid, so we update the revalidation timestamp.
*/
static inline void nfs_renew_times(struct dentry * dentry)
{
dentry->d_time = jiffies;
}
static int nfs_lookup(struct inode *dir, struct dentry * dentry) static int nfs_lookup(struct inode *dir, struct dentry * dentry)
{ {
struct inode *inode; struct inode *inode;
......
...@@ -275,6 +275,7 @@ struct mm_struct; ...@@ -275,6 +275,7 @@ struct mm_struct;
/* Free all resources held by a thread. */ /* Free all resources held by a thread. */
extern void release_thread(struct task_struct *); extern void release_thread(struct task_struct *);
extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
/* Copy and release all segment info associated with a VM */ /* Copy and release all segment info associated with a VM */
extern void copy_segments(int nr, struct task_struct *p, struct mm_struct * mm); extern void copy_segments(int nr, struct task_struct *p, struct mm_struct * mm);
......
...@@ -37,6 +37,7 @@ asmlinkage int __down_failed_interruptible(void /* params in registers */); ...@@ -37,6 +37,7 @@ asmlinkage int __down_failed_interruptible(void /* params in registers */);
asmlinkage void __up_wakeup(void /* special register calling convention */); asmlinkage void __up_wakeup(void /* special register calling convention */);
extern void __down(struct semaphore * sem); extern void __down(struct semaphore * sem);
extern int __down_interruptible(struct semaphore * sem);
extern void __up(struct semaphore * sem); extern void __up(struct semaphore * sem);
extern spinlock_t semaphore_wake_lock; extern spinlock_t semaphore_wake_lock;
......
...@@ -306,8 +306,6 @@ static inline pid_t wait(int * wait_stat) ...@@ -306,8 +306,6 @@ static inline pid_t wait(int * wait_stat)
return waitpid(-1,wait_stat,0); return waitpid(-1,wait_stat,0);
} }
extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
#endif #endif
#endif /* _ASM_I386_UNISTD_H_ */ #endif /* _ASM_I386_UNISTD_H_ */
...@@ -104,10 +104,10 @@ ...@@ -104,10 +104,10 @@
*/ */
#define hfs_h_to_mtime(ARG) htonl((hfs_s32)ntohl(ARG)+3029529600U) #define hfs_h_to_mtime(ARG) htonl((hfs_s32)ntohl(ARG)+3029529600U)
#define hfs_m_to_htime(ARG) ((hfs_s32)htonl(ntohl(ARG)-3029529600U)) #define hfs_m_to_htime(ARG) ((hfs_s32)htonl(ntohl(ARG)-3029529600U))
#define hfs_h_to_utime(ARG) ((hfs_s32)ntohl(ARG)+946684800U) #define hfs_h_to_utime(ARG) ((hfs_s32)hfs_to_utc(ntohl(ARG)+946684800U))
#define hfs_u_to_htime(ARG) ((hfs_s32)htonl((ARG)-946684800U)) #define hfs_u_to_htime(ARG) ((hfs_s32)htonl(hfs_from_utc(ARG)-946684800U))
#define hfs_u_to_mtime(ARG) htonl((ARG)+2082844800U) #define hfs_u_to_mtime(ARG) htonl(hfs_from_utc(ARG)+2082844800U)
#define hfs_m_to_utime(ARG) (ntohl(ARG)-2082844800U) #define hfs_m_to_utime(ARG) (hfs_to_utc(ntohl(ARG)-2082844800U))
/*======== Data structures kept in memory ========*/ /*======== Data structures kept in memory ========*/
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
extern struct timezone sys_tz;
#undef offsetof #undef offsetof
#define offsetof(TYPE, MEMB) ((size_t) &((TYPE *)0)->MEMB) #define offsetof(TYPE, MEMB) ((size_t) &((TYPE *)0)->MEMB)
...@@ -68,8 +69,24 @@ extern inline void hfs_free(void *ptr, unsigned int size) { ...@@ -68,8 +69,24 @@ extern inline void hfs_free(void *ptr, unsigned int size) {
} }
/* handle conversion between times.
*
* NOTE: hfs+ doesn't need this. also, we don't use tz_dsttime as that's
* not a good thing to do. instead, we depend upon tz_minuteswest
* having the correct daylight savings correction.
*/
extern inline hfs_u32 hfs_from_utc(hfs_s32 time)
{
return time - sys_tz.tz_minuteswest*60;
}
extern inline hfs_s32 hfs_to_utc(hfs_u32 time)
{
return time + sys_tz.tz_minuteswest*60;
}
extern inline hfs_u32 hfs_time(void) { extern inline hfs_u32 hfs_time(void) {
return htonl(CURRENT_TIME+2082844800U); return htonl(hfs_from_utc(CURRENT_TIME)+2082844800U);
} }
......
#ifndef _LINUX_PROC_FS_H #ifndef _LINUX_PROC_FS_H
#define _LINUX_PROC_FS_H #define _LINUX_PROC_FS_H
#include <linux/config.h>
#include <linux/malloc.h> #include <linux/malloc.h>
/* /*
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#define __KERNEL_SYSCALLS__ #define __KERNEL_SYSCALLS__
#include <linux/config.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/unistd.h> #include <linux/unistd.h>
#include <linux/ctype.h> #include <linux/ctype.h>
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
* Chris Evans, <chris@ferret.lmh.ox.ac.uk> * Chris Evans, <chris@ferret.lmh.ox.ac.uk>
*/ */
#include <linux/config.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/shm.h> #include <linux/shm.h>
#include <linux/init.h> #include <linux/init.h>
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1991, 1992 Linus Torvalds
*/ */
#include <linux/config.h>
#include <linux/malloc.h> #include <linux/malloc.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
...@@ -350,7 +351,9 @@ NORET_TYPE void do_exit(long code) ...@@ -350,7 +351,9 @@ NORET_TYPE void do_exit(long code)
if (!tsk->pid) if (!tsk->pid)
panic("Attempted to kill the idle task!"); panic("Attempted to kill the idle task!");
tsk->flags |= PF_EXITING; tsk->flags |= PF_EXITING;
start_bh_atomic();
del_timer(&tsk->real_timer); del_timer(&tsk->real_timer);
end_bh_atomic();
lock_kernel(); lock_kernel();
fake_volatile: fake_volatile:
......
...@@ -47,15 +47,15 @@ int do_getitimer(int which, struct itimerval *value) ...@@ -47,15 +47,15 @@ int do_getitimer(int which, struct itimerval *value)
case ITIMER_REAL: case ITIMER_REAL:
interval = current->it_real_incr; interval = current->it_real_incr;
val = 0; val = 0;
if (del_timer(&current->real_timer)) { start_bh_atomic();
unsigned long now = jiffies; if (timer_pending(&current->real_timer)) {
val = current->real_timer.expires; val = current->real_timer.expires - jiffies;
add_timer(&current->real_timer);
/* look out for negative/zero itimer.. */ /* look out for negative/zero itimer.. */
if (val <= now) if ((long) val <= 0)
val = now+1; val = 1;
val -= now;
} }
end_bh_atomic();
break; break;
case ITIMER_VIRTUAL: case ITIMER_VIRTUAL:
val = current->it_virt_value; val = current->it_virt_value;
...@@ -114,7 +114,9 @@ int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue) ...@@ -114,7 +114,9 @@ int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
return k; return k;
switch (which) { switch (which) {
case ITIMER_REAL: case ITIMER_REAL:
start_bh_atomic();
del_timer(&current->real_timer); del_timer(&current->real_timer);
end_bh_atomic();
current->it_real_value = j; current->it_real_value = j;
current->it_real_incr = i; current->it_real_incr = i;
if (!j) if (!j)
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
* by Bjorn Ekwall <bj0rn@blox.se> * by Bjorn Ekwall <bj0rn@blox.se>
*/ */
#include <linux/config.h>
#include <linux/malloc.h> #include <linux/malloc.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
...@@ -356,6 +357,7 @@ EXPORT_SYMBOL(make_bad_inode); ...@@ -356,6 +357,7 @@ EXPORT_SYMBOL(make_bad_inode);
EXPORT_SYMBOL(is_bad_inode); EXPORT_SYMBOL(is_bad_inode);
EXPORT_SYMBOL(event); EXPORT_SYMBOL(event);
EXPORT_SYMBOL(__down); EXPORT_SYMBOL(__down);
EXPORT_SYMBOL(__down_interruptible);
EXPORT_SYMBOL(__up); EXPORT_SYMBOL(__up);
/* all busmice */ /* all busmice */
......
#include <linux/config.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/module.h> #include <linux/module.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
* Made sysctl support optional via CONFIG_SYSCTL, 1/10/97, Chris Horn. * Made sysctl support optional via CONFIG_SYSCTL, 1/10/97, Chris Horn.
*/ */
#include <linux/config.h>
#include <linux/malloc.h> #include <linux/malloc.h>
#include <linux/sysctl.h> #include <linux/sysctl.h>
#include <linux/swapctl.h> #include <linux/swapctl.h>
......
...@@ -174,6 +174,9 @@ static inline int shrink_one_page(struct page *page, int gfp_mask) ...@@ -174,6 +174,9 @@ static inline int shrink_one_page(struct page *page, int gfp_mask)
if (test_and_clear_bit(PG_referenced, &page->flags)) if (test_and_clear_bit(PG_referenced, &page->flags))
break; break;
if (buffer_under_min())
break;
/* is it a buffer cache page? */ /* is it a buffer cache page? */
if (bh && try_to_free_buffer(bh, &bh, 6)) if (bh && try_to_free_buffer(bh, &bh, 6))
return 1; return 1;
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <linux/mman.h> #include <linux/mman.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/swap.h> #include <linux/swap.h>
#include <linux/swapctl.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/file.h> #include <linux/file.h>
...@@ -49,6 +50,12 @@ int vm_enough_memory(long pages) ...@@ -49,6 +50,12 @@ int vm_enough_memory(long pages)
* simple, it hopefully works in most obvious cases.. Easy to * simple, it hopefully works in most obvious cases.. Easy to
* fool it, but this should catch most mistakes. * fool it, but this should catch most mistakes.
*/ */
/* 23/11/98 NJC: Somewhat less stupid version of algorithm,
* which tries to do "TheRightThing". Instead of using half of
* (buffers+cache), use the minimum values. Allow an extra 2%
* of num_physpages for safety margin.
*/
long free; long free;
/* Sometimes we want to use more memory than we have. */ /* Sometimes we want to use more memory than we have. */
...@@ -57,10 +64,9 @@ int vm_enough_memory(long pages) ...@@ -57,10 +64,9 @@ int vm_enough_memory(long pages)
free = buffermem >> PAGE_SHIFT; free = buffermem >> PAGE_SHIFT;
free += page_cache_size; free += page_cache_size;
free >>= 1;
free += nr_free_pages; free += nr_free_pages;
free += nr_swap_pages; free += nr_swap_pages;
free -= num_physpages >> 4; free -= (page_cache.min_percent + buffer_mem.min_percent + 2)*num_physpages/100;
return free > pages; return free > pages;
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
* Swap reorganised 29.12.95, Stephen Tweedie * Swap reorganised 29.12.95, Stephen Tweedie
*/ */
#include <linux/config.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/kernel_stat.h> #include <linux/kernel_stat.h>
#include <linux/swap.h> #include <linux/swap.h>
......
...@@ -100,6 +100,7 @@ ...@@ -100,6 +100,7 @@
* is less than 512 (PAGE_SIZE<<3), but greater than 256. * is less than 512 (PAGE_SIZE<<3), but greater than 256.
*/ */
#include <linux/config.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/init.h> #include <linux/init.h>
......
...@@ -162,7 +162,7 @@ static inline int try_to_swap_out(struct task_struct * tsk, struct vm_area_struc ...@@ -162,7 +162,7 @@ static inline int try_to_swap_out(struct task_struct * tsk, struct vm_area_struc
* copy in memory, so we add it to the swap * copy in memory, so we add it to the swap
* cache. */ * cache. */
if (PageSwapCache(page_map)) { if (PageSwapCache(page_map)) {
free_page_and_swap_cache(page); free_page(page);
return (atomic_read(&page_map->count) == 0); return (atomic_read(&page_map->count) == 0);
} }
add_to_swap_cache(page_map, entry); add_to_swap_cache(page_map, entry);
...@@ -180,7 +180,7 @@ static inline int try_to_swap_out(struct task_struct * tsk, struct vm_area_struc ...@@ -180,7 +180,7 @@ static inline int try_to_swap_out(struct task_struct * tsk, struct vm_area_struc
* asynchronously. That's no problem, shrink_mmap() can * asynchronously. That's no problem, shrink_mmap() can
* correctly clean up the occassional unshared page * correctly clean up the occassional unshared page
* which gets left behind in the swap cache. */ * which gets left behind in the swap cache. */
free_page_and_swap_cache(page); free_page(page);
return 1; /* we slept: the process may not exist any more */ return 1; /* we slept: the process may not exist any more */
} }
...@@ -194,7 +194,7 @@ static inline int try_to_swap_out(struct task_struct * tsk, struct vm_area_struc ...@@ -194,7 +194,7 @@ static inline int try_to_swap_out(struct task_struct * tsk, struct vm_area_struc
set_pte(page_table, __pte(entry)); set_pte(page_table, __pte(entry));
flush_tlb_page(vma, address); flush_tlb_page(vma, address);
swap_duplicate(entry); swap_duplicate(entry);
free_page_and_swap_cache(page); free_page(page);
return (atomic_read(&page_map->count) == 0); return (atomic_read(&page_map->count) == 0);
} }
/* /*
...@@ -210,7 +210,7 @@ static inline int try_to_swap_out(struct task_struct * tsk, struct vm_area_struc ...@@ -210,7 +210,7 @@ static inline int try_to_swap_out(struct task_struct * tsk, struct vm_area_struc
flush_cache_page(vma, address); flush_cache_page(vma, address);
pte_clear(page_table); pte_clear(page_table);
flush_tlb_page(vma, address); flush_tlb_page(vma, address);
entry = page_unuse(page_map); entry = (atomic_read(&page_map->count) == 1);
__free_page(page_map); __free_page(page_map);
return entry; return entry;
} }
......
...@@ -54,6 +54,7 @@ ...@@ -54,6 +54,7 @@
* *
*/ */
#include <linux/config.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/socket.h> #include <linux/socket.h>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment