ia64/linux-2.6.18-xen.hg

view arch/sparc64/kernel/iommu_common.c @ 897:329ea0ccb344

balloon: try harder to balloon up under memory pressure.

Currently if the balloon driver is unable to increase the guest's
reservation it assumes the failure was due to reaching its full
allocation, gives up on the ballooning operation and records the limit
it reached as the "hard limit". The driver will not try again until
the target is set again (even to the same value).

However it is possible that ballooning has in fact failed due to
memory pressure in the host and therefore it is desirable to keep
attempting to reach the target in case memory becomes available. The
most likely scenario is that some guests are ballooning down while
others are ballooning up and therefore there is temporary memory
pressure while things stabilise. You would not expect a well behaved
toolstack to ask a domain to balloon to more than its allocation nor
would you expect it to deliberately over-commit memory by setting
balloon targets which exceed the total host memory.

This patch drops the concept of a hard limit and causes the balloon
driver to retry increasing the reservation on a timer in the same
manner as when decreasing the reservation.

Also if we partially succeed in increasing the reservation
(i.e. receive less pages than we asked for) then we may as well keep
those pages rather than returning them to Xen.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 05 14:01:20 2009 +0100 (2009-06-05)
parents 831230e53067
children
line source
1 /* $Id: iommu_common.c,v 1.9 2001/12/17 07:05:09 davem Exp $
2 * iommu_common.c: UltraSparc SBUS/PCI common iommu code.
3 *
4 * Copyright (C) 1999 David S. Miller (davem@redhat.com)
5 */
7 #include "iommu_common.h"
9 /* You are _strongly_ advised to enable the following debugging code
10 * any time you make changes to the sg code below, run it for a while
11 * with filesystems mounted read-only before buying the farm... -DaveM
12 */
14 #ifdef VERIFY_SG
15 static int verify_lengths(struct scatterlist *sg, int nents, int npages)
16 {
17 int sg_len, dma_len;
18 int i, pgcount;
20 sg_len = 0;
21 for (i = 0; i < nents; i++)
22 sg_len += sg[i].length;
24 dma_len = 0;
25 for (i = 0; i < nents && sg[i].dma_length; i++)
26 dma_len += sg[i].dma_length;
28 if (sg_len != dma_len) {
29 printk("verify_lengths: Error, different, sg[%d] dma[%d]\n",
30 sg_len, dma_len);
31 return -1;
32 }
34 pgcount = 0;
35 for (i = 0; i < nents && sg[i].dma_length; i++) {
36 unsigned long start, end;
38 start = sg[i].dma_address;
39 start = start & IO_PAGE_MASK;
41 end = sg[i].dma_address + sg[i].dma_length;
42 end = (end + (IO_PAGE_SIZE - 1)) & IO_PAGE_MASK;
44 pgcount += ((end - start) >> IO_PAGE_SHIFT);
45 }
47 if (pgcount != npages) {
48 printk("verify_lengths: Error, page count wrong, "
49 "npages[%d] pgcount[%d]\n",
50 npages, pgcount);
51 return -1;
52 }
54 /* This test passes... */
55 return 0;
56 }
58 static int verify_one_map(struct scatterlist *dma_sg, struct scatterlist **__sg, int nents, iopte_t **__iopte)
59 {
60 struct scatterlist *sg = *__sg;
61 iopte_t *iopte = *__iopte;
62 u32 dlen = dma_sg->dma_length;
63 u32 daddr;
64 unsigned int sglen;
65 unsigned long sgaddr;
67 daddr = dma_sg->dma_address;
68 sglen = sg->length;
69 sgaddr = (unsigned long) (page_address(sg->page) + sg->offset);
70 while (dlen > 0) {
71 unsigned long paddr;
73 /* SG and DMA_SG must begin at the same sub-page boundary. */
74 if ((sgaddr & ~IO_PAGE_MASK) != (daddr & ~IO_PAGE_MASK)) {
75 printk("verify_one_map: Wrong start offset "
76 "sg[%08lx] dma[%08x]\n",
77 sgaddr, daddr);
78 nents = -1;
79 goto out;
80 }
82 /* Verify the IOPTE points to the right page. */
83 paddr = iopte_val(*iopte) & IOPTE_PAGE;
84 if ((paddr + PAGE_OFFSET) != (sgaddr & IO_PAGE_MASK)) {
85 printk("verify_one_map: IOPTE[%08lx] maps the "
86 "wrong page, should be [%08lx]\n",
87 iopte_val(*iopte), (sgaddr & IO_PAGE_MASK) - PAGE_OFFSET);
88 nents = -1;
89 goto out;
90 }
92 /* If this SG crosses a page, adjust to that next page
93 * boundary and loop.
94 */
95 if ((sgaddr & IO_PAGE_MASK) ^ ((sgaddr + sglen - 1) & IO_PAGE_MASK)) {
96 unsigned long next_page, diff;
98 next_page = (sgaddr + IO_PAGE_SIZE) & IO_PAGE_MASK;
99 diff = next_page - sgaddr;
100 sgaddr += diff;
101 daddr += diff;
102 sglen -= diff;
103 dlen -= diff;
104 if (dlen > 0)
105 iopte++;
106 continue;
107 }
109 /* SG wholly consumed within this page. */
110 daddr += sglen;
111 dlen -= sglen;
113 if (dlen > 0 && ((daddr & ~IO_PAGE_MASK) == 0))
114 iopte++;
116 sg++;
117 if (--nents <= 0)
118 break;
119 sgaddr = (unsigned long) (page_address(sg->page) + sg->offset);
120 sglen = sg->length;
121 }
122 if (dlen < 0) {
123 /* Transfer overrun, big problems. */
124 printk("verify_one_map: Transfer overrun by %d bytes.\n",
125 -dlen);
126 nents = -1;
127 } else {
128 /* Advance to next dma_sg implies that the next iopte will
129 * begin it.
130 */
131 iopte++;
132 }
134 out:
135 *__sg = sg;
136 *__iopte = iopte;
137 return nents;
138 }
140 static int verify_maps(struct scatterlist *sg, int nents, iopte_t *iopte)
141 {
142 struct scatterlist *dma_sg = sg;
143 struct scatterlist *orig_dma_sg = dma_sg;
144 int orig_nents = nents;
146 for (;;) {
147 nents = verify_one_map(dma_sg, &sg, nents, &iopte);
148 if (nents <= 0)
149 break;
150 dma_sg++;
151 if (dma_sg->dma_length == 0)
152 break;
153 }
155 if (nents > 0) {
156 printk("verify_maps: dma maps consumed by some sgs remain (%d)\n",
157 nents);
158 return -1;
159 }
161 if (nents < 0) {
162 printk("verify_maps: Error, messed up mappings, "
163 "at sg %d dma_sg %d\n",
164 (int) (orig_nents + nents), (int) (dma_sg - orig_dma_sg));
165 return -1;
166 }
168 /* This test passes... */
169 return 0;
170 }
172 void verify_sglist(struct scatterlist *sg, int nents, iopte_t *iopte, int npages)
173 {
174 if (verify_lengths(sg, nents, npages) < 0 ||
175 verify_maps(sg, nents, iopte) < 0) {
176 int i;
178 printk("verify_sglist: Crap, messed up mappings, dumping, iodma at ");
179 printk("%016lx.\n", sg->dma_address & IO_PAGE_MASK);
181 for (i = 0; i < nents; i++) {
182 printk("sg(%d): page_addr(%p) off(%x) length(%x) "
183 "dma_address[%016lx] dma_length[%016lx]\n",
184 i,
185 page_address(sg[i].page), sg[i].offset,
186 sg[i].length,
187 sg[i].dma_address, sg[i].dma_length);
188 }
189 }
191 /* Seems to be ok */
192 }
193 #endif
195 unsigned long prepare_sg(struct scatterlist *sg, int nents)
196 {
197 struct scatterlist *dma_sg = sg;
198 unsigned long prev;
199 u32 dent_addr, dent_len;
201 prev = (unsigned long) (page_address(sg->page) + sg->offset);
202 prev += (unsigned long) (dent_len = sg->length);
203 dent_addr = (u32) ((unsigned long)(page_address(sg->page) + sg->offset)
204 & (IO_PAGE_SIZE - 1UL));
205 while (--nents) {
206 unsigned long addr;
208 sg++;
209 addr = (unsigned long) (page_address(sg->page) + sg->offset);
210 if (! VCONTIG(prev, addr)) {
211 dma_sg->dma_address = dent_addr;
212 dma_sg->dma_length = dent_len;
213 dma_sg++;
215 dent_addr = ((dent_addr +
216 dent_len +
217 (IO_PAGE_SIZE - 1UL)) >> IO_PAGE_SHIFT);
218 dent_addr <<= IO_PAGE_SHIFT;
219 dent_addr += addr & (IO_PAGE_SIZE - 1UL);
220 dent_len = 0;
221 }
222 dent_len += sg->length;
223 prev = addr + sg->length;
224 }
225 dma_sg->dma_address = dent_addr;
226 dma_sg->dma_length = dent_len;
228 return ((unsigned long) dent_addr +
229 (unsigned long) dent_len +
230 (IO_PAGE_SIZE - 1UL)) >> IO_PAGE_SHIFT;
231 }