Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 21 Jun 2014 08:31:21 +0300
From:      Konstantin Belousov <kostikbel@gmail.com>
To:        Roger Pau Monn? <roger.pau@citrix.com>
Cc:        virtualization@FreeBSD.org, "freebsd-xen@freebsd.org" <freebsd-xen@freebsd.org>, bryanv@FreeBSD.org
Subject:   Re: FreeBSD and memory balloon drivers
Message-ID:  <20140621053121.GK3991@kib.kiev.ua>
In-Reply-To: <53A467B4.8070501@citrix.com>
References:  <53A40079.9000804@citrix.com> <20140620132816.GH3991@kib.kiev.ua> <53A4501F.4020201@citrix.com> <20140620152610.GI3991@kib.kiev.ua> <53A467B4.8070501@citrix.com>

next in thread | previous in thread | raw e-mail | index | archive | help

--N7OK10pvBj1bDp4V
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

On Fri, Jun 20, 2014 at 06:56:20PM +0200, Roger Pau Monn? wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>=20
> On 20/06/14 17:26, Konstantin Belousov wrote:
> > On Fri, Jun 20, 2014 at 05:15:43PM +0200, Roger Pau Monn? wrote:
> >> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
> >>=20
> >> On 20/06/14 15:28, Konstantin Belousov wrote:
> >>> On Fri, Jun 20, 2014 at 11:35:53AM +0200, Roger Pau Monn?
> >>> wrote:
> >>>> Hello,
> >>>>=20
> >>>> I've been looking into the Xen balloon driver, because I've=20
> >>>> experienced problems when ballooning memory down which AFAICT
> >>>> are also present in the VirtIO balloon driver. The problem
> >>>> I've experienced is that when ballooning memory down, we
> >>>> basically allocate a bunch of memory as WIRED, to make sure
> >>>> nobody tries to swap it do disk, since it will crash the
> >>>> kernel because the memory is not populated. Due to this
> >>>> massive amount of memory allocated as WIRED, user-space
> >>>> programs that try to use mlock will fail because we hit the
> >>>> limit in vm.max_wired.
> >>>>=20
> >>>> I'm not sure what's the best way to deal with this
> >>>> limitation, should vm.max_wired be changed from the balloon
> >>>> drivers when ballooning down/up? Is there anyway to remove
> >>>> the pages ballooned down from the memory accounting of wired
> >>>> pages?
> >>>=20
> >>> You could change the type of pages the ballon driver is=20
> >>> allocating. Instead of wired pages, you may request unmanaged,
> >>> by passing NULL object to vm_page_alloc().  This would also
> >>> save on the trie nodes for managing the radix trie for the
> >>> object.  There are still plinks or listq to keep track of the
> >>> allocated pages.
> >>=20
> >> Thanks for the info, I have the following patch which fixes the
> >> usage of WIRED for both the Xen and the VirtIO balloon drivers,
> >> could someone please test the VirtIO side?
> > I briefly looked at the xen balloon.  You do not need
> > balloon_append(). Use struct vm_page plinks field to link the
> > pages.
>=20
> Sure, thanks for the review, here is an updated version.
It looks fine to me.

>=20
> Roger.
>=20
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.12 (Darwin)
>=20
> iQEcBAEBAgAGBQJTpGe0AAoJEKXZdqUyumTA5acH/jQ+Iwjw+QTwUtsh9ZLs7Gm0
> h7XaCwa/gASEjzcxK2smIBuKA10LUSoulcYkC3cUWXqaPwFega14JcbySBRI06Z1
> 1bU50DL8TPLuQIzrVWZgtA+QsZkwEu/jhijr0AMxTcnm6Wq1LV5QRDoqhD0kRiHu
> kEW1ez832y/0j+oeQAq0aR67zVw7hoIouH9eLaWXS4Vgxz5YQ2Pal1BMAY/OCgua
> xyF7BHia9KsGTKZ9pPUQfQAW5eJrwAxR0AitQjmOwRKtWyRqymZxhYHjLYOgOKQJ
> w93aLRVeG2oo0NNC6a9JD/c64sGHLABg37mnSTRL/v9gTj9I1DcFoid2q0iDGbM=3D
> =3D8nDn
> -----END PGP SIGNATURE-----

