Re: PATCH 2.4.0.1.ac10: a KISS memory pressure callback

From: Jeff Garzik (jgarzik@mandrakesoft.com)
Date: Wed Jun 07 2000 - 04:25:13 EST


Andi Kleen wrote:
> Jeff Garzik <jgarzik@mandrakesoft.com> writes:
> > int unregister_reboot_notifier(struct notifier_block * nb)
> > +{
> > + int i;
> > +
> > + spin_lock(&notifier_lock);
> > + i = notifier_chain_unregister(&reboot_notifier_list, nb);
> > + spin_unlock(&notifier_lock);
>
> Shouldn't you move the spinlock that into the notifier_chain_* functions
> itself ? In this case every user would be safe.

Not a bad idea..

> Also while you're on it
> you could move the notifier_* functions out of line. They are currently
> inline (I think it was some plot of Alan to force some module writers
> to go GPL ;). Anyways, with spinlocks they are far too big to be
> inlined now. I guess that could save a few hundred bytes.

Any places lurking where a notifier func needs to be called rapidly?

Two more notes while I'm on the subject--

My previous patch was missing a necessary but simple mm.h change.
Updated patch attached (not including the stuff above.. yet).

I've seen some comments saying that a VM pressure operation should occur
in address_space or some VFS or buffer-related area. It would be nice
to be able to notify some of the smarter device drivers of VM pressure
as well... the interface presented here is independent of any VFS,
address_space, or buffer-related operations, while at the same time
being called at a familiar place (do_try_to_free_pages) with familiar
arguments (priority, gfp_mask) and a familiar return value (pages freed,
if any).

        Jeff

-- 
Jeff Garzik              | Liberty is always dangerous, but
Building 1024            | it is the safest thing we have.
MandrakeSoft, Inc.       |      -- Harry Emerson Fosdick

Index: include/linux/mm.h =================================================================== RCS file: /g/cvslan/linux_2_3/include/linux/mm.h,v retrieving revision 1.1.1.45 diff -u -r1.1.1.45 mm.h --- include/linux/mm.h 2000/06/06 18:45:42 1.1.1.45 +++ include/linux/mm.h 2000/06/07 08:03:53 @@ -10,6 +10,7 @@ #include <linux/string.h> #include <linux/list.h> #include <linux/mmzone.h> +#include <linux/notifier.h> extern unsigned long max_mapnr; extern unsigned long num_physpages; @@ -415,6 +416,9 @@ extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write); extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char *dst, int len); extern int ptrace_writedata(struct task_struct *tsk, char * src, unsigned long dst, int len); + +extern int register_freemem_notifier(struct notifier_block *); +extern int unregister_freemem_notifier(struct notifier_block *); extern int pgt_cache_water[2]; extern int check_pgt_cache(void); Index: mm/vmscan.c =================================================================== RCS file: /g/cvslan/linux_2_3/mm/vmscan.c,v retrieving revision 1.1.1.40 diff -u -r1.1.1.40 vmscan.c --- mm/vmscan.c 2000/06/05 03:14:23 1.1.1.40 +++ mm/vmscan.c 2000/06/07 08:04:02 @@ -428,6 +428,31 @@ } /* + * The freemem notifier list holds a list of functions + * that are to be called when trying to free pages. + * + * Call them... We don't use notifier_call_chain + * because the return code from a freemem notifier + * is treated as a shrink_*_memory-style return value. + */ +extern struct notifier_block *freemem_notifier_list; +static int shrink_misc_memory (int priority, unsigned int gfp_mask) +{ + int count = 0; + struct notifier_block *nb = freemem_notifier_list; + + while (nb) { + count += nb->notifier_call(nb, + (unsigned long) priority, + (void *)(unsigned long) gfp_mask); + nb = nb->next; + } + + return count; +} + + +/* * We need to make the locks finer granularity, but right * now we need this so that we can do page allocations * without holding the kernel lock etc. @@ -476,6 +501,13 @@ if (!--count) goto done; } + } + + /* call everybody who registered a mem pressure notifier */ + count -= shrink_misc_memory(priority, gfp_mask); + if (count <= 0) { + ret = 1; + goto done; } /* Index: kernel/ksyms.c =================================================================== RCS file: /g/cvslan/linux_2_3/kernel/ksyms.c,v retrieving revision 1.1.1.62 diff -u -r1.1.1.62 ksyms.c --- kernel/ksyms.c 2000/05/29 23:48:48 1.1.1.62 +++ kernel/ksyms.c 2000/06/07 08:04:05 @@ -448,6 +448,8 @@ EXPORT_SYMBOL(machine_power_off); EXPORT_SYMBOL(register_reboot_notifier); EXPORT_SYMBOL(unregister_reboot_notifier); +EXPORT_SYMBOL(register_freemem_notifier); +EXPORT_SYMBOL(unregister_freemem_notifier); EXPORT_SYMBOL(_ctype); EXPORT_SYMBOL(secure_tcp_sequence_number); EXPORT_SYMBOL(get_random_bytes); Index: kernel/sys.c =================================================================== RCS file: /g/cvslan/linux_2_3/kernel/sys.c,v retrieving revision 1.1.1.19 diff -u -r1.1.1.19 sys.c --- kernel/sys.c 2000/05/31 13:07:05 1.1.1.19 +++ kernel/sys.c 2000/06/07 08:04:05 @@ -47,15 +47,51 @@ */ static struct notifier_block *reboot_notifier_list = NULL; +struct notifier_block *freemem_notifier_list = NULL; +static spinlock_t notifier_lock = SPIN_LOCK_UNLOCKED; int register_reboot_notifier(struct notifier_block * nb) { - return notifier_chain_register(&reboot_notifier_list, nb); + int i; + + spin_lock(&notifier_lock); + i = notifier_chain_register(&reboot_notifier_list, nb); + spin_unlock(&notifier_lock); + + return i; } int unregister_reboot_notifier(struct notifier_block * nb) +{ + int i; + + spin_lock(&notifier_lock); + i = notifier_chain_unregister(&reboot_notifier_list, nb); + spin_unlock(&notifier_lock); + + return i; +} + +int register_freemem_notifier(struct notifier_block * nb) { - return notifier_chain_unregister(&reboot_notifier_list, nb); + int i; + + spin_lock(&notifier_lock); + i = notifier_chain_register(&freemem_notifier_list, nb); + spin_unlock(&notifier_lock); + + return i; +} + +int unregister_freemem_notifier(struct notifier_block * nb) +{ + int i; + + spin_lock(&notifier_lock); + i = notifier_chain_unregister(&freemem_notifier_list, nb); + spin_unlock(&notifier_lock); + + return i; } asmlinkage long sys_ni_syscall(void)

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Wed Jun 07 2000 - 21:00:27 EST