├── .DS_Store ├── FastSwap-Kernel-Patch └── FastSwap-Patch.patch ├── FastSwap-QEMU-Patch └── patch1.diff ├── GuestOS-Kernel-Module ├── Makefile ├── Module.symvers ├── bitmap.o ├── errorlog ├── file_io.o ├── mapper.o ├── mem_swap.o ├── memflex.ko ├── memflex.mod.o ├── memflex.o ├── run.sh └── uio_ivshmem.o ├── Ivshmem-Server ├── Makefile ├── README ├── ivshmem.sh ├── ivshmem_server ├── ivshmem_server.c ├── ivshmem_server.o ├── send_scm.c ├── send_scm.h └── send_scm.o ├── fastswap.xml └── readme.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/git-disl/FastSwap/3b7a1469c333185894fd4ffedb52b0af0bfdba82/.DS_Store -------------------------------------------------------------------------------- /FastSwap-Kernel-Patch/FastSwap-Patch.patch: -------------------------------------------------------------------------------- 1 | diff -ur linux-3.14.4/include/asm-generic/delay.h linux-3.14.4-fastswap/include/asm-generic/delay.h 2 | --- linux-3.14.4/include/asm-generic/delay.h 2014-05-13 07:33:14.000000000 -0400 3 | +++ linux-3.14.4-fastswap/include/asm-generic/delay.h 2016-10-13 15:19:46.000000000 -0400 4 | @@ -10,6 +10,7 @@ 5 | extern void __const_udelay(unsigned long xloops); 6 | extern void __delay(unsigned long loops); 7 | 8 | + 9 | /* 10 | * The weird n/20000 thing suppresses a "comparison is always false due to 11 | * limited range of data type" warning with non-const 8-bit arguments. 12 | diff -ur linux-3.14.4/include/linux/mm_types.h linux-3.14.4-fastswap/include/linux/mm_types.h 13 | --- linux-3.14.4/include/linux/mm_types.h 2014-05-13 07:33:14.000000000 -0400 14 | +++ linux-3.14.4-fastswap/include/linux/mm_types.h 2016-09-24 22:38:47.000000000 -0400 15 | @@ -195,6 +195,11 @@ 16 | #ifdef LAST_CPUPID_NOT_IN_PAGE_FLAGS 17 | int _last_cpupid; 18 | #endif 19 | + 20 | + int idx; 21 | + unsigned long rmap_addrs[10]; 22 | + struct vm_area_struct* rmap_vmas[10]; 23 | + 24 | } 25 | /* 26 | * The struct page can be forced to be double word aligned so that atomic ops 27 | diff -ur linux-3.14.4/include/linux/swap.h linux-3.14.4-fastswap/include/linux/swap.h 28 | --- linux-3.14.4/include/linux/swap.h 2014-05-13 07:33:14.000000000 -0400 29 | +++ linux-3.14.4-fastswap/include/linux/swap.h 2016-09-24 22:38:47.000000000 -0400 30 | @@ -253,6 +253,26 @@ 31 | struct work_struct discard_work; /* discard worker */ 32 | struct swap_cluster_info discard_cluster_head; /* list head of discard clusters */ 33 | struct swap_cluster_info discard_cluster_tail; /* list tail of discard clusters */ 34 | + 35 | + char *shm; /*swap to (shared) memory*/ 36 | + 37 | + unsigned long *mapper; /*mapping from contiguous address to non-continguous in the shared memory*/ 38 | + unsigned long shm_start; 39 | + unsigned long shm_end; 40 | + unsigned long disk_start; 41 | + unsigned long disk_end; 42 | + unsigned long mask; 43 | + int is_shm; 44 | + int dump_thread_running; 45 | + int dump_thread_should_run; 46 | + spinlock_t dump_lock; 47 | + 48 | +}; 49 | + 50 | +struct swapin_mdata{ 51 | + struct vm_area_struct *vma; 52 | + pmd_t *pmd; 53 | + unsigned long address; 54 | }; 55 | 56 | struct swap_list_t { 57 | diff -ur linux-3.14.4/include/linux/swapfile.h linux-3.14.4-fastswap/include/linux/swapfile.h 58 | --- linux-3.14.4/include/linux/swapfile.h 2014-05-13 07:33:14.000000000 -0400 59 | +++ linux-3.14.4-fastswap/include/linux/swapfile.h 2016-09-24 22:38:47.000000000 -0400 60 | @@ -10,4 +10,6 @@ 61 | extern struct swap_info_struct *swap_info[]; 62 | extern int try_to_unuse(unsigned int, bool, unsigned long); 63 | 64 | +void set_memswap_init_size(unsigned long init_size); 65 | + 66 | #endif /* _LINUX_SWAPFILE_H */ 67 | diff -ur linux-3.14.4/mm/ksm.c linux-3.14.4-fastswap/mm/ksm.c 68 | --- linux-3.14.4/mm/ksm.c 2014-05-13 07:33:14.000000000 -0400 69 | +++ linux-3.14.4-fastswap/mm/ksm.c 2016-10-13 15:10:42.000000000 -0400 70 | @@ -41,6 +41,10 @@ 71 | #include 72 | #include "internal.h" 73 | 74 | +EXPORT_SYMBOL(ksm_might_need_to_copy); 75 | + 76 | + 77 | + 78 | #ifdef CONFIG_NUMA 79 | #define NUMA(x) (x) 80 | #define DO_NUMA(x) do { (x); } while (0) 81 | diff -ur linux-3.14.4/mm/page-writeback.c linux-3.14.4-fastswap/mm/page-writeback.c 82 | --- linux-3.14.4/mm/page-writeback.c 2014-05-13 07:33:14.000000000 -0400 83 | +++ linux-3.14.4-fastswap/mm/page-writeback.c 2016-09-24 22:38:47.000000000 -0400 84 | @@ -2376,6 +2376,11 @@ 85 | 86 | spin_lock_irqsave(&mapping->tree_lock, flags); 87 | ret = TestClearPageWriteback(page); 88 | + 89 | + if(!ret){ 90 | + printk("~~~~~~~~~~~~~~ ret1 = %d\n", ret); 91 | + } 92 | + 93 | if (ret) { 94 | radix_tree_tag_clear(&mapping->page_tree, 95 | page_index(page), 96 | @@ -2388,6 +2393,10 @@ 97 | spin_unlock_irqrestore(&mapping->tree_lock, flags); 98 | } else { 99 | ret = TestClearPageWriteback(page); 100 | + 101 | + if(!ret){ 102 | + printk("~~~~~~~~~~~~~~ ret1 = %d\n", ret); 103 | + } 104 | } 105 | if (ret) { 106 | mem_cgroup_dec_page_stat(page, MEM_CGROUP_STAT_WRITEBACK); 107 | diff -ur linux-3.14.4/mm/page_io.c linux-3.14.4-fastswap/mm/page_io.c 108 | --- linux-3.14.4/mm/page_io.c 2014-05-13 07:33:14.000000000 -0400 109 | +++ linux-3.14.4-fastswap/mm/page_io.c 2016-11-05 15:01:22.000000000 -0400 110 | @@ -24,6 +24,42 @@ 111 | #include 112 | #include 113 | 114 | +EXPORT_SYMBOL(swap_writepage); 115 | + 116 | +typedef int (* swap_writepage_hook)(struct page *page, struct writeback_control *wbc, void (*end_write_func)(struct bio *, int)); 117 | + 118 | +typedef int (* swap_readpage_hook)(struct page *page); 119 | + 120 | +typedef struct swapin_mdata* (* get_swapin_mdata_hook)(unsigned long offset); 121 | + 122 | +bool mempipe_installed = false; 123 | +int (* __my_swap_writepage)(struct page *page, struct writeback_control *wbc, void (*end_write_func)(struct bio *, int)) = NULL; 124 | +int (* __my_swap_readpage)(struct page *page) = NULL; 125 | +struct swapin_mdata* (* __my_get_swapin_mdata)(unsigned long offset) = NULL; 126 | + 127 | +void swap_bind_hook(swap_writepage_hook h1, swap_readpage_hook h2, get_swapin_mdata_hook h3) 128 | +{ 129 | + mempipe_installed = true; 130 | + __my_swap_writepage = h1; 131 | + __my_swap_readpage = h2; 132 | + __my_get_swapin_mdata = h3; 133 | + printk("swap_bind_hook...\n"); 134 | +} 135 | + 136 | +void swap_unbind_hook(void) 137 | +{ 138 | + mempipe_installed = false; 139 | + __my_swap_writepage = NULL; 140 | + __my_swap_readpage = NULL; 141 | + __my_get_swapin_mdata = NULL; 142 | + printk("swap_unbind_hook...\n"); 143 | +} 144 | + 145 | +EXPORT_SYMBOL(swap_bind_hook); 146 | +EXPORT_SYMBOL(swap_unbind_hook); 147 | + 148 | + 149 | + 150 | static struct bio *get_swap_bio(gfp_t gfp_flags, 151 | struct page *page, bio_end_io_t end_io) 152 | { 153 | @@ -42,6 +78,7 @@ 154 | } 155 | return bio; 156 | } 157 | +EXPORT_SYMBOL(get_swap_bio); 158 | 159 | void end_swap_bio_write(struct bio *bio, int err) 160 | { 161 | @@ -68,6 +105,7 @@ 162 | end_page_writeback(page); 163 | bio_put(bio); 164 | } 165 | +EXPORT_SYMBOL(end_swap_bio_write); 166 | 167 | void end_swap_bio_read(struct bio *bio, int err) 168 | { 169 | @@ -132,6 +170,7 @@ 170 | unlock_page(page); 171 | bio_put(bio); 172 | } 173 | +EXPORT_SYMBOL(end_swap_bio_read); 174 | 175 | int generic_swapfile_activate(struct swap_info_struct *sis, 176 | struct file *swap_file, 177 | @@ -232,6 +271,10 @@ 178 | int swap_writepage(struct page *page, struct writeback_control *wbc) 179 | { 180 | int ret = 0; 181 | + pgoff_t offset; 182 | + swp_entry_t entry; 183 | + 184 | + struct swap_info_struct *sis = page_swap_info(page); 185 | 186 | if (try_to_free_swap(page)) { 187 | unlock_page(page); 188 | @@ -243,7 +286,15 @@ 189 | end_page_writeback(page); 190 | goto out; 191 | } 192 | - ret = __swap_writepage(page, wbc, end_swap_bio_write); 193 | + 194 | + entry.val = page_private(page); 195 | + offset = swp_offset(entry); 196 | + 197 | + if(mempipe_installed == true && sis->is_shm == 1 && (offset > 0)){ 198 | + ret = __my_swap_writepage(page, wbc, end_swap_bio_write); 199 | + }else{ 200 | + ret = __swap_writepage(page, wbc, end_swap_bio_write); 201 | + } 202 | out: 203 | return ret; 204 | } 205 | diff -ur linux-3.14.4/mm/pgtable-generic.c linux-3.14.4-fastswap/mm/pgtable-generic.c 206 | --- linux-3.14.4/mm/pgtable-generic.c 2014-05-13 07:33:14.000000000 -0400 207 | +++ linux-3.14.4-fastswap/mm/pgtable-generic.c 2016-10-13 15:11:40.000000000 -0400 208 | @@ -16,6 +16,11 @@ 209 | * very seldom) called out from the p?d_none_or_clear_bad macros. 210 | */ 211 | 212 | +EXPORT_SYMBOL(pmd_clear_bad); 213 | +EXPORT_SYMBOL(pgd_clear_bad); 214 | +EXPORT_SYMBOL(pud_clear_bad); 215 | + 216 | + 217 | void pgd_clear_bad(pgd_t *pgd) 218 | { 219 | pgd_ERROR(*pgd); 220 | diff -ur linux-3.14.4/mm/rmap.c linux-3.14.4-fastswap/mm/rmap.c 221 | --- linux-3.14.4/mm/rmap.c 2014-05-13 07:33:14.000000000 -0400 222 | +++ linux-3.14.4-fastswap/mm/rmap.c 2016-10-13 21:22:25.000000000 -0400 223 | @@ -60,8 +60,15 @@ 224 | 225 | #include 226 | 227 | +#include 228 | + 229 | #include "internal.h" 230 | 231 | +EXPORT_SYMBOL(page_address_in_vma); 232 | +EXPORT_SYMBOL(page_add_new_anon_rmap); 233 | +EXPORT_SYMBOL(page_add_anon_rmap); 234 | + 235 | + 236 | static struct kmem_cache *anon_vma_cachep; 237 | static struct kmem_cache *anon_vma_chain_cachep; 238 | 239 | @@ -617,6 +624,13 @@ 240 | return NULL; 241 | 242 | pte = pte_offset_map(pmd, address); 243 | + 244 | + /*Sometimes, we need the value of pte even if it is not present*/ 245 | + if(sync == 8888){ 246 | + pte_unmap(pte); 247 | + return pte; 248 | + } 249 | + 250 | /* Make a quick check before getting the lock */ 251 | if (!sync && !pte_present(*pte)) { 252 | pte_unmap(pte); 253 | @@ -1607,6 +1621,8 @@ 254 | if (!anon_vma) 255 | return ret; 256 | 257 | + page->idx = 0; 258 | + 259 | anon_vma_interval_tree_foreach(avc, &anon_vma->rb_root, pgoff, pgoff) { 260 | struct vm_area_struct *vma = avc->vma; 261 | unsigned long address = vma_address(page, vma); 262 | @@ -1615,6 +1631,14 @@ 263 | continue; 264 | 265 | ret = rwc->rmap_one(page, vma, address, rwc->arg); 266 | + 267 | + if(page->idx < 10) { 268 | + page->rmap_addrs[page->idx] = address; 269 | + page->rmap_vmas[page->idx] = vma; 270 | + page->idx++; 271 | + } 272 | + 273 | + 274 | if (ret != SWAP_AGAIN) 275 | break; 276 | if (rwc->done && rwc->done(page)) 277 | diff -ur linux-3.14.4/mm/shmem.c linux-3.14.4-fastswap/mm/shmem.c 278 | --- linux-3.14.4/mm/shmem.c 2014-05-13 07:33:14.000000000 -0400 279 | +++ linux-3.14.4-fastswap/mm/shmem.c 2016-11-05 15:13:15.000000000 -0400 280 | @@ -42,6 +42,8 @@ 281 | * which makes it a completely usable filesystem. 282 | */ 283 | 284 | + 285 | + 286 | #include 287 | #include 288 | #include 289 | @@ -79,6 +81,10 @@ 290 | /* Symlink up to this size is kmalloc'ed instead of using a swappable page */ 291 | #define SHORT_SYMLINK_LEN 128 292 | 293 | + 294 | +EXPORT_SYMBOL(shmem_unuse); 295 | + 296 | + 297 | /* 298 | * shmem_fallocate and shmem_writepage communicate via inode->i_private 299 | * (with i_mutex making sure that it has only one user at a time): 300 | diff -ur linux-3.14.4/mm/swap.c linux-3.14.4-fastswap/mm/swap.c 301 | --- linux-3.14.4/mm/swap.c 2014-05-13 07:33:14.000000000 -0400 302 | +++ linux-3.14.4-fastswap/mm/swap.c 2016-10-13 14:29:55.000000000 -0400 303 | @@ -48,6 +48,10 @@ 304 | * This path almost never happens for VM activity - pages are normally 305 | * freed via pagevecs. But it gets used by networking. 306 | */ 307 | + 308 | +EXPORT_SYMBOL(activate_page); 309 | + 310 | + 311 | static void __page_cache_release(struct page *page) 312 | { 313 | if (PageLRU(page)) { 314 | diff -ur linux-3.14.4/mm/swap_state.c linux-3.14.4-fastswap/mm/swap_state.c 315 | --- linux-3.14.4/mm/swap_state.c 2014-05-13 07:33:14.000000000 -0400 316 | +++ linux-3.14.4-fastswap/mm/swap_state.c 2016-11-05 15:05:52.000000000 -0400 317 | @@ -21,6 +21,11 @@ 318 | 319 | #include 320 | 321 | +EXPORT_SYMBOL(delete_from_swap_cache); 322 | +EXPORT_SYMBOL(read_swap_cache_async); 323 | +extern bool mempipe_installed; 324 | +extern int (* __my_swap_readpage)(struct page *page); 325 | + 326 | /* 327 | * swapper_space is a fiction, retained to simplify the path through 328 | * vmscan's shrink_page_list. 329 | @@ -310,6 +315,8 @@ 330 | struct page *found_page, *new_page = NULL; 331 | int err; 332 | 333 | + struct swap_info_struct *sis; 334 | + 335 | do { 336 | /* 337 | * First check the swap cache. Since this is normally 338 | @@ -376,7 +383,23 @@ 339 | * Initiate read into locked page and return. 340 | */ 341 | lru_cache_add_anon(new_page); 342 | - swap_readpage(new_page); 343 | + //swap_readpage(new_page); 344 | + 345 | + pgoff_t offset; 346 | + swp_entry_t entry; 347 | + 348 | + entry.val = page_private(new_page); 349 | + offset = swp_offset(entry); 350 | + 351 | + 352 | + sis = page_swap_info(new_page); 353 | + 354 | + if(mempipe_installed == true && (offset > 0) && sis->is_shm == 1) { 355 | + __my_swap_readpage(new_page); 356 | + }else{ 357 | + swap_readpage(new_page); 358 | + } 359 | + 360 | return new_page; 361 | } 362 | radix_tree_preload_end(); 363 | diff -ur linux-3.14.4/mm/swapfile.c linux-3.14.4-fastswap/mm/swapfile.c 364 | --- linux-3.14.4/mm/swapfile.c 2014-05-13 07:33:14.000000000 -0400 365 | +++ linux-3.14.4-fastswap/mm/swapfile.c 2016-11-06 19:43:59.000000000 -0500 366 | @@ -46,6 +46,36 @@ 367 | static sector_t map_swap_entry(swp_entry_t, struct block_device**); 368 | 369 | DEFINE_SPINLOCK(swap_lock); 370 | + 371 | +EXPORT_SYMBOL(swap_lock); 372 | +EXPORT_SYMBOL(swap_free); 373 | +EXPORT_SYMBOL(init_mm); 374 | +EXPORT_SYMBOL(mmlist_lock); 375 | +EXPORT_SYMBOL(try_to_unuse); 376 | + 377 | +/*Initial size of memswap*/ 378 | +static unsigned long memswap_init_size; 379 | +static int next_swap = 0; 380 | + 381 | +void set_memswap_init_size(unsigned long init_size){ 382 | + memswap_init_size = init_size; 383 | +} 384 | +EXPORT_SYMBOL(set_memswap_init_size); 385 | + 386 | +void switch_to_next_swap(void){ 387 | + next_swap = 1; 388 | +} 389 | +EXPORT_SYMBOL(switch_to_next_swap); 390 | + 391 | +void back_to_default_swap(void){ 392 | + next_swap = 0; 393 | +} 394 | +EXPORT_SYMBOL(back_to_default_swap); 395 | +//#define PAGE_NUMS (1<<18) //256K pages -> 1GB 396 | + 397 | +extern struct swapin_mdata * (* __my_get_swapin_mdata)(unsigned long offset); 398 | +extern bool mempipe_installed; 399 | + 400 | static unsigned int nr_swapfiles; 401 | atomic_long_t nr_swap_pages; 402 | /* protected with swap_lock. reading in vm_swap_full() doesn't need lock */ 403 | @@ -467,13 +497,16 @@ 404 | } 405 | 406 | static unsigned long scan_swap_map(struct swap_info_struct *si, 407 | - unsigned char usage) 408 | + unsigned char usage, 409 | + int type) 410 | { 411 | unsigned long offset; 412 | unsigned long scan_base; 413 | unsigned long last_in_cluster = 0; 414 | int latency_ration = LATENCY_LIMIT; 415 | 416 | + if((type == 0)&&(next_swap == 1)) 417 | + goto no_page; 418 | /* 419 | * We try to cluster swap pages by allocating them sequentially 420 | * in swap. Once we've allocated SWAPFILE_CLUSTER pages this 421 | @@ -694,10 +727,12 @@ 422 | 423 | spin_unlock(&swap_lock); 424 | /* This is called for allocating swap entry for cache */ 425 | - offset = scan_swap_map(si, SWAP_HAS_CACHE); 426 | + 427 | + offset = scan_swap_map(si, SWAP_HAS_CACHE, type); 428 | spin_unlock(&si->lock); 429 | - if (offset) 430 | + if (offset){ 431 | return swp_entry(type, offset); 432 | + } 433 | spin_lock(&swap_lock); 434 | next = swap_list.next; 435 | } 436 | @@ -719,7 +754,7 @@ 437 | if (si && (si->flags & SWP_WRITEOK)) { 438 | atomic_long_dec(&nr_swap_pages); 439 | /* This is called for allocating swap entry, not cache */ 440 | - offset = scan_swap_map(si, 1); 441 | + offset = scan_swap_map(si, 1, type); 442 | if (offset) { 443 | spin_unlock(&si->lock); 444 | return swp_entry(type, offset); 445 | @@ -1364,6 +1399,13 @@ 446 | unsigned int i = 0; 447 | int retval = 0; 448 | 449 | + struct swapin_mdata* sm = NULL; 450 | + unsigned long index1 = 0, index2 = 0, index3 = 0; 451 | + long long total0 = 0, total1 = 0, total2 = 0, total3 = 0; 452 | + ktime_t start0, start1, start2, start3, end0, end1, end2, end3; 453 | + 454 | + start0 = ktime_get(); 455 | + 456 | /* 457 | * When searching mms for an entry, a good strategy is to 458 | * start at the first mm we freed the previous entry from 459 | @@ -1386,12 +1428,14 @@ 460 | * one pass through swap_map is enough, but not necessarily: 461 | * there are races when an instance of an entry might be missed. 462 | */ 463 | + 464 | while ((i = find_next_to_unuse(si, i, frontswap)) != 0) { 465 | if (signal_pending(current)) { 466 | retval = -EINTR; 467 | break; 468 | } 469 | 470 | + //__asm__ volatile (".byte 0x0f, 0x31" : "=A" (start1)); 471 | /* 472 | * Get a page for the entry, using the existing swap 473 | * cache page if there is one. Otherwise, get a clean 474 | @@ -1399,8 +1443,12 @@ 475 | */ 476 | swap_map = &si->swap_map[i]; 477 | entry = swp_entry(type, i); 478 | + 479 | + //__asm__ volatile (".byte 0x0f, 0x31" : "=A" (start2)); 480 | + start2 = ktime_get(); 481 | page = read_swap_cache_async(entry, 482 | GFP_HIGHUSER_MOVABLE, NULL, 0); 483 | + 484 | if (!page) { 485 | /* 486 | * Either swap_duplicate() failed because entry 487 | @@ -1419,12 +1467,18 @@ 488 | if (!swcount || swcount == SWAP_MAP_BAD) 489 | continue; 490 | retval = -ENOMEM; 491 | + 492 | break; 493 | } 494 | 495 | + //__asm__ volatile (".byte 0x0f, 0x31" : "=A" (end2)); 496 | + end2 = ktime_get(); 497 | + total2 += ktime_to_ns(ktime_sub(end2, start2)); 498 | + index2++; 499 | /* 500 | * Don't hold on to start_mm if it looks like exiting. 501 | */ 502 | + start1 = ktime_get(); 503 | if (atomic_read(&start_mm->mm_users) == 1) { 504 | mmput(start_mm); 505 | start_mm = &init_mm; 506 | @@ -1441,6 +1495,7 @@ 507 | */ 508 | wait_on_page_locked(page); 509 | wait_on_page_writeback(page); 510 | + 511 | lock_page(page); 512 | wait_on_page_writeback(page); 513 | 514 | @@ -1455,9 +1510,40 @@ 515 | break; 516 | continue; 517 | } 518 | + end1 = ktime_get(); 519 | + total1 += ktime_to_ns(ktime_sub(end1, start1));/*index does not increase here, another start1/end1 at the end of this func*/ 520 | + 521 | + //__asm__ volatile (".byte 0x0f, 0x31" : "=A" (start3)); 522 | + start3 = ktime_get(); 523 | + /* 524 | if (swap_count(swcount) && start_mm != &init_mm) 525 | retval = unuse_mm(start_mm, entry, page); 526 | + */ 527 | + 528 | + if(mempipe_installed == false || si->is_shm == 0) { 529 | + if (swap_count(swcount) && start_mm != &init_mm) 530 | + retval = unuse_mm(start_mm, entry, page); 531 | + }else{ 532 | + if (swap_count(swcount) && start_mm != &init_mm) { 533 | + sm = __my_get_swapin_mdata(i); 534 | + if(sm == NULL) { 535 | + retval = unuse_mm(start_mm, entry, page); 536 | + }else{ 537 | + retval = unuse_pte(sm->vma, sm->pmd, sm->address, entry, page); 538 | + retval = (retval < 0)?retval:0; 539 | + } 540 | + 541 | + } 542 | + } 543 | + 544 | + //__asm__ volatile (".byte 0x0f, 0x31" : "=A" (end3)); 545 | + //total3 += end3 - start3; 546 | + end3 = ktime_get(); 547 | + total3 += ktime_to_ns(ktime_sub(end3, start3)); 548 | + index3++; 549 | 550 | + //__asm__ volatile (".byte 0x0f, 0x31" : "=A" (start1)); 551 | + start1 = ktime_get(); 552 | if (swap_count(*swap_map)) { 553 | int set_start_mm = (*swap_map >= swcount); 554 | struct list_head *p = &start_mm->mmlist; 555 | @@ -1561,13 +1647,34 @@ 556 | * interactive performance. 557 | */ 558 | cond_resched(); 559 | - if (frontswap && pages_to_unuse > 0) { 560 | + 561 | + //[fastswap] modified 562 | + //if (frontswap && pages_to_unuse > 0) { 563 | + if (pages_to_unuse > 0) { 564 | if (!--pages_to_unuse) 565 | break; 566 | } 567 | - } 568 | 569 | + //__asm__ volatile (".byte 0x0f, 0x31" : "=A" (end1)); 570 | + //total1 += end1 - start1; 571 | + end1 = ktime_get(); 572 | + total1 += ktime_to_ns(ktime_sub(end1, start1)); 573 | + index1++; 574 | + } 575 | + //[fastswap] modified 576 | mmput(start_mm); 577 | + 578 | + //__asm__ volatile (".byte 0x0f, 0x31" : "=A" (end0)); 579 | + //total0 += end0 - start0; 580 | + end0 = ktime_get(); 581 | + total0 = ktime_to_ns(ktime_sub(end0, start0)); 582 | + 583 | + printk("index1 = %ld, index2 = %ld, inde3 = %ld\n", index1, index2, index3); 584 | + if(index1&&index2&&index3 != 0){ 585 | + printk("total = %lld\n", total0); 586 | + printk("perpage: read = %lld, unuse_mm = %lld, other = %lld\n", total2/index2, total3/index3, total1/index1); 587 | + } 588 | + 589 | return retval; 590 | } 591 | 592 | @@ -1634,7 +1741,7 @@ 593 | entry.val = page_private(page); 594 | return map_swap_entry(entry, bdev); 595 | } 596 | - 597 | +EXPORT_SYMBOL(map_swap_page); 598 | /* 599 | * Free all of a swapdev's extent information 600 | */ 601 | @@ -1855,6 +1962,7 @@ 602 | if (type < 0) { 603 | err = -EINVAL; 604 | spin_unlock(&swap_lock); 605 | + printk("swapoff 1...\n"); 606 | goto out_dput; 607 | } 608 | if (!security_vm_enough_memory_mm(current->mm, p->pages)) 609 | @@ -1862,6 +1970,7 @@ 610 | else { 611 | err = -ENOMEM; 612 | spin_unlock(&swap_lock); 613 | + printk("swapoff 2...\n"); 614 | goto out_dput; 615 | } 616 | if (prev < 0) 617 | @@ -1907,6 +2016,7 @@ 618 | 619 | /* wait for anyone still in scan_swap_map */ 620 | p->highest_bit = 0; /* cuts scans short */ 621 | + /* 622 | while (p->flags >= SWP_SCANNING) { 623 | spin_unlock(&p->lock); 624 | spin_unlock(&swap_lock); 625 | @@ -1914,6 +2024,7 @@ 626 | spin_lock(&swap_lock); 627 | spin_lock(&p->lock); 628 | } 629 | + */ 630 | 631 | swap_file = p->swap_file; 632 | old_block_size = p->old_block_size; 633 | @@ -2228,12 +2339,15 @@ 634 | */ 635 | maxpages = swp_offset(pte_to_swp_entry( 636 | swp_entry_to_pte(swp_entry(0, ~0UL)))) + 1; 637 | + 638 | last_page = swap_header->info.last_page; 639 | + 640 | if (last_page > maxpages) { 641 | pr_warn("Truncating oversized swap area, only using %luk out of %luk\n", 642 | maxpages << (PAGE_SHIFT - 10), 643 | last_page << (PAGE_SHIFT - 10)); 644 | } 645 | + 646 | if (maxpages > last_page) { 647 | maxpages = last_page + 1; 648 | /* p->max is an unsigned int: don't overflow it */ 649 | @@ -2245,6 +2359,15 @@ 650 | if (!maxpages) 651 | return 0; 652 | swapfilepages = i_size_read(inode) >> PAGE_SHIFT; 653 | + 654 | + //printk("swapfilepages = %lu, maxpages = %lu\n", swapfilepages, maxpages); 655 | + 656 | + if(maxpages > swapfilepages){ 657 | + maxpages = swapfilepages; 658 | + swap_header->info.last_page = maxpages - 1; 659 | + last_page = maxpages - 1; 660 | + } 661 | + 662 | if (swapfilepages && maxpages > swapfilepages) { 663 | pr_warn("Swap area shorter than signature indicates\n"); 664 | return 0; 665 | @@ -2385,6 +2508,8 @@ 666 | if (IS_ERR(p)) 667 | return PTR_ERR(p); 668 | 669 | + p->shm = NULL; 670 | + 671 | INIT_WORK(&p->discard_work, swap_discard_work); 672 | 673 | name = getname(specialfile); 674 | @@ -2434,6 +2559,14 @@ 675 | } 676 | swap_header = kmap(page); 677 | 678 | + /*The first (highest priority) swap partition is the shm area. 679 | + *Size of the shm area is explicitely specified 680 | + */ 681 | + if(p->is_shm == 1 && mempipe_installed == true) {//nr_swapfiles of the first swap partition equals to 1 682 | + swap_header->info.last_page = memswap_init_size; 683 | + swap_header->info.nr_badpages = 0; 684 | + } 685 | + 686 | maxpages = read_swap_header(p, swap_header, inode); 687 | if (unlikely(!maxpages)) { 688 | error = -EINVAL; 689 | @@ -2523,9 +2656,16 @@ 690 | (swap_flags & SWAP_FLAG_PRIO_MASK) >> SWAP_FLAG_PRIO_SHIFT; 691 | enable_swap_info(p, prio, swap_map, cluster_info, frontswap_map); 692 | 693 | - pr_info("Adding %uk swap on %s. " 694 | + if(p->prio == -1){ 695 | + p->is_shm = 1; 696 | + }else{ 697 | + p->is_shm = 0; 698 | + } 699 | + 700 | + 701 | + pr_info("Adding %uk swap on %s (is_shm = %d). " 702 | "Priority:%d extents:%d across:%lluk %s%s%s%s%s\n", 703 | - p->pages<<(PAGE_SHIFT-10), name->name, p->prio, 704 | + p->pages<<(PAGE_SHIFT-10), name->name, p->is_shm, p->prio, 705 | nr_extents, (unsigned long long)span<<(PAGE_SHIFT-10), 706 | (p->flags & SWP_SOLIDSTATE) ? "SS" : "", 707 | (p->flags & SWP_DISCARDABLE) ? "D" : "", 708 | @@ -2572,6 +2712,7 @@ 709 | putname(name); 710 | if (inode && S_ISREG(inode->i_mode)) 711 | mutex_unlock(&inode->i_mutex); 712 | + 713 | return error; 714 | } 715 | 716 | @@ -2718,6 +2859,7 @@ 717 | BUG_ON(!PageSwapCache(page)); 718 | return swap_info[swp_type(swap)]; 719 | } 720 | +EXPORT_SYMBOL(page_swap_info); 721 | 722 | /* 723 | * out-of-line __page_file_ methods to avoid include hell. 724 | -------------------------------------------------------------------------------- /FastSwap-QEMU-Patch/patch1.diff: -------------------------------------------------------------------------------- 1 | *** qemu-2.0.0/qemu-char.c 2014-04-17 08:44:45.000000000 -0500 2 | --- memflex-qemu-2.0.0/qemu-char.c 2016-07-14 23:49:59.378953473 -0500 3 | *************** 4 | *** 3401,3411 **** 5 | 6 | void qemu_chr_fe_claim_no_fail(CharDriverState *s) 7 | { 8 | ! if (qemu_chr_fe_claim(s) != 0) { 9 | fprintf(stderr, "%s: error chardev \"%s\" already used\n", 10 | __func__, s->label); 11 | exit(1); 12 | } 13 | } 14 | 15 | void qemu_chr_fe_release(CharDriverState *s) 16 | --- 3401,3413 ---- 17 | 18 | void qemu_chr_fe_claim_no_fail(CharDriverState *s) 19 | { 20 | ! /* 21 | ! if (qemu_chr_fe_claim(s) != 0) { 22 | fprintf(stderr, "%s: error chardev \"%s\" already used\n", 23 | __func__, s->label); 24 | exit(1); 25 | } 26 | + */ 27 | } 28 | 29 | void qemu_chr_fe_release(CharDriverState *s) 30 | -------------------------------------------------------------------------------- /GuestOS-Kernel-Module/Makefile: -------------------------------------------------------------------------------- 1 | # obj-m is a list of what kernel modules to build. The .o and other 2 | # objects will be automatically built from the corresponding .c file - 3 | # no need to list the source files explicitly. 4 | 5 | #uio_ivshmem_kvmloop-objs := kvmloop.o netutil.o shmem.o maptable.o uio_ivshmem.o mem_swap.o 6 | memflex-objs := uio_ivshmem.o mem_swap.o mapper.o bitmap.o file_io.o 7 | obj-m := memflex.o 8 | 9 | # KDIR is the location of the kernel source. The current standard is 10 | # to link to the associated source tree from the directory containing 11 | # the compiled modules. 12 | KDIR := /lib/modules/$(shell uname -r)/build 13 | 14 | # PWD is the current working directory and the location of our module 15 | # source files. 16 | PWD := $(shell pwd) 17 | 18 | #KBUILD_EXTRA_SYMBOLS = /home/kvmloop/Module.symvers 19 | # default is the default make target. The rule here says to run make 20 | # with a working directory of the directory containing the kernel 21 | # source and compile only the modules in the PWD (local) directory. 22 | default: 23 | $(MAKE) -C $(KDIR) M=$(PWD) modules 24 | 25 | install: 26 | cp uio_ivshmem.ko /lib/modules/$(shell uname -r)/kernel/drivers/uio/ 27 | 28 | clean: 29 | rm -f *.ko *.o .*.cmd *.mod.c uio_ivshmem.mod.c uio_ivshmem_kvmloop.mod.c Module.symvers modules.order 30 | -------------------------------------------------------------------------------- /GuestOS-Kernel-Module/Module.symvers: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/git-disl/FastSwap/3b7a1469c333185894fd4ffedb52b0af0bfdba82/GuestOS-Kernel-Module/Module.symvers -------------------------------------------------------------------------------- /GuestOS-Kernel-Module/bitmap.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/git-disl/FastSwap/3b7a1469c333185894fd4ffedb52b0af0bfdba82/GuestOS-Kernel-Module/bitmap.o -------------------------------------------------------------------------------- /GuestOS-Kernel-Module/errorlog: -------------------------------------------------------------------------------- 1 | Script started on Wed 12 Oct 2016 09:04:01 PM EDT 2 | ]0;wenqi@memflex: ~/Downloads/memFlex-master/corewenqi@memflex:~/Downloads/memFlex-master/core$ sudo mkake 3 | [sudo] password for wenqi: 4 | make -C /lib/modules/3.14.4/build M=/home/wenqi/Downloads/memFlex-master/core modules 5 | make[1]: Entering directory `/home/wenqi/Downloads/linux-3.14.4' 6 | CC [M] /home/wenqi/Downloads/memFlex-master/core/mem_swap.o 7 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c: In function ‘memswap_init’: 8 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:421:2: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] 9 | gfp_t gfp = GFP_KERNEL; 10 | ^ 11 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:451:16: warning: operation on ‘pages_to_dump’ may be undefined [-Wsequence-point] 12 | pages_to_dump = pages_to_dump = 0; 13 | ^ 14 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c: In function ‘fastswap_lru_swapin_thread’: 15 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:498:5: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] 16 | int numofslots; 17 | ^ 18 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:508:5: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] 19 | int i; 20 | ^ 21 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c: In function ‘fastswap_bud_alloc’: 22 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:716:3: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] 23 | int i; 24 | ^ 25 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:750:10: warning: assignment makes integer from pointer without a cast [enabled by default] 26 | *handle = (char *)fsbdr - PAGE_SIZE + (PAGE_SIZE / numofslots) * bud; 27 | ^ 28 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c: In function ‘mempipe_dump_shm’: 29 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:860:2: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] 30 | struct page *page; 31 | ^ 32 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:926:4: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] 33 | unsigned long diskswap_offset = first_zero_bit(diskswap_freelist, PAGE_SIZE * BITS_PER_BYTE * 40); 34 | ^ 35 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:932:4: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] 36 | struct fastswap_bud *fs_bud = (struct fastswap_bud *)((char *)gsis->shm + dump_offset*fastswap_entry_size + PAGE_SIZE); 37 | ^ 38 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:944:4: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] 39 | struct reverse_swap_page_table_entry *rspt_entry = find_reverse_swap_page_table(diskswap_offset); // define find_reverse_swap_page_table function 40 | ^ 41 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:954:4: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] 42 | struct swap_page_table_entry *spt_entry; 43 | ^ 44 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:851:8: warning: unused variable ‘data’ [-Wunused-variable] 45 | char *data; 46 | ^ 47 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:850:18: warning: unused variable ‘i’ [-Wunused-variable] 48 | int ret = 0, i; 49 | ^ 50 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:849:23: warning: unused variable ‘da’ [-Wunused-variable] 51 | struct dump_args *da = (struct dump_args *)args; 52 | ^ 53 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c: In function ‘mempipe_swap_writepage’: 54 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:1236:2: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] 55 | unsigned char* dst = (unsigned char*)kmalloc(lzo1x_worst_compress(PAGE_SIZE),GFP_ATOMIC); 56 | ^ 57 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:1253:5: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] 58 | char *addr; 59 | ^ 60 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:1279:5: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] 61 | struct swap_page_table_entry *spt_entry = find_swap_page_table(offset); 62 | ^ 63 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c: In function ‘mempipe_swap_readpage’: 64 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:1369:5: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] 65 | int r; 66 | ^ 67 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:1406:36: warning: assignment makes integer from pointer without a cast [enabled by default] 68 | bio->bi_iter.bi_sector = spt_entry->address; 69 | ^ 70 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c: In function ‘end_swap_bio_read_compressed_page’: 71 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:1447:2: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] 72 | struct swap_page_table_entry *spt_entry = find_swap_page_table(offset); 73 | ^ 74 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:1466:3: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] 75 | size_t dlen = PAGE_SIZE; 76 | ^ 77 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:1480:3: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] 78 | unsigned long move_offset_add; 79 | ^ 80 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:1481:10: warning: passing argument 1 of ‘find_reverse_swap_page_table’ makes integer from pointer without a cast [enabled by default] 81 | struct reverse_swap_page_table_entry *rspt_entry = find_reverse_swap_page_table(spt_entry->address); 82 | ^ 83 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:781:39: note: expected ‘long unsigned int’ but argument is of type ‘char *’ 84 | struct reverse_swap_page_table_entry *find_reverse_swap_page_table(unsigned long address){ 85 | ^ 86 | In file included from include/asm-generic/percpu.h:6:0, 87 | from /home/wenqi/Downloads/linux-3.14.4/arch/x86/include/asm/percpu.h:523, 88 | from /home/wenqi/Downloads/linux-3.14.4/arch/x86/include/asm/preempt.h:5, 89 | from include/linux/preempt.h:18, 90 | from include/linux/spinlock.h:50, 91 | from include/linux/mmzone.h:7, 92 | from include/linux/gfp.h:5, 93 | from include/linux/mm.h:9, 94 | from /home/wenqi/Downloads/memFlex-master/core/mem_swap.h:1, 95 | from /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:1: 96 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c: At top level: 97 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:110:29: warning: ‘fastswap_dstmem’ defined but not used [-Wunused-variable] 98 | static DEFINE_PER_CPU(u8 *, fastswap_dstmem); 99 | ^ 100 | include/linux/percpu-defs.h:84:19: note: in definition of macro ‘DEFINE_PER_CPU_SECTION’ 101 | __typeof__(type) name 102 | ^ 103 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:110:8: note: in expansion of macro ‘DEFINE_PER_CPU’ 104 | static DEFINE_PER_CPU(u8 *, fastswap_dstmem); 105 | ^ 106 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c: In function ‘fastswap_lru_swapin_thread’: 107 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:684:9: warning: ‘start_mm’ may be used uninitialized in this function [-Wmaybe-uninitialized] 108 | mmput(start_mm); 109 | ^ 110 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c: In function ‘mempipe_dump_shm’: 111 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:994:12: warning: ‘bio’ may be used uninitialized in this function [-Wmaybe-uninitialized] 112 | submit_bio(WRITE, bio); 113 | ^ 114 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:993:13: warning: ‘page’ may be used uninitialized in this function [-Wmaybe-uninitialized] 115 | unlock_page(page); 116 | ^ 117 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c: In function ‘end_swap_bio_read_compressed_page’: 118 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:1492:10: warning: ‘addr’ may be used uninitialized in this function [-Wmaybe-uninitialized] 119 | res = fastswap_bud_alloc(PAGE2K_pool, 2, 2, GFP_KERNEL, move_spt_entry->offset, addr, &slotoffset); 120 | ^ 121 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:1468:31: warning: ‘offset_add’ may be used uninitialized in this function [-Wmaybe-uninitialized] 122 | r = lzo1x_decompress_safe((unsigned char*)kmap_atomic(page)+offset_add, spt_entry->length, dst, &dlen); 123 | ^ 124 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:1494:16: warning: ‘numofslots’ may be used uninitialized in this function [-Wmaybe-uninitialized] 125 | }else if(numofslots == 4){ 126 | ^ 127 | In file included from include/linux/linkage.h:4:0, 128 | from include/linux/preempt.h:9, 129 | from include/linux/spinlock.h:50, 130 | from include/linux/mmzone.h:7, 131 | from include/linux/gfp.h:5, 132 | from include/linux/mm.h:9, 133 | from /home/wenqi/Downloads/memFlex-master/core/mem_swap.h:1, 134 | from /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:1: 135 | include/linux/compiler.h:330:20: error: call to ‘__compiletime_assert_1474’ declared with attribute error: BUILD_BUG_ON failed: __same_type((page), struct page *) 136 | prefix ## suffix(); \ 137 | ^ 138 | include/linux/compiler.h:335:2: note: in expansion of macro ‘__compiletime_assert’ 139 | __compiletime_assert(condition, msg, prefix, suffix) 140 | ^ 141 | include/linux/compiler.h:347:2: note: in expansion of macro ‘_compiletime_assert’ 142 | _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__) 143 | ^ 144 | include/linux/bug.h:50:37: note: in expansion of macro ‘compiletime_assert’ 145 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) 146 | ^ 147 | include/linux/bug.h:74:2: note: in expansion of macro ‘BUILD_BUG_ON_MSG’ 148 | BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition) 149 | ^ 150 | include/linux/highmem.h:125:2: note: in expansion of macro ‘BUILD_BUG_ON’ 151 | BUILD_BUG_ON(__same_type((addr), struct page *)); \ 152 | ^ 153 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:1474:6: note: in expansion of macro ‘kunmap_atomic’ 154 | kunmap_atomic(page); 155 | ^ 156 | include/linux/compiler.h:330:20: error: call to ‘__compiletime_assert_1507’ declared with attribute error: BUILD_BUG_ON failed: __same_type((page), struct page *) 157 | prefix ## suffix(); \ 158 | ^ 159 | include/linux/compiler.h:335:2: note: in expansion of macro ‘__compiletime_assert’ 160 | __compiletime_assert(condition, msg, prefix, suffix) 161 | ^ 162 | include/linux/compiler.h:347:2: note: in expansion of macro ‘_compiletime_assert’ 163 | _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__) 164 | ^ 165 | include/linux/bug.h:50:37: note: in expansion of macro ‘compiletime_assert’ 166 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) 167 | ^ 168 | include/linux/bug.h:74:2: note: in expansion of macro ‘BUILD_BUG_ON_MSG’ 169 | BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition) 170 | ^ 171 | include/linux/highmem.h:125:2: note: in expansion of macro ‘BUILD_BUG_ON’ 172 | BUILD_BUG_ON(__same_type((addr), struct page *)); \ 173 | ^ 174 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:1507:3: note: in expansion of macro ‘kunmap_atomic’ 175 | kunmap_atomic(page); 176 | ^ 177 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c: In function ‘mempipe_swap_writepage’: 178 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:1257:10: warning: ‘addr’ may be used uninitialized in this function [-Wmaybe-uninitialized] 179 | res = fastswap_bud_alloc(PAGE4K_pool, 3, 1, GFP_KERNEL, offset, addr, &slotoffset); 180 | ^ 181 | In file included from include/linux/linkage.h:4:0, 182 | from include/linux/preempt.h:9, 183 | from include/linux/spinlock.h:50, 184 | from include/linux/mmzone.h:7, 185 | from include/linux/gfp.h:5, 186 | from include/linux/mm.h:9, 187 | from /home/wenqi/Downloads/memFlex-master/core/mem_swap.h:1, 188 | from /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:1: 189 | include/linux/compiler.h:330:20: error: call to ‘__compiletime_assert_1248’ declared with attribute error: BUILD_BUG_ON failed: __same_type((page), struct page *) 190 | prefix ## suffix(); \ 191 | ^ 192 | include/linux/compiler.h:335:2: note: in expansion of macro ‘__compiletime_assert’ 193 | __compiletime_assert(condition, msg, prefix, suffix) 194 | ^ 195 | include/linux/compiler.h:347:2: note: in expansion of macro ‘_compiletime_assert’ 196 | _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__) 197 | ^ 198 | include/linux/bug.h:50:37: note: in expansion of macro ‘compiletime_assert’ 199 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) 200 | ^ 201 | include/linux/bug.h:74:2: note: in expansion of macro ‘BUILD_BUG_ON_MSG’ 202 | BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition) 203 | ^ 204 | include/linux/highmem.h:125:2: note: in expansion of macro ‘BUILD_BUG_ON’ 205 | BUILD_BUG_ON(__same_type((addr), struct page *)); \ 206 | ^ 207 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:1248:5: note: in expansion of macro ‘kunmap_atomic’ 208 | kunmap_atomic(page); 209 | ^ 210 | include/linux/compiler.h:330:20: error: call to ‘__compiletime_assert_1259’ declared with attribute error: BUILD_BUG_ON failed: __same_type((page), struct page *) 211 | prefix ## suffix(); \ 212 | ^ 213 | include/linux/compiler.h:335:2: note: in expansion of macro ‘__compiletime_assert’ 214 | __compiletime_assert(condition, msg, prefix, suffix) 215 | ^ 216 | include/linux/compiler.h:347:2: note: in expansion of macro ‘_compiletime_assert’ 217 | _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__) 218 | ^ 219 | include/linux/bug.h:50:37: note: in expansion of macro ‘compiletime_assert’ 220 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) 221 | ^ 222 | include/linux/bug.h:74:2: note: in expansion of macro ‘BUILD_BUG_ON_MSG’ 223 | BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition) 224 | ^ 225 | include/linux/highmem.h:125:2: note: in expansion of macro ‘BUILD_BUG_ON’ 226 | BUILD_BUG_ON(__same_type((addr), struct page *)); \ 227 | ^ 228 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:1259:6: note: in expansion of macro ‘kunmap_atomic’ 229 | kunmap_atomic(page); 230 | ^ 231 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c: In function ‘mempipe_swap_readpage’: 232 | include/linux/compiler.h:330:20: error: call to ‘__compiletime_assert_1394’ declared with attribute error: BUILD_BUG_ON failed: __same_type((page), struct page *) 233 | prefix ## suffix(); \ 234 | ^ 235 | include/linux/compiler.h:335:2: note: in expansion of macro ‘__compiletime_assert’ 236 | __compiletime_assert(condition, msg, prefix, suffix) 237 | ^ 238 | include/linux/compiler.h:347:2: note: in expansion of macro ‘_compiletime_assert’ 239 | _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__) 240 | ^ 241 | include/linux/bug.h:50:37: note: in expansion of macro ‘compiletime_assert’ 242 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) 243 | ^ 244 | include/linux/bug.h:74:2: note: in expansion of macro ‘BUILD_BUG_ON_MSG’ 245 | BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition) 246 | ^ 247 | include/linux/highmem.h:125:2: note: in expansion of macro ‘BUILD_BUG_ON’ 248 | BUILD_BUG_ON(__same_type((addr), struct page *)); \ 249 | ^ 250 | /home/wenqi/Downloads/memFlex-master/core/mem_swap.c:1394:6: note: in expansion of macro ‘kunmap_atomic’ 251 | kunmap_atomic(page); 252 | ^ 253 | make[2]: *** [/home/wenqi/Downloads/memFlex-master/core/mem_swap.o] Error 1 254 | make[1]: *** [_module_/home/wenqi/Downloads/memFlex-master/core] Error 2 255 | make[1]: Leaving directory `/home/wenqi/Downloads/linux-3.14.4' 256 | make: *** [default] Error 2 257 | ]0;wenqi@memflex: ~/Downloads/memFlex-master/corewenqi@memflex:~/Downloads/memFlex-master/core$ exit 258 | 259 | Script done on Wed 12 Oct 2016 09:04:11 PM EDT 260 | -------------------------------------------------------------------------------- /GuestOS-Kernel-Module/file_io.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/git-disl/FastSwap/3b7a1469c333185894fd4ffedb52b0af0bfdba82/GuestOS-Kernel-Module/file_io.o -------------------------------------------------------------------------------- /GuestOS-Kernel-Module/mapper.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/git-disl/FastSwap/3b7a1469c333185894fd4ffedb52b0af0bfdba82/GuestOS-Kernel-Module/mapper.o -------------------------------------------------------------------------------- /GuestOS-Kernel-Module/mem_swap.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/git-disl/FastSwap/3b7a1469c333185894fd4ffedb52b0af0bfdba82/GuestOS-Kernel-Module/mem_swap.o -------------------------------------------------------------------------------- /GuestOS-Kernel-Module/memflex.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/git-disl/FastSwap/3b7a1469c333185894fd4ffedb52b0af0bfdba82/GuestOS-Kernel-Module/memflex.ko -------------------------------------------------------------------------------- /GuestOS-Kernel-Module/memflex.mod.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/git-disl/FastSwap/3b7a1469c333185894fd4ffedb52b0af0bfdba82/GuestOS-Kernel-Module/memflex.mod.o -------------------------------------------------------------------------------- /GuestOS-Kernel-Module/memflex.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/git-disl/FastSwap/3b7a1469c333185894fd4ffedb52b0af0bfdba82/GuestOS-Kernel-Module/memflex.o -------------------------------------------------------------------------------- /GuestOS-Kernel-Module/run.sh: -------------------------------------------------------------------------------- 1 | swapoff -a 2 | rmmod memflex.ko 3 | modprobe uio 4 | insmod memflex.ko 5 | swapon /dev/vda5 -------------------------------------------------------------------------------- /GuestOS-Kernel-Module/uio_ivshmem.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/git-disl/FastSwap/3b7a1469c333185894fd4ffedb52b0af0bfdba82/GuestOS-Kernel-Module/uio_ivshmem.o -------------------------------------------------------------------------------- /Ivshmem-Server/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -O3 -Wall -Werror 3 | LIBS = -lrt 4 | 5 | # a very simple makefile to build the inter-VM shared memory server 6 | 7 | all: ivshmem_server 8 | 9 | .c.o: 10 | $(CC) $(CFLAGS) -c $^ -o $@ 11 | 12 | ivshmem_server: ivshmem_server.o send_scm.o 13 | $(CC) $(CFLAGS) -o $@ $^ $(LIBS) 14 | 15 | clean: 16 | rm -f *.o ivshmem_server 17 | -------------------------------------------------------------------------------- /Ivshmem-Server/README: -------------------------------------------------------------------------------- 1 | Using the ivshmem shared memory server 2 | -------------------------------------- 3 | 4 | This server is only supported on Linux. 5 | 6 | To use the shared memory server, first compile it. Running 'make' should 7 | accomplish this. An executable named 'ivshmem_server' will be built. 8 | 9 | to display the options run: 10 | 11 | ./ivshmem_server -h 12 | 13 | Options 14 | ------- 15 | 16 | -h print help message 17 | 18 | -p 19 | unix socket to listen on. The qemu-kvm chardev needs to connect on 20 | this socket. (default: '/tmp/ivshmem_socket') 21 | 22 | -s 23 | POSIX shared object to create that is the shared memory (default: 'ivshmem') 24 | 25 | -m <#> 26 | size of the POSIX object in MBs (default: 1) 27 | 28 | -n <#> 29 | number of eventfds for each guest. This number must match the 30 | 'vectors' argument passed the ivshmem device. (default: 1) 31 | -------------------------------------------------------------------------------- /Ivshmem-Server/ivshmem.sh: -------------------------------------------------------------------------------- 1 | #/bin/sh 2 | ./ivshmem_server -m 16384 -p /tmp/ivshmem_socket -s dynamo -n 2 3 | 4 | -------------------------------------------------------------------------------- /Ivshmem-Server/ivshmem_server: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/git-disl/FastSwap/3b7a1469c333185894fd4ffedb52b0af0bfdba82/Ivshmem-Server/ivshmem_server -------------------------------------------------------------------------------- /Ivshmem-Server/ivshmem_server.c: -------------------------------------------------------------------------------- 1 | /* 2 | * A stand-alone shared memory server for inter-VM shared memory for KVM 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include "send_scm.h" 20 | 21 | #define DEFAULT_SOCK_PATH "/tmp/ivshmem_socket" 22 | #define DEFAULT_SHM_OBJ "ivshmem" 23 | 24 | #define DEBUG 1 25 | 26 | typedef struct server_state { 27 | vmguest_t *live_vms; 28 | int nr_allocated_vms; 29 | long shm_size; 30 | long live_count; 31 | long total_count; 32 | int shm_fd; 33 | char * path; 34 | char * shmobj; 35 | int maxfd, conn_socket; 36 | long msi_vectors; 37 | } server_state_t; 38 | 39 | void usage(char const *prg); 40 | int find_set(fd_set * readset, int max); 41 | void print_vec(server_state_t * s, const char * c); 42 | 43 | void add_new_guest(server_state_t * s); 44 | void parse_args(int argc, char **argv, server_state_t * s); 45 | int create_listening_socket(char * path); 46 | 47 | int main(int argc, char ** argv) 48 | { 49 | fd_set readset; 50 | server_state_t * s; 51 | 52 | s = (server_state_t *)calloc(1, sizeof(server_state_t)); 53 | 54 | s->live_count = 0; 55 | s->total_count = 0; 56 | parse_args(argc, argv, s); 57 | 58 | /* open shared memory file */ 59 | if ((s->shm_fd = shm_open(s->shmobj, O_CREAT|O_RDWR, S_IRWXU)) < 0) 60 | { 61 | fprintf(stderr, "ivshmem server: could not open shared file\n"); 62 | exit(-1); 63 | } 64 | 65 | printf("~~~~~~~~~~~~~~~~~~~~~~~~~~%s\n", s->shmobj); 66 | 67 | if (ftruncate(s->shm_fd, s->shm_size) != 0) 68 | { 69 | fprintf(stderr, "ivshmem server: could not truncate memory region\n"); 70 | exit(-1); 71 | } 72 | 73 | s->conn_socket = create_listening_socket(s->path); 74 | 75 | s->maxfd = s->conn_socket; 76 | 77 | for(;;) { 78 | int ret, handle, i; 79 | char buf[1024]; 80 | 81 | print_vec(s, "vm_sockets"); 82 | 83 | FD_ZERO(&readset); 84 | /* conn socket is in Live_vms at posn 0 */ 85 | FD_SET(s->conn_socket, &readset); 86 | for (i = 0; i < s->total_count; i++) { 87 | if (s->live_vms[i].alive != 0) { 88 | FD_SET(s->live_vms[i].sockfd, &readset); 89 | } 90 | } 91 | 92 | printf("\nWaiting (maxfd = %d)\n", s->maxfd); 93 | 94 | ret = select(s->maxfd + 1, &readset, NULL, NULL, NULL); 95 | 96 | if (ret == -1) { 97 | perror("select()"); 98 | } 99 | 100 | handle = find_set(&readset, s->maxfd + 1); 101 | if (handle == -1) continue; 102 | 103 | if (handle == s->conn_socket) { 104 | 105 | printf("[NC] new connection\n"); 106 | FD_CLR(s->conn_socket, &readset); 107 | 108 | /* The Total_count is equal to the new guests VM ID */ 109 | add_new_guest(s); 110 | 111 | /* update our the maximum file descriptor number */ 112 | s->maxfd = s->live_vms[s->total_count - 1].sockfd > s->maxfd ? 113 | s->live_vms[s->total_count - 1].sockfd : s->maxfd; 114 | 115 | s->live_count++; 116 | printf("Live_count is %ld\n", s->live_count); 117 | 118 | } else { 119 | /* then we have received a disconnection */ 120 | int recv_ret; 121 | long i, j; 122 | long deadposn = -1; 123 | 124 | recv_ret = recv(handle, buf, 1, 0); 125 | 126 | printf("[DC] recv returned %d\n", recv_ret); 127 | 128 | /* find the dead VM in our list and move it do the dead list. */ 129 | for (i = 0; i < s->total_count; i++) { 130 | if (s->live_vms[i].sockfd == handle) { 131 | deadposn = i; 132 | s->live_vms[i].alive = 0; 133 | close(s->live_vms[i].sockfd); 134 | 135 | for (j = 0; j < s->msi_vectors; j++) { 136 | close(s->live_vms[i].efd[j]); 137 | } 138 | 139 | free(s->live_vms[i].efd); 140 | s->live_vms[i].sockfd = -1; 141 | break; 142 | } 143 | } 144 | 145 | for (j = 0; j < s->total_count; j++) { 146 | /* update remaining clients that one client has left/died */ 147 | if (s->live_vms[j].alive) { 148 | printf("[UD] sending kill of fd[%ld] to %ld\n", 149 | deadposn, j); 150 | sendKill(s->live_vms[j].sockfd, deadposn, sizeof(deadposn)); 151 | } 152 | } 153 | 154 | s->live_count--; 155 | 156 | /* close the socket for the departed VM */ 157 | close(handle); 158 | } 159 | 160 | } 161 | 162 | return 0; 163 | } 164 | 165 | void add_new_guest(server_state_t * s) { 166 | 167 | struct sockaddr_un remote; 168 | socklen_t t = sizeof(remote); 169 | long i, j; 170 | int vm_sock; 171 | long new_posn; 172 | long neg1 = -1; 173 | 174 | vm_sock = accept(s->conn_socket, (struct sockaddr *)&remote, &t); 175 | 176 | if ( vm_sock == -1 ) { 177 | perror("accept"); 178 | exit(1); 179 | } 180 | 181 | new_posn = s->total_count; 182 | 183 | if (new_posn == s->nr_allocated_vms) { 184 | printf("increasing vm slots\n"); 185 | s->nr_allocated_vms = s->nr_allocated_vms * 2; 186 | if (s->nr_allocated_vms < 16) 187 | s->nr_allocated_vms = 16; 188 | s->live_vms = realloc(s->live_vms, 189 | s->nr_allocated_vms * sizeof(vmguest_t)); 190 | 191 | if (s->live_vms == NULL) { 192 | fprintf(stderr, "realloc failed - quitting\n"); 193 | exit(-1); 194 | } 195 | } 196 | 197 | s->live_vms[new_posn].posn = new_posn; 198 | printf("[NC] Live_vms[%ld]\n", new_posn); 199 | s->live_vms[new_posn].efd = (int *) malloc(sizeof(int)); 200 | for (i = 0; i < s->msi_vectors; i++) { 201 | s->live_vms[new_posn].efd[i] = eventfd(0, 0); 202 | printf("\tefd[%ld] = %d\n", i, s->live_vms[new_posn].efd[i]); 203 | } 204 | s->live_vms[new_posn].sockfd = vm_sock; 205 | s->live_vms[new_posn].alive = 1; 206 | 207 | 208 | sendPosition(vm_sock, new_posn); 209 | sendUpdate(vm_sock, neg1, sizeof(long), s->shm_fd); 210 | printf("[NC] trying to send fds to new connection\n"); 211 | sendRights(vm_sock, new_posn, sizeof(new_posn), s->live_vms, s->msi_vectors); 212 | 213 | printf("[NC] Connected (count = %ld).\n", new_posn); 214 | for (i = 0; i < new_posn; i++) { 215 | if (s->live_vms[i].alive) { 216 | // ping all clients that a new client has joined 217 | printf("[UD] sending fd[%ld] to %ld\n", new_posn, i); 218 | for (j = 0; j < s->msi_vectors; j++) { 219 | printf("\tefd[%ld] = [%d]", j, s->live_vms[new_posn].efd[j]); 220 | sendUpdate(s->live_vms[i].sockfd, new_posn, 221 | sizeof(new_posn), s->live_vms[new_posn].efd[j]); 222 | } 223 | printf("\n"); 224 | } 225 | } 226 | 227 | s->total_count++; 228 | } 229 | 230 | int create_listening_socket(char * path) { 231 | 232 | struct sockaddr_un local; 233 | int len, conn_socket; 234 | 235 | if ((conn_socket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { 236 | perror("socket"); 237 | exit(1); 238 | } 239 | 240 | local.sun_family = AF_UNIX; 241 | strcpy(local.sun_path, path); 242 | unlink(local.sun_path); 243 | len = strlen(local.sun_path) + sizeof(local.sun_family); 244 | if (bind(conn_socket, (struct sockaddr *)&local, len) == -1) { 245 | perror("bind"); 246 | exit(1); 247 | } 248 | 249 | if (listen(conn_socket, 5) == -1) { 250 | perror("listen"); 251 | exit(1); 252 | } 253 | 254 | return conn_socket; 255 | 256 | } 257 | 258 | void parse_args(int argc, char **argv, server_state_t * s) { 259 | 260 | int c; 261 | 262 | s->shm_size = 1024 * 1024; // default shm_size 263 | s->path = NULL; 264 | s->shmobj = NULL; 265 | s->msi_vectors = 1; 266 | 267 | while ((c = getopt(argc, argv, "hp:s:m:n:")) != -1) { 268 | 269 | switch (c) { 270 | // path to listening socket 271 | case 'p': 272 | s->path = optarg; 273 | break; 274 | // name of shared memory object 275 | case 's': 276 | s->shmobj = optarg; 277 | break; 278 | // size of shared memory object 279 | case 'm': { 280 | uint64_t value; 281 | char *ptr; 282 | 283 | value = strtoul(optarg, &ptr, 10); 284 | switch (*ptr) { 285 | case 0: case 'M': case 'm': 286 | value <<= 20; 287 | break; 288 | case 'G': case 'g': 289 | value <<= 30; 290 | break; 291 | default: 292 | fprintf(stderr, "qemu: invalid ram size: %s\n", optarg); 293 | exit(1); 294 | } 295 | s->shm_size = value; 296 | break; 297 | } 298 | case 'n': 299 | s->msi_vectors = atol(optarg); 300 | break; 301 | case 'h': 302 | default: 303 | usage(argv[0]); 304 | exit(1); 305 | } 306 | } 307 | 308 | if (s->path == NULL) { 309 | s->path = strdup(DEFAULT_SOCK_PATH); 310 | } 311 | 312 | printf("listening socket: %s\n", s->path); 313 | 314 | if (s->shmobj == NULL) { 315 | s->shmobj = strdup(DEFAULT_SHM_OBJ); 316 | } 317 | 318 | printf("shared object: %s\n", s->shmobj); 319 | printf("shared object size: %ld (bytes)\n", s->shm_size); 320 | 321 | } 322 | 323 | void print_vec(server_state_t * s, const char * c) { 324 | 325 | int i, j; 326 | 327 | #if DEBUG 328 | printf("%s (%ld) = ", c, s->total_count); 329 | for (i = 0; i < s->total_count; i++) { 330 | if (s->live_vms[i].alive) { 331 | for (j = 0; j < s->msi_vectors; j++) { 332 | printf("[%d|%d] ", s->live_vms[i].sockfd, s->live_vms[i].efd[j]); 333 | } 334 | } 335 | } 336 | printf("\n"); 337 | #endif 338 | 339 | } 340 | 341 | int find_set(fd_set * readset, int max) { 342 | 343 | int i; 344 | 345 | for (i = 1; i < max; i++) { 346 | if (FD_ISSET(i, readset)) { 347 | return i; 348 | } 349 | } 350 | 351 | printf("nothing set\n"); 352 | return -1; 353 | 354 | } 355 | 356 | void usage(char const *prg) { 357 | fprintf(stderr, "use: %s [-h] [-p ] [-s ] " 358 | "[-m ] [-n <# of MSI vectors>]\n", prg); 359 | } 360 | -------------------------------------------------------------------------------- /Ivshmem-Server/ivshmem_server.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/git-disl/FastSwap/3b7a1469c333185894fd4ffedb52b0af0bfdba82/Ivshmem-Server/ivshmem_server.o -------------------------------------------------------------------------------- /Ivshmem-Server/send_scm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "send_scm.h" 14 | 15 | #ifndef POLLRDHUP 16 | #define POLLRDHUP 0x2000 17 | #endif 18 | 19 | int readUpdate(int fd, long * posn, int * newfd) 20 | { 21 | struct msghdr msg; 22 | struct iovec iov[1]; 23 | struct cmsghdr *cmptr; 24 | size_t len; 25 | size_t msg_size = sizeof(int); 26 | char control[CMSG_SPACE(msg_size)]; 27 | 28 | msg.msg_name = 0; 29 | msg.msg_namelen = 0; 30 | msg.msg_control = control; 31 | msg.msg_controllen = sizeof(control); 32 | msg.msg_flags = 0; 33 | msg.msg_iov = iov; 34 | msg.msg_iovlen = 1; 35 | 36 | iov[0].iov_base = &posn; 37 | iov[0].iov_len = sizeof(posn); 38 | 39 | do { 40 | len = recvmsg(fd, &msg, 0); 41 | } while (len == (size_t) (-1) && (errno == EINTR || errno == EAGAIN)); 42 | 43 | printf("iov[0].buf is %ld\n", *((long *)iov[0].iov_base)); 44 | printf("len is %ld\n", len); 45 | // TODO: Logging 46 | if (len == (size_t) (-1)) { 47 | perror("recvmsg()"); 48 | return -1; 49 | } 50 | 51 | if (msg.msg_controllen < sizeof(struct cmsghdr)) 52 | return *posn; 53 | 54 | for (cmptr = CMSG_FIRSTHDR(&msg); cmptr != NULL; 55 | cmptr = CMSG_NXTHDR(&msg, cmptr)) { 56 | if (cmptr->cmsg_level != SOL_SOCKET || 57 | cmptr->cmsg_type != SCM_RIGHTS){ 58 | printf("continuing %ld\n", sizeof(size_t)); 59 | printf("read msg_size = %ld\n", msg_size); 60 | if (cmptr->cmsg_len != sizeof(control)) 61 | printf("not equal (%ld != %ld)\n",cmptr->cmsg_len,sizeof(control)); 62 | continue; 63 | } 64 | 65 | memcpy(newfd, CMSG_DATA(cmptr), sizeof(int)); 66 | printf("posn is %ld (fd = %d)\n", *posn, *newfd); 67 | return 0; 68 | } 69 | 70 | fprintf(stderr, "bad data in packet\n"); 71 | return -1; 72 | } 73 | 74 | int readRights(int fd, long count, size_t count_len, int **fds, int msi_vectors) 75 | { 76 | int j, newfd; 77 | 78 | for (; ;){ 79 | long posn = 0; 80 | 81 | readUpdate(fd, &posn, &newfd); 82 | printf("reading posn %ld ", posn); 83 | fds[posn] = (int *)malloc (msi_vectors * sizeof(int)); 84 | fds[posn][0] = newfd; 85 | for (j = 1; j < msi_vectors; j++) { 86 | readUpdate(fd, &posn, &newfd); 87 | fds[posn][j] = newfd; 88 | printf("%d.", fds[posn][j]); 89 | } 90 | printf("\n"); 91 | 92 | /* stop reading once i've read my own eventfds */ 93 | if (posn == count) 94 | break; 95 | } 96 | 97 | return 0; 98 | } 99 | 100 | int sendKill(int fd, long const posn, size_t posn_len) { 101 | 102 | struct cmsghdr *cmsg; 103 | size_t msg_size = sizeof(int); 104 | char control[CMSG_SPACE(msg_size)]; 105 | struct iovec iov[1]; 106 | size_t len; 107 | struct msghdr msg = { 0, 0, iov, 1, control, sizeof control, 0 }; 108 | 109 | struct pollfd mypollfd; 110 | int rv; 111 | 112 | iov[0].iov_base = (void *) &posn; 113 | iov[0].iov_len = posn_len; 114 | 115 | // from cmsg(3) 116 | cmsg = CMSG_FIRSTHDR(&msg); 117 | cmsg->cmsg_level = SOL_SOCKET; 118 | cmsg->cmsg_len = 0; 119 | msg.msg_controllen = cmsg->cmsg_len; 120 | 121 | printf("Killing posn %ld\n", posn); 122 | 123 | // check if the fd is dead or not 124 | mypollfd.fd = fd; 125 | mypollfd.events = POLLRDHUP; 126 | mypollfd.revents = 0; 127 | 128 | rv = poll(&mypollfd, 1, 0); 129 | 130 | printf("rv is %d\n", rv); 131 | 132 | if (rv == 0) { 133 | len = sendmsg(fd, &msg, 0); 134 | if (len == (size_t) (-1)) { 135 | perror("sendmsg()"); 136 | return -1; 137 | } 138 | return (len == posn_len); 139 | } else { 140 | printf("already dead\n"); 141 | return 0; 142 | } 143 | } 144 | 145 | int sendUpdate(int fd, long posn, size_t posn_len, int sendfd) 146 | { 147 | 148 | struct cmsghdr *cmsg; 149 | size_t msg_size = sizeof(int); 150 | char control[CMSG_SPACE(msg_size)]; 151 | struct iovec iov[1]; 152 | size_t len; 153 | struct msghdr msg = { 0, 0, iov, 1, control, sizeof control, 0 }; 154 | 155 | iov[0].iov_base = (void *) (&posn); 156 | iov[0].iov_len = posn_len; 157 | 158 | // from cmsg(3) 159 | cmsg = CMSG_FIRSTHDR(&msg); 160 | cmsg->cmsg_level = SOL_SOCKET; 161 | cmsg->cmsg_type = SCM_RIGHTS; 162 | cmsg->cmsg_len = CMSG_LEN(msg_size); 163 | msg.msg_controllen = cmsg->cmsg_len; 164 | 165 | memcpy((CMSG_DATA(cmsg)), &sendfd, msg_size); 166 | 167 | len = sendmsg(fd, &msg, 0); 168 | if (len == (size_t) (-1)) { 169 | perror("sendmsg()"); 170 | return -1; 171 | } 172 | 173 | return (len == posn_len); 174 | 175 | } 176 | 177 | int sendPosition(int fd, long const posn) 178 | { 179 | int rv; 180 | 181 | rv = send(fd, &posn, sizeof(long), 0); 182 | if (rv != sizeof(long)) { 183 | fprintf(stderr, "error sending posn\n"); 184 | return -1; 185 | } 186 | 187 | return 0; 188 | } 189 | 190 | int sendRights(int fd, long const count, size_t count_len, vmguest_t * Live_vms, 191 | long msi_vectors) 192 | { 193 | /* updates about new guests are sent one at a time */ 194 | 195 | long i, j; 196 | 197 | for (i = 0; i <= count; i++) { 198 | if (Live_vms[i].alive) { 199 | for (j = 0; j < msi_vectors; j++) { 200 | sendUpdate(Live_vms[count].sockfd, i, sizeof(long), 201 | Live_vms[i].efd[j]); 202 | } 203 | } 204 | } 205 | 206 | return 0; 207 | 208 | } 209 | -------------------------------------------------------------------------------- /Ivshmem-Server/send_scm.h: -------------------------------------------------------------------------------- 1 | #ifndef SEND_SCM 2 | #define SEND_SCM 3 | 4 | struct vm_guest_conn { 5 | int posn; 6 | int sockfd; 7 | int * efd; 8 | int alive; 9 | }; 10 | 11 | typedef struct vm_guest_conn vmguest_t; 12 | 13 | int readRights(int fd, long count, size_t count_len, int **fds, int msi_vectors); 14 | int sendRights(int fd, long const count, size_t count_len, vmguest_t *Live_vms, long msi_vectors); 15 | int readUpdate(int fd, long * posn, int * newfd); 16 | int sendUpdate(int fd, long const posn, size_t posn_len, int sendfd); 17 | int sendPosition(int fd, long const posn); 18 | int sendKill(int fd, long const posn, size_t posn_len); 19 | #endif 20 | -------------------------------------------------------------------------------- /Ivshmem-Server/send_scm.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/git-disl/FastSwap/3b7a1469c333185894fd4ffedb52b0af0bfdba82/Ivshmem-Server/send_scm.o -------------------------------------------------------------------------------- /fastswap.xml: -------------------------------------------------------------------------------- 1 | 2 | fastswap 3 | 5760a80b-0884-5345-955e-c8d564ca7f85 4 | 8388608 5 | 8388608 6 | 2 7 | 8 | /machine 9 | 10 | 11 | hvm 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | destroy 21 | restart 22 | restart 23 | 24 | /usr/bin/qemu-system-x86_64 25 | 26 | 27 | 28 | 29 | 30 |
31 | 32 | 33 | 34 |
35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 |
69 | 70 |