diff --git a/xen.changes b/xen.changes index 7d7bca0..872b6b8 100644 --- a/xen.changes +++ b/xen.changes @@ -1,3 +1,44 @@ +------------------------------------------------------------------- +Thu Nov 3 23:50:31 CET 2011 - ohering@suse.de + +- fate#310510 - fix xenpaging + This change reverses the task of xenpaging. Before this change a + fixed number of pages was paged out. With this change the guest + will not have access to more than the given number of pages at + the same time. + The xenpaging= config option is replaced by actmem= + A new xm mem-swap-target is added. + The xenpaging binary is moved to /usr/lib/xen/bin/ + xenpaging.HVMCOPY_gfn_paged_out.patch + xenpaging.XEN_PAGING_DIR.patch + xenpaging.add_evict_pages.patch + xenpaging.bitmap_clear.patch + xenpaging.cmdline-interface.patch + xenpaging.encapsulate_domain_info.patch + xenpaging.file_op-return-code.patch + xenpaging.guest-memusage.patch + xenpaging.install-to-libexec.patch + xenpaging.low_target_policy_nomru.patch + xenpaging.main-loop-exit-handling.patch + xenpaging.misleading-comment.patch + xenpaging.page_in-munmap-size.patch + xenpaging.print-gfn.patch + xenpaging.record-numer-paged-out-pages.patch + xenpaging.reset-uncomsumed.patch + xenpaging.stale-comments.patch + xenpaging.target-tot_pages.patch + xenpaging.use-PERROR.patch + xenpaging.watch-target-tot_pages.patch + xenpaging.watch_event-DPRINTF.patch + xenpaging.xc_interface_open-comment.patch + +------------------------------------------------------------------- +Thu Nov 3 23:32:12 CET 2011 - ohering@suse.de + +- xen.spec: update filelist + package /usr/lib*/xen with wildcard to pickup new files + remove duplicate /usr/sbin/xen-list from filelist + ------------------------------------------------------------------- Wed Oct 26 10:13:04 MDT 2011 - carnold@novell.com diff --git a/xen.spec b/xen.spec index d94fbf8..9a979e5 100644 --- a/xen.spec +++ b/xen.spec @@ -381,7 +381,29 @@ Patch1010: xen-unstable.xentrace.t_info_first_offset.patch Patch1011: xen-unstable.xentrace.data_size__read_mostly.patch Patch1012: xen-unstable.xentrace.__insert_record-dst-type.patch # FATE 310510 -Patch1106: xenpaging.autostart.patch +Patch1107: xenpaging.stale-comments.patch +Patch1108: xenpaging.misleading-comment.patch +Patch1109: xenpaging.use-PERROR.patch +Patch1110: xenpaging.file_op-return-code.patch +Patch1111: xenpaging.print-gfn.patch +Patch1112: xenpaging.xc_interface_open-comment.patch +Patch1113: xenpaging.encapsulate_domain_info.patch +Patch1114: xenpaging.record-numer-paged-out-pages.patch +Patch1115: xenpaging.add_evict_pages.patch +Patch1116: xenpaging.main-loop-exit-handling.patch +Patch1117: xenpaging.bitmap_clear.patch +Patch1118: xenpaging.reset-uncomsumed.patch +Patch1119: xenpaging.install-to-libexec.patch +Patch1120: xenpaging.XEN_PAGING_DIR.patch +Patch1121: xenpaging.target-tot_pages.patch +Patch1122: xenpaging.watch-target-tot_pages.patch +Patch1123: xenpaging.cmdline-interface.patch +Patch1125: xenpaging.watch_event-DPRINTF.patch +Patch1126: xenpaging.guest-memusage.patch +Patch1127: xenpaging.page_in-munmap-size.patch +Patch1128: xenpaging.low_target_policy_nomru.patch +Patch1129: xenpaging.autostart.patch +Patch1130: xenpaging.HVMCOPY_gfn_paged_out.patch # xenalyze Patch20000: xenalyze.gcc46.patch # Build patch @@ -394,6 +416,7 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-build %suse_kernel_module_package -n xen um xen -f kmp_filelist %endif + %description Xen is a virtual machine monitor for x86 that supports execution of multiple guest operating systems with unprecedented levels of @@ -455,6 +478,7 @@ Group: System/Kernel #Requires: xen = %{version} AutoReqProv: on + %description libs Xen is a virtual machine monitor for x86 that supports execution of multiple guest operating systems with unprecedented levels of @@ -500,6 +524,7 @@ Authors: %if %{?with_dom0_support}0 + %package tools License: GPLv2+ Summary: Xen Virtualization: Control tools for domain 0 @@ -511,6 +536,7 @@ Provides: xen-tools-ioemu = 3.2 Obsoletes: xen-tools-ioemu <= 3.2 AutoReqProv: on + %description tools Xen is a virtual machine monitor for x86 that supports execution of multiple guest operating systems with unprecedented levels of @@ -558,6 +584,7 @@ Authors: Ian Pratt %endif + %package tools-domU License: GPLv2+ Summary: Xen Virtualization: Control tools for domain U @@ -565,6 +592,7 @@ Group: System/Kernel Conflicts: xen-tools AutoReqProv: on + %description tools-domU Xen is a virtual machine monitor for x86 that supports execution of multiple guest operating systems with unprecedented levels of @@ -585,6 +613,7 @@ Summary: Xen Virtualization: Headers and libraries for development Group: System/Kernel Requires: xen-libs = %{version} + %description devel Xen is a virtual machine monitor for x86 that supports execution of multiple guest operating systems with unprecedented levels of @@ -630,12 +659,14 @@ Authors: %if %{?with_kmp}0 + %package KMP License: GPLv2+ Group: System/Kernel Summary: Xen para-virtual device drivers for fully virtualized guests Conflicts: xen + %description KMP Xen para-virtual device drivers for fully virtualized guests @@ -681,11 +712,13 @@ Xen, but is not available for release due to license restrictions. %if %{?with_dom0_support}0 + %package doc-html License: GPLv2+ Summary: Xen Virtualization: HTML documentation Group: Documentation/HTML + %description doc-html Xen is a virtual machine monitor for x86 that supports execution of multiple guest operating systems with unprecedented levels of @@ -705,6 +738,7 @@ License: GPLv2+ Summary: Xen Virtualization: PDF documentation Group: Documentation/Other + %description doc-pdf Xen is a virtual machine monitor for x86 that supports execution of multiple guest operating systems with unprecedented levels of @@ -721,6 +755,7 @@ Authors: Ian Pratt %endif + %prep %setup -q -n %xen_build_dir -a 1 -a 20000 %patch20000 -p1 @@ -958,11 +993,34 @@ tar xfj %{SOURCE2} -C $RPM_BUILD_DIR/%{xen_build_dir}/tools %patch1011 -p1 %patch1012 -p1 # FATE 310510 -%patch1106 -p1 +%patch1107 -p1 +%patch1108 -p1 +%patch1109 -p1 +%patch1110 -p1 +%patch1111 -p1 +%patch1112 -p1 +%patch1113 -p1 +%patch1114 -p1 +%patch1115 -p1 +%patch1116 -p1 +%patch1117 -p1 +%patch1118 -p1 +%patch1119 -p1 +%patch1120 -p1 +%patch1121 -p1 +%patch1122 -p1 +%patch1123 -p1 +%patch1125 -p1 +%patch1126 -p1 +%patch1127 -p1 +%patch1128 -p1 +%patch1129 -p1 +%patch1130 -p1 # %patch99998 -p1 %patch99999 -p1 + %build XEN_EXTRAVERSION=%version-%release XEN_EXTRAVERSION=${XEN_EXTRAVERSION#%{xvers}} @@ -998,6 +1056,7 @@ for flavor in %flavors_to_build; do done %endif + %install export CFLAGS="$RPM_OPT_FLAGS" %if %{?with_dom0_support}0 @@ -1200,6 +1259,7 @@ rm -f $RPM_BUILD_ROOT/%{_bindir}/xencons %if %{?with_dom0_support}0 + %files -f xen.files.txt %defattr(-,root,root) /boot/xen-%{version}-%{release}.gz @@ -1216,6 +1276,7 @@ rm -f $RPM_BUILD_ROOT/%{_bindir}/xencons /boot/xen.gz %endif + %files libs %defattr(-,root,root) %{_libdir}/fs/ @@ -1223,6 +1284,7 @@ rm -f $RPM_BUILD_ROOT/%{_bindir}/xencons %if %{?with_dom0_support}0 + %files tools %defattr(-,root,root) /usr/bin/xenalyze @@ -1254,24 +1316,14 @@ rm -f $RPM_BUILD_ROOT/%{_bindir}/xencons /usr/sbin/td-util /usr/sbin/vhd-update /usr/sbin/vhd-util -/usr/sbin/xen-list /usr/sbin/gdbsx /usr/sbin/xl /usr/sbin/kdd /usr/sbin/tap-ctl -%dir %{_libdir}/xen -%dir %{_libdir}/xen/bin +%{_libdir}/xen %ifarch x86_64 -%dir /usr/lib/xen -%dir /usr/lib/xen/bin +/usr/lib/xen %endif -%dir /usr/lib/xen/boot -%{_libdir}/xen/bin/readnotes -%{_libdir}/xen/bin/xc_restore -%{_libdir}/xen/bin/xc_save -%{_libdir}/xen/bin/xenconsole -%{_libdir}/xen/bin/xenctx -%{_libdir}/xen/bin/lsevtchn %{_mandir}/man1/*.1.gz %{_mandir}/man5/*.5.gz %{_mandir}/man8/*.8.gz @@ -1330,45 +1382,20 @@ rm -f $RPM_BUILD_ROOT/%{_bindir}/xencons %{_datadir}/xen/qemu/* %{_datadir}/xen/man/man1/* %{_datadir}/xen/man/man8/* -%if %{?with_stubdom}0 -/usr/lib/xen/bin/stubdom-dm -/usr/lib/xen/bin/stubdompath.sh -%ifarch x86_64 -%{_libdir}/xen/bin/stubdom-dm -%{_libdir}/xen/bin/stubdompath.sh -%endif -%endif -%{_libdir}/xen/bin/qemu-dm -%ifarch x86_64 -/usr/lib/xen/bin/qemu-dm -# NEEDS FIXING -##/usr/lib64/xen/bin/xc_kexec -%else -# NEEDS FIXING -#/usr/lib/xen/bin/xc_kexec -%endif -/usr/lib/xen/boot/hvmloader %{_libdir}/python%{pyver}/site-packages/xen/* -/usr/lib/xen/boot/domUloader.py %{_libdir}/python%{pyver}/site-packages/grub/* %{_libdir}/python%{pyver}/site-packages/fsimage.so -%if %{?with_stubdom}0 -/usr/lib/xen/boot/ioemu-stubdom.gz -%ifarch x86_64 -/usr/lib/xen/boot/pv-grub-x86_64.gz -%else -/usr/lib/xen/boot/pv-grub-x86_32.gz -%endif -%endif %config %{_fwdefdir}/xend-relocation-server %endif + %files tools-domU %defattr(-,root,root) /usr/bin/xen-detect /bin/domu-xenstore /bin/xenstore-* + %files devel %defattr(-,root,root) %{_bindir}/serial-split @@ -1378,10 +1405,12 @@ rm -f $RPM_BUILD_ROOT/%{_bindir}/xencons %if %{?with_dom0_support}0 + %files doc-html %defattr(-,root,root) %{_defaultdocdir}/xen/html + %files doc-pdf %defattr(-,root,root) %{_defaultdocdir}/xen/pdf @@ -1389,6 +1418,7 @@ rm -f $RPM_BUILD_ROOT/%{_bindir}/xencons %if %{?with_dom0_support}0 + %post tools %if %{?with_xend}0 # with_xend @@ -1434,9 +1464,11 @@ if [ -f /usr/bin/qemu-nbd ]; then ln -s /usr/bin/qemu-nbd /usr/bin/qemu-nbd-xen fi + %preun tools %{stop_on_removal xendomains xend xencommons} + %postun tools %if %{?with_xend}0 # with_xend @@ -1451,8 +1483,12 @@ if [ -f /usr/bin/qemu-nbd-xen ]; then fi %endif + %post libs -p /sbin/ldconfig + %postun libs -p /sbin/ldconfig + + %changelog diff --git a/xenpaging.HVMCOPY_gfn_paged_out.patch b/xenpaging.HVMCOPY_gfn_paged_out.patch new file mode 100644 index 0000000..c17655e --- /dev/null +++ b/xenpaging.HVMCOPY_gfn_paged_out.patch @@ -0,0 +1,151 @@ + +xenpaging: handle HVMCOPY_gfn_paged_out in copy_from/to_user + +copy_from_user_hvm can fail when __hvm_copy returns +HVMCOPY_gfn_paged_out for a referenced gfn, for example during guests +pagetable walk. This has to be handled in some way. + +For the time being, return -EAGAIN for the most common case (xen_balloon +driver crashing in guest) until the recently added waitqueues will be +used. + +Signed-off-by: Olaf Hering + +--- + xen/arch/x86/hvm/hvm.c | 4 ++++ + xen/common/memory.c | 39 ++++++++++++++++++++++++++++++++++----- + 2 files changed, 38 insertions(+), 5 deletions(-) + +Index: xen-4.1.2-testing/xen/arch/x86/hvm/hvm.c +=================================================================== +--- xen-4.1.2-testing.orig/xen/arch/x86/hvm/hvm.c ++++ xen-4.1.2-testing/xen/arch/x86/hvm/hvm.c +@@ -2247,6 +2247,8 @@ unsigned long copy_to_user_hvm(void *to, + + rc = hvm_copy_to_guest_virt_nofault((unsigned long)to, (void *)from, + len, 0); ++ if ( unlikely(rc == HVMCOPY_gfn_paged_out) ) ++ return -EAGAIN; + return rc ? len : 0; /* fake a copy_to_user() return code */ + } + +@@ -2264,6 +2266,8 @@ unsigned long copy_from_user_hvm(void *t + #endif + + rc = hvm_copy_from_guest_virt_nofault(to, (unsigned long)from, len, 0); ++ if ( unlikely(rc == HVMCOPY_gfn_paged_out) ) ++ return -EAGAIN; + return rc ? len : 0; /* fake a copy_from_user() return code */ + } + +Index: xen-4.1.2-testing/xen/common/memory.c +=================================================================== +--- xen-4.1.2-testing.orig/xen/common/memory.c ++++ xen-4.1.2-testing/xen/common/memory.c +@@ -48,6 +48,7 @@ static void increase_reservation(struct + { + struct page_info *page; + unsigned long i; ++ unsigned long ctg_ret; + xen_pfn_t mfn; + struct domain *d = a->domain; + +@@ -81,8 +82,13 @@ static void increase_reservation(struct + if ( !guest_handle_is_null(a->extent_list) ) + { + mfn = page_to_mfn(page); +- if ( unlikely(__copy_to_guest_offset(a->extent_list, i, &mfn, 1)) ) ++ ctg_ret = __copy_to_guest_offset(a->extent_list, i, &mfn, 1); ++ if ( unlikely(ctg_ret) ) ++ { ++ if ( (long)ctg_ret == -EAGAIN ) ++ a->preempted = 1; + goto out; ++ } + } + } + +@@ -94,6 +100,7 @@ static void populate_physmap(struct memo + { + struct page_info *page; + unsigned long i, j; ++ unsigned long cftg_ret; + xen_pfn_t gpfn, mfn; + struct domain *d = a->domain; + +@@ -112,8 +119,13 @@ static void populate_physmap(struct memo + goto out; + } + +- if ( unlikely(__copy_from_guest_offset(&gpfn, a->extent_list, i, 1)) ) ++ cftg_ret = __copy_from_guest_offset(&gpfn, a->extent_list, i, 1); ++ if ( unlikely(cftg_ret) ) ++ { ++ if ( (long)cftg_ret == -EAGAIN ) ++ a->preempted = 1; + goto out; ++ } + + if ( a->memflags & MEMF_populate_on_demand ) + { +@@ -143,8 +155,13 @@ static void populate_physmap(struct memo + set_gpfn_from_mfn(mfn + j, gpfn + j); + + /* Inform the domain of the new page's machine address. */ +- if ( unlikely(__copy_to_guest_offset(a->extent_list, i, &mfn, 1)) ) ++ cftg_ret = __copy_to_guest_offset(a->extent_list, i, &mfn, 1); ++ if ( unlikely(cftg_ret) ) ++ { ++ if ( (long)cftg_ret == -EAGAIN ) ++ a->preempted = 1; + goto out; ++ } + } + } + } +@@ -213,6 +230,7 @@ int guest_remove_page(struct domain *d, + static void decrease_reservation(struct memop_args *a) + { + unsigned long i, j; ++ unsigned long cfg_ret; + xen_pfn_t gmfn; + + if ( !guest_handle_subrange_okay(a->extent_list, a->nr_done, +@@ -227,8 +245,13 @@ static void decrease_reservation(struct + goto out; + } + +- if ( unlikely(__copy_from_guest_offset(&gmfn, a->extent_list, i, 1)) ) ++ cfg_ret = __copy_from_guest_offset(&gmfn, a->extent_list, i, 1); ++ if ( unlikely(cfg_ret) ) ++ { ++ if ( (long)cfg_ret == -EAGAIN ) ++ a->preempted = 1; + goto out; ++ } + + if ( tb_init_done ) + { +@@ -509,6 +532,7 @@ long do_memory_op(unsigned long cmd, XEN + int rc, op; + unsigned int address_bits; + unsigned long start_extent; ++ unsigned long cfg_ret; + struct xen_memory_reservation reservation; + struct memop_args args; + domid_t domid; +@@ -522,8 +546,13 @@ long do_memory_op(unsigned long cmd, XEN + case XENMEM_populate_physmap: + start_extent = cmd >> MEMOP_EXTENT_SHIFT; + +- if ( copy_from_guest(&reservation, arg, 1) ) ++ cfg_ret = copy_from_guest(&reservation, arg, 1); ++ if ( unlikely(cfg_ret) ) ++ { ++ if ( (long)cfg_ret == -EAGAIN ) ++ return hypercall_create_continuation(__HYPERVISOR_memory_op, "lh", cmd, arg); + return start_extent; ++ } + + /* Is size too large for us to encode a continuation? */ + if ( reservation.nr_extents > (ULONG_MAX >> MEMOP_EXTENT_SHIFT) ) diff --git a/xenpaging.XEN_PAGING_DIR.patch b/xenpaging.XEN_PAGING_DIR.patch new file mode 100644 index 0000000..b2d9598 --- /dev/null +++ b/xenpaging.XEN_PAGING_DIR.patch @@ -0,0 +1,51 @@ +xenpaging: add XEN_PAGING_DIR / libxl_xenpaging_dir_path() + +Signed-off-by: Olaf Hering + +--- + Config.mk | 1 + + config/StdGNU.mk | 2 ++ + tools/xenpaging/Makefile | 2 +- + 3 files changed, 4 insertions(+), 1 deletion(-) + +Index: xen-4.1.2-testing/Config.mk +=================================================================== +--- xen-4.1.2-testing.orig/Config.mk ++++ xen-4.1.2-testing/Config.mk +@@ -124,6 +124,7 @@ define buildmakevars2file-closure + echo "XEN_CONFIG_DIR=\"$(XEN_CONFIG_DIR)\"" >> $(1).tmp; \ + echo "XEN_SCRIPT_DIR=\"$(XEN_SCRIPT_DIR)\"" >> $(1).tmp; \ + echo "XEN_LOCK_DIR=\"$(XEN_LOCK_DIR)\"" >> $(1).tmp; \ ++ echo "XEN_PAGING_DIR=\"$(XEN_PAGING_DIR)\"" >> $(1).tmp; \ + if ! cmp $(1).tmp $(1); then mv -f $(1).tmp $(1); fi + endef + +Index: xen-4.1.2-testing/config/StdGNU.mk +=================================================================== +--- xen-4.1.2-testing.orig/config/StdGNU.mk ++++ xen-4.1.2-testing/config/StdGNU.mk +@@ -46,9 +46,11 @@ PRIVATE_BINDIR = $(PRIVATE_PREFIX)/bin + ifeq ($(PREFIX),/usr) + CONFIG_DIR = /etc + XEN_LOCK_DIR = /var/lock ++XEN_PAGING_DIR = /var/lib/xen/xenpaging + else + CONFIG_DIR = $(PREFIX)/etc + XEN_LOCK_DIR = $(PREFIX)/var/lock ++XEN_PAGING_DIR = $(PREFIX)/var/lib/xen/xenpaging + endif + + SYSCONFIG_DIR = $(CONFIG_DIR)/$(CONFIG_LEAF_DIR) +Index: xen-4.1.2-testing/tools/xenpaging/Makefile +=================================================================== +--- xen-4.1.2-testing.orig/tools/xenpaging/Makefile ++++ xen-4.1.2-testing/tools/xenpaging/Makefile +@@ -28,7 +28,7 @@ xenpaging: $(OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) + + install: all +- $(INSTALL_DIR) $(DESTDIR)/var/lib/xen/xenpaging ++ $(INSTALL_DIR) $(DESTDIR)$(XEN_PAGING_DIR) + $(INSTALL_DIR) $(DESTDIR)$(LIBEXEC) + $(INSTALL_PROG) $(IBINS) $(DESTDIR)$(LIBEXEC) + diff --git a/xenpaging.add_evict_pages.patch b/xenpaging.add_evict_pages.patch new file mode 100644 index 0000000..38914ac --- /dev/null +++ b/xenpaging.add_evict_pages.patch @@ -0,0 +1,165 @@ +xenpaging: move page add/resume loops into its own function. + +Move page resume loop into its own function. +Move page eviction loop into its own function. +Allocate all possible slots in a paging file to allow growing and +shrinking of the number of paged-out pages. Adjust other places to +iterate over all slots. + +This change is required by subsequent patches. + +v2: + - check if victims allocation succeeded + +Signed-off-by: Olaf Hering + +--- + tools/xenpaging/xenpaging.c | 94 ++++++++++++++++++++++++++++---------------- + 1 file changed, 61 insertions(+), 33 deletions(-) + +Index: xen-4.1.2-testing/tools/xenpaging/xenpaging.c +=================================================================== +--- xen-4.1.2-testing.orig/tools/xenpaging/xenpaging.c ++++ xen-4.1.2-testing/tools/xenpaging/xenpaging.c +@@ -553,6 +553,27 @@ static int xenpaging_populate_page(xenpa + return ret; + } + ++/* Trigger a page-in for a batch of pages */ ++static void resume_pages(xenpaging_t *paging, int num_pages) ++{ ++ xc_interface *xch = paging->xc_handle; ++ int i, num = 0; ++ ++ for ( i = 0; i < paging->max_pages && num < num_pages; i++ ) ++ { ++ if ( test_bit(i, paging->bitmap) ) ++ { ++ paging->pagein_queue[num] = i; ++ num++; ++ if ( num == XENPAGING_PAGEIN_QUEUE_SIZE ) ++ break; ++ } ++ } ++ /* num may be less than num_pages, caller has to try again */ ++ if ( num ) ++ page_in_trigger(); ++} ++ + static int evict_victim(xenpaging_t *paging, + xenpaging_victim_t *victim, int fd, int i) + { +@@ -596,6 +617,30 @@ static int evict_victim(xenpaging_t *pag + return ret; + } + ++/* Evict a batch of pages and write them to a free slot in the paging file */ ++static int evict_pages(xenpaging_t *paging, int fd, xenpaging_victim_t *victims, int num_pages) ++{ ++ xc_interface *xch = paging->xc_handle; ++ int rc, slot, num = 0; ++ ++ for ( slot = 0; slot < paging->max_pages && num < num_pages; slot++ ) ++ { ++ /* Slot is allocated */ ++ if ( victims[slot].gfn != INVALID_MFN ) ++ continue; ++ ++ rc = evict_victim(paging, &victims[slot], fd, slot); ++ if ( rc == -ENOSPC ) ++ break; ++ if ( rc == -EINTR ) ++ break; ++ if ( num && num % 100 == 0 ) ++ DPRINTF("%d pages evicted\n", num); ++ num++; ++ } ++ return num; ++} ++ + int main(int argc, char *argv[]) + { + struct sigaction act; +@@ -638,7 +683,14 @@ int main(int argc, char *argv[]) + return 2; + } + +- victims = calloc(paging->num_pages, sizeof(xenpaging_victim_t)); ++ /* Allocate upper limit of pages to allow growing and shrinking */ ++ victims = calloc(paging->max_pages, sizeof(xenpaging_victim_t)); ++ if ( !victims ) ++ goto out; ++ ++ /* Mark all slots as unallocated */ ++ for ( i = 0; i < paging->max_pages; i++ ) ++ victims[i].gfn = INVALID_MFN; + + /* ensure that if we get a signal, we'll do cleanup, then exit */ + act.sa_handler = close_handler; +@@ -652,18 +704,7 @@ int main(int argc, char *argv[]) + /* listen for page-in events to stop pager */ + create_page_in_thread(paging); + +- /* Evict pages */ +- for ( i = 0; i < paging->num_pages; i++ ) +- { +- rc = evict_victim(paging, &victims[i], fd, i); +- if ( rc == -ENOSPC ) +- break; +- if ( rc == -EINTR ) +- break; +- if ( i % 100 == 0 ) +- DPRINTF("%d pages evicted\n", i); +- } +- ++ i = evict_pages(paging, fd, victims, paging->num_pages); + DPRINTF("%d pages evicted. Done.\n", i); + + /* Swap pages in and out */ +@@ -689,13 +730,13 @@ int main(int argc, char *argv[]) + if ( test_and_clear_bit(req.gfn, paging->bitmap) ) + { + /* Find where in the paging file to read from */ +- for ( i = 0; i < paging->num_pages; i++ ) ++ for ( i = 0; i < paging->max_pages; i++ ) + { + if ( victims[i].gfn == req.gfn ) + break; + } + +- if ( i >= paging->num_pages ) ++ if ( i >= paging->max_pages ) + { + DPRINTF("Couldn't find page %"PRIx64"\n", req.gfn); + goto out; +@@ -767,25 +808,12 @@ int main(int argc, char *argv[]) + /* Write all pages back into the guest */ + if ( interrupted == SIGTERM || interrupted == SIGINT ) + { +- int num = 0; +- for ( i = 0; i < paging->max_pages; i++ ) +- { +- if ( test_bit(i, paging->bitmap) ) +- { +- paging->pagein_queue[num] = i; +- num++; +- if ( num == XENPAGING_PAGEIN_QUEUE_SIZE ) +- break; +- } +- } +- /* +- * One more round if there are still pages to process. +- * If no more pages to process, exit loop. +- */ +- if ( num ) +- page_in_trigger(); +- else if ( i == paging->max_pages ) ++ /* If no more pages to process, exit loop. */ ++ if ( !paging->num_paged_out ) + break; ++ ++ /* One more round if there are still pages to process. */ ++ resume_pages(paging, paging->num_paged_out); + } + else + { diff --git a/xenpaging.autostart.patch b/xenpaging.autostart.patch index 096634e..e516ef1 100644 --- a/xenpaging.autostart.patch +++ b/xenpaging.autostart.patch @@ -1,4 +1,7 @@ -xenpaging: start xenpaging via config option +# HG changeset patch +# Parent 659ee31faec91ac543578db7c9b2849fb7367419 + +xenpaging: xend: start xenpaging via config option Start xenpaging via config option. @@ -8,10 +11,14 @@ TODO: parse config values like 42K, 42M, 42G, 42% Signed-off-by: Olaf Hering --- +v5: + use actmem=, xenpaging_file=, xenpaging_extra= + add xm mem-swap-target + v4: add config option for pagefile directory add config option to enable debug - add config option to set polic mru_size + add config option to set policy mru_size fail if chdir fails force self.xenpaging* variables to be strings because a xm new may turn some of them into type int and later os.execve fails with a TypeError @@ -26,35 +33,34 @@ v2: allows hardlinking for further inspection --- - tools/examples/xmexample.hvm | 12 ++++ - tools/python/README.XendConfig | 4 + - tools/python/README.sxpcfg | 4 + - tools/python/xen/xend/XendConfig.py | 12 ++++ - tools/python/xen/xend/XendDomainInfo.py | 12 ++++ - tools/python/xen/xend/image.py | 87 ++++++++++++++++++++++++++++++++ - tools/python/xen/xm/create.py | 20 +++++++ - tools/python/xen/xm/xenapi_create.py | 4 + - 8 files changed, 155 insertions(+) + tools/examples/xmexample.hvm | 9 +++ + tools/python/README.XendConfig | 3 + + tools/python/README.sxpcfg | 3 + + tools/python/xen/xend/XendConfig.py | 9 +++ + tools/python/xen/xend/XendDomain.py | 15 +++++ + tools/python/xen/xend/XendDomainInfo.py | 22 ++++++++ + tools/python/xen/xend/image.py | 85 ++++++++++++++++++++++++++++++++ + tools/python/xen/xm/create.py | 15 +++++ + tools/python/xen/xm/main.py | 14 +++++ + tools/python/xen/xm/xenapi_create.py | 3 + + 10 files changed, 178 insertions(+) Index: xen-4.1.2-testing/tools/examples/xmexample.hvm =================================================================== --- xen-4.1.2-testing.orig/tools/examples/xmexample.hvm +++ xen-4.1.2-testing/tools/examples/xmexample.hvm -@@ -127,6 +127,18 @@ disk = [ 'file:/var/lib/xen/images/disk. +@@ -127,6 +127,15 @@ disk = [ 'file:/var/lib/xen/images/disk. # Device Model to be used device_model = 'qemu-dm' -+# number of guest pages to page-out, or -1 for entire guest memory range -+xenpaging=42 ++# the amount of memory in MiB for the guest ++#actmem=42 + -+# directory to store guest page file -+#xenpaging_workdir="/var/lib/xen/xenpaging" ++# Optional: guest page file ++#xenpaging_file="/var/lib/xen/xenpaging/..paging" + -+# enable debug output in pager -+#xenpaging_debug=0 -+ -+# number of paged-in pages to keep in memory -+#xenpaging_policy_mru_size=1024 ++# Optional: extra cmdline options for xenpaging ++#xenpaging_extra=[ 'string', 'string' ] + #----------------------------------------------------------------------------- # boot on floppy (a), hard disk (c), Network (n) or CD-ROM (d) @@ -63,14 +69,13 @@ Index: xen-4.1.2-testing/tools/python/README.XendConfig =================================================================== --- xen-4.1.2-testing.orig/tools/python/README.XendConfig +++ xen-4.1.2-testing/tools/python/README.XendConfig -@@ -120,6 +120,10 @@ otherConfig +@@ -120,6 +120,9 @@ otherConfig image.vncdisplay image.vncunused image.hvm.device_model -+ image.hvm.xenpaging -+ image.hvm.xenpaging_workdir -+ image.hvm.xenpaging_debug -+ image.hvm.xenpaging_policy_mru_size ++ image.hvm.actmem ++ image.hvm.xenpaging_file ++ image.hvm.xenpaging_extra image.hvm.display image.hvm.xauthority image.hvm.vncconsole @@ -78,14 +83,13 @@ Index: xen-4.1.2-testing/tools/python/README.sxpcfg =================================================================== --- xen-4.1.2-testing.orig/tools/python/README.sxpcfg +++ xen-4.1.2-testing/tools/python/README.sxpcfg -@@ -51,6 +51,10 @@ image +@@ -51,6 +51,9 @@ image - vncunused (HVM) - device_model -+ - xenpaging -+ - xenpaging_workdir -+ - xenpaging_debug -+ - xenpaging_policy_mru_size ++ - actmem ++ - xenpaging_file ++ - xenpaging_extra - display - xauthority - vncconsole @@ -93,37 +97,77 @@ Index: xen-4.1.2-testing/tools/python/xen/xend/XendConfig.py =================================================================== --- xen-4.1.2-testing.orig/tools/python/xen/xend/XendConfig.py +++ xen-4.1.2-testing/tools/python/xen/xend/XendConfig.py -@@ -147,6 +147,10 @@ XENAPI_PLATFORM_CFG_TYPES = { +@@ -147,6 +147,9 @@ XENAPI_PLATFORM_CFG_TYPES = { 'apic': int, 'boot': str, 'device_model': str, -+ 'xenpaging': str, -+ 'xenpaging_workdir': str, -+ 'xenpaging_debug': str, -+ 'xenpaging_policy_mru_size': str, ++ 'actmem': str, ++ 'xenpaging_file': str, ++ 'xenpaging_extra': str, 'loader': str, 'display' : str, 'fda': str, -@@ -516,6 +520,14 @@ class XendConfig(dict): +@@ -516,6 +519,12 @@ class XendConfig(dict): self['platform']['nomigrate'] = 0 if self.is_hvm(): -+ if 'xenpaging' not in self['platform']: -+ self['platform']['xenpaging'] = "0" -+ if 'xenpaging_workdir' not in self['platform']: -+ self['platform']['xenpaging_workdir'] = "/var/lib/xen/xenpaging" -+ if 'xenpaging_debug' not in self['platform']: -+ self['platform']['xenpaging_debug'] = "0" -+ if 'xenpaging_policy_mru_size' not in self['platform']: -+ self['platform']['xenpaging_policy_mru_size'] = "0" ++ if 'actmem' not in self['platform']: ++ self['platform']['actmem'] = "0" ++ if 'xenpaging_file' not in self['platform']: ++ self['platform']['xenpaging_file'] = "" ++ if 'xenpaging_extra' not in self['platform']: ++ self['platform']['xenpaging_extra'] = [] if 'timer_mode' not in self['platform']: self['platform']['timer_mode'] = 1 if 'extid' in self['platform'] and int(self['platform']['extid']) == 1: +Index: xen-4.1.2-testing/tools/python/xen/xend/XendDomain.py +=================================================================== +--- xen-4.1.2-testing.orig/tools/python/xen/xend/XendDomain.py ++++ xen-4.1.2-testing/tools/python/xen/xend/XendDomain.py +@@ -2022,6 +2022,21 @@ class XendDomain: + log.exception(ex) + raise XendError(str(ex)) + ++ def domain_swaptarget_set(self, domid, mem): ++ """Set the memory limit for a domain. ++ ++ @param domid: Domain ID or Name ++ @type domid: int or string. ++ @param mem: memory limit (in MiB) ++ @type mem: int ++ @raise XendError: fail to set memory ++ @rtype: 0 ++ """ ++ dominfo = self.domain_lookup_nr(domid) ++ if not dominfo: ++ raise XendInvalidDomain(str(domid)) ++ dominfo.setSwapTarget(mem) ++ + def domain_maxmem_set(self, domid, mem): + """Set the memory limit for a domain. + Index: xen-4.1.2-testing/tools/python/xen/xend/XendDomainInfo.py =================================================================== --- xen-4.1.2-testing.orig/tools/python/xen/xend/XendDomainInfo.py +++ xen-4.1.2-testing/tools/python/xen/xend/XendDomainInfo.py -@@ -2291,6 +2291,8 @@ class XendDomainInfo: +@@ -1503,6 +1503,16 @@ class XendDomainInfo: + break + xen.xend.XendDomain.instance().managed_config_save(self) + ++ def setSwapTarget(self, target): ++ """Set the swap target of this domain. ++ @param target: In MiB. ++ """ ++ log.debug("Setting swap target of domain %s (%s) to %d MiB.", ++ self.info['name_label'], str(self.domid), target) ++ ++ if self.domid > 0: ++ self.storeDom("memory/target-tot_pages", target * 1024) ++ + def setMemoryTarget(self, target): + """Set the memory target of this domain. + @param target: In MiB. +@@ -2291,6 +2301,8 @@ class XendDomainInfo: self.info['name_label'], self.domid, self.info['uuid'], new_name, new_uuid) self._unwatchVm() @@ -132,7 +176,7 @@ Index: xen-4.1.2-testing/tools/python/xen/xend/XendDomainInfo.py self._releaseDevices() # Remove existing vm node in xenstore self._removeVm() -@@ -2965,6 +2967,9 @@ class XendDomainInfo: +@@ -2965,6 +2977,9 @@ class XendDomainInfo: self._createDevices() @@ -142,7 +186,7 @@ Index: xen-4.1.2-testing/tools/python/xen/xend/XendDomainInfo.py self.image.cleanupTmpImages() self.info['start_time'] = time.time() -@@ -2989,6 +2994,8 @@ class XendDomainInfo: +@@ -2989,6 +3004,8 @@ class XendDomainInfo: self.refresh_shutdown_lock.acquire() try: self.unwatchShutdown() @@ -151,7 +195,7 @@ Index: xen-4.1.2-testing/tools/python/xen/xend/XendDomainInfo.py self._releaseDevices() bootloader_tidy(self) -@@ -3073,6 +3080,7 @@ class XendDomainInfo: +@@ -3073,6 +3090,7 @@ class XendDomainInfo: self.image = image.create(self, self.info) if self.image: self._createDevices(True) @@ -159,7 +203,7 @@ Index: xen-4.1.2-testing/tools/python/xen/xend/XendDomainInfo.py self.console_port = console_port self._storeDomDetails() self._registerWatches() -@@ -3214,6 +3222,8 @@ class XendDomainInfo: +@@ -3214,6 +3232,8 @@ class XendDomainInfo: # could also fetch a parsed note from xenstore fast = self.info.get_notes().get('SUSPEND_CANCEL') and 1 or 0 if not fast: @@ -168,7 +212,7 @@ Index: xen-4.1.2-testing/tools/python/xen/xend/XendDomainInfo.py self._releaseDevices() self.testDeviceComplete() self.testvifsComplete() -@@ -3229,6 +3239,8 @@ class XendDomainInfo: +@@ -3229,6 +3249,8 @@ class XendDomainInfo: self._storeDomDetails() self._createDevices() @@ -181,38 +225,34 @@ Index: xen-4.1.2-testing/tools/python/xen/xend/image.py =================================================================== --- xen-4.1.2-testing.orig/tools/python/xen/xend/image.py +++ xen-4.1.2-testing/tools/python/xen/xend/image.py -@@ -122,6 +122,11 @@ class ImageHandler: +@@ -122,6 +122,10 @@ class ImageHandler: self.vm.permissionsVm("image/cmdline", { 'dom': self.vm.getDomid(), 'read': True } ) self.device_model = vmConfig['platform'].get('device_model') -+ self.xenpaging = str(vmConfig['platform'].get('xenpaging')) -+ self.xenpaging_workdir = str(vmConfig['platform'].get('xenpaging_workdir')) -+ self.xenpaging_debug = str(vmConfig['platform'].get('xenpaging_debug')) -+ self.xenpaging_policy_mru_size = str(vmConfig['platform'].get('xenpaging_policy_mru_size')) ++ self.actmem = str(vmConfig['platform'].get('actmem')) ++ self.xenpaging_file = str(vmConfig['platform'].get('xenpaging_file')) ++ self.xenpaging_extra = vmConfig['platform'].get('xenpaging_extra') + self.xenpaging_pid = None self.display = vmConfig['platform'].get('display') self.xauthority = vmConfig['platform'].get('xauthority') -@@ -392,6 +397,88 @@ class ImageHandler: +@@ -392,6 +396,87 @@ class ImageHandler: sentinel_fifos_inuse[sentinel_path_fifo] = 1 self.sentinel_path_fifo = sentinel_path_fifo + def createXenPaging(self): + if not self.vm.info.is_hvm(): + return -+ if self.xenpaging == "0": ++ if self.actmem == "0": + return + if self.xenpaging_pid: + return + xenpaging_bin = auxbin.pathTo("xenpaging") + args = [xenpaging_bin] -+ args = args + ([ "%d" % self.vm.getDomid()]) -+ args = args + ([ "%s" % self.xenpaging]) -+ env = dict(os.environ) -+ if not self.xenpaging_debug == "0": -+ env['XENPAGING_DEBUG'] = self.xenpaging_debug -+ if not self.xenpaging_policy_mru_size == "0": -+ env['XENPAGING_POLICY_MRU_SIZE'] = self.xenpaging_policy_mru_size ++ args = args + ([ "-f", "/var/lib/xen/xenpaging/%s.%d.paging" % (str(self.vm.info['name_label']), self.vm.getDomid())]) ++ if self.xenpaging_extra: ++ args = args + (self.xenpaging_extra) ++ args = args + ([ "-d", "%d" % self.vm.getDomid()]) + self.xenpaging_logfile = "/var/log/xen/xenpaging-%s.log" % str(self.vm.info['name_label']) + logfile_mode = os.O_WRONLY|os.O_CREAT|os.O_APPEND|os.O_TRUNC + null = os.open("/dev/null", os.O_RDONLY) @@ -230,24 +270,26 @@ Index: xen-4.1.2-testing/tools/python/xen/xend/image.py + os.dup2(null, 0) + os.dup2(logfd, 1) + os.dup2(logfd, 2) -+ os.chdir(self.xenpaging_workdir) + try: ++ env = dict(os.environ) + log.info("starting %s" % args) + os.execve(xenpaging_bin, args, env) + except Exception, e: + log.warn('failed to execute xenpaging: %s' % utils.exception_string(e)) + os._exit(126) + except: -+ log.warn("starting xenpaging in %s failed" % self.xenpaging_workdir) ++ log.warn("starting xenpaging failed") + os._exit(127) + else: + osdep.postfork(contract, abandon=True) + self.xenpaging_pid = xenpaging_pid + os.close(null) + os.close(logfd) ++ self.vm.storeDom("xenpaging/xenpaging-pid", self.xenpaging_pid) ++ self.vm.storeDom("memory/target-tot_pages", int(self.actmem) * 1024) + + def destroyXenPaging(self): -+ if self.xenpaging == "0": ++ if self.actmem == "0": + return + if self.xenpaging_pid: + try: @@ -286,52 +328,85 @@ Index: xen-4.1.2-testing/tools/python/xen/xm/create.py =================================================================== --- xen-4.1.2-testing.orig/tools/python/xen/xm/create.py +++ xen-4.1.2-testing/tools/python/xen/xm/create.py -@@ -495,6 +495,22 @@ gopts.var('nfs_root', val="PATH", +@@ -495,6 +495,18 @@ gopts.var('nfs_root', val="PATH", fn=set_value, default=None, use="Set the path of the root NFS directory.") -+gopts.var('xenpaging', val='NUM', ++gopts.var('actmem', val='NUM', + fn=set_value, default='0', + use="Number of pages to swap.") + -+gopts.var('xenpaging_workdir', val='PATH', -+ fn=set_value, default='/var/lib/xen/xenpaging', -+ use="Number of pages to swap.") ++gopts.var('xenpaging_file', val='PATH', ++ fn=set_value, default=None, ++ use="pagefile to use (optional)") + -+gopts.var('xenpaging_debug', val='NUM', -+ fn=set_value, default='0', -+ use="Number of pages to swap.") -+ -+gopts.var('xenpaging_policy_mru_size', val='NUM', -+ fn=set_value, default='0', -+ use="Number of pages to swap.") ++gopts.var('xenpaging_extra', val='string1,string2', ++ fn=append_value, default=[], ++ use="additional args for xenpaging (optional)") + gopts.var('device_model', val='FILE', fn=set_value, default=None, use="Path to device model program.") -@@ -1095,6 +1111,10 @@ def configure_hvm(config_image, vals): +@@ -1095,6 +1107,9 @@ def configure_hvm(config_image, vals): args = [ 'acpi', 'apic', 'boot', 'cpuid', 'cpuid_check', -+ 'xenpaging', -+ 'xenpaging_workdir', -+ 'xenpaging_debug', -+ 'xenpaging_policy_mru_size', ++ 'actmem', ++ 'xenpaging_file', ++ 'xenpaging_extra', 'device_model', 'display', 'fda', 'fdb', 'gfx_passthru', 'guest_os_type', +Index: xen-4.1.2-testing/tools/python/xen/xm/main.py +=================================================================== +--- xen-4.1.2-testing.orig/tools/python/xen/xm/main.py ++++ xen-4.1.2-testing/tools/python/xen/xm/main.py +@@ -115,6 +115,8 @@ SUBCOMMAND_HELP = { + 'Set the maximum amount reservation for a domain.'), + 'mem-set' : (' ', + 'Set the current memory usage for a domain.'), ++ 'mem-swap-target' : (' ', ++ 'Set the memory usage for a domain.'), + 'migrate' : (' ', + 'Migrate a domain to another machine.'), + 'pause' : ('', 'Pause execution of a domain.'), +@@ -1667,6 +1669,17 @@ def xm_mem_set(args): + mem_target = int_unit(args[1], 'm') + server.xend.domain.setMemoryTarget(dom, mem_target) + ++def xm_mem_swap_target(args): ++ arg_check(args, "mem-swap-target", 2) ++ ++ dom = args[0] ++ ++ if serverType == SERVER_XEN_API: ++ err("xenapi not supported") ++ else: ++ swap_target = int_unit(args[1], 'm') ++ server.xend.domain.swaptarget_set(dom, swap_target) ++ + def xm_usb_add(args): + arg_check(args, "usb-add", 2) + server.xend.domain.usb_add(args[0],args[1]) +@@ -3926,6 +3939,7 @@ commands = { + # memory commands + "mem-max": xm_mem_max, + "mem-set": xm_mem_set, ++ "mem-swap-target": xm_mem_swap_target, + # cpu commands + "vcpu-pin": xm_vcpu_pin, + "vcpu-list": xm_vcpu_list, Index: xen-4.1.2-testing/tools/python/xen/xm/xenapi_create.py =================================================================== --- xen-4.1.2-testing.orig/tools/python/xen/xm/xenapi_create.py +++ xen-4.1.2-testing/tools/python/xen/xm/xenapi_create.py -@@ -1085,6 +1085,10 @@ class sxp2xml: +@@ -1085,6 +1085,9 @@ class sxp2xml: 'acpi', 'apic', 'boot', -+ 'xenpaging', -+ 'xenpaging_workdir', -+ 'xenpaging_debug', -+ 'xenpaging_policy_mru_size', ++ 'actmem', ++ 'xenpaging_file', ++ 'xenpaging_extra', 'device_model', 'loader', 'fda', diff --git a/xenpaging.bitmap_clear.patch b/xenpaging.bitmap_clear.patch new file mode 100644 index 0000000..01fb7b1 --- /dev/null +++ b/xenpaging.bitmap_clear.patch @@ -0,0 +1,34 @@ +# HG changeset patch +# Parent 2ac53905d95e6d02f53c99f6e2fa38f7306b8800 +libxc: add bitmap_clear function + +Signed-off-by: Olaf Hering + +--- + tools/libxc/xc_bitops.h | 6 ++++++ + 1 file changed, 6 insertions(+) + +Index: xen-4.1.2-testing/tools/libxc/xc_bitops.h +=================================================================== +--- xen-4.1.2-testing.orig/tools/libxc/xc_bitops.h ++++ xen-4.1.2-testing/tools/libxc/xc_bitops.h +@@ -4,6 +4,7 @@ + /* bitmap operations for single threaded access */ + + #include ++#include + + #define BITS_PER_LONG (sizeof(unsigned long) * 8) + #define ORDER_LONG (sizeof(unsigned long) == 4 ? 5 : 6) +@@ -25,6 +26,11 @@ static inline unsigned long *bitmap_allo + return calloc(1, bitmap_size(nr_bits)); + } + ++static inline void bitmap_clear(unsigned long *addr, int nr_bits) ++{ ++ memset(addr, 0, bitmap_size(nr_bits)); ++} ++ + static inline int test_bit(int nr, volatile unsigned long *addr) + { + return (BITMAP_ENTRY(nr, addr) >> BITMAP_SHIFT(nr)) & 1; diff --git a/xenpaging.cmdline-interface.patch b/xenpaging.cmdline-interface.patch new file mode 100644 index 0000000..8a965e9 --- /dev/null +++ b/xenpaging.cmdline-interface.patch @@ -0,0 +1,268 @@ +# HG changeset patch +# Parent 434f0b4da9148b101e184e0108be6c31f67038f4 +xenpaging: add cmdline interface for pager + +Introduce a cmdline handling for the pager. This simplifies libxl support, +debug and mru_size are not passed via the environment anymore. +The new interface looks like this: + +xenpaging [options] -f -d +options: + -d --domain= numerical domain_id of guest. This option is required. + -f --pagefile= pagefile to use. This option is required. + -m --max_memkb= maximum amount of memory to handle. + -r --mru_size= number of paged-in pages to keep in memory. + -d --debug enable debug output. + -h --help this output. + + +Signed-off-by: Olaf Hering + +--- + tools/xenpaging/xenpaging.c | 139 ++++++++++++++++++++++++++++++++------------ + tools/xenpaging/xenpaging.h | 1 + 2 files changed, 103 insertions(+), 37 deletions(-) + +Index: xen-4.1.2-testing/tools/xenpaging/xenpaging.c +=================================================================== +--- xen-4.1.2-testing.orig/tools/xenpaging/xenpaging.c ++++ xen-4.1.2-testing/tools/xenpaging/xenpaging.c +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + + #include "xc_bitops.h" + #include "file_ops.h" +@@ -42,12 +43,12 @@ + static char *watch_target_tot_pages; + static char *dom_path; + static char watch_token[16]; +-static char filename[80]; ++static char *filename; + static int interrupted; + + static void unlink_pagefile(void) + { +- if ( filename[0] ) ++ if ( filename && filename[0] ) + { + unlink(filename); + filename[0] = '\0'; +@@ -201,11 +202,85 @@ static void *init_page(void) + return NULL; + } + +-static xenpaging_t *xenpaging_init(domid_t domain_id, int target_tot_pages) ++static void usage(void) ++{ ++ printf("usage:\n\n"); ++ ++ printf(" xenpaging [options] -f -d \n\n"); ++ ++ printf("options:\n"); ++ printf(" -d --domain= numerical domain_id of guest. This option is required.\n"); ++ printf(" -f --pagefile= pagefile to use. This option is required.\n"); ++ printf(" -m --max_memkb= maximum amount of memory to handle.\n"); ++ printf(" -r --mru_size= number of paged-in pages to keep in memory.\n"); ++ printf(" -v --verbose enable debug output.\n"); ++ printf(" -h --help this output.\n"); ++} ++ ++static int xenpaging_getopts(xenpaging_t *paging, int argc, char *argv[]) ++{ ++ int ch; ++ static const char sopts[] = "hvd:f:m:r:"; ++ static const struct option lopts[] = { ++ {"help", 0, NULL, 'h'}, ++ {"verbose", 0, NULL, 'v'}, ++ {"domain", 1, NULL, 'd'}, ++ {"pagefile", 1, NULL, 'f'}, ++ {"mru_size", 1, NULL, 'm'}, ++ { } ++ }; ++ ++ while ((ch = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) ++ { ++ switch(ch) { ++ case 'd': ++ paging->mem_event.domain_id = atoi(optarg); ++ break; ++ case 'f': ++ filename = strdup(optarg); ++ break; ++ case 'm': ++ /* KiB to pages */ ++ paging->max_pages = atoi(optarg) >> 2; ++ break; ++ case 'r': ++ paging->policy_mru_size = atoi(optarg); ++ break; ++ case 'v': ++ paging->debug = 1; ++ break; ++ case 'h': ++ case '?': ++ usage(); ++ return 1; ++ } ++ } ++ ++ argv += optind; argc -= optind; ++ ++ /* Path to pagefile is required */ ++ if ( !filename ) ++ { ++ printf("Filename for pagefile missing!\n"); ++ usage(); ++ return 1; ++ } ++ ++ /* Set domain id */ ++ if ( !paging->mem_event.domain_id ) ++ { ++ printf("Numerical missing!\n"); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static xenpaging_t *xenpaging_init(int argc, char *argv[]) + { + xenpaging_t *paging; + xc_domaininfo_t domain_info; +- xc_interface *xch; ++ xc_interface *xch = NULL; + xentoollog_logger *dbg = NULL; + char *p; + int rc; +@@ -215,7 +290,12 @@ static xenpaging_t *xenpaging_init(domid + if ( !paging ) + goto err; + +- if ( getenv("XENPAGING_DEBUG") ) ++ /* Get cmdline options and domain_id */ ++ if ( xenpaging_getopts(paging, argc, argv) ) ++ goto err; ++ ++ /* Enable debug output */ ++ if ( paging->debug ) + dbg = (xentoollog_logger *)xtl_createlogger_stdiostream(stderr, XTL_DEBUG, 0); + + /* Open connection to xen */ +@@ -234,7 +314,7 @@ static xenpaging_t *xenpaging_init(domid + } + + /* write domain ID to watch so we can ignore other domain shutdowns */ +- snprintf(watch_token, sizeof(watch_token), "%u", domain_id); ++ snprintf(watch_token, sizeof(watch_token), "%u", paging->mem_event.domain_id); + if ( xs_watch(paging->xs_handle, "@releaseDomain", watch_token) == false ) + { + PERROR("Could not bind to shutdown watch\n"); +@@ -242,7 +322,7 @@ static xenpaging_t *xenpaging_init(domid + } + + /* Watch xenpagings working target */ +- dom_path = xs_get_domain_path(paging->xs_handle, domain_id); ++ dom_path = xs_get_domain_path(paging->xs_handle, paging->mem_event.domain_id); + if ( !dom_path ) + { + PERROR("Could not find domain path\n"); +@@ -260,16 +340,6 @@ static xenpaging_t *xenpaging_init(domid + goto err; + } + +- p = getenv("XENPAGING_POLICY_MRU_SIZE"); +- if ( p && *p ) +- { +- paging->policy_mru_size = atoi(p); +- DPRINTF("Setting policy mru_size to %d\n", paging->policy_mru_size); +- } +- +- /* Set domain id */ +- paging->mem_event.domain_id = domain_id; +- + /* Initialise shared page */ + paging->mem_event.shared_page = init_page(); + if ( paging->mem_event.shared_page == NULL ) +@@ -335,16 +405,20 @@ static xenpaging_t *xenpaging_init(domid + + paging->mem_event.port = rc; + +- rc = xc_domain_getinfolist(xch, paging->mem_event.domain_id, 1, +- &domain_info); +- if ( rc != 1 ) ++ /* Get max_pages from guest if not provided via cmdline */ ++ if ( !paging->max_pages ) + { +- PERROR("Error getting domain info"); +- goto err; +- } ++ rc = xc_domain_getinfolist(xch, paging->mem_event.domain_id, 1, ++ &domain_info); ++ if ( rc != 1 ) ++ { ++ PERROR("Error getting domain info"); ++ goto err; ++ } + +- /* Record number of max_pages */ +- paging->max_pages = domain_info.max_pages; ++ /* Record number of max_pages */ ++ paging->max_pages = domain_info.max_pages; ++ } + + /* Allocate bitmap for tracking pages that have been paged out */ + paging->bitmap = bitmap_alloc(paging->max_pages); +@@ -355,8 +429,6 @@ static xenpaging_t *xenpaging_init(domid + } + DPRINTF("max_pages = %d\n", paging->max_pages); + +- paging->target_tot_pages = target_tot_pages; +- + /* Initialise policy */ + rc = policy_init(paging); + if ( rc != 0 ) +@@ -718,25 +790,18 @@ int main(int argc, char *argv[]) + mode_t open_mode = S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH; + int fd; + +- if ( argc != 3 ) +- { +- fprintf(stderr, "Usage: %s \n", argv[0]); +- return -1; +- } +- + /* Initialise domain paging */ +- paging = xenpaging_init(atoi(argv[1]), atoi(argv[2])); ++ paging = xenpaging_init(argc, argv); + if ( paging == NULL ) + { +- fprintf(stderr, "Error initialising paging"); ++ fprintf(stderr, "Error initialising paging\n"); + return 1; + } + xch = paging->xc_handle; + +- DPRINTF("starting %s %u %d\n", argv[0], paging->mem_event.domain_id, paging->target_tot_pages); ++ DPRINTF("starting %s for domain_id %u with pagefile %s\n", argv[0], paging->mem_event.domain_id, filename); + + /* Open file */ +- sprintf(filename, "page_cache_%u", paging->mem_event.domain_id); + fd = open(filename, open_flags, open_mode); + if ( fd < 0 ) + { +Index: xen-4.1.2-testing/tools/xenpaging/xenpaging.h +=================================================================== +--- xen-4.1.2-testing.orig/tools/xenpaging/xenpaging.h ++++ xen-4.1.2-testing/tools/xenpaging/xenpaging.h +@@ -52,6 +52,7 @@ typedef struct xenpaging { + int num_paged_out; + int target_tot_pages; + int policy_mru_size; ++ int debug; + unsigned long pagein_queue[XENPAGING_PAGEIN_QUEUE_SIZE]; + } xenpaging_t; + diff --git a/xenpaging.encapsulate_domain_info.patch b/xenpaging.encapsulate_domain_info.patch new file mode 100644 index 0000000..b730cab --- /dev/null +++ b/xenpaging.encapsulate_domain_info.patch @@ -0,0 +1,140 @@ +# HG changeset patch +# Parent f665912bc70e0b12e194cf1dd1d37bd22b29c54f +xenpaging: remove xc_dominfo_t from paging_t + +Remove xc_dominfo_t from paging_t, record only max_pages. +This value is used to setup internal data structures. + +Signed-off-by: Olaf Hering + +--- + tools/xenpaging/policy_default.c | 8 ++++---- + tools/xenpaging/xenpaging.c | 27 +++++++++++---------------- + tools/xenpaging/xenpaging.h | 4 ++-- + 3 files changed, 17 insertions(+), 22 deletions(-) + +Index: xen-4.1.2-testing/tools/xenpaging/policy_default.c +=================================================================== +--- xen-4.1.2-testing.orig/tools/xenpaging/policy_default.c ++++ xen-4.1.2-testing/tools/xenpaging/policy_default.c +@@ -41,17 +41,17 @@ int policy_init(xenpaging_t *paging) + int i; + int rc = -ENOMEM; + ++ max_pages = paging->max_pages; ++ + /* Allocate bitmap for pages not to page out */ +- bitmap = bitmap_alloc(paging->domain_info->max_pages); ++ bitmap = bitmap_alloc(max_pages); + if ( !bitmap ) + goto out; + /* Allocate bitmap to track unusable pages */ +- unconsumed = bitmap_alloc(paging->domain_info->max_pages); ++ unconsumed = bitmap_alloc(max_pages); + if ( !unconsumed ) + goto out; + +- max_pages = paging->domain_info->max_pages; +- + /* Initialise MRU list of paged in pages */ + if ( paging->policy_mru_size > 0 ) + mru_size = paging->policy_mru_size; +Index: xen-4.1.2-testing/tools/xenpaging/xenpaging.c +=================================================================== +--- xen-4.1.2-testing.orig/tools/xenpaging/xenpaging.c ++++ xen-4.1.2-testing/tools/xenpaging/xenpaging.c +@@ -164,6 +164,7 @@ static void *init_page(void) + static xenpaging_t *xenpaging_init(domid_t domain_id, int num_pages) + { + xenpaging_t *paging; ++ xc_domaininfo_t domain_info; + xc_interface *xch; + xentoollog_logger *dbg = NULL; + char *p; +@@ -275,34 +276,29 @@ static xenpaging_t *xenpaging_init(domid + + paging->mem_event.port = rc; + +- /* Get domaininfo */ +- paging->domain_info = malloc(sizeof(xc_domaininfo_t)); +- if ( paging->domain_info == NULL ) +- { +- PERROR("Error allocating memory for domain info"); +- goto err; +- } +- + rc = xc_domain_getinfolist(xch, paging->mem_event.domain_id, 1, +- paging->domain_info); ++ &domain_info); + if ( rc != 1 ) + { + PERROR("Error getting domain info"); + goto err; + } + ++ /* Record number of max_pages */ ++ paging->max_pages = domain_info.max_pages; ++ + /* Allocate bitmap for tracking pages that have been paged out */ +- paging->bitmap = bitmap_alloc(paging->domain_info->max_pages); ++ paging->bitmap = bitmap_alloc(paging->max_pages); + if ( !paging->bitmap ) + { + PERROR("Error allocating bitmap"); + goto err; + } +- DPRINTF("max_pages = %"PRIx64"\n", paging->domain_info->max_pages); ++ DPRINTF("max_pages = %d\n", paging->max_pages); + +- if ( num_pages < 0 || num_pages > paging->domain_info->max_pages ) ++ if ( num_pages < 0 || num_pages > paging->max_pages ) + { +- num_pages = paging->domain_info->max_pages; ++ num_pages = paging->max_pages; + DPRINTF("setting num_pages to %d\n", num_pages); + } + paging->num_pages = num_pages; +@@ -337,7 +333,6 @@ static xenpaging_t *xenpaging_init(domid + } + + free(paging->bitmap); +- free(paging->domain_info); + free(paging); + } + +@@ -765,7 +760,7 @@ int main(int argc, char *argv[]) + if ( interrupted == SIGTERM || interrupted == SIGINT ) + { + int num = 0; +- for ( i = 0; i < paging->domain_info->max_pages; i++ ) ++ for ( i = 0; i < paging->max_pages; i++ ) + { + if ( test_bit(i, paging->bitmap) ) + { +@@ -781,7 +776,7 @@ int main(int argc, char *argv[]) + */ + if ( num ) + page_in_trigger(); +- else if ( i == paging->domain_info->max_pages ) ++ else if ( i == paging->max_pages ) + break; + } + else +Index: xen-4.1.2-testing/tools/xenpaging/xenpaging.h +=================================================================== +--- xen-4.1.2-testing.orig/tools/xenpaging/xenpaging.h ++++ xen-4.1.2-testing/tools/xenpaging/xenpaging.h +@@ -44,11 +44,11 @@ typedef struct xenpaging { + xc_interface *xc_handle; + struct xs_handle *xs_handle; + +- xc_domaininfo_t *domain_info; +- + unsigned long *bitmap; + + mem_event_t mem_event; ++ /* number of pages for which data structures were allocated */ ++ int max_pages; + int num_pages; + int policy_mru_size; + unsigned long pagein_queue[XENPAGING_PAGEIN_QUEUE_SIZE]; diff --git a/xenpaging.file_op-return-code.patch b/xenpaging.file_op-return-code.patch new file mode 100644 index 0000000..811b967 --- /dev/null +++ b/xenpaging.file_op-return-code.patch @@ -0,0 +1,85 @@ +# HG changeset patch +# Parent 7a4a6935bfa145b24d5183cbf43ce8cc140d9183 +xenpaging: simplify file_op + +Use -1 as return value and let caller read errno. +Remove const casts from buffer pointers, the page is writeable. +Use wrapper for write() which matches the read() prototype. +Remove unused stdarg.h inclusion. +Remove unused macro. + +Signed-off-by: Olaf Hering + +--- + tools/xenpaging/file_ops.c | 29 +++++++++-------------------- + 1 file changed, 9 insertions(+), 20 deletions(-) + +Index: xen-4.1.2-testing/tools/xenpaging/file_ops.c +=================================================================== +--- xen-4.1.2-testing.orig/tools/xenpaging/file_ops.c ++++ xen-4.1.2-testing/tools/xenpaging/file_ops.c +@@ -21,55 +21,44 @@ + + + #include +-#include + #include + +- +-#define page_offset(_pfn) (((off_t)(_pfn)) << PAGE_SHIFT) +- +- + static int file_op(int fd, void *page, int i, +- ssize_t (*fn)(int, const void *, size_t)) ++ ssize_t (*fn)(int, void *, size_t)) + { + off_t seek_ret; +- int total; ++ int total = 0; + int bytes; +- int ret; + + seek_ret = lseek(fd, i << PAGE_SHIFT, SEEK_SET); ++ if ( seek_ret == (off_t)-1 ) ++ return -1; + +- total = 0; + while ( total < PAGE_SIZE ) + { + bytes = fn(fd, page + total, PAGE_SIZE - total); + if ( bytes <= 0 ) +- { +- ret = -errno; +- goto err; +- } ++ return -1; + + total += bytes; + } + + return 0; +- +- err: +- return ret; + } + +-static ssize_t my_read(int fd, const void *buf, size_t count) ++static ssize_t my_write(int fd, void *buf, size_t count) + { +- return read(fd, (void *)buf, count); ++ return write(fd, buf, count); + } + + int read_page(int fd, void *page, int i) + { +- return file_op(fd, page, i, &my_read); ++ return file_op(fd, page, i, &read); + } + + int write_page(int fd, void *page, int i) + { +- return file_op(fd, page, i, &write); ++ return file_op(fd, page, i, &my_write); + } + + diff --git a/xenpaging.guest-memusage.patch b/xenpaging.guest-memusage.patch new file mode 100644 index 0000000..807003a --- /dev/null +++ b/xenpaging.guest-memusage.patch @@ -0,0 +1,80 @@ +--- + tools/xenpaging/Makefile | 2 - + tools/xenpaging/xenmem.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 58 insertions(+), 1 deletion(-) + +Index: xen-4.1.2-testing/tools/xenpaging/Makefile +=================================================================== +--- xen-4.1.2-testing.orig/tools/xenpaging/Makefile ++++ xen-4.1.2-testing/tools/xenpaging/Makefile +@@ -20,7 +20,7 @@ CFLAGS += -Wp,-MD,.$(@F).d + DEPS = .*.d + + OBJS = $(SRCS:.c=.o) +-IBINS = xenpaging ++IBINS = xenpaging xenmem + + all: $(IBINS) + +Index: xen-4.1.2-testing/tools/xenpaging/xenmem.c +=================================================================== +--- /dev/null ++++ xen-4.1.2-testing/tools/xenpaging/xenmem.c +@@ -0,0 +1,57 @@ ++#include ++#include ++ ++static void dump_mem(const char *domid) ++{ ++ xc_interface *xch; ++ xc_dominfo_t info; ++ unsigned char handle[16]; ++ char uuid[16 * 2 + 1]; ++ int i; ++ ++ xch = xc_interface_open(NULL, NULL, 0); ++ if (!xch) ++ perror("xc_interface_open"); ++ else { ++ i = xc_domain_getinfo(xch, atoi(domid), 1, &info); ++ if (i != 1) ++ perror("xc_domain_getinfo"); ++ else { ++ printf("domid\t%u\n", info.domid); ++ printf("ssidref\t%u\n", info.ssidref); ++ printf("dying\t%u\n", info.dying); ++ printf("crashed\t%u\n", info.crashed); ++ printf("shutdown\t%u\n", info.shutdown); ++ printf("paused\t%u\n", info.paused); ++ printf("blocked\t%u\n", info.blocked); ++ printf("running\t%u\n", info.running); ++ printf("hvm\t%u\n", info.hvm); ++ printf("debugged\t%u\n", info.debugged); ++ printf("shutdown_reason\t%u\n", info.shutdown_reason); ++ printf("nr_pages\t%lu\t%lu KiB\t%lu MiB\n", info.nr_pages, info.nr_pages * 4, info.nr_pages * 4 / 1024); ++ printf("nr_shared_pages\t%lu\t%lu KiB\t%lu MiB\n", info.nr_shared_pages, info.nr_shared_pages * 4, info.nr_shared_pages * 4 / 1024); ++ printf("nr_paged_pages\t%lu\t%lu KiB\t%lu MiB\n", info.nr_paged_pages, info.nr_paged_pages * 4, info.nr_paged_pages * 4 / 1024); ++ printf("max_memkb\t%lu KiB\t%lu MiB\n", info.max_memkb, info.max_memkb / 1024); ++ printf("shared_info_frame\t%lu\t%lx\n", info.shared_info_frame, info.shared_info_frame); ++ printf("cpu_time\t%llu\t%016llx\n", (unsigned long long)info.cpu_time, (unsigned long long)info.cpu_time); ++ printf("nr_online_vcpus\t%u\n", info.nr_online_vcpus); ++ printf("max_vcpu_id\t%u\n", info.max_vcpu_id); ++ printf("cpupool\t%u\n", info.cpupool); ++ ++ memcpy(&handle, &info.handle, sizeof(handle)); ++ uuid[0] = '\0'; ++ for (i = 0; i < sizeof(handle); i++) ++ snprintf(&uuid[i * 2], sizeof(uuid) - strlen(uuid), "%02x", handle[i]); ++ printf("handle\t%s\n", uuid); ++ } ++ if (xc_interface_close(xch) < 0) ++ perror("xc_interface_close"); ++ } ++} ++ ++int main(int argc, char **argv) ++{ ++ if (argv[1]) ++ dump_mem(argv[1]); ++ return 0; ++} diff --git a/xenpaging.install-to-libexec.patch b/xenpaging.install-to-libexec.patch new file mode 100644 index 0000000..79b69d2 --- /dev/null +++ b/xenpaging.install-to-libexec.patch @@ -0,0 +1,28 @@ +# HG changeset patch +# Parent a30ec96cbaa43bc7abd90b7d974a8033265409c1 +xenpaging: install into LIBEXEC dir + +In preparation of upcoming libxl integration, +move xenpaging binary from /usr/sbin/ to /usr/lib/xen/bin/ + +Signed-off-by: Olaf Hering + +--- + tools/xenpaging/Makefile | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +Index: xen-4.1.2-testing/tools/xenpaging/Makefile +=================================================================== +--- xen-4.1.2-testing.orig/tools/xenpaging/Makefile ++++ xen-4.1.2-testing/tools/xenpaging/Makefile +@@ -29,8 +29,8 @@ xenpaging: $(OBJS) + + install: all + $(INSTALL_DIR) $(DESTDIR)/var/lib/xen/xenpaging +- $(INSTALL_DIR) $(DESTDIR)$(SBINDIR) +- $(INSTALL_PROG) $(IBINS) $(DESTDIR)$(SBINDIR) ++ $(INSTALL_DIR) $(DESTDIR)$(LIBEXEC) ++ $(INSTALL_PROG) $(IBINS) $(DESTDIR)$(LIBEXEC) + + clean: + rm -f *.o *~ $(DEPS) xen TAGS $(IBINS) $(LIB) diff --git a/xenpaging.low_target_policy_nomru.patch b/xenpaging.low_target_policy_nomru.patch new file mode 100644 index 0000000..b873595 --- /dev/null +++ b/xenpaging.low_target_policy_nomru.patch @@ -0,0 +1,122 @@ +# HG changeset patch +# Parent 79677f532a2406ca501250b50fa8b33965a8d7d7 +xenpaging: improve policy mru list handling + +Without this change it is not possible to page-out all guest pages, then +trigger a page-in for all pages, and then page-out everything once +again. All pages in the mru list can not be paged out because they +remain active in the internal bitmap of paged pages. + +Use the mru list only if the number of paged-out pages is larger than +the mru list. If the number is smaller, start to clear the mru list. In +case the number of paged-out pages drops to zero the mru list and the +internal bitmap will be empty as well. + +Also add a new interface for dropped pages. If a gfn was dropped there +is no need to adjust the mru list because dropping a page is not usage +of a page. + +Signed-off-by: Olaf Hering + +--- + tools/xenpaging/policy.h | 2 ++ + tools/xenpaging/policy_default.c | 27 ++++++++++++++++++++++++--- + tools/xenpaging/xenpaging.c | 11 +++++++++-- + 3 files changed, 35 insertions(+), 5 deletions(-) + +Index: xen-4.1.2-testing/tools/xenpaging/policy.h +=================================================================== +--- xen-4.1.2-testing.orig/tools/xenpaging/policy.h ++++ xen-4.1.2-testing/tools/xenpaging/policy.h +@@ -32,6 +32,8 @@ int policy_init(xenpaging_t *paging); + int policy_choose_victim(xenpaging_t *paging, xenpaging_victim_t *victim); + void policy_notify_paged_out(unsigned long gfn); + void policy_notify_paged_in(unsigned long gfn); ++void policy_notify_paged_in_nomru(unsigned long gfn); ++void policy_notify_dropped(unsigned long gfn); + + #endif // __XEN_PAGING_POLICY_H__ + +Index: xen-4.1.2-testing/tools/xenpaging/policy_default.c +=================================================================== +--- xen-4.1.2-testing.orig/tools/xenpaging/policy_default.c ++++ xen-4.1.2-testing/tools/xenpaging/policy_default.c +@@ -57,7 +57,7 @@ int policy_init(xenpaging_t *paging) + if ( paging->policy_mru_size > 0 ) + mru_size = paging->policy_mru_size; + else +- mru_size = DEFAULT_MRU_SIZE; ++ mru_size = paging->policy_mru_size = DEFAULT_MRU_SIZE; + + mru = malloc(sizeof(*mru) * mru_size); + if ( mru == NULL ) +@@ -120,17 +120,38 @@ void policy_notify_paged_out(unsigned lo + clear_bit(gfn, unconsumed); + } + +-void policy_notify_paged_in(unsigned long gfn) ++static void policy_handle_paged_in(unsigned long gfn, int do_mru) + { + unsigned long old_gfn = mru[i_mru & (mru_size - 1)]; + + if ( old_gfn != INVALID_MFN ) + clear_bit(old_gfn, bitmap); + +- mru[i_mru & (mru_size - 1)] = gfn; ++ if (do_mru) { ++ mru[i_mru & (mru_size - 1)] = gfn; ++ } else { ++ clear_bit(gfn, bitmap); ++ mru[i_mru & (mru_size - 1)] = INVALID_MFN; ++ } ++ + i_mru++; + } + ++void policy_notify_paged_in(unsigned long gfn) ++{ ++ policy_handle_paged_in(gfn, 1); ++} ++ ++void policy_notify_paged_in_nomru(unsigned long gfn) ++{ ++ policy_handle_paged_in(gfn, 0); ++} ++ ++void policy_notify_dropped(unsigned long gfn) ++{ ++ clear_bit(gfn, bitmap); ++} ++ + + /* + * Local variables: +Index: xen-4.1.2-testing/tools/xenpaging/xenpaging.c +=================================================================== +--- xen-4.1.2-testing.orig/tools/xenpaging/xenpaging.c ++++ xen-4.1.2-testing/tools/xenpaging/xenpaging.c +@@ -616,7 +616,14 @@ static int xenpaging_resume_page(xenpagi + /* Notify policy of page being paged in */ + if ( notify_policy ) + { +- policy_notify_paged_in(rsp->gfn); ++ /* ++ * Do not add gfn to mru list if the target is lower than mru size. ++ * This allows page-out of these gfns if the target grows again. ++ */ ++ if (paging->num_paged_out > paging->policy_mru_size) ++ policy_notify_paged_in(rsp->gfn); ++ else ++ policy_notify_paged_in_nomru(rsp->gfn); + + /* Record number of resumed pages */ + paging->num_paged_out--; +@@ -870,7 +877,7 @@ int main(int argc, char *argv[]) + { + DPRINTF("drop_page ^ gfn %"PRIx64" pageslot %d\n", req.gfn, i); + /* Notify policy of page being dropped */ +- policy_notify_paged_in(req.gfn); ++ policy_notify_dropped(req.gfn); + } + else + { diff --git a/xenpaging.main-loop-exit-handling.patch b/xenpaging.main-loop-exit-handling.patch new file mode 100644 index 0000000..6f3e512 --- /dev/null +++ b/xenpaging.main-loop-exit-handling.patch @@ -0,0 +1,48 @@ +# HG changeset patch +# Parent f08959fb7528e1724e26365973914ae3e0af78ea +xenpaging: improve mainloop exit handling + +Remove the if/else logic to exit from the in case a signal arrives. +Update comments. + +Signed-off-by: Olaf Hering + +--- + tools/xenpaging/xenpaging.c | 16 +++++++++------- + 1 file changed, 9 insertions(+), 7 deletions(-) + +Index: xen-4.1.2-testing/tools/xenpaging/xenpaging.c +=================================================================== +--- xen-4.1.2-testing.orig/tools/xenpaging/xenpaging.c ++++ xen-4.1.2-testing/tools/xenpaging/xenpaging.c +@@ -805,7 +805,7 @@ int main(int argc, char *argv[]) + } + } + +- /* Write all pages back into the guest */ ++ /* If interrupted, write all pages back into the guest */ + if ( interrupted == SIGTERM || interrupted == SIGINT ) + { + /* If no more pages to process, exit loop. */ +@@ -814,13 +814,15 @@ int main(int argc, char *argv[]) + + /* One more round if there are still pages to process. */ + resume_pages(paging, paging->num_paged_out); ++ ++ /* Resume main loop */ ++ continue; + } +- else +- { +- /* Exit on any other signal */ +- if ( interrupted ) +- break; +- } ++ ++ /* Exit main loop on any other signal */ ++ if ( interrupted ) ++ break; ++ + } + DPRINTF("xenpaging got signal %d\n", interrupted); + diff --git a/xenpaging.misleading-comment.patch b/xenpaging.misleading-comment.patch new file mode 100644 index 0000000..7a591b5 --- /dev/null +++ b/xenpaging.misleading-comment.patch @@ -0,0 +1,26 @@ +# HG changeset patch +# Parent 138406814b338c07af349a477dd7602ecca8be70 +xenpaging: remove obsolete comment in resume path + +Remove stale comment. +If a page was populated several times the vcpu is paused and +xenpaging has to unpause it again. + +Signed-off-by: Olaf Hering + +--- + tools/xenpaging/xenpaging.c | 1 - + 1 file changed, 1 deletion(-) + +Index: xen-4.1.2-testing/tools/xenpaging/xenpaging.c +=================================================================== +--- xen-4.1.2-testing.orig/tools/xenpaging/xenpaging.c ++++ xen-4.1.2-testing/tools/xenpaging/xenpaging.c +@@ -744,7 +744,6 @@ int main(int argc, char *argv[]) + !!(req.flags & MEM_EVENT_FLAG_EVICT_FAIL) ); + + /* Tell Xen to resume the vcpu */ +- /* XXX: Maybe just check if the vcpu was paused? */ + if ( req.flags & MEM_EVENT_FLAG_VCPU_PAUSED ) + { + /* Prepare the response */ diff --git a/xenpaging.page_in-munmap-size.patch b/xenpaging.page_in-munmap-size.patch new file mode 100644 index 0000000..391ddd8 --- /dev/null +++ b/xenpaging.page_in-munmap-size.patch @@ -0,0 +1,28 @@ +# HG changeset patch +# Parent 951a9879c34bee1dd2fa0329a541ae089f271c11 +xenpaging: munmap all pages after page-in + +Do munmap() on all mapped pages, not just the first one. Without this +change the gfns backing the remaining pages can not be paged out again +because the page count does not go down to 1. This change was missing +from changeset 23827:d1d6abc1db20. + +Signed-off-by: Olaf Hering + +--- + tools/xenpaging/pagein.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: xen-4.1.2-testing/tools/xenpaging/pagein.c +=================================================================== +--- xen-4.1.2-testing.orig/tools/xenpaging/pagein.c ++++ xen-4.1.2-testing/tools/xenpaging/pagein.c +@@ -44,7 +44,7 @@ static void *page_in(void *arg) + /* Ignore errors */ + page = xc_map_foreign_pages(pia->xch, pia->dom, PROT_READ, gfns, num); + if (page) +- munmap(page, PAGE_SIZE); ++ munmap(page, PAGE_SIZE * num); + } + page_in_possible = 0; + pthread_exit(NULL); diff --git a/xenpaging.print-gfn.patch b/xenpaging.print-gfn.patch new file mode 100644 index 0000000..906bd82 --- /dev/null +++ b/xenpaging.print-gfn.patch @@ -0,0 +1,95 @@ +# HG changeset patch +# Parent 9c7e82499e983ad11b13dd41d2fa5f12072adecf +xenpaging: print gfn in failure case + +Signed-off-by: Olaf Hering + +--- + tools/xenpaging/xenpaging.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +Index: xen-4.1.2-testing/tools/xenpaging/xenpaging.c +=================================================================== +--- xen-4.1.2-testing.orig/tools/xenpaging/xenpaging.c ++++ xen-4.1.2-testing/tools/xenpaging/xenpaging.c +@@ -444,7 +444,7 @@ static int xenpaging_evict_page(xenpagin + PROT_READ | PROT_WRITE, &gfn, 1); + if ( page == NULL ) + { +- PERROR("Error mapping page"); ++ PERROR("Error mapping page %lx", victim->gfn); + goto out; + } + +@@ -452,7 +452,7 @@ static int xenpaging_evict_page(xenpagin + ret = write_page(fd, page, i); + if ( ret != 0 ) + { +- PERROR("Error copying page"); ++ PERROR("Error copying page %lx", victim->gfn); + munmap(page, PAGE_SIZE); + goto out; + } +@@ -464,7 +464,7 @@ static int xenpaging_evict_page(xenpagin + victim->gfn); + if ( ret != 0 ) + { +- PERROR("Error evicting page"); ++ PERROR("Error evicting page %lx", victim->gfn); + goto out; + } + +@@ -520,7 +520,7 @@ static int xenpaging_populate_page(xenpa + sleep(1); + continue; + } +- PERROR("Error preparing for page in"); ++ PERROR("Error preparing %"PRI_xen_pfn" for page-in", gfn); + goto out_map; + } + } +@@ -532,7 +532,7 @@ static int xenpaging_populate_page(xenpa + PROT_READ | PROT_WRITE, &gfn, 1); + if ( page == NULL ) + { +- PERROR("Error mapping page: page is null"); ++ PERROR("Error mapping page %"PRI_xen_pfn": page is null", gfn); + goto out_map; + } + +@@ -540,7 +540,7 @@ static int xenpaging_populate_page(xenpa + ret = read_page(fd, page, i); + if ( ret != 0 ) + { +- PERROR("Error reading page"); ++ PERROR("Error reading page %"PRI_xen_pfn"", gfn); + goto out; + } + +@@ -710,7 +710,7 @@ int main(int argc, char *argv[]) + rc = xenpaging_populate_page(paging, req.gfn, fd, i); + if ( rc != 0 ) + { +- PERROR("Error populating page"); ++ PERROR("Error populating page %"PRIx64"", req.gfn); + goto out; + } + } +@@ -723,7 +723,7 @@ int main(int argc, char *argv[]) + rc = xenpaging_resume_page(paging, &rsp, 1); + if ( rc != 0 ) + { +- PERROR("Error resuming page"); ++ PERROR("Error resuming page %"PRIx64"", req.gfn); + goto out; + } + +@@ -754,7 +754,7 @@ int main(int argc, char *argv[]) + rc = xenpaging_resume_page(paging, &rsp, 0); + if ( rc != 0 ) + { +- PERROR("Error resuming"); ++ PERROR("Error resuming page %"PRIx64"", req.gfn); + goto out; + } + } diff --git a/xenpaging.record-numer-paged-out-pages.patch b/xenpaging.record-numer-paged-out-pages.patch new file mode 100644 index 0000000..6de62d9 --- /dev/null +++ b/xenpaging.record-numer-paged-out-pages.patch @@ -0,0 +1,53 @@ +# HG changeset patch +# Parent 8e31f3194c87e1cdb41621caa5a41810ef787293 +xenpaging: track the number of paged-out pages + +This change is required by subsequent changes. + +Signed-off-by: Olaf Hering + +--- + tools/xenpaging/xenpaging.c | 8 ++++++++ + tools/xenpaging/xenpaging.h | 1 + + 2 files changed, 9 insertions(+) + +Index: xen-4.1.2-testing/tools/xenpaging/xenpaging.c +=================================================================== +--- xen-4.1.2-testing.orig/tools/xenpaging/xenpaging.c ++++ xen-4.1.2-testing/tools/xenpaging/xenpaging.c +@@ -467,6 +467,9 @@ static int xenpaging_evict_page(xenpagin + /* Notify policy of page being paged out */ + policy_notify_paged_out(victim->gfn); + ++ /* Record number of evicted pages */ ++ paging->num_paged_out++; ++ + out: + return ret; + } +@@ -480,8 +483,13 @@ static int xenpaging_resume_page(xenpagi + + /* Notify policy of page being paged in */ + if ( notify_policy ) ++ { + policy_notify_paged_in(rsp->gfn); + ++ /* Record number of resumed pages */ ++ paging->num_paged_out--; ++ } ++ + /* Tell Xen page is ready */ + ret = xc_mem_paging_resume(paging->xc_handle, paging->mem_event.domain_id, + rsp->gfn); +Index: xen-4.1.2-testing/tools/xenpaging/xenpaging.h +=================================================================== +--- xen-4.1.2-testing.orig/tools/xenpaging/xenpaging.h ++++ xen-4.1.2-testing/tools/xenpaging/xenpaging.h +@@ -49,6 +49,7 @@ typedef struct xenpaging { + mem_event_t mem_event; + /* number of pages for which data structures were allocated */ + int max_pages; ++ int num_paged_out; + int num_pages; + int policy_mru_size; + unsigned long pagein_queue[XENPAGING_PAGEIN_QUEUE_SIZE]; diff --git a/xenpaging.reset-uncomsumed.patch b/xenpaging.reset-uncomsumed.patch new file mode 100644 index 0000000..036d5fb --- /dev/null +++ b/xenpaging.reset-uncomsumed.patch @@ -0,0 +1,50 @@ +# HG changeset patch +# Parent 5d87917314c0b4f13c987575d5329dfa215c5698 +xenpaging: retry unpageable gfns + +Nomination of gfns can fail, but may succeed later. +Thats the case for a guest that starts ballooned. + +v2: + - print debug when clearing uncosumed happens + +Signed-off-by: Olaf Hering + +--- + tools/xenpaging/policy_default.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +Index: xen-4.1.2-testing/tools/xenpaging/policy_default.c +=================================================================== +--- xen-4.1.2-testing.orig/tools/xenpaging/policy_default.c ++++ xen-4.1.2-testing/tools/xenpaging/policy_default.c +@@ -32,6 +32,7 @@ static unsigned int i_mru; + static unsigned int mru_size; + static unsigned long *bitmap; + static unsigned long *unconsumed; ++static unsigned int unconsumed_cleared; + static unsigned long current_gfn; + static unsigned long max_pages; + +@@ -87,8 +88,21 @@ int policy_choose_victim(xenpaging_t *pa + current_gfn++; + if ( current_gfn >= max_pages ) + current_gfn = 0; ++ /* Could not nominate any gfn */ + if ( wrap == current_gfn ) + { ++ /* Count wrap arounds */ ++ unconsumed_cleared++; ++ /* Force retry every few seconds (depends on poll() timeout) */ ++ if ( unconsumed_cleared > 123) ++ { ++ /* Force retry of unconsumed gfns */ ++ bitmap_clear(unconsumed, max_pages); ++ unconsumed_cleared = 0; ++ DPRINTF("clearing unconsumed, wrap %lx", wrap); ++ /* One more round before returning ENOSPC */ ++ continue; ++ } + victim->gfn = INVALID_MFN; + return -ENOSPC; + } diff --git a/xenpaging.stale-comments.patch b/xenpaging.stale-comments.patch new file mode 100644 index 0000000..fe0ac10 --- /dev/null +++ b/xenpaging.stale-comments.patch @@ -0,0 +1,42 @@ +# HG changeset patch +# Parent 401247fe2a24c4923a0106c5d8230fb16de0bb96 +xenpaging: remove filename from comment + +Signed-off-by: Olaf Hering + +--- + tools/xenpaging/file_ops.c | 1 - + tools/xenpaging/policy_default.c | 1 - + tools/xenpaging/xenpaging.c | 1 - + 3 files changed, 3 deletions(-) + +Index: xen-4.1.2-testing/tools/xenpaging/file_ops.c +=================================================================== +--- xen-4.1.2-testing.orig/tools/xenpaging/file_ops.c ++++ xen-4.1.2-testing/tools/xenpaging/file_ops.c +@@ -1,5 +1,4 @@ + /****************************************************************************** +- * tools/xenpaging/file_ops.c + * + * Common file operations. + * +Index: xen-4.1.2-testing/tools/xenpaging/policy_default.c +=================================================================== +--- xen-4.1.2-testing.orig/tools/xenpaging/policy_default.c ++++ xen-4.1.2-testing/tools/xenpaging/policy_default.c +@@ -1,5 +1,4 @@ + /****************************************************************************** +- * tools/xenpaging/policy.c + * + * Xen domain paging default policy. + * +Index: xen-4.1.2-testing/tools/xenpaging/xenpaging.c +=================================================================== +--- xen-4.1.2-testing.orig/tools/xenpaging/xenpaging.c ++++ xen-4.1.2-testing/tools/xenpaging/xenpaging.c +@@ -1,5 +1,4 @@ + /****************************************************************************** +- * tools/xenpaging/xenpaging.c + * + * Domain paging. + * Copyright (c) 2009 by Citrix Systems, Inc. (Patrick Colp) diff --git a/xenpaging.target-tot_pages.patch b/xenpaging.target-tot_pages.patch new file mode 100644 index 0000000..038ea9b --- /dev/null +++ b/xenpaging.target-tot_pages.patch @@ -0,0 +1,187 @@ +# HG changeset patch +# Parent f057eb06706e2bacaadb41cf80fa45001e786e69 +xenpaging: use guests tot_pages as working target + +This change reverses the task of xenpaging. Before this change a fixed number +of pages was paged out. With this change the guest will not have access to +more than the given number of pages at the same time. + +Signed-off-by: Olaf Hering + +--- + tools/xenpaging/policy_default.c | 1 + tools/xenpaging/xenpaging.c | 78 ++++++++++++++++++++++++++++++--------- + tools/xenpaging/xenpaging.h | 2 - + 3 files changed, 61 insertions(+), 20 deletions(-) + +Index: xen-4.1.2-testing/tools/xenpaging/policy_default.c +=================================================================== +--- xen-4.1.2-testing.orig/tools/xenpaging/policy_default.c ++++ xen-4.1.2-testing/tools/xenpaging/policy_default.c +@@ -71,7 +71,6 @@ int policy_init(xenpaging_t *paging) + + /* Start in the middle to avoid paging during BIOS startup */ + current_gfn = max_pages / 2; +- current_gfn -= paging->num_pages / 2; + + rc = 0; + out: +Index: xen-4.1.2-testing/tools/xenpaging/xenpaging.c +=================================================================== +--- xen-4.1.2-testing.orig/tools/xenpaging/xenpaging.c ++++ xen-4.1.2-testing/tools/xenpaging/xenpaging.c +@@ -136,6 +136,21 @@ err: + return rc; + } + ++static int xenpaging_get_tot_pages(xenpaging_t *paging) ++{ ++ xc_interface *xch = paging->xc_handle; ++ xc_domaininfo_t domain_info; ++ int rc; ++ ++ rc = xc_domain_getinfolist(xch, paging->mem_event.domain_id, 1, &domain_info); ++ if ( rc != 1 ) ++ { ++ PERROR("Error getting domain info"); ++ return -1; ++ } ++ return domain_info.tot_pages; ++} ++ + static void *init_page(void) + { + void *buffer; +@@ -161,7 +176,7 @@ static void *init_page(void) + return NULL; + } + +-static xenpaging_t *xenpaging_init(domid_t domain_id, int num_pages) ++static xenpaging_t *xenpaging_init(domid_t domain_id, int target_tot_pages) + { + xenpaging_t *paging; + xc_domaininfo_t domain_info; +@@ -296,12 +311,7 @@ static xenpaging_t *xenpaging_init(domid + } + DPRINTF("max_pages = %d\n", paging->max_pages); + +- if ( num_pages < 0 || num_pages > paging->max_pages ) +- { +- num_pages = paging->max_pages; +- DPRINTF("setting num_pages to %d\n", num_pages); +- } +- paging->num_pages = num_pages; ++ paging->target_tot_pages = target_tot_pages; + + /* Initialise policy */ + rc = policy_init(paging); +@@ -648,7 +658,9 @@ int main(int argc, char *argv[]) + xenpaging_victim_t *victims; + mem_event_request_t req; + mem_event_response_t rsp; ++ int num, prev_num = 0; + int i; ++ int tot_pages; + int rc = -1; + int rc1; + xc_interface *xch; +@@ -659,7 +671,7 @@ int main(int argc, char *argv[]) + + if ( argc != 3 ) + { +- fprintf(stderr, "Usage: %s \n", argv[0]); ++ fprintf(stderr, "Usage: %s \n", argv[0]); + return -1; + } + +@@ -672,7 +684,7 @@ int main(int argc, char *argv[]) + } + xch = paging->xc_handle; + +- DPRINTF("starting %s %u %d\n", argv[0], paging->mem_event.domain_id, paging->num_pages); ++ DPRINTF("starting %s %u %d\n", argv[0], paging->mem_event.domain_id, paging->target_tot_pages); + + /* Open file */ + sprintf(filename, "page_cache_%u", paging->mem_event.domain_id); +@@ -704,9 +716,6 @@ int main(int argc, char *argv[]) + /* listen for page-in events to stop pager */ + create_page_in_thread(paging); + +- i = evict_pages(paging, fd, victims, paging->num_pages); +- DPRINTF("%d pages evicted. Done.\n", i); +- + /* Swap pages in and out */ + while ( 1 ) + { +@@ -771,12 +780,8 @@ int main(int argc, char *argv[]) + goto out; + } + +- /* Evict a new page to replace the one we just paged in, +- * or clear this pagefile slot on exit */ +- if ( interrupted ) +- victims[i].gfn = INVALID_MFN; +- else +- evict_victim(paging, &victims[i], fd, i); ++ /* Clear this pagefile slot */ ++ victims[i].gfn = INVALID_MFN; + } + else + { +@@ -823,6 +828,43 @@ int main(int argc, char *argv[]) + if ( interrupted ) + break; + ++ /* Check if the target has been reached already */ ++ tot_pages = xenpaging_get_tot_pages(paging); ++ if ( tot_pages < 0 ) ++ goto out; ++ ++ /* Resume all pages if paging is disabled or no target was set */ ++ if ( paging->target_tot_pages == 0 ) ++ { ++ if ( paging->num_paged_out ) ++ resume_pages(paging, paging->num_paged_out); ++ } ++ /* Evict more pages if target not reached */ ++ else if ( tot_pages > paging->target_tot_pages ) ++ { ++ num = tot_pages - paging->target_tot_pages; ++ if ( num != prev_num ) ++ { ++ DPRINTF("Need to evict %d pages to reach %d target_tot_pages\n", num, paging->target_tot_pages); ++ prev_num = num; ++ } ++ /* Limit the number of evicts to be able to process page-in requests */ ++ if ( num > 42 ) ++ num = 42; ++ evict_pages(paging, fd, victims, num); ++ } ++ /* Resume some pages if target not reached */ ++ else if ( tot_pages < paging->target_tot_pages && paging->num_paged_out ) ++ { ++ num = paging->target_tot_pages - tot_pages; ++ if ( num != prev_num ) ++ { ++ DPRINTF("Need to resume %d pages to reach %d target_tot_pages\n", num, paging->target_tot_pages); ++ prev_num = num; ++ } ++ resume_pages(paging, num); ++ } ++ + } + DPRINTF("xenpaging got signal %d\n", interrupted); + +Index: xen-4.1.2-testing/tools/xenpaging/xenpaging.h +=================================================================== +--- xen-4.1.2-testing.orig/tools/xenpaging/xenpaging.h ++++ xen-4.1.2-testing/tools/xenpaging/xenpaging.h +@@ -50,7 +50,7 @@ typedef struct xenpaging { + /* number of pages for which data structures were allocated */ + int max_pages; + int num_paged_out; +- int num_pages; ++ int target_tot_pages; + int policy_mru_size; + unsigned long pagein_queue[XENPAGING_PAGEIN_QUEUE_SIZE]; + } xenpaging_t; diff --git a/xenpaging.use-PERROR.patch b/xenpaging.use-PERROR.patch new file mode 100644 index 0000000..d8411a7 --- /dev/null +++ b/xenpaging.use-PERROR.patch @@ -0,0 +1,281 @@ +# HG changeset patch +# Parent 5eb76b80baa127278e0fc1574bef22a79d9513f5 +xenpaging: use PERROR to print errno + +v3: + - adjust arguments for xc_mem_paging_enable() failures + +v2: + - move changes to file_op() to different patch + +Signed-off-by: Olaf Hering + +--- + tools/xenpaging/xenpaging.c | 58 ++++++++++++++++++++++---------------------- + 1 file changed, 29 insertions(+), 29 deletions(-) + +Index: xen-4.1.2-testing/tools/xenpaging/xenpaging.c +=================================================================== +--- xen-4.1.2-testing.orig/tools/xenpaging/xenpaging.c ++++ xen-4.1.2-testing/tools/xenpaging/xenpaging.c +@@ -90,7 +90,7 @@ static int xenpaging_wait_for_event_or_t + if (errno == EINTR) + return 0; + +- ERROR("Poll exited with an error"); ++ PERROR("Poll exited with an error"); + return -errno; + } + +@@ -121,7 +121,7 @@ static int xenpaging_wait_for_event_or_t + port = xc_evtchn_pending(xce); + if ( port == -1 ) + { +- ERROR("Failed to read port from event channel"); ++ PERROR("Failed to read port from event channel"); + rc = -1; + goto err; + } +@@ -129,7 +129,7 @@ static int xenpaging_wait_for_event_or_t + rc = xc_evtchn_unmask(xce, port); + if ( rc < 0 ) + { +- ERROR("Failed to unmask event channel port"); ++ PERROR("Failed to unmask event channel port"); + } + } + err: +@@ -185,7 +185,7 @@ static xenpaging_t *xenpaging_init(domid + paging->xs_handle = xs_open(0); + if ( paging->xs_handle == NULL ) + { +- ERROR("Error initialising xenstore connection"); ++ PERROR("Error initialising xenstore connection"); + goto err; + } + +@@ -193,7 +193,7 @@ static xenpaging_t *xenpaging_init(domid + snprintf(watch_token, sizeof(watch_token), "%u", domain_id); + if ( xs_watch(paging->xs_handle, "@releaseDomain", watch_token) == false ) + { +- ERROR("Could not bind to shutdown watch\n"); ++ PERROR("Could not bind to shutdown watch\n"); + goto err; + } + +@@ -214,7 +214,7 @@ static xenpaging_t *xenpaging_init(domid + paging->mem_event.shared_page = init_page(); + if ( paging->mem_event.shared_page == NULL ) + { +- ERROR("Error initialising shared page"); ++ PERROR("Error initialising shared page"); + goto err; + } + +@@ -222,7 +222,7 @@ static xenpaging_t *xenpaging_init(domid + paging->mem_event.ring_page = init_page(); + if ( paging->mem_event.ring_page == NULL ) + { +- ERROR("Error initialising ring page"); ++ PERROR("Error initialising ring page"); + goto err; + } + +@@ -249,7 +249,7 @@ static xenpaging_t *xenpaging_init(domid + ERROR("xenpaging not supported in a PoD guest"); + break; + default: +- ERROR("Error initialising shared page: %s", strerror(errno)); ++ PERROR("Error initialising shared page"); + break; + } + goto err; +@@ -259,7 +259,7 @@ static xenpaging_t *xenpaging_init(domid + paging->mem_event.xce_handle = xc_evtchn_open(NULL, 0); + if ( paging->mem_event.xce_handle == NULL ) + { +- ERROR("Failed to open event channel"); ++ PERROR("Failed to open event channel"); + goto err; + } + +@@ -269,7 +269,7 @@ static xenpaging_t *xenpaging_init(domid + paging->mem_event.shared_page->port); + if ( rc < 0 ) + { +- ERROR("Failed to bind event channel"); ++ PERROR("Failed to bind event channel"); + goto err; + } + +@@ -279,7 +279,7 @@ static xenpaging_t *xenpaging_init(domid + paging->domain_info = malloc(sizeof(xc_domaininfo_t)); + if ( paging->domain_info == NULL ) + { +- ERROR("Error allocating memory for domain info"); ++ PERROR("Error allocating memory for domain info"); + goto err; + } + +@@ -287,7 +287,7 @@ static xenpaging_t *xenpaging_init(domid + paging->domain_info); + if ( rc != 1 ) + { +- ERROR("Error getting domain info"); ++ PERROR("Error getting domain info"); + goto err; + } + +@@ -295,7 +295,7 @@ static xenpaging_t *xenpaging_init(domid + paging->bitmap = bitmap_alloc(paging->domain_info->max_pages); + if ( !paging->bitmap ) + { +- ERROR("Error allocating bitmap"); ++ PERROR("Error allocating bitmap"); + goto err; + } + DPRINTF("max_pages = %"PRIx64"\n", paging->domain_info->max_pages); +@@ -311,7 +311,7 @@ static xenpaging_t *xenpaging_init(domid + rc = policy_init(paging); + if ( rc != 0 ) + { +- ERROR("Error initialising policy"); ++ PERROR("Error initialising policy"); + goto err; + } + +@@ -358,14 +358,14 @@ static int xenpaging_teardown(xenpaging_ + rc = xc_mem_paging_disable(xch, paging->mem_event.domain_id); + if ( rc != 0 ) + { +- ERROR("Error tearing down domain paging in xen"); ++ PERROR("Error tearing down domain paging in xen"); + } + + /* Unbind VIRQ */ + rc = xc_evtchn_unbind(paging->mem_event.xce_handle, paging->mem_event.port); + if ( rc != 0 ) + { +- ERROR("Error unbinding event port"); ++ PERROR("Error unbinding event port"); + } + paging->mem_event.port = -1; + +@@ -373,7 +373,7 @@ static int xenpaging_teardown(xenpaging_ + rc = xc_evtchn_close(paging->mem_event.xce_handle); + if ( rc != 0 ) + { +- ERROR("Error closing event channel"); ++ PERROR("Error closing event channel"); + } + paging->mem_event.xce_handle = NULL; + +@@ -384,7 +384,7 @@ static int xenpaging_teardown(xenpaging_ + rc = xc_interface_close(xch); + if ( rc != 0 ) + { +- ERROR("Error closing connection to xen"); ++ PERROR("Error closing connection to xen"); + } + + return 0; +@@ -444,7 +444,7 @@ static int xenpaging_evict_page(xenpagin + PROT_READ | PROT_WRITE, &gfn, 1); + if ( page == NULL ) + { +- ERROR("Error mapping page"); ++ PERROR("Error mapping page"); + goto out; + } + +@@ -452,8 +452,8 @@ static int xenpaging_evict_page(xenpagin + ret = write_page(fd, page, i); + if ( ret != 0 ) + { ++ PERROR("Error copying page"); + munmap(page, PAGE_SIZE); +- ERROR("Error copying page"); + goto out; + } + +@@ -464,7 +464,7 @@ static int xenpaging_evict_page(xenpagin + victim->gfn); + if ( ret != 0 ) + { +- ERROR("Error evicting page"); ++ PERROR("Error evicting page"); + goto out; + } + +@@ -520,7 +520,7 @@ static int xenpaging_populate_page(xenpa + sleep(1); + continue; + } +- ERROR("Error preparing for page in"); ++ PERROR("Error preparing for page in"); + goto out_map; + } + } +@@ -532,7 +532,7 @@ static int xenpaging_populate_page(xenpa + PROT_READ | PROT_WRITE, &gfn, 1); + if ( page == NULL ) + { +- ERROR("Error mapping page: page is null"); ++ PERROR("Error mapping page: page is null"); + goto out_map; + } + +@@ -540,7 +540,7 @@ static int xenpaging_populate_page(xenpa + ret = read_page(fd, page, i); + if ( ret != 0 ) + { +- ERROR("Error reading page"); ++ PERROR("Error reading page"); + goto out; + } + +@@ -579,7 +579,7 @@ static int evict_victim(xenpaging_t *pag + { + if ( j++ % 1000 == 0 ) + if ( xenpaging_mem_paging_flush_ioemu_cache(paging) ) +- ERROR("Error flushing ioemu cache"); ++ PERROR("Error flushing ioemu cache"); + } + } + while ( ret ); +@@ -670,7 +670,7 @@ int main(int argc, char *argv[]) + rc = xenpaging_wait_for_event_or_timeout(paging); + if ( rc < 0 ) + { +- ERROR("Error getting event"); ++ PERROR("Error getting event"); + goto out; + } + else if ( rc != 0 ) +@@ -710,7 +710,7 @@ int main(int argc, char *argv[]) + rc = xenpaging_populate_page(paging, req.gfn, fd, i); + if ( rc != 0 ) + { +- ERROR("Error populating page"); ++ PERROR("Error populating page"); + goto out; + } + } +@@ -723,7 +723,7 @@ int main(int argc, char *argv[]) + rc = xenpaging_resume_page(paging, &rsp, 1); + if ( rc != 0 ) + { +- ERROR("Error resuming page"); ++ PERROR("Error resuming page"); + goto out; + } + +@@ -754,7 +754,7 @@ int main(int argc, char *argv[]) + rc = xenpaging_resume_page(paging, &rsp, 0); + if ( rc != 0 ) + { +- ERROR("Error resuming"); ++ PERROR("Error resuming"); + goto out; + } + } diff --git a/xenpaging.watch-target-tot_pages.patch b/xenpaging.watch-target-tot_pages.patch new file mode 100644 index 0000000..7611b77 --- /dev/null +++ b/xenpaging.watch-target-tot_pages.patch @@ -0,0 +1,120 @@ +# HG changeset patch +# Parent 0d872bf1203dd36200477f688908797875035b50 +xenpaging: watch the guests memory/target-tot_pages xenstore value + +Subsequent patches will use xenstored to store the numbers of pages +xenpaging is suppose to page-out. +Remove num_pages and use target_pages instead. + +Signed-off-by: Olaf Hering + +--- + tools/xenpaging/xenpaging.c | 51 +++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 50 insertions(+), 1 deletion(-) + +Index: xen-4.1.2-testing/tools/xenpaging/xenpaging.c +=================================================================== +--- xen-4.1.2-testing.orig/tools/xenpaging/xenpaging.c ++++ xen-4.1.2-testing/tools/xenpaging/xenpaging.c +@@ -19,8 +19,10 @@ + */ + + #define _XOPEN_SOURCE 600 ++#define _GNU_SOURCE + + #include ++#include + #include + #include + #include +@@ -35,6 +37,10 @@ + #include "policy.h" + #include "xenpaging.h" + ++/* Defines number of mfns a guest should use at a time, in KiB */ ++#define WATCH_TARGETPAGES "memory/target-tot_pages" ++static char *watch_target_tot_pages; ++static char *dom_path; + static char watch_token[16]; + static char filename[80]; + static int interrupted; +@@ -72,7 +78,7 @@ static int xenpaging_wait_for_event_or_t + { + xc_interface *xch = paging->xc_handle; + xc_evtchn *xce = paging->mem_event.xce_handle; +- char **vec; ++ char **vec, *val; + unsigned int num; + struct pollfd fd[2]; + int port; +@@ -111,6 +117,25 @@ static int xenpaging_wait_for_event_or_t + rc = 0; + } + } ++ else if ( strcmp(vec[XS_WATCH_PATH], watch_target_tot_pages) == 0 ) ++ { ++ int ret, target_tot_pages; ++ val = xs_read(paging->xs_handle, XBT_NULL, vec[XS_WATCH_PATH], NULL); ++ if ( val ) ++ { ++ ret = sscanf(val, "%d", &target_tot_pages); ++ if ( ret > 0 ) ++ { ++ /* KiB to pages */ ++ target_tot_pages >>= 2; ++ if ( target_tot_pages < 0 || target_tot_pages > paging->max_pages ) ++ target_tot_pages = paging->max_pages; ++ paging->target_tot_pages = target_tot_pages; ++ DPRINTF("new target_tot_pages %d\n", target_tot_pages); ++ } ++ free(val); ++ } ++ } + free(vec); + } + } +@@ -216,6 +241,25 @@ static xenpaging_t *xenpaging_init(domid + goto err; + } + ++ /* Watch xenpagings working target */ ++ dom_path = xs_get_domain_path(paging->xs_handle, domain_id); ++ if ( !dom_path ) ++ { ++ PERROR("Could not find domain path\n"); ++ goto err; ++ } ++ if ( asprintf(&watch_target_tot_pages, "%s/%s", dom_path, WATCH_TARGETPAGES) < 0 ) ++ { ++ PERROR("Could not alloc watch path\n"); ++ goto err; ++ } ++ DPRINTF("watching '%s'\n", watch_target_tot_pages); ++ if ( xs_watch(paging->xs_handle, watch_target_tot_pages, "") == false ) ++ { ++ PERROR("Could not bind to xenpaging watch\n"); ++ goto err; ++ } ++ + p = getenv("XENPAGING_POLICY_MRU_SIZE"); + if ( p && *p ) + { +@@ -342,6 +386,8 @@ static xenpaging_t *xenpaging_init(domid + free(paging->mem_event.ring_page); + } + ++ free(dom_path); ++ free(watch_target_tot_pages); + free(paging->bitmap); + free(paging); + } +@@ -357,6 +403,9 @@ static int xenpaging_teardown(xenpaging_ + if ( paging == NULL ) + return 0; + ++ xs_unwatch(paging->xs_handle, watch_target_tot_pages, ""); ++ xs_unwatch(paging->xs_handle, "@releaseDomain", watch_token); ++ + xch = paging->xc_handle; + paging->xc_handle = NULL; + /* Tear down domain paging in Xen */ diff --git a/xenpaging.watch_event-DPRINTF.patch b/xenpaging.watch_event-DPRINTF.patch new file mode 100644 index 0000000..de69a54 --- /dev/null +++ b/xenpaging.watch_event-DPRINTF.patch @@ -0,0 +1,22 @@ +# HG changeset patch +# Parent 5b764d6fc1e8165d9012cc8866ba08332fb13021 +xenpaging: add debug to show received watch event. + +Signed-off-by: Olaf Hering + +--- + tools/xenpaging/xenpaging.c | 1 + + 1 file changed, 1 insertion(+) + +Index: xen-4.1.2-testing/tools/xenpaging/xenpaging.c +=================================================================== +--- xen-4.1.2-testing.orig/tools/xenpaging/xenpaging.c ++++ xen-4.1.2-testing/tools/xenpaging/xenpaging.c +@@ -108,6 +108,7 @@ static int xenpaging_wait_for_event_or_t + vec = xs_read_watch(paging->xs_handle, &num); + if ( vec ) + { ++ DPRINTF("path '%s' token '%s'\n", vec[XS_WATCH_PATH], vec[XS_WATCH_TOKEN]); + if ( strcmp(vec[XS_WATCH_TOKEN], watch_token) == 0 ) + { + /* If our guest disappeared, set interrupt flag and fall through */ diff --git a/xenpaging.xc_interface_open-comment.patch b/xenpaging.xc_interface_open-comment.patch new file mode 100644 index 0000000..727f741 --- /dev/null +++ b/xenpaging.xc_interface_open-comment.patch @@ -0,0 +1,73 @@ +# HG changeset patch +# Parent c6014fd38d1f150dd433985f8388b4858ba5aaca +xenpaging: update xenpaging_init + +Move comment about xc_handle to the right place. +Allocate paging early and use calloc. + +Signed-off-by: Olaf Hering + +--- + tools/xenpaging/xenpaging.c | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +Index: xen-4.1.2-testing/tools/xenpaging/xenpaging.c +=================================================================== +--- xen-4.1.2-testing.orig/tools/xenpaging/xenpaging.c ++++ xen-4.1.2-testing/tools/xenpaging/xenpaging.c +@@ -169,18 +169,21 @@ static xenpaging_t *xenpaging_init(domid + char *p; + int rc; + ++ /* Allocate memory */ ++ paging = calloc(1, sizeof(xenpaging_t)); ++ if ( !paging ) ++ goto err; ++ + if ( getenv("XENPAGING_DEBUG") ) + dbg = (xentoollog_logger *)xtl_createlogger_stdiostream(stderr, XTL_DEBUG, 0); +- xch = xc_interface_open(dbg, NULL, 0); ++ ++ /* Open connection to xen */ ++ paging->xc_handle = xch = xc_interface_open(dbg, NULL, 0); + if ( !xch ) +- goto err_iface; ++ goto err; + + DPRINTF("xenpaging init\n"); + +- /* Allocate memory */ +- paging = malloc(sizeof(xenpaging_t)); +- memset(paging, 0, sizeof(xenpaging_t)); +- + /* Open connection to xenstore */ + paging->xs_handle = xs_open(0); + if ( paging->xs_handle == NULL ) +@@ -204,9 +207,6 @@ static xenpaging_t *xenpaging_init(domid + DPRINTF("Setting policy mru_size to %d\n", paging->policy_mru_size); + } + +- /* Open connection to xen */ +- paging->xc_handle = xch; +- + /* Set domain id */ + paging->mem_event.domain_id = domain_id; + +@@ -322,7 +322,8 @@ static xenpaging_t *xenpaging_init(domid + { + if ( paging->xs_handle ) + xs_close(paging->xs_handle); +- xc_interface_close(xch); ++ if ( xch ) ++ xc_interface_close(xch); + if ( paging->mem_event.shared_page ) + { + munlock(paging->mem_event.shared_page, PAGE_SIZE); +@@ -340,7 +341,6 @@ static xenpaging_t *xenpaging_init(domid + free(paging); + } + +- err_iface: + return NULL; + } +