- buffermem
- freepages
- overcommit_memory
+- pagecache
- swapctl
- swapout_interval
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:
==============================================================
+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.
*/
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 */
#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 */
*/
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 */
*/
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 ?, ?? */
*/
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 */
*/
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 */
*/
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 */
*/
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 */
#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 */
#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 */
#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 */
* 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) */
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
SYSCALL(open)
SYSCALL(close)
SYSCALL(waitpid)
+SYSCALL(delete_module)
/* Why isn't this a) automatic, b) written in 'C'? */
__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
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)
{
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 */
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)
{
"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;
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)
{
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.
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)
{
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)
{
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)
{
#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) */
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);
}
/*
{
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);
}
/*
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;
}
{
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);
}
/*
{
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);
}
/*
{
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 */
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;
}
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.
*/
} 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
{
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 */
};
#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
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);
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);
/*
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}
};
} 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;
}
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);
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;
30 /* maximum percent buffer */
};
+buffer_mem_t page_cache = {
+ 10, /* minimum percent page cache */
+ 30, /* borrow percent page cache */
+ 75 /* maximum */
+};
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) {
* 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;
}
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);
#include <asm/uaccess.h>
#include <asm/system.h>
+/*
+ * Skb list spinlock
+ */
+spinlock_t skb_queue_lock = SPIN_LOCK_UNLOCKED;
+
/*
* Resource tracking variables
*/
* 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;