balloon.c (803eb047a28d239809fff1f87274cdaa94e0d8ea) | balloon.c (b6f3067985f12d514187059fb10fe3c877f87cb2) |
---|---|
1/****************************************************************************** 2 * Xen balloon driver - enables returning/claiming memory to/from Xen. 3 * 4 * Copyright (c) 2003, B Dragovic 5 * Copyright (c) 2003-2004, M Williamson, K Fraser 6 * Copyright (c) 2005 Dan M. Smith, IBM Corporation 7 * 8 * This program is free software; you can redistribute it and/or --- 114 unchanged lines hidden (view full) --- 123 124static void balloon_append(struct page *page) 125{ 126 __balloon_append(page); 127 totalram_pages--; 128} 129 130/* balloon_retrieve: rescue a page from the balloon, if it is not empty. */ | 1/****************************************************************************** 2 * Xen balloon driver - enables returning/claiming memory to/from Xen. 3 * 4 * Copyright (c) 2003, B Dragovic 5 * Copyright (c) 2003-2004, M Williamson, K Fraser 6 * Copyright (c) 2005 Dan M. Smith, IBM Corporation 7 * 8 * This program is free software; you can redistribute it and/or --- 114 unchanged lines hidden (view full) --- 123 124static void balloon_append(struct page *page) 125{ 126 __balloon_append(page); 127 totalram_pages--; 128} 129 130/* balloon_retrieve: rescue a page from the balloon, if it is not empty. */ |
131static struct page *balloon_retrieve(void) | 131static struct page *balloon_retrieve(bool prefer_highmem) |
132{ 133 struct page *page; 134 135 if (list_empty(&ballooned_pages)) 136 return NULL; 137 | 132{ 133 struct page *page; 134 135 if (list_empty(&ballooned_pages)) 136 return NULL; 137 |
138 page = list_entry(ballooned_pages.next, struct page, lru); | 138 if (prefer_highmem) 139 page = list_entry(ballooned_pages.prev, struct page, lru); 140 else 141 page = list_entry(ballooned_pages.next, struct page, lru); |
139 list_del(&page->lru); 140 141 if (PageHighMem(page)) { 142 balloon_stats.balloon_high--; 143 inc_totalhigh_pages(); 144 } 145 else 146 balloon_stats.balloon_low--; --- 81 unchanged lines hidden (view full) --- 228 229 set_xen_guest_handle(reservation.extent_start, frame_list); 230 reservation.nr_extents = nr_pages; 231 rc = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation); 232 if (rc <= 0) 233 return BP_EAGAIN; 234 235 for (i = 0; i < rc; i++) { | 142 list_del(&page->lru); 143 144 if (PageHighMem(page)) { 145 balloon_stats.balloon_high--; 146 inc_totalhigh_pages(); 147 } 148 else 149 balloon_stats.balloon_low--; --- 81 unchanged lines hidden (view full) --- 231 232 set_xen_guest_handle(reservation.extent_start, frame_list); 233 reservation.nr_extents = nr_pages; 234 rc = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation); 235 if (rc <= 0) 236 return BP_EAGAIN; 237 238 for (i = 0; i < rc; i++) { |
236 page = balloon_retrieve(); | 239 page = balloon_retrieve(false); |
237 BUG_ON(page == NULL); 238 239 pfn = page_to_pfn(page); 240 BUG_ON(!xen_feature(XENFEAT_auto_translated_physmap) && 241 phys_to_machine_mapping_valid(pfn)); 242 243 set_phys_to_machine(pfn, frame_list[i]); 244 --- 13 unchanged lines hidden (view full) --- 258 __free_page(page); 259 } 260 261 balloon_stats.current_pages += rc; 262 263 return BP_DONE; 264} 265 | 240 BUG_ON(page == NULL); 241 242 pfn = page_to_pfn(page); 243 BUG_ON(!xen_feature(XENFEAT_auto_translated_physmap) && 244 phys_to_machine_mapping_valid(pfn)); 245 246 set_phys_to_machine(pfn, frame_list[i]); 247 --- 13 unchanged lines hidden (view full) --- 261 __free_page(page); 262 } 263 264 balloon_stats.current_pages += rc; 265 266 return BP_DONE; 267} 268 |
266static enum bp_state decrease_reservation(unsigned long nr_pages) | 269static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) |
267{ 268 enum bp_state state = BP_DONE; 269 unsigned long pfn, i; 270 struct page *page; 271 int ret; 272 struct xen_memory_reservation reservation = { 273 .address_bits = 0, 274 .extent_order = 0, 275 .domid = DOMID_SELF 276 }; 277 278 if (nr_pages > ARRAY_SIZE(frame_list)) 279 nr_pages = ARRAY_SIZE(frame_list); 280 281 for (i = 0; i < nr_pages; i++) { | 270{ 271 enum bp_state state = BP_DONE; 272 unsigned long pfn, i; 273 struct page *page; 274 int ret; 275 struct xen_memory_reservation reservation = { 276 .address_bits = 0, 277 .extent_order = 0, 278 .domid = DOMID_SELF 279 }; 280 281 if (nr_pages > ARRAY_SIZE(frame_list)) 282 nr_pages = ARRAY_SIZE(frame_list); 283 284 for (i = 0; i < nr_pages; i++) { |
282 if ((page = alloc_page(GFP_BALLOON)) == NULL) { | 285 if ((page = alloc_page(gfp)) == NULL) { |
283 nr_pages = i; 284 state = BP_EAGAIN; 285 break; 286 } 287 288 pfn = page_to_pfn(page); 289 frame_list[i] = pfn_to_mfn(pfn); 290 --- 44 unchanged lines hidden (view full) --- 335 336 do { 337 credit = current_target() - balloon_stats.current_pages; 338 339 if (credit > 0) 340 state = increase_reservation(credit); 341 342 if (credit < 0) | 286 nr_pages = i; 287 state = BP_EAGAIN; 288 break; 289 } 290 291 pfn = page_to_pfn(page); 292 frame_list[i] = pfn_to_mfn(pfn); 293 --- 44 unchanged lines hidden (view full) --- 338 339 do { 340 credit = current_target() - balloon_stats.current_pages; 341 342 if (credit > 0) 343 state = increase_reservation(credit); 344 345 if (credit < 0) |
343 state = decrease_reservation(-credit); | 346 state = decrease_reservation(-credit, GFP_BALLOON); |
344 345 state = update_schedule(state); 346 347#ifndef CONFIG_PREEMPT 348 if (need_resched()) 349 schedule(); 350#endif 351 } while (credit && state == BP_DONE); --- 9 unchanged lines hidden (view full) --- 361void balloon_set_new_target(unsigned long target) 362{ 363 /* No need for lock. Not read-modify-write updates. */ 364 balloon_stats.target_pages = target; 365 schedule_delayed_work(&balloon_worker, 0); 366} 367EXPORT_SYMBOL_GPL(balloon_set_new_target); 368 | 347 348 state = update_schedule(state); 349 350#ifndef CONFIG_PREEMPT 351 if (need_resched()) 352 schedule(); 353#endif 354 } while (credit && state == BP_DONE); --- 9 unchanged lines hidden (view full) --- 364void balloon_set_new_target(unsigned long target) 365{ 366 /* No need for lock. Not read-modify-write updates. */ 367 balloon_stats.target_pages = target; 368 schedule_delayed_work(&balloon_worker, 0); 369} 370EXPORT_SYMBOL_GPL(balloon_set_new_target); 371 |
372/** 373 * alloc_xenballooned_pages - get pages that have been ballooned out 374 * @nr_pages: Number of pages to get 375 * @pages: pages returned 376 * @return 0 on success, error otherwise 377 */ 378int alloc_xenballooned_pages(int nr_pages, struct page** pages) 379{ 380 int pgno = 0; 381 struct page* page; 382 mutex_lock(&balloon_mutex); 383 while (pgno < nr_pages) { 384 page = balloon_retrieve(true); 385 if (page) { 386 pages[pgno++] = page; 387 } else { 388 enum bp_state st; 389 st = decrease_reservation(nr_pages - pgno, GFP_HIGHUSER); 390 if (st != BP_DONE) 391 goto out_undo; 392 } 393 } 394 mutex_unlock(&balloon_mutex); 395 return 0; 396 out_undo: 397 while (pgno) 398 balloon_append(pages[--pgno]); 399 /* Free the memory back to the kernel soon */ 400 schedule_delayed_work(&balloon_worker, 0); 401 mutex_unlock(&balloon_mutex); 402 return -ENOMEM; 403} 404EXPORT_SYMBOL(alloc_xenballooned_pages); 405 406/** 407 * free_xenballooned_pages - return pages retrieved with get_ballooned_pages 408 * @nr_pages: Number of pages 409 * @pages: pages to return 410 */ 411void free_xenballooned_pages(int nr_pages, struct page** pages) 412{ 413 int i; 414 415 mutex_lock(&balloon_mutex); 416 417 for (i = 0; i < nr_pages; i++) { 418 if (pages[i]) 419 balloon_append(pages[i]); 420 } 421 422 /* The balloon may be too large now. Shrink it if needed. */ 423 if (current_target() != balloon_stats.current_pages) 424 schedule_delayed_work(&balloon_worker, 0); 425 426 mutex_unlock(&balloon_mutex); 427} 428EXPORT_SYMBOL(free_xenballooned_pages); 429 |
|
369static int __init balloon_init(void) 370{ 371 unsigned long pfn, extra_pfn_end; 372 struct page *page; 373 374 if (!xen_pv_domain()) 375 return -ENODEV; 376 --- 38 unchanged lines hidden --- | 430static int __init balloon_init(void) 431{ 432 unsigned long pfn, extra_pfn_end; 433 struct page *page; 434 435 if (!xen_pv_domain()) 436 return -ENODEV; 437 --- 38 unchanged lines hidden --- |