Commit cad34273 authored by Linus Torvalds's avatar Linus Torvalds

Linux 2.1.91

I just made a real 91 on ftp.kernel.org, let's hope that this has all the
sillies gone. As usual, it is prefectly smooth on my machine, but this
time we also have a better chance of it being smooth on machines with less
memory too, as Rik has done some good work in testing the algorithms out.
So throw some problems at it to see just how good it is..

                Linus
parent b884a92a
......@@ -19,6 +19,7 @@ Currently, these files are in /proc/sys/vm:
- buffermem
- freepages
- overcommit_memory
- pagecache
- swapctl
- swapout_interval
......@@ -93,17 +94,16 @@ buffermem:
The three values in this file correspond to the values in
the struct buffer_mem. It controls how much memory should
be used for buffer and cache memory. Note that memorymapped
files are also counted as cache memory...
be used for buffer memory.
The values are:
min_percent -- this is the minumum percentage of memory
that should be spent on buffer + page cache
borrow_percent -- when Linux is short on memory, and buffer
and cache use more than this percentage of
memory, free pages are stolen from them
that should be spent on buffer memory
borrow_percent -- when Linux is short on memory, and the
buffer cache uses more memory, free pages
are stolen from it
max_percent -- this is the maximum amount of memory that
can be used for buffer and cache memory
can be used for buffer memory
==============================================================
freepages:
......@@ -176,6 +176,18 @@ static inline int vm_enough_memory(long pages)
==============================================================
pagecache:
This file does exactly the same as buffermem, only this
file controls the struct page_cache, and thus controls
the amount of memory allowed for memory mapping of files.
You don't want the minimum level to be too low, otherwise
your system might thrash when memory is tight or fragmentation
is high...
==============================================================
swapctl:
This file contains no less than 8 variables.
......
......@@ -813,7 +813,7 @@ common_fixup(long min_idsel, long max_idsel, long irqs_per_slot,
*/
static inline void eb66p_fixup(void)
{
static char irq_tab[5][5] __initdata = {
static char irq_tab[5][5] __initlocaldata = {
{16+0, 16+0, 16+5, 16+9, 16+13}, /* IdSel 6, slot 0, J25 */
{16+1, 16+1, 16+6, 16+10, 16+14}, /* IdSel 7, slot 1, J26 */
{ -1, -1, -1, -1, -1}, /* IdSel 8, SIO */
......@@ -869,7 +869,7 @@ static inline void eb66p_fixup(void)
#if defined(CONFIG_ALPHA_PC164) || defined(CONFIG_ALPHA_LX164)
static inline void alphapc164_fixup(void)
{
static char irq_tab[7][5] __initdata = {
static char irq_tab[7][5] __initlocaldata = {
/*INT INTA INTB INTC INTD */
{ 16+2, 16+2, 16+9, 16+13, 16+17}, /* IdSel 5, slot 2, J20 */
{ 16+0, 16+0, 16+7, 16+11, 16+15}, /* IdSel 6, slot 0, J29 */
......@@ -900,7 +900,7 @@ static inline void alphapc164_fixup(void)
*/
static inline void cabriolet_fixup(void)
{
static char irq_tab[5][5] __initdata = {
static char irq_tab[5][5] __initlocaldata = {
{ 16+2, 16+2, 16+7, 16+11, 16+15}, /* IdSel 5, slot 2, J21 */
{ 16+0, 16+0, 16+5, 16+9, 16+13}, /* IdSel 6, slot 0, J19 */
{ 16+1, 16+1, 16+6, 16+10, 16+14}, /* IdSel 7, slot 1, J20 */
......@@ -956,7 +956,7 @@ static inline void cabriolet_fixup(void)
*/
static inline void eb66_and_eb64p_fixup(void)
{
static char irq_tab[5][5] __initdata = {
static char irq_tab[5][5] __initlocaldata = {
{16+7, 16+7, 16+7, 16+7, 16+7}, /* IdSel 5, slot ?, ?? */
{16+0, 16+0, 16+2, 16+4, 16+9}, /* IdSel 6, slot ?, ?? */
{16+1, 16+1, 16+3, 16+8, 16+10}, /* IdSel 7, slot ?, ?? */
......@@ -1005,7 +1005,7 @@ static inline void eb66_and_eb64p_fixup(void)
*/
static inline void mikasa_fixup(void)
{
static char irq_tab[8][5] __initdata = {
static char irq_tab[8][5] __initlocaldata = {
/*INT INTA INTB INTC INTD */
{16+12, 16+12, 16+12, 16+12, 16+12}, /* IdSel 17, SCSI */
{ -1, -1, -1, -1, -1}, /* IdSel 18, PCEB */
......@@ -1076,7 +1076,7 @@ static inline void mikasa_fixup(void)
*/
static inline void noritake_fixup(void)
{
static char irq_tab[13][5] __initdata = {
static char irq_tab[13][5] __initlocaldata = {
/*INT INTA INTB INTC INTD */
{ -1, -1, -1, -1, -1}, /* IdSel 18, PCEB */
{ -1, -1, -1, -1, -1}, /* IdSel 19, PPB */
......@@ -1140,7 +1140,7 @@ static inline void noritake_fixup(void)
*/
static inline void alcor_fixup(void)
{
static char irq_tab[6][5] __initdata = {
static char irq_tab[6][5] __initlocaldata = {
/*INT INTA INTB INTC INTD */
{ 16+8, 16+8, 16+9, 16+10, 16+11}, /* IdSel 18, slot 0 */
{16+16, 16+16, 16+17, 16+18, 16+19}, /* IdSel 19, slot 3 */
......@@ -1195,7 +1195,7 @@ static inline void alcor_fixup(void)
*/
static inline void xlt_fixup(void)
{
static char irq_tab[7][5] __initdata = {
static char irq_tab[7][5] __initlocaldata = {
/*INT INTA INTB INTC INTD */
{16+13, 16+13, 16+13, 16+13, 16+13}, /* IdSel 17, TULIP */
{ 16+8, 16+8, 16+9, 16+10, 16+11}, /* IdSel 18, slot 0 */
......@@ -1266,7 +1266,7 @@ static inline void xlt_fixup(void)
#ifdef CONFIG_ALPHA_SABLE
static inline void sable_fixup(void)
{
static char irq_tab[9][5] __initdata = {
static char irq_tab[9][5] __initlocaldata = {
/*INT INTA INTB INTC INTD */
{ 32+0, 32+0, 32+0, 32+0, 32+0}, /* IdSel 0, TULIP */
{ 32+1, 32+1, 32+1, 32+1, 32+1}, /* IdSel 1, SCSI */
......@@ -1349,7 +1349,7 @@ static inline void sable_fixup(void)
#ifdef CONFIG_ALPHA_MIATA
static inline void miata_fixup(void)
{
static char irq_tab[18][5] __initdata = {
static char irq_tab[18][5] __initlocaldata = {
/*INT INTA INTB INTC INTD */
{16+ 8, 16+ 8, 16+ 8, 16+ 8, 16+ 8}, /* IdSel 14, DC21142 */
{ -1, -1, -1, -1, -1}, /* IdSel 15, EIDE */
......@@ -1420,7 +1420,7 @@ static inline void miata_fixup(void)
#ifdef CONFIG_ALPHA_SX164
static inline void sx164_fixup(void)
{
static char irq_tab[5][5] __initdata = {
static char irq_tab[5][5] __initlocaldata = {
/*INT INTA INTB INTC INTD */
{ 16+ 9, 16+ 9, 16+13, 16+17, 16+21}, /* IdSel 5 slot 2 J17 */
{ 16+11, 16+11, 16+15, 16+19, 16+23}, /* IdSel 6 slot 0 J19 */
......@@ -1461,7 +1461,7 @@ static inline void sio_fixup(void)
* that they use the default INTA line, if they are interrupt
* driven at all).
*/
static const char pirq_tab[][5] __initdata = {
static const char pirq_tab[][5] __initlocaldata = {
#ifdef CONFIG_ALPHA_P2K
{ 0, 0, -1, -1, -1}, /* idsel 6 (53c810) */
{-1, -1, -1, -1, -1}, /* idsel 7 (SIO: PCI/ISA bridge) */
......
......@@ -16,10 +16,10 @@ ENTRY(__lock_kernel)
jnc 3f
sti
2:
btl %dl, SYMBOL_NAME(smp_invalidate_needed)
btl %edx, SYMBOL_NAME(smp_invalidate_needed)
jnc 0f
lock
btrl %dl, SYMBOL_NAME(smp_invalidate_needed)
btrl %edx, SYMBOL_NAME(smp_invalidate_needed)
jnc 0f
pushl %eax
movl %cr3, %eax
......
......@@ -413,6 +413,7 @@ SYSCALL(execve)
SYSCALL(open)
SYSCALL(close)
SYSCALL(waitpid)
SYSCALL(delete_module)
/* Why isn't this a) automatic, b) written in 'C'? */
......
......@@ -7,6 +7,12 @@
__arginit __init; \
__arginit
#if __GNUC__ >= 2 && __GNUC_MINOR__ >= 8
#define __initlocaldata __initdata
#else
#define __initlocaldata
#endif
/* For assembly routines */
#define __INIT .section .text.init,"ax"
#define __FINIT .previous
......
......@@ -421,6 +421,12 @@ static inline int read(int fd, char * buf, int nr)
return sys_read(fd, buf, nr);
}
extern int sys_fork(void);
static inline int fork(void)
{
return sys_fork();
}
extern int __kernel_execve(char *, char **, char **, struct pt_regs *);
static inline int execve(char * file, char ** argvp, char ** envp)
{
......@@ -452,6 +458,12 @@ static inline pid_t wait(int * wait_stat)
return waitpid(-1,wait_stat,0);
}
extern int sys_delete_module(const char *name);
static inline int delete_module(const char *name)
{
return sys_delete_module(name);
}
#endif
#endif /* _ALPHA_UNISTD_H */
......@@ -325,6 +325,7 @@ static inline _syscall3(int,open,const char *,file,int,flag,int,mode);
static inline _syscall1(int,close,int,fd);
static inline _syscall1(int,_exit,int,exitcode);
static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options);
static inline _syscall1(int,delete_module,const char *,name)
static inline pid_t wait(int * wait_stat)
{
......
......@@ -114,7 +114,7 @@ __asm__ __volatile__(
"xorl %%eax,%%eax\n\t"
"jmp 3f\n"
"2:\tsbbl %%eax,%%eax\n\t"
"orb $1,%%eax\n"
"orb $1,%%al\n"
"3:"
:"=a" (__res):"S" (cs),"D" (ct):"si","di");
return __res;
......
......@@ -296,6 +296,7 @@ static inline _syscall3(int,open,const char *,file,int,flag,int,mode)
static inline _syscall1(int,close,int,fd)
static inline _syscall1(int,_exit,int,exitcode)
static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
static inline _syscall1(int,delete_module,const char *,name)
static inline pid_t wait(int * wait_stat)
{
......
......@@ -316,6 +316,7 @@ static inline _syscall3(int,open,const char *,file,int,flag,int,mode)
static inline _syscall1(int,close,int,fd)
static inline _syscall1(int,_exit,int,exitcode)
static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
static inline _syscall1(int,delete_module,const char *,name)
/*
* This is the mechanism for creating a new kernel thread.
......
......@@ -1410,6 +1410,7 @@ static inline _syscall3(int,open,const char *,file,int,flag,int,mode)
static inline _syscall1(int,close,int,fd)
static inline _syscall1(int,_exit,int,exitcode)
static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
static inline _syscall1(int,delete_module,const char *,name)
static inline pid_t wait(int * wait_stat)
{
......
......@@ -438,6 +438,7 @@ static __inline__ _syscall3(int,open,__const__ char *,file,int,flag,int,mode)
static __inline__ _syscall1(int,close,int,fd)
static __inline__ _syscall1(int,_exit,int,exitcode)
static __inline__ _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
static __inline__ _syscall1(int,delete_module,const char *,name)
static __inline__ pid_t wait(int * wait_stat)
{
......
......@@ -426,6 +426,7 @@ static __inline__ _syscall3(int,open,__const__ char *,file,int,flag,int,mode)
static __inline__ _syscall1(int,close,int,fd)
static __inline__ _syscall1(int,_exit,int,exitcode)
static __inline__ _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
static __inline__ _syscall1(int,delete_module,const char *,name)
static __inline__ pid_t wait(int * wait_stat)
{
......
......@@ -19,6 +19,7 @@
#include <asm/atomic.h>
#include <asm/types.h>
#include <asm/spinlock.h>
#define HAVE_ALLOC_SKB /* For the drivers to know */
#define HAVE_ALIGNABLE_SKB /* Ditto 8) */
......@@ -275,14 +276,15 @@ extern __inline__ void __skb_queue_head(struct sk_buff_head *list, struct sk_buf
prev->next = newsk;
}
extern spinlock_t skb_queue_lock;
extern __inline__ void skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk)
{
unsigned long flags;
save_flags(flags);
cli();
spin_lock_irqsave(&skb_queue_lock, flags);
__skb_queue_head(list, newsk);
restore_flags(flags);
spin_unlock_irqrestore(&skb_queue_lock, flags);
}
/*
......@@ -307,10 +309,9 @@ extern __inline__ void skb_queue_tail(struct sk_buff_head *list, struct sk_buff
{
unsigned long flags;
save_flags(flags);
cli();
spin_lock_irqsave(&skb_queue_lock, flags);
__skb_queue_tail(list, newsk);
restore_flags(flags);
spin_unlock_irqrestore(&skb_queue_lock, flags);
}
/*
......@@ -342,10 +343,9 @@ extern __inline__ struct sk_buff *skb_dequeue(struct sk_buff_head *list)
long flags;
struct sk_buff *result;
save_flags(flags);
cli();
spin_lock_irqsave(&skb_queue_lock, flags);
result = __skb_dequeue(list);
restore_flags(flags);
spin_unlock_irqrestore(&skb_queue_lock, flags);
return result;
}
......@@ -372,10 +372,9 @@ extern __inline__ void skb_insert(struct sk_buff *old, struct sk_buff *newsk)
{
unsigned long flags;
save_flags(flags);
cli();
spin_lock_irqsave(&skb_queue_lock, flags);
__skb_insert(newsk, old->prev, old, old->list);
restore_flags(flags);
spin_unlock_irqrestore(&skb_queue_lock, flags);
}
/*
......@@ -386,10 +385,9 @@ extern __inline__ void skb_append(struct sk_buff *old, struct sk_buff *newsk)
{
unsigned long flags;
save_flags(flags);
cli();
spin_lock_irqsave(&skb_queue_lock, flags);
__skb_insert(newsk, old, old->next, old->list);
restore_flags(flags);
spin_unlock_irqrestore(&skb_queue_lock, flags);
}
/*
......@@ -421,11 +419,10 @@ extern __inline__ void skb_unlink(struct sk_buff *skb)
{
unsigned long flags;
save_flags(flags);
cli();
spin_lock_irqsave(&skb_queue_lock, flags);
if(skb->list)
__skb_unlink(skb, skb->list);
restore_flags(flags);
spin_unlock_irqrestore(&skb_queue_lock, flags);
}
/* XXX: more streamlined implementation */
......@@ -442,10 +439,9 @@ extern __inline__ struct sk_buff *skb_dequeue_tail(struct sk_buff_head *list)
long flags;
struct sk_buff *result;
save_flags(flags);
cli();
spin_lock_irqsave(&skb_queue_lock, flags);
result = __skb_dequeue_tail(list);
restore_flags(flags);
spin_unlock_irqrestore(&skb_queue_lock, flags);
return result;
}
......
......@@ -121,6 +121,21 @@ static inline int is_page_shared(struct page *page)
return (count > 1);
}
/*
* When we're freeing pages from a user application, we want
* to cluster swapouts too. -- Rik.
* linux/mm/page_alloc.c
*/
static inline int try_to_free_pages(int gfp_mask, int count)
{
int retval = 0;
while (count--) {
if (try_to_free_page(gfp_mask))
retval = 1;
}
return retval;
}
/*
* Make these inline later once they are working properly.
*/
......
......@@ -39,6 +39,7 @@ typedef struct buffer_mem_v1
} buffer_mem_v1;
typedef buffer_mem_v1 buffer_mem_t;
extern buffer_mem_t buffer_mem;
extern buffer_mem_t page_cache;
typedef struct freepages_v1
{
......
......@@ -84,7 +84,8 @@ enum
VM_FREEPG, /* struct: Set free page thresholds */
VM_BDFLUSH, /* struct: Control buffer cache flushing */
VM_OVERCOMMIT_MEMORY, /* Turn off the virtual memory safety limit */
VM_BUFFERMEM /* struct: Set cache memory thresholds */
VM_BUFFERMEM, /* struct: Set buffer memory thresholds */
VM_PAGECACHE /* struct: Set cache memory thresholds */
};
......
......@@ -9,24 +9,22 @@
#include <linux/types.h>
#include <linux/unistd.h>
static inline _syscall1(int,delete_module,const char *,name_user)
/*
kmod_unload_delay and modprobe_path are set via /proc/sys.
*/
int kmod_unload_delay = 60;
char modprobe_path[256] = "/sbin/modprobe";
char module_name[64] = "";
char * argv[] = { "modprobe", "-k", NULL, NULL, };
char * envp[] = { "HOME=/", "TERM=linux", NULL, };
static char module_name[64] = "";
static char * argv[] = { "modprobe", "-k", module_name, NULL, };
static char * envp[] = { "HOME=/", "TERM=linux", NULL, };
/*
kmod_queue synchronizes the kmod thread and the rest of the system
kmod_unload_timer is what we use to unload modules
after kmod_unload_delay seconds
*/
struct wait_queue * kmod_queue = NULL;
struct timer_list kmod_unload_timer;
static struct wait_queue * kmod_queue = NULL;
static struct timer_list kmod_unload_timer;
/*
kmod_thread is the thread that does most of the work. kmod_unload and
......@@ -74,7 +72,6 @@ int kmod_thread(void * data)
Call modprobe with module_name. If execve returns,
print out an error.
*/
argv[2] = module_name;
execve(modprobe_path, argv, envp);
printk("kmod: failed to load module %s\n", module_name);
......@@ -136,7 +133,8 @@ int request_module(const char * name)
the module into module_name. Once that is done, wake up
kmod_thread.
*/
strcpy(module_name, name);
strncpy(module_name, name, sizeof(module_name));
module_name[sizeof(module_name)-1] = '\0';
wake_up(&kmod_queue);
/*
......
......@@ -201,6 +201,8 @@ static ctl_table vm_table[] = {
sizeof(sysctl_overcommit_memory), 0644, NULL, &proc_dointvec},
{VM_BUFFERMEM, "buffermem",
&buffer_mem, sizeof(buffer_mem_t), 0600, NULL, &proc_dointvec},
{VM_PAGECACHE, "pagecache",
&page_cache, sizeof(buffer_mem_t), 0600, NULL, &proc_dointvec},
{0}
};
......
......@@ -152,7 +152,7 @@ int shrink_mmap(int priority, int gfp_mask)
} while (tmp != bh);
/* Refuse to swap out all buffer pages */
if ((buffermem >> PAGE_SHIFT) * 100 > (buffer_mem.min_percent * num_physpages))
if ((buffermem >> PAGE_SHIFT) * 100 < (buffer_mem.min_percent * num_physpages))
goto next;
}
......@@ -171,7 +171,7 @@ int shrink_mmap(int priority, int gfp_mask)
break;
}
age_page(page);
if (page->age)
if (page->age || page_cache_size * 100 < (page_cache.min_percent * num_physpages))
break;
if (PageSwapCache(page)) {
delete_from_swap_cache(page);
......
......@@ -282,7 +282,7 @@ unsigned long __get_free_pages(int gfp_mask, unsigned long order)
spin_lock_irqsave(&page_alloc_lock, flags);
RMQUEUE(order, maxorder, (gfp_mask & GFP_DMA));
spin_unlock_irqrestore(&page_alloc_lock, flags);
if ((gfp_mask & __GFP_WAIT) && try_to_free_page(gfp_mask))
if ((gfp_mask & __GFP_WAIT) && try_to_free_pages(gfp_mask,SWAP_CLUSTER_MAX))
goto repeat;
nopage:
return 0;
......
......@@ -72,3 +72,8 @@ buffer_mem_t buffer_mem = {
30 /* maximum percent buffer */
};
buffer_mem_t page_cache = {
10, /* minimum percent page cache */
30, /* borrow percent page cache */
75 /* maximum */
};
......@@ -451,7 +451,8 @@ static inline int do_try_to_free_page(int gfp_mask)
stop = 3;
if (gfp_mask & __GFP_WAIT)
stop = 0;
if ((buffermem >> PAGE_SHIFT) * 100 > buffer_mem.borrow_percent * num_physpages)
if (((buffermem >> PAGE_SHIFT) * 100 > buffer_mem.borrow_percent * num_physpages)
|| (page_cache_size * 100 > page_cache.borrow_percent * num_physpages))
state = 0;
switch (state) {
......@@ -568,7 +569,7 @@ int kswapd(void *unused)
* per second (1.6MB/s). This should be a /proc
* thing.
*/
tries = 50;
tries = (50 << 2) >> free_memory_available(3);
while (tries--) {
int gfp_mask;
......@@ -620,7 +621,8 @@ void swap_tick(void)
}
if ((long) (now - want) >= 0) {
if (want_wakeup || (num_physpages * buffer_mem.max_percent) < (buffermem >> PAGE_SHIFT) * 100) {
if (want_wakeup || (num_physpages * buffer_mem.max_percent) < (buffermem >> PAGE_SHIFT) * 100
|| (num_physpages * page_cache.max_percent < page_cache_size)) {
/* Set the next wake-up time */
next_swap_jiffies = now + swapout_interval;
wake_up(&kswapd_wait);
......
......@@ -59,6 +59,11 @@
#include <asm/uaccess.h>
#include <asm/system.h>
/*
* Skb list spinlock
*/
spinlock_t skb_queue_lock = SPIN_LOCK_UNLOCKED;
/*
* Resource tracking variables
*/
......@@ -300,7 +305,7 @@ struct sk_buff *skb_realloc_headroom(struct sk_buff *skb, int newheadroom)
* Allocate the copy buffer
*/
n=alloc_skb(skb->truesize+newheadroom-headroom-sizeof(struct sk_buff), GFP_ATOMIC);
n=alloc_skb(skb->truesize+newheadroom-headroom, GFP_ATOMIC);
if(n==NULL)
return NULL;
......
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