direct-io.hg
changeset 6316:2052ce3345c1
Apply Ross Mcilroy's balloon_dealloc_empty_page_range patch
and generally clean up the ballon driver a bunch.
Signed-off-by: Keir Fraser <keir@xensource.com>
and generally clean up the ballon driver a bunch.
Signed-off-by: Keir Fraser <keir@xensource.com>
author | kaf24@firebug.cl.cam.ac.uk |
---|---|
date | Mon Aug 22 16:38:13 2005 +0000 (2005-08-22) |
parents | 531ad4bde8f2 |
children | 8c58bf335465 3a8f27c6d56c |
files | linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c linux-2.6-xen-sparse/drivers/xen/blktap/blktap_userdev.c linux-2.6-xen-sparse/drivers/xen/netback/netback.c linux-2.6-xen-sparse/drivers/xen/usbback/usbback.c linux-2.6-xen-sparse/include/asm-xen/balloon.h linux-2.6-xen-sparse/include/asm-xen/hypervisor.h |
line diff
1.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c Mon Aug 22 10:21:18 2005 +0000 1.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c Mon Aug 22 16:38:13 2005 +0000 1.3 @@ -405,54 +405,6 @@ void xen_destroy_contiguous_region(unsig 1.4 balloon_unlock(flags); 1.5 } 1.6 1.7 - 1.8 -unsigned long allocate_empty_lowmem_region(unsigned long pages) 1.9 -{ 1.10 - pgd_t *pgd; 1.11 - pud_t *pud; 1.12 - pmd_t *pmd; 1.13 - pte_t *pte; 1.14 - unsigned long *pfn_array; 1.15 - unsigned long vstart; 1.16 - unsigned long i; 1.17 - unsigned int order = get_order(pages*PAGE_SIZE); 1.18 - 1.19 - vstart = __get_free_pages(GFP_KERNEL, order); 1.20 - if (vstart == 0) 1.21 - return 0UL; 1.22 - 1.23 - scrub_pages(vstart, 1 << order); 1.24 - 1.25 - pfn_array = vmalloc((1<<order) * sizeof(*pfn_array)); 1.26 - BUG_ON(pfn_array == NULL); 1.27 - 1.28 - for (i = 0; i < (1<<order); i++) { 1.29 - pgd = pgd_offset_k( (vstart + (i*PAGE_SIZE))); 1.30 - pud = pud_offset(pgd, (vstart + (i*PAGE_SIZE))); 1.31 - pmd = pmd_offset(pud, (vstart + (i*PAGE_SIZE))); 1.32 - pte = pte_offset_kernel(pmd, (vstart + (i*PAGE_SIZE))); 1.33 - pfn_array[i] = pte_mfn(*pte); 1.34 -#ifdef CONFIG_X86_64 1.35 - xen_l1_entry_update(pte, __pte(0)); 1.36 -#else 1.37 - BUG_ON(HYPERVISOR_update_va_mapping(vstart + (i*PAGE_SIZE), 1.38 - __pte_ma(0), 0)); 1.39 -#endif 1.40 - phys_to_machine_mapping[(__pa(vstart)>>PAGE_SHIFT)+i] = 1.41 - INVALID_P2M_ENTRY; 1.42 - } 1.43 - 1.44 - flush_tlb_all(); 1.45 - 1.46 - balloon_put_pages(pfn_array, 1 << order); 1.47 - 1.48 - vfree(pfn_array); 1.49 - 1.50 - return vstart; 1.51 -} 1.52 - 1.53 -EXPORT_SYMBOL(allocate_empty_lowmem_region); 1.54 - 1.55 /* 1.56 * Local variables: 1.57 * c-file-style: "linux"
2.1 --- a/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c Mon Aug 22 10:21:18 2005 +0000 2.2 +++ b/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c Mon Aug 22 16:38:13 2005 +0000 2.3 @@ -83,12 +83,15 @@ static struct timer_list balloon_timer; 2.4 2.5 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) 2.6 /* Use the private and mapping fields of struct page as a list. */ 2.7 -#define PAGE_TO_LIST(p) ( (struct list_head *)&p->private ) 2.8 -#define LIST_TO_PAGE(l) ( list_entry( ((unsigned long *)l), \ 2.9 - struct page, private ) ) 2.10 -#define UNLIST_PAGE(p) do { list_del(PAGE_TO_LIST(p)); \ 2.11 - p->mapping = NULL; \ 2.12 - p->private = 0; } while(0) 2.13 +#define PAGE_TO_LIST(p) ((struct list_head *)&p->private) 2.14 +#define LIST_TO_PAGE(l) \ 2.15 + (list_entry(((unsigned long *)l), struct page, private)) 2.16 +#define UNLIST_PAGE(p) \ 2.17 + do { \ 2.18 + list_del(PAGE_TO_LIST(p)); \ 2.19 + p->mapping = NULL; \ 2.20 + p->private = 0; \ 2.21 + } while(0) 2.22 #else 2.23 /* There's a dedicated list field in struct page we can use. */ 2.24 #define PAGE_TO_LIST(p) ( &p->list ) 2.25 @@ -104,56 +107,53 @@ static struct timer_list balloon_timer; 2.26 #endif 2.27 2.28 #define IPRINTK(fmt, args...) \ 2.29 - printk(KERN_INFO "xen_mem: " fmt, ##args) 2.30 + printk(KERN_INFO "xen_mem: " fmt, ##args) 2.31 #define WPRINTK(fmt, args...) \ 2.32 - printk(KERN_WARNING "xen_mem: " fmt, ##args) 2.33 + printk(KERN_WARNING "xen_mem: " fmt, ##args) 2.34 2.35 /* balloon_append: add the given page to the balloon. */ 2.36 static void balloon_append(struct page *page) 2.37 { 2.38 - /* Low memory is re-populated first, so highmem pages go at list tail. */ 2.39 - if ( PageHighMem(page) ) 2.40 - { 2.41 - list_add_tail(PAGE_TO_LIST(page), &ballooned_pages); 2.42 - balloon_high++; 2.43 - } 2.44 - else 2.45 - { 2.46 - list_add(PAGE_TO_LIST(page), &ballooned_pages); 2.47 - balloon_low++; 2.48 - } 2.49 + /* Lowmem is re-populated first, so highmem pages go at list tail. */ 2.50 + if (PageHighMem(page)) { 2.51 + list_add_tail(PAGE_TO_LIST(page), &ballooned_pages); 2.52 + balloon_high++; 2.53 + } else { 2.54 + list_add(PAGE_TO_LIST(page), &ballooned_pages); 2.55 + balloon_low++; 2.56 + } 2.57 } 2.58 2.59 /* balloon_retrieve: rescue a page from the balloon, if it is not empty. */ 2.60 static struct page *balloon_retrieve(void) 2.61 { 2.62 - struct page *page; 2.63 + struct page *page; 2.64 2.65 - if ( list_empty(&ballooned_pages) ) 2.66 - return NULL; 2.67 + if (list_empty(&ballooned_pages)) 2.68 + return NULL; 2.69 2.70 - page = LIST_TO_PAGE(ballooned_pages.next); 2.71 - UNLIST_PAGE(page); 2.72 + page = LIST_TO_PAGE(ballooned_pages.next); 2.73 + UNLIST_PAGE(page); 2.74 2.75 - if ( PageHighMem(page) ) 2.76 - balloon_high--; 2.77 - else 2.78 - balloon_low--; 2.79 + if (PageHighMem(page)) 2.80 + balloon_high--; 2.81 + else 2.82 + balloon_low--; 2.83 2.84 - return page; 2.85 + return page; 2.86 } 2.87 2.88 static void balloon_alarm(unsigned long unused) 2.89 { 2.90 - schedule_work(&balloon_worker); 2.91 + schedule_work(&balloon_worker); 2.92 } 2.93 2.94 static unsigned long current_target(void) 2.95 { 2.96 - unsigned long target = min(target_pages, hard_limit); 2.97 - if ( target > (current_pages + balloon_low + balloon_high) ) 2.98 - target = current_pages + balloon_low + balloon_high; 2.99 - return target; 2.100 + unsigned long target = min(target_pages, hard_limit); 2.101 + if (target > (current_pages + balloon_low + balloon_high)) 2.102 + target = current_pages + balloon_low + balloon_high; 2.103 + return target; 2.104 } 2.105 2.106 /* 2.107 @@ -164,161 +164,147 @@ static unsigned long current_target(void 2.108 */ 2.109 static void balloon_process(void *unused) 2.110 { 2.111 - unsigned long *mfn_list, pfn, i, flags; 2.112 - struct page *page; 2.113 - long credit, debt, rc; 2.114 - void *v; 2.115 + unsigned long *mfn_list, pfn, i, flags; 2.116 + struct page *page; 2.117 + long credit, debt, rc; 2.118 + void *v; 2.119 2.120 - down(&balloon_mutex); 2.121 + down(&balloon_mutex); 2.122 2.123 retry: 2.124 - mfn_list = NULL; 2.125 + mfn_list = NULL; 2.126 2.127 - if ( (credit = current_target() - current_pages) > 0 ) 2.128 - { 2.129 - mfn_list = (unsigned long *)vmalloc(credit * sizeof(*mfn_list)); 2.130 - if ( mfn_list == NULL ) 2.131 - goto out; 2.132 + if ((credit = current_target() - current_pages) > 0) { 2.133 + mfn_list = vmalloc(credit * sizeof(*mfn_list)); 2.134 + if (mfn_list == NULL) 2.135 + goto out; 2.136 2.137 - balloon_lock(flags); 2.138 - rc = HYPERVISOR_dom_mem_op( 2.139 - MEMOP_increase_reservation, mfn_list, credit, 0); 2.140 - balloon_unlock(flags); 2.141 - if ( rc < credit ) 2.142 - { 2.143 - /* We hit the Xen hard limit: reprobe. */ 2.144 - if ( HYPERVISOR_dom_mem_op( 2.145 - MEMOP_decrease_reservation, mfn_list, rc, 0) != rc ) 2.146 - BUG(); 2.147 - hard_limit = current_pages + rc - driver_pages; 2.148 - vfree(mfn_list); 2.149 - goto retry; 2.150 - } 2.151 + balloon_lock(flags); 2.152 + rc = HYPERVISOR_dom_mem_op( 2.153 + MEMOP_increase_reservation, mfn_list, credit, 0); 2.154 + balloon_unlock(flags); 2.155 + if (rc < credit) { 2.156 + /* We hit the Xen hard limit: reprobe. */ 2.157 + BUG_ON(HYPERVISOR_dom_mem_op( 2.158 + MEMOP_decrease_reservation, 2.159 + mfn_list, rc, 0) != rc); 2.160 + hard_limit = current_pages + rc - driver_pages; 2.161 + vfree(mfn_list); 2.162 + goto retry; 2.163 + } 2.164 2.165 - for ( i = 0; i < credit; i++ ) 2.166 - { 2.167 - if ( (page = balloon_retrieve()) == NULL ) 2.168 - BUG(); 2.169 + for (i = 0; i < credit; i++) { 2.170 + page = balloon_retrieve(); 2.171 + BUG_ON(page == NULL); 2.172 2.173 - pfn = page - mem_map; 2.174 - if ( phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY ) 2.175 - BUG(); 2.176 + pfn = page - mem_map; 2.177 + if (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY) 2.178 + BUG(); 2.179 2.180 - /* Update P->M and M->P tables. */ 2.181 - phys_to_machine_mapping[pfn] = mfn_list[i]; 2.182 - xen_machphys_update(mfn_list[i], pfn); 2.183 + /* Update P->M and M->P tables. */ 2.184 + phys_to_machine_mapping[pfn] = mfn_list[i]; 2.185 + xen_machphys_update(mfn_list[i], pfn); 2.186 2.187 - /* Link back into the page tables if it's not a highmem page. */ 2.188 - if ( pfn < max_low_pfn ) 2.189 - { 2.190 - BUG_ON(HYPERVISOR_update_va_mapping( 2.191 - (unsigned long)__va(pfn << PAGE_SHIFT), 2.192 - pfn_pte_ma(mfn_list[i], PAGE_KERNEL), 0)); 2.193 - } 2.194 + /* Link back into the page tables if not highmem. */ 2.195 + if (pfn < max_low_pfn) 2.196 + BUG_ON(HYPERVISOR_update_va_mapping( 2.197 + (unsigned long)__va(pfn << PAGE_SHIFT), 2.198 + pfn_pte_ma(mfn_list[i], PAGE_KERNEL), 2.199 + 0)); 2.200 2.201 - /* Finally, relinquish the memory back to the system allocator. */ 2.202 - ClearPageReserved(page); 2.203 - set_page_count(page, 1); 2.204 - __free_page(page); 2.205 - } 2.206 + /* Relinquish the page back to the allocator. */ 2.207 + ClearPageReserved(page); 2.208 + set_page_count(page, 1); 2.209 + __free_page(page); 2.210 + } 2.211 2.212 - current_pages += credit; 2.213 - } 2.214 - else if ( credit < 0 ) 2.215 - { 2.216 - debt = -credit; 2.217 + current_pages += credit; 2.218 + } else if (credit < 0) { 2.219 + debt = -credit; 2.220 2.221 - mfn_list = (unsigned long *)vmalloc(debt * sizeof(*mfn_list)); 2.222 - if ( mfn_list == NULL ) 2.223 - goto out; 2.224 + mfn_list = vmalloc(debt * sizeof(*mfn_list)); 2.225 + if (mfn_list == NULL) 2.226 + goto out; 2.227 2.228 - for ( i = 0; i < debt; i++ ) 2.229 - { 2.230 - if ( (page = alloc_page(GFP_HIGHUSER)) == NULL ) 2.231 - { 2.232 - debt = i; 2.233 - break; 2.234 - } 2.235 + for (i = 0; i < debt; i++) { 2.236 + if ((page = alloc_page(GFP_HIGHUSER)) == NULL) { 2.237 + debt = i; 2.238 + break; 2.239 + } 2.240 2.241 - pfn = page - mem_map; 2.242 - mfn_list[i] = phys_to_machine_mapping[pfn]; 2.243 + pfn = page - mem_map; 2.244 + mfn_list[i] = phys_to_machine_mapping[pfn]; 2.245 2.246 - if ( !PageHighMem(page) ) 2.247 - { 2.248 - v = phys_to_virt(pfn << PAGE_SHIFT); 2.249 - scrub_pages(v, 1); 2.250 - BUG_ON(HYPERVISOR_update_va_mapping( 2.251 - (unsigned long)v, __pte_ma(0), 0)); 2.252 - } 2.253 + if (!PageHighMem(page)) { 2.254 + v = phys_to_virt(pfn << PAGE_SHIFT); 2.255 + scrub_pages(v, 1); 2.256 + BUG_ON(HYPERVISOR_update_va_mapping( 2.257 + (unsigned long)v, __pte_ma(0), 0)); 2.258 + } 2.259 #ifdef CONFIG_XEN_SCRUB_PAGES 2.260 - else 2.261 - { 2.262 - v = kmap(page); 2.263 - scrub_pages(v, 1); 2.264 - kunmap(page); 2.265 - } 2.266 + else { 2.267 + v = kmap(page); 2.268 + scrub_pages(v, 1); 2.269 + kunmap(page); 2.270 + } 2.271 #endif 2.272 - } 2.273 + } 2.274 2.275 - /* Ensure that ballooned highmem pages don't have cached mappings. */ 2.276 - kmap_flush_unused(); 2.277 - flush_tlb_all(); 2.278 + /* Ensure that ballooned highmem pages don't have kmaps. */ 2.279 + kmap_flush_unused(); 2.280 + flush_tlb_all(); 2.281 2.282 - /* No more mappings: invalidate pages in P2M and add to balloon. */ 2.283 - for ( i = 0; i < debt; i++ ) 2.284 - { 2.285 - pfn = mfn_to_pfn(mfn_list[i]); 2.286 - phys_to_machine_mapping[pfn] = INVALID_P2M_ENTRY; 2.287 - balloon_append(pfn_to_page(pfn)); 2.288 - } 2.289 + /* No more mappings: invalidate P2M and add to balloon. */ 2.290 + for (i = 0; i < debt; i++) { 2.291 + pfn = mfn_to_pfn(mfn_list[i]); 2.292 + phys_to_machine_mapping[pfn] = INVALID_P2M_ENTRY; 2.293 + balloon_append(pfn_to_page(pfn)); 2.294 + } 2.295 2.296 - if ( HYPERVISOR_dom_mem_op( 2.297 - MEMOP_decrease_reservation, mfn_list, debt, 0) != debt ) 2.298 - BUG(); 2.299 + BUG_ON(HYPERVISOR_dom_mem_op( 2.300 + MEMOP_decrease_reservation,mfn_list, debt, 0) != debt); 2.301 2.302 - current_pages -= debt; 2.303 - } 2.304 + current_pages -= debt; 2.305 + } 2.306 2.307 out: 2.308 - if ( mfn_list != NULL ) 2.309 - vfree(mfn_list); 2.310 + if (mfn_list != NULL) 2.311 + vfree(mfn_list); 2.312 2.313 - /* Schedule more work if there is some still to be done. */ 2.314 - if ( current_target() != current_pages ) 2.315 - mod_timer(&balloon_timer, jiffies + HZ); 2.316 + /* Schedule more work if there is some still to be done. */ 2.317 + if (current_target() != current_pages) 2.318 + mod_timer(&balloon_timer, jiffies + HZ); 2.319 2.320 - up(&balloon_mutex); 2.321 + up(&balloon_mutex); 2.322 } 2.323 2.324 /* Resets the Xen limit, sets new target, and kicks off processing. */ 2.325 static void set_new_target(unsigned long target) 2.326 { 2.327 - /* No need for lock. Not read-modify-write updates. */ 2.328 - hard_limit = ~0UL; 2.329 - target_pages = target; 2.330 - schedule_work(&balloon_worker); 2.331 + /* No need for lock. Not read-modify-write updates. */ 2.332 + hard_limit = ~0UL; 2.333 + target_pages = target; 2.334 + schedule_work(&balloon_worker); 2.335 } 2.336 2.337 static struct xenbus_watch target_watch = 2.338 { 2.339 - .node = "memory/target" 2.340 + .node = "memory/target" 2.341 }; 2.342 2.343 /* React to a change in the target key */ 2.344 static void watch_target(struct xenbus_watch *watch, const char *node) 2.345 { 2.346 - unsigned long new_target; 2.347 - int err; 2.348 + unsigned long new_target; 2.349 + int err; 2.350 2.351 - err = xenbus_scanf("memory", "target", "%lu", &new_target); 2.352 + err = xenbus_scanf("memory", "target", "%lu", &new_target); 2.353 + if (err != 1) { 2.354 + printk(KERN_ERR "Unable to read memory/target\n"); 2.355 + return; 2.356 + } 2.357 2.358 - if(err != 1) 2.359 - { 2.360 - printk(KERN_ERR "Unable to read memory/target\n"); 2.361 - return; 2.362 - } 2.363 - 2.364 - set_new_target(new_target >> PAGE_SHIFT); 2.365 + set_new_target(new_target >> PAGE_SHIFT); 2.366 2.367 } 2.368 2.369 @@ -329,141 +315,185 @@ int balloon_init_watcher(struct notifier 2.370 unsigned long event, 2.371 void *data) 2.372 { 2.373 - int err; 2.374 + int err; 2.375 2.376 - BUG_ON(down_trylock(&xenbus_lock) == 0); 2.377 - 2.378 - err = register_xenbus_watch(&target_watch); 2.379 + BUG_ON(down_trylock(&xenbus_lock) == 0); 2.380 2.381 - if (err) { 2.382 - printk(KERN_ERR "Failed to set balloon watcher\n"); 2.383 - } 2.384 + err = register_xenbus_watch(&target_watch); 2.385 + if (err) 2.386 + printk(KERN_ERR "Failed to set balloon watcher\n"); 2.387 2.388 - return NOTIFY_DONE; 2.389 + return NOTIFY_DONE; 2.390 2.391 } 2.392 2.393 static int balloon_write(struct file *file, const char __user *buffer, 2.394 unsigned long count, void *data) 2.395 { 2.396 - char memstring[64], *endchar; 2.397 - unsigned long long target_bytes; 2.398 + char memstring[64], *endchar; 2.399 + unsigned long long target_bytes; 2.400 2.401 - if ( !capable(CAP_SYS_ADMIN) ) 2.402 - return -EPERM; 2.403 + if (!capable(CAP_SYS_ADMIN)) 2.404 + return -EPERM; 2.405 2.406 - if ( count <= 1 ) 2.407 - return -EBADMSG; /* runt */ 2.408 - if ( count > sizeof(memstring) ) 2.409 - return -EFBIG; /* too long */ 2.410 + if (count <= 1) 2.411 + return -EBADMSG; /* runt */ 2.412 + if (count > sizeof(memstring)) 2.413 + return -EFBIG; /* too long */ 2.414 2.415 - if ( copy_from_user(memstring, buffer, count) ) 2.416 - return -EFAULT; 2.417 - memstring[sizeof(memstring)-1] = '\0'; 2.418 + if (copy_from_user(memstring, buffer, count)) 2.419 + return -EFAULT; 2.420 + memstring[sizeof(memstring)-1] = '\0'; 2.421 2.422 - target_bytes = memparse(memstring, &endchar); 2.423 - set_new_target(target_bytes >> PAGE_SHIFT); 2.424 + target_bytes = memparse(memstring, &endchar); 2.425 + set_new_target(target_bytes >> PAGE_SHIFT); 2.426 2.427 - return count; 2.428 + return count; 2.429 } 2.430 2.431 static int balloon_read(char *page, char **start, off_t off, 2.432 int count, int *eof, void *data) 2.433 { 2.434 - int len; 2.435 + int len; 2.436 2.437 - len = sprintf( 2.438 - page, 2.439 - "Current allocation: %8lu kB\n" 2.440 - "Requested target: %8lu kB\n" 2.441 - "Low-mem balloon: %8lu kB\n" 2.442 - "High-mem balloon: %8lu kB\n" 2.443 - "Xen hard limit: ", 2.444 - PAGES2KB(current_pages), PAGES2KB(target_pages), 2.445 - PAGES2KB(balloon_low), PAGES2KB(balloon_high)); 2.446 + len = sprintf( 2.447 + page, 2.448 + "Current allocation: %8lu kB\n" 2.449 + "Requested target: %8lu kB\n" 2.450 + "Low-mem balloon: %8lu kB\n" 2.451 + "High-mem balloon: %8lu kB\n" 2.452 + "Xen hard limit: ", 2.453 + PAGES2KB(current_pages), PAGES2KB(target_pages), 2.454 + PAGES2KB(balloon_low), PAGES2KB(balloon_high)); 2.455 2.456 - if ( hard_limit != ~0UL ) 2.457 - len += sprintf( 2.458 - page + len, 2.459 - "%8lu kB (inc. %8lu kB driver headroom)\n", 2.460 - PAGES2KB(hard_limit), PAGES2KB(driver_pages)); 2.461 - else 2.462 - len += sprintf( 2.463 - page + len, 2.464 - " ??? kB\n"); 2.465 + if (hard_limit != ~0UL) { 2.466 + len += sprintf( 2.467 + page + len, 2.468 + "%8lu kB (inc. %8lu kB driver headroom)\n", 2.469 + PAGES2KB(hard_limit), PAGES2KB(driver_pages)); 2.470 + } else { 2.471 + len += sprintf( 2.472 + page + len, 2.473 + " ??? kB\n"); 2.474 + } 2.475 2.476 - *eof = 1; 2.477 - return len; 2.478 + *eof = 1; 2.479 + return len; 2.480 } 2.481 2.482 static struct notifier_block xenstore_notifier; 2.483 2.484 static int __init balloon_init(void) 2.485 { 2.486 - unsigned long pfn; 2.487 - struct page *page; 2.488 + unsigned long pfn; 2.489 + struct page *page; 2.490 2.491 - IPRINTK("Initialising balloon driver.\n"); 2.492 + IPRINTK("Initialising balloon driver.\n"); 2.493 2.494 - current_pages = min(xen_start_info.nr_pages, max_pfn); 2.495 - target_pages = current_pages; 2.496 - balloon_low = 0; 2.497 - balloon_high = 0; 2.498 - driver_pages = 0UL; 2.499 - hard_limit = ~0UL; 2.500 + current_pages = min(xen_start_info.nr_pages, max_pfn); 2.501 + target_pages = current_pages; 2.502 + balloon_low = 0; 2.503 + balloon_high = 0; 2.504 + driver_pages = 0UL; 2.505 + hard_limit = ~0UL; 2.506 2.507 - init_timer(&balloon_timer); 2.508 - balloon_timer.data = 0; 2.509 - balloon_timer.function = balloon_alarm; 2.510 + init_timer(&balloon_timer); 2.511 + balloon_timer.data = 0; 2.512 + balloon_timer.function = balloon_alarm; 2.513 2.514 - if ( (balloon_pde = create_xen_proc_entry("balloon", 0644)) == NULL ) 2.515 - { 2.516 - WPRINTK("Unable to create /proc/xen/balloon.\n"); 2.517 - return -1; 2.518 - } 2.519 + if ((balloon_pde = create_xen_proc_entry("balloon", 0644)) == NULL) { 2.520 + WPRINTK("Unable to create /proc/xen/balloon.\n"); 2.521 + return -1; 2.522 + } 2.523 2.524 - balloon_pde->read_proc = balloon_read; 2.525 - balloon_pde->write_proc = balloon_write; 2.526 + balloon_pde->read_proc = balloon_read; 2.527 + balloon_pde->write_proc = balloon_write; 2.528 2.529 - /* Initialise the balloon with excess memory space. */ 2.530 - for ( pfn = xen_start_info.nr_pages; pfn < max_pfn; pfn++ ) 2.531 - { 2.532 - page = &mem_map[pfn]; 2.533 - if ( !PageReserved(page) ) 2.534 - balloon_append(page); 2.535 - } 2.536 + /* Initialise the balloon with excess memory space. */ 2.537 + for (pfn = xen_start_info.nr_pages; pfn < max_pfn; pfn++) { 2.538 + page = &mem_map[pfn]; 2.539 + if (!PageReserved(page)) 2.540 + balloon_append(page); 2.541 + } 2.542 2.543 - target_watch.callback = watch_target; 2.544 - xenstore_notifier.notifier_call = balloon_init_watcher; 2.545 + target_watch.callback = watch_target; 2.546 + xenstore_notifier.notifier_call = balloon_init_watcher; 2.547 2.548 - register_xenstore_notifier(&xenstore_notifier); 2.549 + register_xenstore_notifier(&xenstore_notifier); 2.550 2.551 - return 0; 2.552 + return 0; 2.553 } 2.554 2.555 subsys_initcall(balloon_init); 2.556 2.557 void balloon_update_driver_allowance(long delta) 2.558 { 2.559 - unsigned long flags; 2.560 - balloon_lock(flags); 2.561 - driver_pages += delta; /* non-atomic update */ 2.562 - balloon_unlock(flags); 2.563 + unsigned long flags; 2.564 + balloon_lock(flags); 2.565 + driver_pages += delta; /* non-atomic update */ 2.566 + balloon_unlock(flags); 2.567 } 2.568 2.569 -void balloon_put_pages(unsigned long *mfn_list, unsigned long nr_mfns) 2.570 +struct page *balloon_alloc_empty_page_range(unsigned long nr_pages) 2.571 { 2.572 - unsigned long flags; 2.573 + int f(pte_t *pte, struct page *pte_page, 2.574 + unsigned long addr, void *data) 2.575 + { 2.576 + unsigned long mfn = pte_mfn(*pte); 2.577 + set_pte(pte, __pte_ma(0)); 2.578 + phys_to_machine_mapping[__pa(addr) >> PAGE_SHIFT] = 2.579 + INVALID_P2M_ENTRY; 2.580 + BUG_ON(HYPERVISOR_dom_mem_op( 2.581 + MEMOP_decrease_reservation, &mfn, 1, 0) != 1); 2.582 + return 0; 2.583 + } 2.584 + 2.585 + unsigned long vstart, flags; 2.586 + unsigned int order = get_order(nr_pages * PAGE_SIZE); 2.587 + 2.588 + vstart = __get_free_pages(GFP_KERNEL, order); 2.589 + if (vstart == 0) 2.590 + return NULL; 2.591 + 2.592 + scrub_pages(vstart, 1 << order); 2.593 2.594 - balloon_lock(flags); 2.595 - if ( HYPERVISOR_dom_mem_op(MEMOP_decrease_reservation, 2.596 - mfn_list, nr_mfns, 0) != nr_mfns ) 2.597 - BUG(); 2.598 - current_pages -= nr_mfns; /* non-atomic update */ 2.599 - balloon_unlock(flags); 2.600 + balloon_lock(flags); 2.601 + BUG_ON(generic_page_range( 2.602 + &init_mm, vstart, PAGE_SIZE << order, f, NULL) != 0); 2.603 + current_pages -= 1UL << order; 2.604 + balloon_unlock(flags); 2.605 + 2.606 + schedule_work(&balloon_worker); 2.607 + 2.608 + flush_tlb_all(); 2.609 + 2.610 + return virt_to_page(vstart); 2.611 +} 2.612 2.613 - schedule_work(&balloon_worker); 2.614 +void balloon_dealloc_empty_page_range( 2.615 + struct page *page, unsigned long nr_pages) 2.616 +{ 2.617 + unsigned long i, flags; 2.618 + unsigned int order = get_order(nr_pages * PAGE_SIZE); 2.619 + 2.620 + balloon_lock(flags); 2.621 + for (i = 0; i < (1UL << order); i++) 2.622 + balloon_append(page + i); 2.623 + balloon_unlock(flags); 2.624 + 2.625 + schedule_work(&balloon_worker); 2.626 } 2.627 2.628 EXPORT_SYMBOL(balloon_update_driver_allowance); 2.629 -EXPORT_SYMBOL(balloon_put_pages); 2.630 +EXPORT_SYMBOL(balloon_alloc_empty_page_range); 2.631 +EXPORT_SYMBOL(balloon_dealloc_empty_page_range); 2.632 + 2.633 +/* 2.634 + * Local variables: 2.635 + * c-file-style: "linux" 2.636 + * indent-tabs-mode: t 2.637 + * c-indent-level: 8 2.638 + * c-basic-offset: 8 2.639 + * tab-width: 8 2.640 + * End: 2.641 + */
3.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c Mon Aug 22 10:21:18 2005 +0000 3.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c Mon Aug 22 16:38:13 2005 +0000 3.3 @@ -569,6 +569,7 @@ void blkif_deschedule(blkif_t *blkif) 3.4 static int __init blkif_init(void) 3.5 { 3.6 int i; 3.7 + struct page *page; 3.8 3.9 if ( !(xen_start_info.flags & SIF_INITDOMAIN) && 3.10 !(xen_start_info.flags & SIF_BLK_BE_DOMAIN) ) 3.11 @@ -576,8 +577,9 @@ static int __init blkif_init(void) 3.12 3.13 blkif_interface_init(); 3.14 3.15 - if ( (mmap_vstart = allocate_empty_lowmem_region(MMAP_PAGES)) == 0 ) 3.16 - BUG(); 3.17 + page = balloon_alloc_empty_page_range(MMAP_PAGES); 3.18 + BUG_ON(page == NULL); 3.19 + mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page)); 3.20 3.21 pending_cons = 0; 3.22 pending_prod = MAX_PENDING_REQS;
4.1 --- a/linux-2.6-xen-sparse/drivers/xen/blktap/blktap_userdev.c Mon Aug 22 10:21:18 2005 +0000 4.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/blktap_userdev.c Mon Aug 22 16:38:13 2005 +0000 4.3 @@ -775,9 +775,11 @@ static struct miscdevice blktap_miscdev 4.4 int blktap_init(void) 4.5 { 4.6 int err, i, j; 4.7 + struct page *page; 4.8 4.9 - if ( (mmap_vstart = allocate_empty_lowmem_region(MMAP_PAGES)) == 0 ) 4.10 - BUG(); 4.11 + page = balloon_alloc_empty_page_range(MMAP_PAGES); 4.12 + BUG_ON(page == NULL); 4.13 + mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page)); 4.14 4.15 #ifdef CONFIG_XEN_BLKDEV_GRANT 4.16 for (i=0; i<MAX_PENDING_REQS ; i++)
5.1 --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Mon Aug 22 10:21:18 2005 +0000 5.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Mon Aug 22 16:38:13 2005 +0000 5.3 @@ -968,8 +968,9 @@ static int __init netback_init(void) 5.4 5.5 netif_interface_init(); 5.6 5.7 - mmap_vstart = allocate_empty_lowmem_region(MAX_PENDING_REQS); 5.8 - BUG_ON(mmap_vstart == 0); 5.9 + page = balloon_alloc_empty_page_range(MAX_PENDING_REQS); 5.10 + BUG_ON(page == NULL); 5.11 + mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page)); 5.12 5.13 for ( i = 0; i < MAX_PENDING_REQS; i++ ) 5.14 {
6.1 --- a/linux-2.6-xen-sparse/drivers/xen/usbback/usbback.c Mon Aug 22 10:21:18 2005 +0000 6.2 +++ b/linux-2.6-xen-sparse/drivers/xen/usbback/usbback.c Mon Aug 22 16:38:13 2005 +0000 6.3 @@ -1027,13 +1027,15 @@ void usbif_release_ports(usbif_priv_t *u 6.4 static int __init usbif_init(void) 6.5 { 6.6 int i; 6.7 + struct page *page; 6.8 6.9 if ( !(xen_start_info.flags & SIF_INITDOMAIN) && 6.10 !(xen_start_info.flags & SIF_USB_BE_DOMAIN) ) 6.11 return 0; 6.12 - 6.13 - if ( (mmap_vstart = allocate_empty_lowmem_region(MMAP_PAGES)) == 0 ) 6.14 - BUG(); 6.15 + 6.16 + page = balloon_alloc_empty_page_range(MMAP_PAGES); 6.17 + BUG_ON(page == NULL); 6.18 + mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page)); 6.19 6.20 pending_cons = 0; 6.21 pending_prod = MAX_PENDING_REQS;
7.1 --- a/linux-2.6-xen-sparse/include/asm-xen/balloon.h Mon Aug 22 10:21:18 2005 +0000 7.2 +++ b/linux-2.6-xen-sparse/include/asm-xen/balloon.h Mon Aug 22 16:38:13 2005 +0000 7.3 @@ -35,10 +35,19 @@ 7.4 * Inform the balloon driver that it should allow some slop for device-driver 7.5 * memory activities. 7.6 */ 7.7 -extern void balloon_update_driver_allowance(long delta); 7.8 +extern void 7.9 +balloon_update_driver_allowance( 7.10 + long delta); 7.11 7.12 -/* Give up unmapped pages to the balloon driver. */ 7.13 -extern void balloon_put_pages(unsigned long *mfn_list, unsigned long nr_mfns); 7.14 +/* Allocate an empty low-memory page range. */ 7.15 +extern struct page * 7.16 +balloon_alloc_empty_page_range( 7.17 + unsigned long nr_pages); 7.18 + 7.19 +/* Deallocate an empty page range, adding to the balloon. */ 7.20 +extern void 7.21 +balloon_dealloc_empty_page_range( 7.22 + struct page *page, unsigned long nr_pages); 7.23 7.24 /* 7.25 * Prevent the balloon driver from changing the memory reservation during
8.1 --- a/linux-2.6-xen-sparse/include/asm-xen/hypervisor.h Mon Aug 22 10:21:18 2005 +0000 8.2 +++ b/linux-2.6-xen-sparse/include/asm-xen/hypervisor.h Mon Aug 22 16:38:13 2005 +0000 8.3 @@ -137,9 +137,6 @@ void xen_invlpg_mask(cpumask_t *mask, un 8.4 void xen_create_contiguous_region(unsigned long vstart, unsigned int order); 8.5 void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order); 8.6 8.7 -/* Allocate a contiguous empty region of low memory. Return virtual start. */ 8.8 -unsigned long allocate_empty_lowmem_region(unsigned long pages); 8.9 - 8.10 #include <asm/hypercall.h> 8.11 8.12 #if defined(CONFIG_X86_64)