> >From e5c898b1b2b734fdc4aa2acf645efd481f09b71d Mon Sep 17 00:00:00 2001
> From: Roger Pau Monne <roger.pau@citrix.com>
> Date: Fri, 20 Jun 2014 16:34:31 +0200
> Subject: [PATCH] xen/virtio: fix balloon drivers to not mark pages as WIR=
ED
>=20
> Prevent the Xen and VirtIO balloon drivers from marking pages as
> wired. This prevents them from increasing the system wired page count,
> which can lead to mlock failing because of hitting the limit in
> vm.max_wired.
>=20
> In the Xen case make sure pages are zeroed before giving them back to
> the hypervisor, or else we might be leaking data. Also remove the
> balloon_{append/retrieve} and link pages directly into the
> ballooned_pages queue using the plinks.q field in the page struct.
>=20
> Sponsored by: Citrix Systems R&D
> Reviewed by: xxx
> Approved by: xxx
>=20
> dev/virtio/balloon/virtio_balloon.c:
>  - Don't allocate pages with VM_ALLOC_WIRED.
>=20
> dev/xen/balloon/balloon.c:
>  - Don't allocate pages with VM_ALLOC_WIRED.
>  - Make sure pages are zeroed before giving them back to the
>    hypervisor.
>  - Remove the balloon_entry struct and the balloon_{append/retrieve}
>    functions and use the page plinks.q entry to link the pages
>    directly into the ballooned_pages queue.
> ---
>  sys/dev/virtio/balloon/virtio_balloon.c |    4 +-
>  sys/dev/xen/balloon/balloon.c           |   87 ++++++++-----------------=
------
>  2 files changed, 23 insertions(+), 68 deletions(-)
>=20
> diff --git a/sys/dev/virtio/balloon/virtio_balloon.c b/sys/dev/virtio/bal=
loon/virtio_balloon.c
> index d540099..6d00ef3 100644
> --- a/sys/dev/virtio/balloon/virtio_balloon.c
> +++ b/sys/dev/virtio/balloon/virtio_balloon.c
> @@ -438,8 +438,7 @@ vtballoon_alloc_page(struct vtballoon_softc *sc)
>  {
>  	vm_page_t m;
> =20
> -	m =3D vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL | VM_ALLOC_WIRED |
> -	    VM_ALLOC_NOOBJ);
> +	m =3D vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL | VM_ALLOC_NOOBJ);
>  	if (m !=3D NULL)
>  		sc->vtballoon_current_npages++;
> =20
> @@ -450,7 +449,6 @@ static void
>  vtballoon_free_page(struct vtballoon_softc *sc, vm_page_t m)
>  {
> =20
> -	vm_page_unwire(m, PQ_INACTIVE);
>  	vm_page_free(m);
>  	sc->vtballoon_current_npages--;
>  }
> diff --git a/sys/dev/xen/balloon/balloon.c b/sys/dev/xen/balloon/balloon.c
> index fa56c86..0d2bba2 100644
> --- a/sys/dev/xen/balloon/balloon.c
> +++ b/sys/dev/xen/balloon/balloon.c
> @@ -94,13 +94,8 @@ SYSCTL_ULONG(_dev_xen_balloon, OID_AUTO, low_mem, CTLF=
LAG_RD,
>  SYSCTL_ULONG(_dev_xen_balloon, OID_AUTO, high_mem, CTLFLAG_RD,
>      &bs.balloon_high, 0, "High-mem balloon");
> =20
> -struct balloon_entry {
> -	vm_page_t page;
> -	STAILQ_ENTRY(balloon_entry) list;
> -};
> -
>  /* List of ballooned pages, threaded through the mem_map array. */
> -static STAILQ_HEAD(,balloon_entry) ballooned_pages;
> +static TAILQ_HEAD(,vm_page) ballooned_pages;
> =20
>  /* Main work function, always executed in process context. */
>  static void balloon_process(void *unused);
> @@ -110,47 +105,6 @@ static void balloon_process(void *unused);
>  #define WPRINTK(fmt, args...) \
>  	printk(KERN_WARNING "xen_mem: " fmt, ##args)
> =20
> -/* balloon_append: add the given page to the balloon. */
> -static int
> -balloon_append(vm_page_t page)
> -{
> -	struct balloon_entry *entry;
> -
> -	mtx_assert(&balloon_mutex, MA_OWNED);
> -
> -	entry =3D malloc(sizeof(struct balloon_entry), M_BALLOON, M_NOWAIT);
> -	if (!entry)
> -		return (ENOMEM);
> -	entry->page =3D page;
> -	STAILQ_INSERT_HEAD(&ballooned_pages, entry, list);
> -	bs.balloon_low++;
> -
> -	return (0);
> -}
> -
> -/* balloon_retrieve: rescue a page from the balloon, if it is not empty.=
 */
> -static vm_page_t
> -balloon_retrieve(void)
> -{
> -	vm_page_t page;
> -	struct balloon_entry *entry;
> -
> -	mtx_assert(&balloon_mutex, MA_OWNED);
> -
> -	if (STAILQ_EMPTY(&ballooned_pages))
> -		return (NULL);
> -
> -	entry =3D STAILQ_FIRST(&ballooned_pages);
> -	STAILQ_REMOVE_HEAD(&ballooned_pages, list);
> -
> -	page =3D entry->page;
> -	free(entry, M_BALLOON);
> -=09
> -	bs.balloon_low--;
> -
> -	return (page);
> -}
> -
>  static unsigned long=20
>  current_target(void)
>  {
> @@ -203,7 +157,6 @@ static int
>  increase_reservation(unsigned long nr_pages)
>  {
>  	unsigned long  pfn, i;
> -	struct balloon_entry *entry;
>  	vm_page_t      page;
>  	long           rc;
>  	struct xen_memory_reservation reservation =3D {
> @@ -217,10 +170,9 @@ increase_reservation(unsigned long nr_pages)
>  	if (nr_pages > nitems(frame_list))
>  		nr_pages =3D nitems(frame_list);
> =20
> -	for (entry =3D STAILQ_FIRST(&ballooned_pages), i =3D 0;
> -	     i < nr_pages; i++, entry =3D STAILQ_NEXT(entry, list)) {
> -		KASSERT(entry, ("ballooned_pages list corrupt"));
> -		page =3D entry->page;
> +	for (page =3D TAILQ_FIRST(&ballooned_pages), i =3D 0;
> +	     i < nr_pages; i++, page =3D TAILQ_NEXT(page, plinks.q)) {
> +		KASSERT(page !=3D NULL, ("ballooned_pages list corrupt"));
>  		frame_list[i] =3D (VM_PAGE_TO_PHYS(page) >> PAGE_SHIFT);
>  	}
> =20
> @@ -245,8 +197,10 @@ increase_reservation(unsigned long nr_pages)
>  	}
> =20
>  	for (i =3D 0; i < nr_pages; i++) {
> -		page =3D balloon_retrieve();
> -		KASSERT(page, ("balloon_retrieve failed"));
> +		page =3D TAILQ_FIRST(&ballooned_pages);
> +		KASSERT(page !=3D NULL, ("Unable to get ballooned page"));
> +		TAILQ_REMOVE(&ballooned_pages, page, plinks.q);
> +		bs.balloon_low--;
> =20
>  		pfn =3D (VM_PAGE_TO_PHYS(page) >> PAGE_SHIFT);
>  		KASSERT((xen_feature(XENFEAT_auto_translated_physmap) ||
> @@ -255,7 +209,6 @@ increase_reservation(unsigned long nr_pages)
> =20
>  		set_phys_to_machine(pfn, frame_list[i]);
> =20
> -		vm_page_unwire(page, PQ_INACTIVE);
>  		vm_page_free(page);
>  	}
> =20
> @@ -286,24 +239,27 @@ decrease_reservation(unsigned long nr_pages)
>  	for (i =3D 0; i < nr_pages; i++) {
>  		if ((page =3D vm_page_alloc(NULL, 0,=20
>  			    VM_ALLOC_NORMAL | VM_ALLOC_NOOBJ |=20
> -			    VM_ALLOC_WIRED | VM_ALLOC_ZERO)) =3D=3D NULL) {
> +			    VM_ALLOC_ZERO)) =3D=3D NULL) {
>  			nr_pages =3D i;
>  			need_sleep =3D 1;
>  			break;
>  		}
> =20
> +		if ((page->flags & PG_ZERO) =3D=3D 0) {
> +			/*
> +			 * Zero the page, or else we might be leaking
> +			 * important data to other domains on the same
> +			 * host.
> +			 */
> +			pmap_zero_page(page);
> +		}
> +
>  		pfn =3D (VM_PAGE_TO_PHYS(page) >> PAGE_SHIFT);
>  		frame_list[i] =3D PFNTOMFN(pfn);
> =20
>  		set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
> -		if (balloon_append(page) !=3D 0) {
> -			vm_page_unwire(page, PQ_INACTIVE);
> -			vm_page_free(page);
> -
> -			nr_pages =3D i;
> -			need_sleep =3D 1;
> -			break;
> -		}
> +		TAILQ_INSERT_HEAD(&ballooned_pages, page, plinks.q);
> +		bs.balloon_low++;
>  	}
> =20
>  	set_xen_guest_handle(reservation.extent_start, frame_list);
> @@ -438,7 +394,8 @@ balloon_init(void *arg)
>  	/* Initialise the balloon with excess memory space. */
>  	for (pfn =3D xen_start_info->nr_pages; pfn < max_pfn; pfn++) {
>  		page =3D PHYS_TO_VM_PAGE(pfn << PAGE_SHIFT);
> -		balloon_append(page);
> +		TAILQ_INSERT_HEAD(&ballooned_pages, page, plinks.q);
> +		bs.balloon_low++;
>  	}
>  #undef max_pfn
>  #endif
> --=20
> 1.7.7.5 (Apple Git-26)
>=20


--N7OK10pvBj1bDp4V
Content-Type: application/pgp-signature

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2

iQIcBAEBAgAGBQJTpRioAAoJEJDCuSvBvK1BSxEP/1Oxdr7ActnPpw7M6pRHqXMe
63ZkiIdwovfBdABA/Qs/+EAgCuPxbZmaD3e3b/1ypi/qXihB4kbnWTTneXUei5NF
7Xot0YppkCmnKLiGiku3rV/biIFjmTJg5aCsrKdTpQfHCG1WInDwWZTW4UlMwkf2
j05qqBY6CeI8ckvmGDDZPpVAtnUnMI0AQOV2hve77kN3zWisxHG3qsBpCFIsDLAk
9eNBKasKHVWZlDTj1SHT9Fk3UgEqNOoSdOPgeMA+RMNAerLlg6uQXkdFZL8+nCA9
KzChvmglVepdC46qwai2UgkCr7ikEy6btijb4d+3pr0+XbzlfOCJ5nduwaYN72Uz
7qgxpX3AgagBIdLfv1zBtWX7K1fbQVkCLIe0pwPqKw8fAUP1lu2TmjsU+Ziq6wLa
ncN0Lafh3sihUt6rsrW2GGFTtXiWqJqtb2QHdLYgxA7F27OupxLXl+ZXFgqTHSdc
BXOFsE6NxtGkf8U9dnNHgHVDDyXKTMzy8/VblRxw2VIBSPV4ilCOXuE8E0+3/ASg
mFZv2o8Yr7SO5OHouZAdKYvtW29Ch4YYl1HvJJt+ZHgZmvGQiv9HUqzPJvgOGrKK
tNth+Vcbp14xEhgHrnuJeymtAa39hhBXJVvgOQJRJsWpyhhycLCAaIgr8h0qC8A/
Ax1qZuC61xLOmFWRHPMf
=fFv2
-----END PGP SIGNATURE-----

--N7OK10pvBj1bDp4V--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20140621053121.GK3991>