From 63f5d27a86dd3793fa60e74ac927dacd4361be67 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:17:26 -0500 Subject: [PATCH] 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 --- arch/i386/kernel/i386_ksyms.c | 1 + arch/i386/kernel/process.c | 2 +- drivers/net/depca.c | 1 + fs/hfs/ChangeLog | 8 ++++++++ fs/hfs/binsert.c | 22 ++++++++++++++++------ fs/nfs/dir.c | 21 ++++++++++++--------- include/asm-i386/processor.h | 1 + include/asm-i386/semaphore.h | 1 + include/asm-i386/unistd.h | 2 -- include/linux/hfs_fs.h | 8 ++++---- include/linux/hfs_sysdep.h | 19 ++++++++++++++++++- include/linux/proc_fs.h | 1 + init/main.c | 1 + ipc/util.c | 1 + kernel/exit.c | 3 +++ kernel/itimer.c | 16 +++++++++------- kernel/ksyms.c | 2 ++ kernel/module.c | 1 + kernel/sysctl.c | 1 + mm/filemap.c | 3 +++ mm/mmap.c | 10 ++++++++-- mm/page_alloc.c | 1 + mm/slab.c | 1 + mm/vmscan.c | 8 ++++---- net/socket.c | 1 + 25 files changed, 100 insertions(+), 36 deletions(-) diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c index 50bffc888aa0..e1833f43c83f 100644 --- a/arch/i386/kernel/i386_ksyms.c +++ b/arch/i386/kernel/i386_ksyms.c @@ -39,6 +39,7 @@ EXPORT_SYMBOL(local_bh_count); EXPORT_SYMBOL(local_irq_count); EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); +EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL_NOVERS(__down_failed); EXPORT_SYMBOL_NOVERS(__down_failed_interruptible); diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 9457bcb2a78b..4ddefa931b2e 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -507,7 +507,7 @@ void release_segments(struct mm_struct *mm) /* * 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; diff --git a/drivers/net/depca.c b/drivers/net/depca.c index 4caad61b7319..c3701e230423 100644 --- a/drivers/net/depca.c +++ b/drivers/net/depca.c @@ -227,6 +227,7 @@ static const char *version = "depca.c:v0.5 1998/11/14 davies@maniac.ultranet.com\n"; +#include #include #include diff --git a/fs/hfs/ChangeLog b/fs/hfs/ChangeLog index 3015bd4f589f..0bd14f24cc08 100644 --- a/fs/hfs/ChangeLog +++ b/fs/hfs/ChangeLog @@ -1,3 +1,11 @@ +1998-11-21 a sun + + * 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 * extent.c (shrink_fork): added some lock_bitmap/unlock_bitmap's diff --git a/fs/hfs/binsert.c b/fs/hfs/binsert.c index daab8c22d239..0c0c5076ac7b 100644 --- a/fs/hfs/binsert.c +++ b/fs/hfs/binsert.c @@ -17,6 +17,20 @@ /*================ 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() * @@ -512,15 +526,11 @@ restart: /* make certain we have enough nodes to proceed */ if ((tree->bthFree - tree->reserved) < reserve) { hfs_brec_relse(&brec, NULL); - while (tree->lock) { - hfs_sleep_on(&tree->wait); - } - tree->lock = 1; + hfs_btree_lock(tree); if ((tree->bthFree - tree->reserved) < reserve) { hfs_btree_extend(tree); } - tree->lock = 0; - hfs_wake_up(&tree->wait); + hfs_btree_unlock(tree); if ((tree->bthFree - tree->reserved) < reserve) { return -ENOSPC; } else { diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 3036971e2ea3..b44d7ed1ed36 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -371,6 +371,15 @@ nfs_free_dircache(void) 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) /* * This is called every time the dcache has a lookup hit, @@ -427,6 +436,9 @@ parent->d_name.name, dentry->d_name.name); if (memcmp(dentry->d_fsdata, &fhandle, sizeof(struct nfs_fh))) goto out_bad; + /* Ok, remeber that we successfully checked it.. */ + nfs_renew_times(dentry); + out_valid: return 1; out_bad: @@ -514,15 +526,6 @@ static void show_dentry(struct list_head * dlist) } #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) { struct inode *inode; diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h index cb593b1d3ad5..1cc5ea4139c5 100644 --- a/include/asm-i386/processor.h +++ b/include/asm-i386/processor.h @@ -275,6 +275,7 @@ struct mm_struct; /* Free all resources held by a thread. */ 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 */ extern void copy_segments(int nr, struct task_struct *p, struct mm_struct * mm); diff --git a/include/asm-i386/semaphore.h b/include/asm-i386/semaphore.h index a68b23fc638e..17ed1200f835 100644 --- a/include/asm-i386/semaphore.h +++ b/include/asm-i386/semaphore.h @@ -37,6 +37,7 @@ asmlinkage int __down_failed_interruptible(void /* params in registers */); asmlinkage void __up_wakeup(void /* special register calling convention */); extern void __down(struct semaphore * sem); +extern int __down_interruptible(struct semaphore * sem); extern void __up(struct semaphore * sem); extern spinlock_t semaphore_wake_lock; diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h index 3147e23fd2c4..76c7241bfe37 100644 --- a/include/asm-i386/unistd.h +++ b/include/asm-i386/unistd.h @@ -306,8 +306,6 @@ static inline pid_t wait(int * wait_stat) return waitpid(-1,wait_stat,0); } -extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); - #endif #endif /* _ASM_I386_UNISTD_H_ */ diff --git a/include/linux/hfs_fs.h b/include/linux/hfs_fs.h index 9b43579c0b80..eaae0ecc53f5 100644 --- a/include/linux/hfs_fs.h +++ b/include/linux/hfs_fs.h @@ -104,10 +104,10 @@ */ #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_h_to_utime(ARG) ((hfs_s32)ntohl(ARG)+946684800U) -#define hfs_u_to_htime(ARG) ((hfs_s32)htonl((ARG)-946684800U)) -#define hfs_u_to_mtime(ARG) htonl((ARG)+2082844800U) -#define hfs_m_to_utime(ARG) (ntohl(ARG)-2082844800U) +#define hfs_h_to_utime(ARG) ((hfs_s32)hfs_to_utc(ntohl(ARG)+946684800U)) +#define hfs_u_to_htime(ARG) ((hfs_s32)htonl(hfs_from_utc(ARG)-946684800U)) +#define hfs_u_to_mtime(ARG) htonl(hfs_from_utc(ARG)+2082844800U) +#define hfs_m_to_utime(ARG) (hfs_to_utc(ntohl(ARG)-2082844800U)) /*======== Data structures kept in memory ========*/ diff --git a/include/linux/hfs_sysdep.h b/include/linux/hfs_sysdep.h index 22e2ac66b670..00cc640084b6 100644 --- a/include/linux/hfs_sysdep.h +++ b/include/linux/hfs_sysdep.h @@ -25,6 +25,7 @@ #include #include +extern struct timezone sys_tz; #undef offsetof #define offsetof(TYPE, MEMB) ((size_t) &((TYPE *)0)->MEMB) @@ -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) { - return htonl(CURRENT_TIME+2082844800U); + return htonl(hfs_from_utc(CURRENT_TIME)+2082844800U); } diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 633bd48ba07b..2bd5c1f71efc 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -1,6 +1,7 @@ #ifndef _LINUX_PROC_FS_H #define _LINUX_PROC_FS_H +#include #include /* diff --git a/init/main.c b/init/main.c index d96658ec97b4..8f8456cc9ecc 100644 --- a/init/main.c +++ b/init/main.c @@ -11,6 +11,7 @@ #define __KERNEL_SYSCALLS__ +#include #include #include #include diff --git a/ipc/util.c b/ipc/util.c index 9fa0eab30be4..83d35f35d02b 100644 --- a/ipc/util.c +++ b/ipc/util.c @@ -8,6 +8,7 @@ * Chris Evans, */ +#include #include #include #include diff --git a/kernel/exit.c b/kernel/exit.c index 1dd252352afc..89440092e95e 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -4,6 +4,7 @@ * Copyright (C) 1991, 1992 Linus Torvalds */ +#include #include #include #include @@ -350,7 +351,9 @@ NORET_TYPE void do_exit(long code) if (!tsk->pid) panic("Attempted to kill the idle task!"); tsk->flags |= PF_EXITING; + start_bh_atomic(); del_timer(&tsk->real_timer); + end_bh_atomic(); lock_kernel(); fake_volatile: diff --git a/kernel/itimer.c b/kernel/itimer.c index c226b07b1d37..fe9fe1f8f978 100644 --- a/kernel/itimer.c +++ b/kernel/itimer.c @@ -47,15 +47,15 @@ int do_getitimer(int which, struct itimerval *value) case ITIMER_REAL: interval = current->it_real_incr; val = 0; - if (del_timer(¤t->real_timer)) { - unsigned long now = jiffies; - val = current->real_timer.expires; - add_timer(¤t->real_timer); + start_bh_atomic(); + if (timer_pending(¤t->real_timer)) { + val = current->real_timer.expires - jiffies; + /* look out for negative/zero itimer.. */ - if (val <= now) - val = now+1; - val -= now; + if ((long) val <= 0) + val = 1; } + end_bh_atomic(); break; case ITIMER_VIRTUAL: val = current->it_virt_value; @@ -114,7 +114,9 @@ int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue) return k; switch (which) { case ITIMER_REAL: + start_bh_atomic(); del_timer(¤t->real_timer); + end_bh_atomic(); current->it_real_value = j; current->it_real_incr = i; if (!j) diff --git a/kernel/ksyms.c b/kernel/ksyms.c index 07ec0981b713..d567240e6ac6 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -9,6 +9,7 @@ * by Bjorn Ekwall */ +#include #include #include #include @@ -356,6 +357,7 @@ EXPORT_SYMBOL(make_bad_inode); EXPORT_SYMBOL(is_bad_inode); EXPORT_SYMBOL(event); EXPORT_SYMBOL(__down); +EXPORT_SYMBOL(__down_interruptible); EXPORT_SYMBOL(__up); /* all busmice */ diff --git a/kernel/module.c b/kernel/module.c index 6929cd8311d0..59884d8e2a62 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1,3 +1,4 @@ +#include #include #include #include diff --git a/kernel/sysctl.c b/kernel/sysctl.c index c6ea83358068..12455ee07ddb 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -11,6 +11,7 @@ * Made sysctl support optional via CONFIG_SYSCTL, 1/10/97, Chris Horn. */ +#include #include #include #include diff --git a/mm/filemap.c b/mm/filemap.c index fae7f0b96a0a..e2fd16518d4b 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -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)) break; + if (buffer_under_min()) + break; + /* is it a buffer cache page? */ if (bh && try_to_free_buffer(bh, &bh, 6)) return 1; diff --git a/mm/mmap.c b/mm/mmap.c index 2164ccffe43b..4cbdbe3ca39b 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -49,6 +50,12 @@ int vm_enough_memory(long pages) * simple, it hopefully works in most obvious cases.. Easy to * 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; /* Sometimes we want to use more memory than we have. */ @@ -57,10 +64,9 @@ int vm_enough_memory(long pages) free = buffermem >> PAGE_SHIFT; free += page_cache_size; - free >>= 1; free += nr_free_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; } diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 695aecabc4d4..7ceec01b9170 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -5,6 +5,7 @@ * Swap reorganised 29.12.95, Stephen Tweedie */ +#include #include #include #include diff --git a/mm/slab.c b/mm/slab.c index 256bea0c7fbd..85051047cd29 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -100,6 +100,7 @@ * is less than 512 (PAGE_SIZE<<3), but greater than 256. */ +#include #include #include #include diff --git a/mm/vmscan.c b/mm/vmscan.c index d2e14a85a98c..a93fdf6d2f5b 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -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 * cache. */ if (PageSwapCache(page_map)) { - free_page_and_swap_cache(page); + free_page(page); return (atomic_read(&page_map->count) == 0); } 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 * asynchronously. That's no problem, shrink_mmap() can * correctly clean up the occassional unshared page * 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 */ } @@ -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)); flush_tlb_page(vma, address); swap_duplicate(entry); - free_page_and_swap_cache(page); + free_page(page); 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 flush_cache_page(vma, address); pte_clear(page_table); flush_tlb_page(vma, address); - entry = page_unuse(page_map); + entry = (atomic_read(&page_map->count) == 1); __free_page(page_map); return entry; } diff --git a/net/socket.c b/net/socket.c index e0da21f32486..e53d74252892 100644 --- a/net/socket.c +++ b/net/socket.c @@ -54,6 +54,7 @@ * */ +#include #include #include #include -- 2.39.5