- 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

- xen.spec: update filelist
  package /usr/lib*/xen with wildcard to pickup new files
  remove duplicate /usr/sbin/xen-list from filelist

OBS-URL: https://build.opensuse.org/package/show/Virtualization/xen?expand=0&rev=157
This commit is contained in:
Olaf Hering 2011-11-03 22:59:30 +00:00 committed by Git OBS Bridge
parent 7505a6b224
commit ee2be8156e
25 changed files with 2432 additions and 131 deletions

View File

@ -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

118
xen.spec
View File

@ -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 <ian.pratt@cl.cam.ac.uk>
%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 <ian.pratt@cl.cam.ac.uk>
%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

View File

@ -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 <olaf@aepfle.de>
---
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) )

View File

@ -0,0 +1,51 @@
xenpaging: add XEN_PAGING_DIR / libxl_xenpaging_dir_path()
Signed-off-by: Olaf Hering <olaf@aepfle.de>
---
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)

View File

@ -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 <olaf@aepfle.de>
---
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
{

View File

@ -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 <olaf@aepfle.de>
---
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/<domain_name>.<domaind_id>.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' : ('<Domain> <Mem>',
'Set the current memory usage for a domain.'),
+ 'mem-swap-target' : ('<Domain> <Mem>',
+ 'Set the memory usage for a domain.'),
'migrate' : ('<Domain> <Host>',
'Migrate a domain to another machine.'),
'pause' : ('<Domain>', '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',

View File

@ -0,0 +1,34 @@
# HG changeset patch
# Parent 2ac53905d95e6d02f53c99f6e2fa38f7306b8800
libxc: add bitmap_clear function
Signed-off-by: Olaf Hering <olaf@aepfle.de>
---
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 <stdlib.h>
+#include <string.h>
#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;

View File

@ -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 <pagefile> -d <domain_id>
options:
-d <domid> --domain=<domid> numerical domain_id of guest. This option is required.
-f <file> --pagefile=<file> pagefile to use. This option is required.
-m <max_memkb> --max_memkb=<max_memkb> maximum amount of memory to handle.
-r <num> --mru_size=<num> number of paged-in pages to keep in memory.
-d --debug enable debug output.
-h --help this output.
Signed-off-by: Olaf Hering <olaf@aepfle.de>
---
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 <poll.h>
#include <xc_private.h>
#include <xs.h>
+#include <getopt.h>
#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 <pagefile> -d <domain_id>\n\n");
+
+ printf("options:\n");
+ printf(" -d <domid> --domain=<domid> numerical domain_id of guest. This option is required.\n");
+ printf(" -f <file> --pagefile=<file> pagefile to use. This option is required.\n");
+ printf(" -m <max_memkb> --max_memkb=<max_memkb> maximum amount of memory to handle.\n");
+ printf(" -r <num> --mru_size=<num> 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 <domain_id> 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 <domain_id> <tot_pages>\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;

View File

@ -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 <olaf@aepfle.de>
---
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];

View File

@ -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 <olaf@aepfle.de>
---
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 <unistd.h>
-#include <stdarg.h>
#include <xc_private.h>
-
-#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);
}

View File

@ -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 <stdio.h>
+#include <xc_private.h>
+
+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;
+}

View File

@ -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 <olaf@aepfle.de>
---
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)

View File

@ -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 <olaf@aepfle.de>
---
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
{

View File

@ -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 <olaf@aepfle.de>
---
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);

View File

@ -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 <olaf@aepfle.de>
---
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 */

View File

@ -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 <olaf@aepfle.de>
---
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);

95
xenpaging.print-gfn.patch Normal file
View File

@ -0,0 +1,95 @@
# HG changeset patch
# Parent 9c7e82499e983ad11b13dd41d2fa5f12072adecf
xenpaging: print gfn in failure case
Signed-off-by: Olaf Hering <olaf@aepfle.de>
---
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;
}
}

View File

@ -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 <olaf@aepfle.de>
---
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];

View File

@ -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 <olaf@aepfle.de>
---
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;
}

View File

@ -0,0 +1,42 @@
# HG changeset patch
# Parent 401247fe2a24c4923a0106c5d8230fb16de0bb96
xenpaging: remove filename from comment
Signed-off-by: Olaf Hering <olaf@aepfle.de>
---
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)

View File

@ -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 <olaf@aepfle.de>
---
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 <domain_id> <num_pages>\n", argv[0]);
+ fprintf(stderr, "Usage: %s <domain_id> <tot_pages>\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;

281
xenpaging.use-PERROR.patch Normal file
View File

@ -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 <olaf@aepfle.de>
---
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;
}
}

View File

@ -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 <olaf@aepfle.de>
---
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 <inttypes.h>
+#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <time.h>
@@ -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 */

View File

@ -0,0 +1,22 @@
# HG changeset patch
# Parent 5b764d6fc1e8165d9012cc8866ba08332fb13021
xenpaging: add debug to show received watch event.
Signed-off-by: Olaf Hering <olaf@aepfle.de>
---
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 */

View File

@ -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 <olaf@aepfle.de>
---
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;
}