direct-io.hg

changeset 3239:5c16d6acb085

bitkeeper revision 1.1159.183.42 (41af421fdfmkte1q5_bhPDh1LJlfIQ)

Merge scramble.cl.cam.ac.uk:/auto/groups/xeno-xenod/BK/xen-2.0-testing.bk
into scramble.cl.cam.ac.uk:/auto/groups/xeno-xenod/BK/xen-unstable.bk
author kaf24@scramble.cl.cam.ac.uk
date Thu Dec 02 16:26:07 2004 +0000 (2004-12-02)
parents 554487247cb1 fdd2c0ba9164
children 551306ae7cd0
files .rootkeys Makefile linux-2.4.28-xen-sparse/mkbuildtree linux-2.6.9-xen-sparse/arch/xen/i386/kernel/pci-dma.c linux-2.6.9-xen-sparse/arch/xen/i386/mm/hypervisor.c linux-2.6.9-xen-sparse/drivers/xen/Makefile linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c linux-2.6.9-xen-sparse/drivers/xen/netback/netback.c linux-2.6.9-xen-sparse/drivers/xen/netfront/netfront.c linux-2.6.9-xen-sparse/drivers/xen/privcmd/privcmd.c linux-2.6.9-xen-sparse/include/asm-xen/balloon.h linux-2.6.9-xen-sparse/include/asm-xen/hypervisor.h
line diff
     1.1 --- a/.rootkeys	Thu Dec 02 09:22:36 2004 +0000
     1.2 +++ b/.rootkeys	Thu Dec 02 16:26:07 2004 +0000
     1.3 @@ -243,6 +243,7 @@ 40f5623bVdKP7Dt7qm8twu3NcnGNbA linux-2.6
     1.4  40f5623bc8LKPRO09wY5dGDnY_YCpw linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/tlbflush.h
     1.5  41062ab7uFxnCq-KtPeAm-aV8CicgA linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/vga.h
     1.6  40f5623bxUbeGjkRrjDguCy_Gm8RLw linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/xor.h
     1.7 +41af4017PDMuSmMWtSRU5UC9Vylw5g linux-2.6.9-xen-sparse/include/asm-xen/balloon.h
     1.8  40f5623bYNP7tHE2zX6YQxp9Zq2utQ linux-2.6.9-xen-sparse/include/asm-xen/ctrl_if.h
     1.9  40f5623b3Eqs8pAc5WpPX8_jTzV2qw linux-2.6.9-xen-sparse/include/asm-xen/evtchn.h
    1.10  419b4e9367PjTEvdjwavWN12BeBBXg linux-2.6.9-xen-sparse/include/asm-xen/foreign_page.h
     2.1 --- a/Makefile	Thu Dec 02 09:22:36 2004 +0000
     2.2 +++ b/Makefile	Thu Dec 02 16:26:07 2004 +0000
     2.3 @@ -19,28 +19,28 @@ export INSTALL_DIR
     2.4  include buildconfigs/Rules.mk
     2.5  
     2.6  .PHONY:	all dist install xen tools kernels docs world clean mkpatches mrproper
     2.7 -.PHONY:	kbuild kdelete kclean install_tools install_xen install_docs
     2.8 -.PHONY: install_kernel
     2.9 +.PHONY:	kbuild kdelete kclean install-tools install-xen install-docs
    2.10 +.PHONY: install-kernels
    2.11  
    2.12  all: dist
    2.13  
    2.14  # install everything into the standard system directories
    2.15  # NB: install explicitly does not check that everything is up to date!
    2.16 -install: install_tools install_xen install_kernels install_docs
    2.17 +install: install-tools install-xen install-kernels install-docs
    2.18  
    2.19 -install_xen:
    2.20 +install-xen:
    2.21  	$(MAKE) -C xen install
    2.22  
    2.23 -install_tools:
    2.24 +install-tools:
    2.25  	$(MAKE) -C tools install
    2.26  
    2.27 -install_kernels:
    2.28 +install-kernels:
    2.29  	$(shell cp -a $(INSTALL_DIR)/boot/* /boot/)
    2.30  	$(shell cp -a $(INSTALL_DIR)/lib/modules/* /lib/modules/)
    2.31  	$(shell cp -dR $(INSTALL_DIR)/boot/*$(LINUX_VER)* $(prefix)/boot/)
    2.32  	$(shell cp -dR $(INSTALL_DIR)/lib/modules/* $(prefix)/lib/modules/)
    2.33  
    2.34 -install_docs:
    2.35 +install-docs:
    2.36  	sh ./docs/check_pkgs && $(MAKE) -C docs install || true
    2.37  
    2.38  # build and install everything into local dist directory
     3.1 --- a/linux-2.4.28-xen-sparse/mkbuildtree	Thu Dec 02 09:22:36 2004 +0000
     3.2 +++ b/linux-2.4.28-xen-sparse/mkbuildtree	Thu Dec 02 16:26:07 2004 +0000
     3.3 @@ -204,6 +204,7 @@ ln -sf ../asm-i386/unaligned.h
     3.4  ln -sf ../asm-i386/unistd.h 
     3.5  ln -sf ../asm-i386/user.h 
     3.6  ln -sf ../asm-i386/vm86.h 
     3.7 +ln -sf ../../${LINUX_26}/include/asm-xen/balloon.h
     3.8  ln -sf ../../${LINUX_26}/include/asm-xen/ctrl_if.h
     3.9  ln -sf ../../${LINUX_26}/include/asm-xen/evtchn.h
    3.10  ln -sf ../../${LINUX_26}/include/asm-xen/gnttab.h
     4.1 --- a/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/pci-dma.c	Thu Dec 02 09:22:36 2004 +0000
     4.2 +++ b/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/pci-dma.c	Thu Dec 02 16:26:07 2004 +0000
     4.3 @@ -13,6 +13,7 @@
     4.4  #include <linux/pci.h>
     4.5  #include <linux/version.h>
     4.6  #include <asm/io.h>
     4.7 +#include <asm-xen/balloon.h>
     4.8  
     4.9  #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
    4.10  #define pte_offset_kernel pte_offset
    4.11 @@ -37,9 +38,12 @@ xen_contig_memory(unsigned long vstart, 
    4.12  	pgd_t         *pgd; 
    4.13  	pmd_t         *pmd;
    4.14  	pte_t         *pte;
    4.15 -	unsigned long  pfn, i;
    4.16 +	unsigned long  pfn, i, flags;
    4.17  
    4.18  	scrub_pages(vstart, 1 << order);
    4.19 +
    4.20 +        balloon_lock(flags);
    4.21 +
    4.22  	/* 1. Zap current PTEs, giving away the underlying pages. */
    4.23  	for (i = 0; i < (1<<order); i++) {
    4.24  		pgd = pgd_offset_k(   (vstart + (i*PAGE_SIZE)));
    4.25 @@ -70,6 +74,8 @@ xen_contig_memory(unsigned long vstart, 
    4.26  	}
    4.27  	/* Flush updates through and flush the TLB. */
    4.28  	xen_tlb_flush();
    4.29 +
    4.30 +        balloon_unlock(flags);
    4.31  }
    4.32  
    4.33  #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
     5.1 --- a/linux-2.6.9-xen-sparse/arch/xen/i386/mm/hypervisor.c	Thu Dec 02 09:22:36 2004 +0000
     5.2 +++ b/linux-2.6.9-xen-sparse/arch/xen/i386/mm/hypervisor.c	Thu Dec 02 16:26:07 2004 +0000
     5.3 @@ -35,6 +35,7 @@
     5.4  #include <asm/pgtable.h>
     5.5  #include <asm-xen/hypervisor.h>
     5.6  #include <asm-xen/multicall.h>
     5.7 +#include <asm-xen/balloon.h>
     5.8  
     5.9  /*
    5.10   * This suffices to protect us if we ever move to SMP domains.
    5.11 @@ -352,7 +353,6 @@ unsigned long allocate_empty_lowmem_regi
    5.12      unsigned long *pfn_array;
    5.13      unsigned long  vstart;
    5.14      unsigned long  i;
    5.15 -    int            ret;
    5.16      unsigned int   order = get_order(pages*PAGE_SIZE);
    5.17  
    5.18      vstart = __get_free_pages(GFP_KERNEL, order);
    5.19 @@ -378,57 +378,11 @@ unsigned long allocate_empty_lowmem_regi
    5.20      /* Flush updates through and flush the TLB. */
    5.21      xen_tlb_flush();
    5.22  
    5.23 -    ret = HYPERVISOR_dom_mem_op(MEMOP_decrease_reservation, 
    5.24 -                                pfn_array, 1<<order, 0);
    5.25 -    if ( unlikely(ret != (1<<order)) )
    5.26 -    {
    5.27 -        printk(KERN_WARNING "Unable to reduce memory reservation (%d)\n", ret);
    5.28 -        BUG();
    5.29 -    }
    5.30 +    balloon_put_pages(pfn_array, 1 << order);
    5.31  
    5.32      vfree(pfn_array);
    5.33  
    5.34      return vstart;
    5.35  }
    5.36  
    5.37 -void deallocate_lowmem_region(unsigned long vstart, unsigned long pages)
    5.38 -{
    5.39 -    pgd_t         *pgd; 
    5.40 -    pmd_t         *pmd;
    5.41 -    pte_t         *pte;
    5.42 -    unsigned long *pfn_array;
    5.43 -    unsigned long  i;
    5.44 -    int            ret;
    5.45 -    unsigned int   order = get_order(pages*PAGE_SIZE);
    5.46 -
    5.47 -    pfn_array = vmalloc((1<<order) * sizeof(*pfn_array));
    5.48 -    if ( pfn_array == NULL )
    5.49 -        BUG();
    5.50 -
    5.51 -    ret = HYPERVISOR_dom_mem_op(MEMOP_increase_reservation,
    5.52 -                                pfn_array, 1<<order, 0);
    5.53 -    if ( unlikely(ret != (1<<order)) )
    5.54 -    {
    5.55 -        printk(KERN_WARNING "Unable to increase memory reservation (%d)\n",
    5.56 -               ret);
    5.57 -        BUG();
    5.58 -    }
    5.59 -
    5.60 -    for ( i = 0; i < (1<<order); i++ )
    5.61 -    {
    5.62 -        pgd = pgd_offset_k(   (vstart + (i*PAGE_SIZE)));
    5.63 -        pmd = pmd_offset(pgd, (vstart + (i*PAGE_SIZE)));
    5.64 -        pte = pte_offset_kernel(pmd, (vstart + (i*PAGE_SIZE)));
    5.65 -        queue_l1_entry_update(pte, (pfn_array[i]<<PAGE_SHIFT)|__PAGE_KERNEL);
    5.66 -        queue_machphys_update(pfn_array[i], __pa(vstart)>>PAGE_SHIFT);
    5.67 -        phys_to_machine_mapping[__pa(vstart)>>PAGE_SHIFT] = pfn_array[i];
    5.68 -    }
    5.69 -
    5.70 -    flush_page_update_queue();
    5.71 -
    5.72 -    vfree(pfn_array);
    5.73 -
    5.74 -    free_pages(vstart, order);
    5.75 -}
    5.76 -
    5.77  #endif /* CONFIG_XEN_PHYSDEV_ACCESS */
     6.1 --- a/linux-2.6.9-xen-sparse/drivers/xen/Makefile	Thu Dec 02 09:22:36 2004 +0000
     6.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/Makefile	Thu Dec 02 16:26:07 2004 +0000
     6.3 @@ -2,9 +2,9 @@
     6.4  
     6.5  obj-y	+= console/
     6.6  obj-y	+= evtchn/
     6.7 -obj-y	+= privcmd/
     6.8 -obj-y   += balloon/
     6.9 +obj-y	+= balloon/
    6.10  
    6.11 +obj-$(CONFIG_XEN_PRIVILEGED_GUEST)	+= privcmd/
    6.12  obj-$(CONFIG_XEN_BLKDEV_BACKEND)	+= blkback/
    6.13  obj-$(CONFIG_XEN_NETDEV_BACKEND)	+= netback/
    6.14  obj-$(CONFIG_XEN_BLKDEV_FRONTEND)	+= blkfront/
     7.1 --- a/linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c	Thu Dec 02 09:22:36 2004 +0000
     7.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c	Thu Dec 02 16:26:07 2004 +0000
     7.3 @@ -29,8 +29,8 @@
     7.4   */
     7.5  
     7.6  #include <linux/config.h>
     7.7 +#include <linux/kernel.h>
     7.8  #include <linux/module.h>
     7.9 -#include <linux/kernel.h>
    7.10  #include <linux/sched.h>
    7.11  #include <linux/errno.h>
    7.12  #include <linux/mm.h>
    7.13 @@ -43,16 +43,41 @@
    7.14  #include <asm-xen/xen_proc.h>
    7.15  #include <asm-xen/hypervisor.h>
    7.16  #include <asm-xen/ctrl_if.h>
    7.17 +#include <asm-xen/balloon.h>
    7.18  #include <asm/pgalloc.h>
    7.19  #include <asm/pgtable.h>
    7.20  #include <asm/uaccess.h>
    7.21  #include <asm/tlb.h>
    7.22  #include <linux/list.h>
    7.23  
    7.24 +#define MIN_TARGET ((16 << 20) >> PAGE_SHIFT) /* 16MB */
    7.25 +
    7.26  static struct proc_dir_entry *balloon_pde;
    7.27  
    7.28 -unsigned long credit;
    7.29 +static DECLARE_MUTEX(balloon_mutex);
    7.30 +spinlock_t balloon_lock = SPIN_LOCK_UNLOCKED;
    7.31 +
    7.32 +/* We aim for 'current allocation' == 'target allocation'. */
    7.33  static unsigned long current_pages;
    7.34 +static unsigned long target_pages;
    7.35 +
    7.36 +/* We may hit the hard limit in Xen. If we do then we remember it. */
    7.37 +static unsigned long hard_limit;
    7.38 +
    7.39 +/*
    7.40 + * Drivers may alter the memory reservation independently, but they must
    7.41 + * inform the balloon driver so that we can avoid hitting the hard limit.
    7.42 + */
    7.43 +static unsigned long driver_pages;
    7.44 +
    7.45 +/* List of ballooned pages, threaded through the mem_map array. */
    7.46 +static LIST_HEAD(ballooned_pages);
    7.47 +static unsigned long balloon_low, balloon_high;
    7.48 +
    7.49 +/* Main work function, always executed in process context. */
    7.50 +static void balloon_process(void *unused);
    7.51 +static DECLARE_WORK(balloon_worker, balloon_process, NULL);
    7.52 +static struct timer_list balloon_timer;
    7.53  
    7.54  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
    7.55  /* Use the private and mapping fields of struct page as a list. */
    7.56 @@ -75,17 +100,24 @@ static unsigned long current_pages;
    7.57  #define WPRINTK(fmt, args...) \
    7.58      printk(KERN_WARNING "xen_mem: " fmt, ##args)
    7.59  
    7.60 -/* List of ballooned pages, threaded through the mem_map array. */
    7.61 -LIST_HEAD(ballooned_pages);
    7.62 -
    7.63  /* balloon_append: add the given page to the balloon. */
    7.64 -void balloon_append(struct page *page)
    7.65 +static void balloon_append(struct page *page)
    7.66  {
    7.67 -    list_add(PAGE_TO_LIST(page), &ballooned_pages);
    7.68 +    /* Low memory is re-populated first, so highmem pages go at list tail. */
    7.69 +    if ( PageHighMem(page) )
    7.70 +    {
    7.71 +        list_add_tail(PAGE_TO_LIST(page), &ballooned_pages);
    7.72 +        balloon_high++;
    7.73 +    }
    7.74 +    else
    7.75 +    {
    7.76 +        list_add(PAGE_TO_LIST(page), &ballooned_pages);
    7.77 +        balloon_low++;
    7.78 +    }
    7.79  }
    7.80  
    7.81  /* balloon_retrieve: rescue a page from the balloon, if it is not empty. */
    7.82 -struct page *balloon_retrieve(void)
    7.83 +static struct page *balloon_retrieve(void)
    7.84  {
    7.85      struct page *page;
    7.86  
    7.87 @@ -94,6 +126,12 @@ struct page *balloon_retrieve(void)
    7.88  
    7.89      page = LIST_TO_PAGE(ballooned_pages.next);
    7.90      UNLIST_PAGE(page);
    7.91 +
    7.92 +    if ( PageHighMem(page) )
    7.93 +        balloon_high--;
    7.94 +    else
    7.95 +        balloon_low--;
    7.96 +
    7.97      return page;
    7.98  }
    7.99  
   7.100 @@ -111,194 +149,148 @@ static inline pte_t *get_ptep(unsigned l
   7.101      return pte_offset_kernel(pmd, addr);
   7.102  }
   7.103  
   7.104 -/* Main function for relinquishing memory. */
   7.105 -static unsigned long inflate_balloon(unsigned long num_pages)
   7.106 +static void balloon_alarm(unsigned long unused)
   7.107  {
   7.108 -    unsigned long *parray, *currp, curraddr, ret = 0, i, j, mfn, pfn;
   7.109 -    struct page *page;
   7.110 -
   7.111 -    parray = (unsigned long *)vmalloc(num_pages * sizeof(unsigned long));
   7.112 -    if ( parray == NULL )
   7.113 -    {
   7.114 -        WPRINTK("inflate_balloon: Unable to vmalloc parray\n");
   7.115 -        return -ENOMEM;
   7.116 -    }
   7.117 -
   7.118 -    currp = parray;
   7.119 -
   7.120 -    for ( i = 0; i < num_pages; i++, currp++ )
   7.121 -    {
   7.122 -        page = alloc_page(GFP_HIGHUSER);
   7.123 -        pfn  = page - mem_map;
   7.124 -
   7.125 -        /* If allocation fails then free all reserved pages. */
   7.126 -        if ( page == NULL )
   7.127 -        {
   7.128 -            printk(KERN_ERR "Unable to inflate balloon by %ld, only"
   7.129 -                   " %ld pages free.", num_pages, i);
   7.130 -            currp = parray;
   7.131 -            for ( j = 0; j < i; j++, currp++ )
   7.132 -                __free_page((struct page *) (mem_map + *currp));
   7.133 -
   7.134 -            ret = -EFAULT;
   7.135 -            goto cleanup;
   7.136 -        }
   7.137 -
   7.138 -        *currp = pfn;
   7.139 -    }
   7.140 +    schedule_work(&balloon_worker);
   7.141 +}
   7.142  
   7.143 -    for ( i = 0, currp = parray; i < num_pages; i++, currp++ )
   7.144 -    {
   7.145 -        mfn      = phys_to_machine_mapping[*currp];
   7.146 -        curraddr = (unsigned long)page_address(mem_map + *currp);
   7.147 -        /* Blow away page contents for security, and also p.t. ref if any. */
   7.148 -        if ( curraddr != 0 )
   7.149 -        {
   7.150 -            scrub_pages(curraddr, 1);
   7.151 -            queue_l1_entry_update(get_ptep(curraddr), 0);
   7.152 -        }
   7.153 -#ifdef CONFIG_XEN_SCRUB_PAGES
   7.154 -        else
   7.155 -        {
   7.156 -            void *p = kmap(&mem_map[*currp]);
   7.157 -            scrub_pages(p, 1);
   7.158 -            kunmap(&mem_map[*currp]);
   7.159 -        }
   7.160 -#endif
   7.161 -
   7.162 -        balloon_append(&mem_map[*currp]);
   7.163 -
   7.164 -        phys_to_machine_mapping[*currp] = INVALID_P2M_ENTRY;
   7.165 -        *currp = mfn;
   7.166 -    }
   7.167 -
   7.168 -    /* Flush updates through and flush the TLB. */
   7.169 -    xen_tlb_flush();
   7.170 -
   7.171 -    ret = HYPERVISOR_dom_mem_op(MEMOP_decrease_reservation, 
   7.172 -                                parray, num_pages, 0);
   7.173 -    if ( unlikely(ret != num_pages) )
   7.174 -    {
   7.175 -        printk(KERN_ERR "Unable to inflate balloon, error %lx\n", ret);
   7.176 -        goto cleanup;
   7.177 -    }
   7.178 -
   7.179 -    credit += num_pages;
   7.180 -    ret = num_pages;
   7.181 -
   7.182 - cleanup:
   7.183 -    vfree(parray);
   7.184 -
   7.185 -    return ret;
   7.186 +static unsigned long current_target(void)
   7.187 +{
   7.188 +    unsigned long target = min(target_pages, hard_limit);
   7.189 +    if ( target > (current_pages + balloon_low + balloon_high) )
   7.190 +        target = current_pages + balloon_low + balloon_high;
   7.191 +    if ( target < MIN_TARGET )
   7.192 +        target = MIN_TARGET;
   7.193 +    return target;
   7.194  }
   7.195  
   7.196 -/* Install a set of new pages (@mfn_list, @nr_mfns) into the memory map. */
   7.197 -static unsigned long process_returned_pages(
   7.198 -    unsigned long *mfn_list, unsigned long nr_mfns)
   7.199 +static void balloon_process(void *unused)
   7.200  {
   7.201 -    unsigned long pfn, i;
   7.202 -    struct page *page;
   7.203 +    unsigned long *mfn_list, pfn, i, flags;
   7.204 +    struct page   *page;
   7.205 +    long           credit, debt, rc;
   7.206 +    void          *v;
   7.207 +
   7.208 +    down(&balloon_mutex);
   7.209 +
   7.210 + retry:
   7.211 +    mfn_list = NULL;
   7.212 +
   7.213 +    if ( (credit = current_target() - current_pages) > 0 )
   7.214 +    {
   7.215 +        mfn_list = (unsigned long *)vmalloc(credit * sizeof(*mfn_list));
   7.216 +        if ( mfn_list == NULL )
   7.217 +            goto out;
   7.218 +
   7.219 +        balloon_lock(flags);
   7.220 +        rc = HYPERVISOR_dom_mem_op(
   7.221 +            MEMOP_increase_reservation, mfn_list, credit, 0);
   7.222 +        balloon_unlock(flags);
   7.223 +        if ( rc < credit )
   7.224 +        {
   7.225 +            /* We hit the Xen hard limit: reprobe. */
   7.226 +            if ( HYPERVISOR_dom_mem_op(
   7.227 +                MEMOP_decrease_reservation, mfn_list, rc, 0) != rc )
   7.228 +                BUG();
   7.229 +            hard_limit = current_pages + rc - driver_pages;
   7.230 +            vfree(mfn_list);
   7.231 +            goto retry;
   7.232 +        }
   7.233 +
   7.234 +        for ( i = 0; i < credit; i++ )
   7.235 +        {
   7.236 +            if ( (page = balloon_retrieve()) == NULL )
   7.237 +                BUG();
   7.238 +
   7.239 +            pfn = page - mem_map;
   7.240 +            if ( phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY )
   7.241 +                BUG();
   7.242  
   7.243 -    for ( i = 0; i < nr_mfns; i++ )
   7.244 +            /* Update P->M and M->P tables. */
   7.245 +            phys_to_machine_mapping[pfn] = mfn_list[i];
   7.246 +            queue_machphys_update(mfn_list[i], pfn);
   7.247 +            
   7.248 +            /* Link back into the page tables if it's not a highmem page. */
   7.249 +            if ( pfn < max_low_pfn )
   7.250 +                queue_l1_entry_update(
   7.251 +                    get_ptep((unsigned long)__va(pfn << PAGE_SHIFT)),
   7.252 +                    (mfn_list[i] << PAGE_SHIFT) | pgprot_val(PAGE_KERNEL));
   7.253 +            
   7.254 +            /* Finally, relinquish the memory back to the system allocator. */
   7.255 +            ClearPageReserved(page);
   7.256 +            set_page_count(page, 1);
   7.257 +            __free_page(page);
   7.258 +        }
   7.259 +
   7.260 +        current_pages += credit;
   7.261 +    }
   7.262 +    else if ( credit < 0 )
   7.263      {
   7.264 -        if ( (page = balloon_retrieve()) != NULL )
   7.265 -            break;
   7.266 +        debt = -credit;
   7.267 +
   7.268 +        mfn_list = (unsigned long *)vmalloc(debt * sizeof(*mfn_list));
   7.269 +        if ( mfn_list == NULL )
   7.270 +            goto out;
   7.271 +
   7.272 +        for ( i = 0; i < debt; i++ )
   7.273 +        {
   7.274 +            if ( (page = alloc_page(GFP_HIGHUSER)) == NULL )
   7.275 +            {
   7.276 +                debt = i;
   7.277 +                break;
   7.278 +            }
   7.279 +
   7.280 +            pfn = page - mem_map;
   7.281 +            mfn_list[i] = phys_to_machine_mapping[pfn];
   7.282 +            phys_to_machine_mapping[pfn] = INVALID_P2M_ENTRY;
   7.283  
   7.284 -        pfn = page - mem_map;
   7.285 -        if ( phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY )
   7.286 +            if ( !PageHighMem(page) )
   7.287 +            {
   7.288 +                v = phys_to_virt((page - mem_map) << PAGE_SHIFT);
   7.289 +                scrub_pages(v, 1);
   7.290 +                queue_l1_entry_update(get_ptep((unsigned long)v), 0);
   7.291 +            }
   7.292 +#ifdef CONFIG_XEN_SCRUB_PAGES
   7.293 +            else
   7.294 +            {
   7.295 +                v = kmap(page);
   7.296 +                scrub_pages(v, 1);
   7.297 +                kunmap(page);
   7.298 +            }
   7.299 +#endif            
   7.300 +
   7.301 +            balloon_append(page);
   7.302 +        }
   7.303 +
   7.304 +        /* Flush updates through and flush the TLB. */
   7.305 +        xen_tlb_flush();
   7.306 +
   7.307 +        if ( HYPERVISOR_dom_mem_op(
   7.308 +            MEMOP_decrease_reservation, mfn_list, debt, 0) != debt )
   7.309              BUG();
   7.310  
   7.311 -        /* Update P->M and M->P tables. */
   7.312 -        phys_to_machine_mapping[pfn] = mfn_list[i];
   7.313 -        queue_machphys_update(mfn_list[i], pfn);
   7.314 -
   7.315 -        /* Link back into the page tables if it's not a highmem page. */
   7.316 -        if ( pfn < max_low_pfn )
   7.317 -            queue_l1_entry_update(
   7.318 -                get_ptep((unsigned long)__va(pfn << PAGE_SHIFT)),
   7.319 -                (mfn_list[i] << PAGE_SHIFT) | pgprot_val(PAGE_KERNEL));
   7.320 -
   7.321 -        /* Finally, relinquish the memory back to the system allocator. */
   7.322 -        ClearPageReserved(page);
   7.323 -        set_page_count(page, 1);
   7.324 -        __free_page(page);
   7.325 -    }
   7.326 -
   7.327 -    return i;
   7.328 -}
   7.329 -
   7.330 -unsigned long deflate_balloon(unsigned long num_pages)
   7.331 -{
   7.332 -    unsigned long ret;
   7.333 -    unsigned long *parray;
   7.334 -
   7.335 -    if ( num_pages > credit )
   7.336 -    {
   7.337 -        printk(KERN_ERR "deflate_balloon: %lu pages > %lu credit.\n",
   7.338 -               num_pages, credit);
   7.339 -        return -EAGAIN;
   7.340 +        current_pages -= debt;
   7.341      }
   7.342  
   7.343 -    parray = (unsigned long *)vmalloc(num_pages * sizeof(unsigned long));
   7.344 -    if ( parray == NULL )
   7.345 -    {
   7.346 -        printk(KERN_ERR "deflate_balloon: Unable to vmalloc parray\n");
   7.347 -        return 0;
   7.348 -    }
   7.349 -
   7.350 -    ret = HYPERVISOR_dom_mem_op(MEMOP_increase_reservation, 
   7.351 -                                parray, num_pages, 0);
   7.352 -    if ( unlikely(ret != num_pages) )
   7.353 -    {
   7.354 -        printk(KERN_ERR "deflate_balloon: xen increase_reservation err %lx\n",
   7.355 -               ret);
   7.356 -        goto cleanup;
   7.357 -    }
   7.358 + out:
   7.359 +    if ( mfn_list != NULL )
   7.360 +        vfree(mfn_list);
   7.361  
   7.362 -    if ( (ret = process_returned_pages(parray, num_pages)) < num_pages )
   7.363 -    {
   7.364 -        printk(KERN_WARNING
   7.365 -               "deflate_balloon: restored only %lx of %lx pages.\n",
   7.366 -           ret, num_pages);
   7.367 -        goto cleanup;
   7.368 -    }
   7.369 +    /* Schedule more work if there is some still to be done. */
   7.370 +    if ( current_target() != current_pages )
   7.371 +        mod_timer(&balloon_timer, jiffies + HZ);
   7.372  
   7.373 -    ret = num_pages;
   7.374 -    credit -= num_pages;
   7.375 -
   7.376 - cleanup:
   7.377 -    vfree(parray);
   7.378 -
   7.379 -    return ret;
   7.380 +    up(&balloon_mutex);
   7.381  }
   7.382  
   7.383 -#define PAGE_TO_MB_SHIFT 8
   7.384 -
   7.385 -static int balloon_try_target(int target)
   7.386 +/* Resets the Xen limit, sets new target, and kicks off processing. */
   7.387 +static void set_new_target(unsigned long target)
   7.388  {
   7.389 -    int change, reclaim;
   7.390 -
   7.391 -    if ( target < current_pages )
   7.392 -    {
   7.393 -        if ( (change = inflate_balloon(current_pages-target)) <= 0 )
   7.394 -            return change;
   7.395 -        current_pages -= change;
   7.396 -        printk(KERN_INFO "Relinquish %dMB to xen. Domain now has %luMB\n",
   7.397 -            change>>PAGE_TO_MB_SHIFT, current_pages>>PAGE_TO_MB_SHIFT);
   7.398 -    }
   7.399 -    else if ( (reclaim = target - current_pages) > 0 )
   7.400 -    {
   7.401 -        if ( (change = deflate_balloon(reclaim)) <= 0 )
   7.402 -            return change;
   7.403 -        current_pages += change;
   7.404 -        printk(KERN_INFO "Reclaim %dMB from xen. Domain now has %luMB\n",
   7.405 -               change>>PAGE_TO_MB_SHIFT, current_pages>>PAGE_TO_MB_SHIFT);
   7.406 -    }
   7.407 -
   7.408 -    return 1;
   7.409 +    hard_limit   = ~0UL;
   7.410 +    target_pages = target;
   7.411 +    balloon_process(NULL);
   7.412  }
   7.413  
   7.414 -
   7.415  static void balloon_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
   7.416  {
   7.417      switch ( msg->subtype )
   7.418 @@ -308,7 +300,8 @@ static void balloon_ctrlif_rx(ctrl_msg_t
   7.419              goto parse_error;
   7.420          {
   7.421              mem_request_t *req = (mem_request_t *)&msg->msg[0];
   7.422 -            req->status = balloon_try_target(req->target);
   7.423 +            set_new_target(req->target);
   7.424 +            req->status = 0;
   7.425          }
   7.426          break;        
   7.427      default:
   7.428 @@ -323,20 +316,13 @@ static void balloon_ctrlif_rx(ctrl_msg_t
   7.429      ctrl_if_send_response(msg);
   7.430  }
   7.431  
   7.432 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
   7.433 -typedef size_t count_t;
   7.434 -#else
   7.435 -typedef u_long count_t;
   7.436 -#endif
   7.437 -
   7.438 -static int do_balloon_write(const char *buffer, count_t count)
   7.439 +static int balloon_write(struct file *file, const char *buffer,
   7.440 +                         size_t count, loff_t *offp)
   7.441  {
   7.442      char memstring[64], *endchar;
   7.443      int len, i;
   7.444 -    unsigned long target;
   7.445 -    unsigned long long targetbytes;
   7.446 +    unsigned long long target_bytes;
   7.447  
   7.448 -    /* Only admin can play with the balloon :) */
   7.449      if ( !capable(CAP_SYS_ADMIN) )
   7.450          return -EPERM;
   7.451  
   7.452 @@ -344,8 +330,10 @@ static int do_balloon_write(const char *
   7.453          return -EFBIG;
   7.454  
   7.455      len = strnlen_user(buffer, count);
   7.456 -    if ( len == 0 ) return -EBADMSG;
   7.457 -    if ( len == 1 ) return 1; /* input starts with a NUL char */
   7.458 +    if ( len == 0 )
   7.459 +        return -EBADMSG;
   7.460 +    if ( len == 1 )
   7.461 +        goto out; /* input starts with a NUL char */
   7.462      if ( strncpy_from_user(memstring, buffer, len) < 0 )
   7.463          return -EFAULT;
   7.464  
   7.465 @@ -356,24 +344,10 @@ static int do_balloon_write(const char *
   7.466      if ( i == 0 )
   7.467          return -EBADMSG;
   7.468  
   7.469 -    targetbytes = memparse(memstring,&endchar);
   7.470 -    target = targetbytes >> PAGE_SHIFT;
   7.471 -
   7.472 -    i = balloon_try_target(target);
   7.473 -
   7.474 -    if ( i <= 0 ) return i;
   7.475 +    target_bytes = memparse(memstring,&endchar);
   7.476 +    set_new_target(target_bytes >> PAGE_SHIFT);
   7.477  
   7.478 -    return len;
   7.479 -}
   7.480 -
   7.481 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
   7.482 -static int balloon_write(struct file *file, const char *buffer,
   7.483 -                         size_t count, loff_t *offp)
   7.484 -{
   7.485 -    int len = do_balloon_write(buffer, count);
   7.486 -    
   7.487 -    if ( len <= 0 ) return len;
   7.488 -
   7.489 + out:
   7.490      *offp += len;
   7.491      return len;
   7.492  }
   7.493 @@ -381,18 +355,44 @@ static int balloon_write(struct file *fi
   7.494  static int balloon_read(struct file *filp, char *buffer,
   7.495                          size_t count, loff_t *offp)
   7.496  {
   7.497 -    static char priv_buf[32];
   7.498 -    char *priv_bufp = priv_buf;
   7.499 +    char *priv_buf;
   7.500      int len;
   7.501 -    len = sprintf(priv_buf,"%lu\n",current_pages<<PAGE_SHIFT);
   7.502 +
   7.503 +    priv_buf = (char *)__get_free_page(GFP_KERNEL);
   7.504 +    if ( priv_buf == NULL )
   7.505 +        return -ENOMEM;
   7.506 +
   7.507 +#define K(_p) ((_p)<<(PAGE_SHIFT-10))
   7.508 +    len = sprintf(
   7.509 +        priv_buf,
   7.510 +        "Current allocation: %8lu kB\n"
   7.511 +        "Target allocation:  %8lu kB / %8lu kB (actual / requested)\n"
   7.512 +        "Unused heap space:  %8lu kB / %8lu kB (low-mem / high-mem)\n"
   7.513 +        "Xen hard limit:     ",
   7.514 +        K(current_pages),
   7.515 +        K(current_target()), K(target_pages),
   7.516 +        K(balloon_low), K(balloon_high));
   7.517 +
   7.518 +    if ( hard_limit != ~0UL )
   7.519 +        len += sprintf(
   7.520 +            priv_buf + len, 
   7.521 +            "%8lu kB (inc. %8lu kB driver headroom)\n",
   7.522 +            K(hard_limit), K(driver_pages));
   7.523 +    else
   7.524 +        len += sprintf(
   7.525 +            priv_buf + len,
   7.526 +            "     ??? kB\n");
   7.527  
   7.528      len -= *offp;
   7.529 -    priv_bufp += *offp;
   7.530 -    if (len>count) len = count;
   7.531 -    if (len<0) len = 0;
   7.532 +    if ( len > count)
   7.533 +        len = count;
   7.534 +    if ( len < 0 )
   7.535 +        len = 0;
   7.536  
   7.537 -    if ( copy_to_user(buffer, priv_bufp, len) != 0 )
   7.538 -        return -EFAULT;
   7.539 +    if ( len != 0 )
   7.540 +        (void)copy_to_user(buffer, &priv_buf[*offp], len);
   7.541 +
   7.542 +    free_page((unsigned long)priv_buf);
   7.543  
   7.544      *offp += len;
   7.545      return len;
   7.546 @@ -403,30 +403,6 @@ static struct file_operations balloon_fo
   7.547      .write = balloon_write
   7.548  };
   7.549  
   7.550 -#else
   7.551 -
   7.552 -static int balloon_write(struct file *file, const char *buffer,
   7.553 -                         u_long count, void *data)
   7.554 -{
   7.555 -    return do_balloon_write(buffer, count);
   7.556 -}
   7.557 -
   7.558 -static int balloon_read(char *page, char **start, off_t off,
   7.559 -			int count, int *eof, void *data)
   7.560 -{
   7.561 -  int len;
   7.562 -  len = sprintf(page,"%lu\n",current_pages<<PAGE_SHIFT);
   7.563 -  
   7.564 -  if (len <= off+count) *eof = 1;
   7.565 -  *start = page + off;
   7.566 -  len -= off;
   7.567 -  if (len>count) len = count;
   7.568 -  if (len<0) len = 0;
   7.569 -  return len;
   7.570 -}
   7.571 -
   7.572 -#endif
   7.573 -
   7.574  static int __init balloon_init(void)
   7.575  {
   7.576      unsigned long pfn;
   7.577 @@ -435,20 +411,23 @@ static int __init balloon_init(void)
   7.578      IPRINTK("Initialising balloon driver.\n");
   7.579  
   7.580      current_pages = min(xen_start_info.nr_pages, max_pfn);
   7.581 -    if ( (balloon_pde = create_xen_proc_entry("memory_target", 0644)) == NULL )
   7.582 +    target_pages  = current_pages;
   7.583 +    balloon_low   = 0;
   7.584 +    balloon_high  = 0;
   7.585 +    driver_pages  = 0UL;
   7.586 +    hard_limit    = ~0UL;
   7.587 +
   7.588 +    init_timer(&balloon_timer);
   7.589 +    balloon_timer.data = 0;
   7.590 +    balloon_timer.function = balloon_alarm;
   7.591 +    
   7.592 +    if ( (balloon_pde = create_xen_proc_entry("balloon", 0644)) == NULL )
   7.593      {
   7.594 -        WPRINTK("Unable to create balloon driver proc entry!");
   7.595 +        WPRINTK("Unable to create /proc/xen/balloon.\n");
   7.596          return -1;
   7.597      }
   7.598  
   7.599 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
   7.600 -    balloon_pde->owner     = THIS_MODULE;
   7.601 -    balloon_pde->nlink     = 1;
   7.602      balloon_pde->proc_fops = &balloon_fops;
   7.603 -#else
   7.604 -    balloon_pde->write_proc = balloon_write;
   7.605 -    balloon_pde->read_proc  = balloon_read;
   7.606 -#endif
   7.607  
   7.608      (void)ctrl_if_register_receiver(CMSG_MEM_REQUEST, balloon_ctrlif_rx,
   7.609                                      CALLBACK_IN_BLOCKING_CONTEXT);
   7.610 @@ -464,14 +443,29 @@ static int __init balloon_init(void)
   7.611      return 0;
   7.612  }
   7.613  
   7.614 -static void __exit balloon_cleanup(void)
   7.615 +__initcall(balloon_init);
   7.616 +
   7.617 +void balloon_update_driver_allowance(long delta)
   7.618  {
   7.619 -    if ( balloon_pde != NULL )
   7.620 -    {
   7.621 -        remove_xen_proc_entry("memory_target");
   7.622 -        balloon_pde = NULL;
   7.623 -    }
   7.624 +    unsigned long flags;
   7.625 +    balloon_lock(flags);
   7.626 +    driver_pages += delta;
   7.627 +    balloon_unlock(flags);
   7.628  }
   7.629  
   7.630 -module_init(balloon_init);
   7.631 -module_exit(balloon_cleanup);
   7.632 +void balloon_put_pages(unsigned long *mfn_list, unsigned long nr_mfns)
   7.633 +{
   7.634 +    unsigned long flags;
   7.635 +
   7.636 +    balloon_lock(flags);
   7.637 +    if ( HYPERVISOR_dom_mem_op(MEMOP_decrease_reservation, 
   7.638 +                               mfn_list, nr_mfns, 0) != nr_mfns )
   7.639 +        BUG();
   7.640 +    current_pages -= nr_mfns;
   7.641 +    balloon_unlock(flags);
   7.642 +
   7.643 +    schedule_work(&balloon_worker);
   7.644 +}
   7.645 +
   7.646 +EXPORT_SYMBOL(balloon_update_driver_allowance);
   7.647 +EXPORT_SYMBOL(balloon_put_pages);
     8.1 --- a/linux-2.6.9-xen-sparse/drivers/xen/netback/netback.c	Thu Dec 02 09:22:36 2004 +0000
     8.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/netback/netback.c	Thu Dec 02 16:26:07 2004 +0000
     8.3 @@ -11,6 +11,7 @@
     8.4   */
     8.5  
     8.6  #include "common.h"
     8.7 +#include <asm-xen/balloon.h>
     8.8  
     8.9  static void netif_page_release(struct page *page);
    8.10  static void netif_skb_release(struct sk_buff *skb);
    8.11 @@ -29,6 +30,8 @@ static DECLARE_TASKLET(net_tx_tasklet, n
    8.12  static void net_rx_action(unsigned long unused);
    8.13  static DECLARE_TASKLET(net_rx_tasklet, net_rx_action, 0);
    8.14  
    8.15 +static struct timer_list net_timer;
    8.16 +
    8.17  static struct sk_buff_head rx_queue;
    8.18  static multicall_entry_t rx_mcl[NETIF_RX_RING_SIZE*2];
    8.19  static mmu_update_t rx_mmu[NETIF_RX_RING_SIZE*3];
    8.20 @@ -69,27 +72,20 @@ static unsigned long mfn_list[MAX_MFN_AL
    8.21  static unsigned int alloc_index = 0;
    8.22  static spinlock_t mfn_lock = SPIN_LOCK_UNLOCKED;
    8.23  
    8.24 -static void __refresh_mfn_list(void)
    8.25 +static unsigned long alloc_mfn(void)
    8.26  {
    8.27 -    int ret = HYPERVISOR_dom_mem_op(MEMOP_increase_reservation,
    8.28 -                                    mfn_list, MAX_MFN_ALLOC, 0);
    8.29 -    if ( unlikely(ret != MAX_MFN_ALLOC) )
    8.30 -        BUG();
    8.31 -    alloc_index = MAX_MFN_ALLOC;
    8.32 -}
    8.33 -
    8.34 -static unsigned long get_new_mfn(void)
    8.35 -{
    8.36 -    unsigned long mfn, flags;
    8.37 +    unsigned long mfn = 0, flags;
    8.38      spin_lock_irqsave(&mfn_lock, flags);
    8.39 -    if ( alloc_index == 0 )
    8.40 -        __refresh_mfn_list();
    8.41 -    mfn = mfn_list[--alloc_index];
    8.42 +    if ( unlikely(alloc_index == 0) )
    8.43 +        alloc_index = HYPERVISOR_dom_mem_op(
    8.44 +            MEMOP_increase_reservation, mfn_list, MAX_MFN_ALLOC, 0);
    8.45 +    if ( alloc_index != 0 )
    8.46 +        mfn = mfn_list[--alloc_index];
    8.47      spin_unlock_irqrestore(&mfn_lock, flags);
    8.48      return mfn;
    8.49  }
    8.50  
    8.51 -static void dealloc_mfn(unsigned long mfn)
    8.52 +static void free_mfn(unsigned long mfn)
    8.53  {
    8.54      unsigned long flags;
    8.55      spin_lock_irqsave(&mfn_lock, flags);
    8.56 @@ -210,8 +206,16 @@ static void net_rx_action(unsigned long 
    8.57          netif   = (netif_t *)skb->dev->priv;
    8.58          vdata   = (unsigned long)skb->data;
    8.59          mdata   = virt_to_machine(vdata);
    8.60 -        new_mfn = get_new_mfn();
    8.61 -        
    8.62 +
    8.63 +        /* Memory squeeze? Back off for an arbitrary while. */
    8.64 +        if ( (new_mfn = alloc_mfn()) == 0 )
    8.65 +        {
    8.66 +            if ( net_ratelimit() )
    8.67 +                printk(KERN_WARNING "Memory squeeze in netback driver.\n");
    8.68 +            mod_timer(&net_timer, jiffies + HZ);
    8.69 +            break;
    8.70 +        }
    8.71 +
    8.72          /*
    8.73           * Set the new P2M table entry before reassigning the old data page.
    8.74           * Heed the comment in pgtable-2level.h:pte_page(). :-)
    8.75 @@ -280,7 +284,7 @@ static void net_rx_action(unsigned long 
    8.76          if ( unlikely(mcl[1].args[5] != 0) )
    8.77          {
    8.78              DPRINTK("Failed MMU update transferring to DOM%u\n", netif->domid);
    8.79 -            dealloc_mfn(mdata >> PAGE_SHIFT);
    8.80 +            free_mfn(mdata >> PAGE_SHIFT);
    8.81              status = NETIF_RSP_ERROR;
    8.82          }
    8.83  
    8.84 @@ -307,7 +311,7 @@ static void net_rx_action(unsigned long 
    8.85      }
    8.86  
    8.87      /* More work to do? */
    8.88 -    if ( !skb_queue_empty(&rx_queue) )
    8.89 +    if ( !skb_queue_empty(&rx_queue) && !timer_pending(&net_timer) )
    8.90          tasklet_schedule(&net_rx_tasklet);
    8.91  #if 0
    8.92      else
    8.93 @@ -315,6 +319,11 @@ static void net_rx_action(unsigned long 
    8.94  #endif
    8.95  }
    8.96  
    8.97 +static void net_alarm(unsigned long unused)
    8.98 +{
    8.99 +    tasklet_schedule(&net_rx_tasklet);
   8.100 +}
   8.101 +
   8.102  struct net_device_stats *netif_be_get_stats(struct net_device *dev)
   8.103  {
   8.104      netif_t *netif = dev->priv;
   8.105 @@ -781,9 +790,16 @@ static int __init netback_init(void)
   8.106  
   8.107      printk("Initialising Xen netif backend\n");
   8.108  
   8.109 +    /* We can increase reservation by this much in net_rx_action(). */
   8.110 +    balloon_update_driver_allowance(NETIF_RX_RING_SIZE);
   8.111 +
   8.112      skb_queue_head_init(&rx_queue);
   8.113      skb_queue_head_init(&tx_queue);
   8.114  
   8.115 +    init_timer(&net_timer);
   8.116 +    net_timer.data = 0;
   8.117 +    net_timer.function = net_alarm;
   8.118 +    
   8.119      netif_interface_init();
   8.120  
   8.121      if ( (mmap_vstart = allocate_empty_lowmem_region(MAX_PENDING_REQS)) == 0 )
     9.1 --- a/linux-2.6.9-xen-sparse/drivers/xen/netfront/netfront.c	Thu Dec 02 09:22:36 2004 +0000
     9.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/netfront/netfront.c	Thu Dec 02 16:26:07 2004 +0000
     9.3 @@ -45,6 +45,7 @@
     9.4  #include <asm-xen/evtchn.h>
     9.5  #include <asm-xen/ctrl_if.h>
     9.6  #include <asm-xen/xen-public/io/netif.h>
     9.7 +#include <asm-xen/balloon.h>
     9.8  #include <asm/page.h>
     9.9  
    9.10  #include <net/arp.h>
    9.11 @@ -409,6 +410,9 @@ static void network_alloc_rx_buffers(str
    9.12      rx_mcl[i].args[3] = 0;
    9.13      rx_mcl[i].args[4] = DOMID_SELF;
    9.14  
    9.15 +    /* Tell the ballon driver what is going on. */
    9.16 +    balloon_update_driver_allowance(i);
    9.17 +
    9.18      /* Zap PTEs and give away pages in one big multicall. */
    9.19      (void)HYPERVISOR_multicall(rx_mcl, i+1);
    9.20  
    9.21 @@ -557,14 +561,15 @@ static int netif_poll(struct net_device 
    9.22          /*
    9.23           * An error here is very odd. Usually indicates a backend bug,
    9.24           * low-memory condition, or that we didn't have reservation headroom.
    9.25 -         * Whatever - print an error and queue the id again straight away.
    9.26           */
    9.27          if ( unlikely(rx->status <= 0) )
    9.28          {
    9.29 -	    printk(KERN_ALERT "bad buffer on RX ring!(%d)\n", rx->status);
    9.30 +            if ( net_ratelimit() )
    9.31 +                printk(KERN_WARNING "Bad rx buffer (memory squeeze?).\n");
    9.32              np->rx->ring[MASK_NETIF_RX_IDX(np->rx->req_prod)].req.id = rx->id;
    9.33              wmb();
    9.34              np->rx->req_prod++;
    9.35 +            work_done--;
    9.36              continue;
    9.37          }
    9.38  
    9.39 @@ -595,6 +600,9 @@ static int netif_poll(struct net_device 
    9.40          __skb_queue_tail(&rxq, skb);
    9.41      }
    9.42  
    9.43 +    /* Some pages are no longer absent... */
    9.44 +    balloon_update_driver_allowance(-work_done);
    9.45 +
    9.46      /* Do all the remapping work, and M->P updates, in one big hypercall. */
    9.47      if ( likely((mcl - rx_mcl) != 0) )
    9.48      {
    10.1 --- a/linux-2.6.9-xen-sparse/drivers/xen/privcmd/privcmd.c	Thu Dec 02 09:22:36 2004 +0000
    10.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/privcmd/privcmd.c	Thu Dec 02 16:26:07 2004 +0000
    10.3 @@ -7,7 +7,6 @@
    10.4   */
    10.5  
    10.6  #include <linux/config.h>
    10.7 -#include <linux/module.h>
    10.8  #include <linux/kernel.h>
    10.9  #include <linux/sched.h>
   10.10  #include <linux/slab.h>
   10.11 @@ -213,23 +212,9 @@ static int __init privcmd_init(void)
   10.12  
   10.13      privcmd_intf = create_xen_proc_entry("privcmd", 0400);
   10.14      if ( privcmd_intf != NULL )
   10.15 -    {
   10.16 -        privcmd_intf->owner      = THIS_MODULE;
   10.17 -        privcmd_intf->nlink      = 1;
   10.18 -        privcmd_intf->proc_fops  = &privcmd_file_ops;
   10.19 -    }
   10.20 +        privcmd_intf->proc_fops = &privcmd_file_ops;
   10.21  
   10.22      return 0;
   10.23  }
   10.24  
   10.25 -
   10.26 -static void __exit privcmd_cleanup(void)
   10.27 -{
   10.28 -    if ( privcmd_intf == NULL ) return;
   10.29 -    remove_xen_proc_entry("privcmd");
   10.30 -    privcmd_intf = NULL;
   10.31 -}
   10.32 -
   10.33 -
   10.34 -module_init(privcmd_init);
   10.35 -module_exit(privcmd_cleanup);
   10.36 +__initcall(privcmd_init);
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/linux-2.6.9-xen-sparse/include/asm-xen/balloon.h	Thu Dec 02 16:26:07 2004 +0000
    11.3 @@ -0,0 +1,51 @@
    11.4 +/******************************************************************************
    11.5 + * balloon.h
    11.6 + *
    11.7 + * Xen balloon driver - enables returning/claiming memory to/from Xen.
    11.8 + *
    11.9 + * Copyright (c) 2003, B Dragovic
   11.10 + * Copyright (c) 2003-2004, M Williamson, K Fraser
   11.11 + * 
   11.12 + * This file may be distributed separately from the Linux kernel, or
   11.13 + * incorporated into other software packages, subject to the following license:
   11.14 + * 
   11.15 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   11.16 + * of this source file (the "Software"), to deal in the Software without
   11.17 + * restriction, including without limitation the rights to use, copy, modify,
   11.18 + * merge, publish, distribute, sublicense, and/or sell copies of the Software,
   11.19 + * and to permit persons to whom the Software is furnished to do so, subject to
   11.20 + * the following conditions:
   11.21 + * 
   11.22 + * The above copyright notice and this permission notice shall be included in
   11.23 + * all copies or substantial portions of the Software.
   11.24 + * 
   11.25 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   11.26 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   11.27 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   11.28 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   11.29 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   11.30 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
   11.31 + * IN THE SOFTWARE.
   11.32 + */
   11.33 +
   11.34 +#ifndef __ASM_BALLOON_H__
   11.35 +#define __ASM_BALLOON_H__
   11.36 +
   11.37 +/*
   11.38 + * Inform the balloon driver that it should allow some slop for device-driver
   11.39 + * memory activities.
   11.40 + */
   11.41 +extern void balloon_update_driver_allowance(long delta);
   11.42 +
   11.43 +/* Give up unmapped pages to the balloon driver. */
   11.44 +extern void balloon_put_pages(unsigned long *mfn_list, unsigned long nr_mfns);
   11.45 +
   11.46 +/*
   11.47 + * Prevent the balloon driver from changing the memory reservation during
   11.48 + * a driver critical region.
   11.49 + */
   11.50 +extern spinlock_t balloon_lock;
   11.51 +#define balloon_lock(__flags)   spin_lock_irqsave(&balloon_lock, __flags)
   11.52 +#define balloon_unlock(__flags) spin_unlock_irqrestore(&balloon_lock, __flags)
   11.53 +
   11.54 +#endif /* __ASM_BALLOON_H__ */
    12.1 --- a/linux-2.6.9-xen-sparse/include/asm-xen/hypervisor.h	Thu Dec 02 09:22:36 2004 +0000
    12.2 +++ b/linux-2.6.9-xen-sparse/include/asm-xen/hypervisor.h	Thu Dec 02 16:26:07 2004 +0000
    12.3 @@ -102,8 +102,6 @@ void MULTICALL_flush_page_update_queue(v
    12.4  #ifdef CONFIG_XEN_PHYSDEV_ACCESS
    12.5  /* Allocate a contiguous empty region of low memory. Return virtual start. */
    12.6  unsigned long allocate_empty_lowmem_region(unsigned long pages);
    12.7 -/* Deallocate a contiguous region of low memory. Return it to the allocator. */
    12.8 -void deallocate_lowmem_region(unsigned long vstart, unsigned long pages);
    12.9  #endif
   12.10  
   12.11  /*