From nobody Sat Nov 15 11:54:34 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1594867442; cv=none; d=zohomail.com; s=zohoarc; b=ZC9lf8U/FH664BNvVvDyQXIZDY4r4L6dFXAs6enIumJAst20qNDK/AKJVVaWyYr3cftGv4hlPVvMv5TeV1QlvFKL3fnmlGouEHg3/iYz0roMV7KkZAo17tf5YfM2zf95VMF9VOuR2StO3oMEO7yKHimgrbdZzNCUc7tOtDnpmkw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1594867442; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To; bh=4SDJJ4HZFIcjUYXNv5mhn9sTyVNJiZegXJBjuEdUcAI=; b=TjcZWtLIulHFzFaQMa/Vj5lwq2akPG4WM3Cd20iVv1Xs1zgIajjFeoFDnpmaiI53sQx8CD1ga2/do9pl5mV6Isq8fG8kmzmb9+zeILJZWKPnlc6Ro5s0xXh0yt7z9WfY6pk7ZvEx2wv7mJqJb+dgdpcx12WbMJ2VA5cIXaquBuQ= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1594867442624952.9688057043395; Wed, 15 Jul 2020 19:44:02 -0700 (PDT) Received: from localhost ([::1]:42376 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jvtsP-0007NS-BL for importer@patchew.org; Wed, 15 Jul 2020 22:44:01 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37132) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jvtrH-0005hh-EW for qemu-devel@nongnu.org; Wed, 15 Jul 2020 22:42:51 -0400 Received: from out4436.biz.mail.alibaba.com ([47.88.44.36]:52214) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jvtrF-00043r-9i for qemu-devel@nongnu.org; Wed, 15 Jul 2020 22:42:51 -0400 Received: from localhost(mailfrom:teawaterz@linux.alibaba.com fp:SMTPD_---0U2rEMvL_1594867329) by smtp.aliyun-inc.com(127.0.0.1); Thu, 16 Jul 2020 10:42:28 +0800 X-Alimail-AntiSpam: AC=PASS; BC=-1|-1; BR=01201311R131e4; CH=green; DM=||false|; DS=||; FP=0|-1|-1|-1|0|-1|-1|-1; HT=e01e04407; MF=teawaterz@linux.alibaba.com; NM=1; PH=DS; RN=11; SR=0; TI=SMTPD_---0U2rEMvL_1594867329; From: Hui Zhu To: mst@redhat.com, david@redhat.com, jasowang@redhat.com, akpm@linux-foundation.org, virtualization@lists.linux-foundation.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org, qemu-devel@nongnu.org, virtio-dev@lists.oasis-open.org Subject: [RFC for Linux v4 1/2] virtio_balloon: Add VIRTIO_BALLOON_F_CONT_PAGES and inflate_cont_vq Date: Thu, 16 Jul 2020 10:41:51 +0800 Message-Id: <1594867315-8626-2-git-send-email-teawater@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1594867315-8626-1-git-send-email-teawater@gmail.com> References: <1594867315-8626-1-git-send-email-teawater@gmail.com> Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=47.88.44.36; envelope-from=teawaterz@linux.alibaba.com; helo=out4436.biz.mail.alibaba.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/07/15 22:42:26 X-ACL-Warn: Detected OS = Linux 3.1-3.10 X-Spam_score_int: -71 X-Spam_score: -7.2 X-Spam_bar: ------- X-Spam_report: (-7.2 / 5.0 requ) BAYES_00=-1.9, DKIM_ADSP_CUSTOM_MED=0.001, FORGED_GMAIL_RCVD=1, FREEMAIL_FORGED_FROMDOMAIN=1, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=1, NML_ADSP_CUSTOM_MED=0.9, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=-1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, UNPARSEABLE_RELAY=0.001, USER_IN_DEF_SPF_WL=-7.5 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Hui Zhu , Hui Zhu Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This commit adds a new flag VIRTIO_BALLOON_F_CONT_PAGES to virtio_balloon. Add it adds a vq inflate_cont_vq to inflate continuous pages. When VIRTIO_BALLOON_F_CONT_PAGES is set, try to allocate continuous pages and report them use inflate_cont_vq. Signed-off-by: Hui Zhu --- drivers/virtio/virtio_balloon.c | 119 ++++++++++++++++++++++++++++++--= ---- include/linux/balloon_compaction.h | 9 ++- include/uapi/linux/virtio_balloon.h | 1 + mm/balloon_compaction.c | 41 ++++++++++--- 4 files changed, 142 insertions(+), 28 deletions(-) diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloo= n.c index 1f157d2..b89f566 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -42,6 +42,9 @@ (1 << (VIRTIO_BALLOON_HINT_BLOCK_ORDER + PAGE_SHIFT)) #define VIRTIO_BALLOON_HINT_BLOCK_PAGES (1 << VIRTIO_BALLOON_HINT_BLOCK_OR= DER) =20 +#define VIRTIO_BALLOON_INFLATE_MAX_ORDER min((int) (sizeof(__virtio32) * B= ITS_PER_BYTE - \ + 1 - PAGE_SHIFT), (MAX_ORDER-1)) + #ifdef CONFIG_BALLOON_COMPACTION static struct vfsmount *balloon_mnt; #endif @@ -52,6 +55,7 @@ enum virtio_balloon_vq { VIRTIO_BALLOON_VQ_STATS, VIRTIO_BALLOON_VQ_FREE_PAGE, VIRTIO_BALLOON_VQ_REPORTING, + VIRTIO_BALLOON_VQ_INFLATE_CONT, VIRTIO_BALLOON_VQ_MAX }; =20 @@ -61,7 +65,7 @@ enum virtio_balloon_config_read { =20 struct virtio_balloon { struct virtio_device *vdev; - struct virtqueue *inflate_vq, *deflate_vq, *stats_vq, *free_page_vq; + struct virtqueue *inflate_vq, *deflate_vq, *stats_vq, *free_page_vq, *inf= late_cont_vq; =20 /* Balloon's own wq for cpu-intensive work items */ struct workqueue_struct *balloon_wq; @@ -126,6 +130,9 @@ struct virtio_balloon { /* Free page reporting device */ struct virtqueue *reporting_vq; struct page_reporting_dev_info pr_dev_info; + + /* Current order of inflate continuous pages - VIRTIO_BALLOON_F_CONT_PAGE= S */ + __u32 current_pages_order; }; =20 static struct virtio_device_id id_table[] =3D { @@ -208,19 +215,59 @@ static void set_page_pfns(struct virtio_balloon *vb, page_to_balloon_pfn(page) + i); } =20 +static void set_page_pfns_order(struct virtio_balloon *vb, + __virtio32 pfns[], struct page *page, + unsigned int order) +{ + if (order =3D=3D 0) + return set_page_pfns(vb, pfns, page); + + /* Set the first pfn of the continuous pages. */ + pfns[0] =3D cpu_to_virtio32(vb->vdev, page_to_balloon_pfn(page)); + /* Set the size of the continuous pages. */ + pfns[1] =3D PAGE_SIZE << order; +} + static unsigned fill_balloon(struct virtio_balloon *vb, size_t num) { unsigned num_allocated_pages; - unsigned num_pfns; + unsigned int num_pfns, pfn_per_alloc; struct page *page; LIST_HEAD(pages); + bool is_cont =3D vb->current_pages_order !=3D 0; =20 - /* We can only do one array worth at a time. */ - num =3D min(num, ARRAY_SIZE(vb->pfns)); - - for (num_pfns =3D 0; num_pfns < num; - num_pfns +=3D VIRTIO_BALLOON_PAGES_PER_PAGE) { - struct page *page =3D balloon_page_alloc(); + if (is_cont) + pfn_per_alloc =3D 2; + else + pfn_per_alloc =3D VIRTIO_BALLOON_PAGES_PER_PAGE; + + for (num_pfns =3D 0, num_allocated_pages =3D 0; + num_pfns < ARRAY_SIZE(vb->pfns) && num_allocated_pages < num; + num_pfns +=3D pfn_per_alloc, + num_allocated_pages +=3D VIRTIO_BALLOON_PAGES_PER_PAGE << vb->curren= t_pages_order) { + struct page *page; + + for (; vb->current_pages_order >=3D 0; vb->current_pages_order--) { + if (vb->current_pages_order && + num - num_allocated_pages < + VIRTIO_BALLOON_PAGES_PER_PAGE << vb->current_pages_order) + continue; + page =3D balloon_pages_alloc(vb->current_pages_order); + if (page) { + /* If the first allocated page is not continuous pages, + * go back to transport page as signle page. + */ + if (is_cont && num_pfns =3D=3D 0 && !vb->current_pages_order) { + is_cont =3D false; + pfn_per_alloc =3D VIRTIO_BALLOON_PAGES_PER_PAGE; + } + set_page_private(page, vb->current_pages_order); + balloon_page_push(&pages, page); + break; + } + if (!vb->current_pages_order) + break; + } =20 if (!page) { dev_info_ratelimited(&vb->vdev->dev, @@ -230,8 +277,6 @@ static unsigned fill_balloon(struct virtio_balloon *vb,= size_t num) msleep(200); break; } - - balloon_page_push(&pages, page); } =20 mutex_lock(&vb->balloon_lock); @@ -239,20 +284,34 @@ static unsigned fill_balloon(struct virtio_balloon *v= b, size_t num) vb->num_pfns =3D 0; =20 while ((page =3D balloon_page_pop(&pages))) { - balloon_page_enqueue(&vb->vb_dev_info, page); + unsigned int order =3D page_private(page); + + set_page_private(page, 0); + + /* Split the continuous pages because they will be freed + * by release_pages_balloon respectively. + */ + if (order) + split_page(page, order); + + balloon_pages_enqueue(&vb->vb_dev_info, page, order); + + set_page_pfns_order(vb, vb->pfns + vb->num_pfns, page, order); =20 - set_page_pfns(vb, vb->pfns + vb->num_pfns, page); - vb->num_pages +=3D VIRTIO_BALLOON_PAGES_PER_PAGE; if (!virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM)) - adjust_managed_page_count(page, -1); - vb->num_pfns +=3D VIRTIO_BALLOON_PAGES_PER_PAGE; + adjust_managed_page_count(page, -(1 << order)); + vb->num_pfns +=3D pfn_per_alloc; } + vb->num_pages +=3D num_allocated_pages; =20 - num_allocated_pages =3D vb->num_pfns; /* Did we get any? */ - if (vb->num_pfns !=3D 0) - tell_host(vb, vb->inflate_vq); + if (vb->num_pfns !=3D 0) { + if (is_cont) + tell_host(vb, vb->inflate_cont_vq); + else + tell_host(vb, vb->inflate_vq); + } mutex_unlock(&vb->balloon_lock); =20 return num_allocated_pages; @@ -488,7 +547,7 @@ static void update_balloon_size_func(struct work_struct= *work) diff =3D towards_target(vb); =20 if (!diff) - return; + goto stop_out; =20 if (diff > 0) diff -=3D fill_balloon(vb, diff); @@ -498,6 +557,11 @@ static void update_balloon_size_func(struct work_struc= t *work) =20 if (diff) queue_work(system_freezable_wq, work); + else { +stop_out: + if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_CONT_PAGES)) + vb->current_pages_order =3D VIRTIO_BALLOON_INFLATE_MAX_ORDER; + } } =20 static int init_vqs(struct virtio_balloon *vb) @@ -521,6 +585,8 @@ static int init_vqs(struct virtio_balloon *vb) callbacks[VIRTIO_BALLOON_VQ_FREE_PAGE] =3D NULL; names[VIRTIO_BALLOON_VQ_FREE_PAGE] =3D NULL; names[VIRTIO_BALLOON_VQ_REPORTING] =3D NULL; + names[VIRTIO_BALLOON_VQ_INFLATE_CONT] =3D NULL; + callbacks[VIRTIO_BALLOON_VQ_INFLATE_CONT] =3D NULL; =20 if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ)) { names[VIRTIO_BALLOON_VQ_STATS] =3D "stats"; @@ -537,6 +603,11 @@ static int init_vqs(struct virtio_balloon *vb) callbacks[VIRTIO_BALLOON_VQ_REPORTING] =3D balloon_ack; } =20 + if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_CONT_PAGES)) { + names[VIRTIO_BALLOON_VQ_INFLATE_CONT] =3D "inflate_cont"; + callbacks[VIRTIO_BALLOON_VQ_INFLATE_CONT] =3D balloon_ack; + } + err =3D vb->vdev->config->find_vqs(vb->vdev, VIRTIO_BALLOON_VQ_MAX, vqs, callbacks, names, NULL, NULL); if (err) @@ -572,6 +643,10 @@ static int init_vqs(struct virtio_balloon *vb) if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_REPORTING)) vb->reporting_vq =3D vqs[VIRTIO_BALLOON_VQ_REPORTING]; =20 + if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_CONT_PAGES)) + vb->inflate_cont_vq + =3D vqs[VIRTIO_BALLOON_VQ_INFLATE_CONT]; + return 0; } =20 @@ -997,6 +1072,11 @@ static int virtballoon_probe(struct virtio_device *vd= ev) goto out_unregister_oom; } =20 + if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_CONT_PAGES)) + vb->current_pages_order =3D VIRTIO_BALLOON_INFLATE_MAX_ORDER; + else + vb->current_pages_order =3D 0; + virtio_device_ready(vdev); =20 if (towards_target(vb)) @@ -1131,6 +1211,7 @@ static unsigned int features[] =3D { VIRTIO_BALLOON_F_FREE_PAGE_HINT, VIRTIO_BALLOON_F_PAGE_POISON, VIRTIO_BALLOON_F_REPORTING, + VIRTIO_BALLOON_F_CONT_PAGES, }; =20 static struct virtio_driver virtio_balloon_driver =3D { diff --git a/include/linux/balloon_compaction.h b/include/linux/balloon_com= paction.h index 338aa27..8180bbf 100644 --- a/include/linux/balloon_compaction.h +++ b/include/linux/balloon_compaction.h @@ -60,15 +60,22 @@ struct balloon_dev_info { struct inode *inode; }; =20 -extern struct page *balloon_page_alloc(void); +extern struct page *balloon_pages_alloc(unsigned int order); extern void balloon_page_enqueue(struct balloon_dev_info *b_dev_info, struct page *page); +extern void balloon_pages_enqueue(struct balloon_dev_info *b_dev_info, + struct page *page, unsigned int order); extern struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_in= fo); extern size_t balloon_page_list_enqueue(struct balloon_dev_info *b_dev_inf= o, struct list_head *pages); extern size_t balloon_page_list_dequeue(struct balloon_dev_info *b_dev_inf= o, struct list_head *pages, size_t n_req_pages); =20 +static inline struct page *balloon_page_alloc(void) +{ + return balloon_pages_alloc(0); +} + static inline void balloon_devinfo_init(struct balloon_dev_info *balloon) { balloon->isolated_pages =3D 0; diff --git a/include/uapi/linux/virtio_balloon.h b/include/uapi/linux/virti= o_balloon.h index dc3e656..4d0151a 100644 --- a/include/uapi/linux/virtio_balloon.h +++ b/include/uapi/linux/virtio_balloon.h @@ -37,6 +37,7 @@ #define VIRTIO_BALLOON_F_FREE_PAGE_HINT 3 /* VQ to report free pages */ #define VIRTIO_BALLOON_F_PAGE_POISON 4 /* Guest is using page poisoning */ #define VIRTIO_BALLOON_F_REPORTING 5 /* Page reporting virtqueue */ +#define VIRTIO_BALLOON_F_CONT_PAGES 6 /* VQ to report continuous pages */ =20 /* Size of a PFN in the balloon interface. */ #define VIRTIO_BALLOON_PFN_SHIFT 12 diff --git a/mm/balloon_compaction.c b/mm/balloon_compaction.c index 26de020..397d0b9 100644 --- a/mm/balloon_compaction.c +++ b/mm/balloon_compaction.c @@ -112,8 +112,8 @@ size_t balloon_page_list_dequeue(struct balloon_dev_inf= o *b_dev_info, EXPORT_SYMBOL_GPL(balloon_page_list_dequeue); =20 /* - * balloon_page_alloc - allocates a new page for insertion into the balloon - * page list. + * balloon_pages_alloc - allocates a new page for insertion into the ballo= on + * page list. * * Driver must call this function to properly allocate a new balloon page. * Driver must call balloon_page_enqueue before definitively removing the = page @@ -121,14 +121,19 @@ EXPORT_SYMBOL_GPL(balloon_page_list_dequeue); * * Return: struct page for the allocated page or NULL on allocation failur= e. */ -struct page *balloon_page_alloc(void) +struct page *balloon_pages_alloc(unsigned int order) { - struct page *page =3D alloc_page(balloon_mapping_gfp_mask() | - __GFP_NOMEMALLOC | __GFP_NORETRY | - __GFP_NOWARN); - return page; + gfp_t gfp_mask; + + if (order > 1) + gfp_mask =3D __GFP_RETRY_MAYFAIL; + else + gfp_mask =3D __GFP_NORETRY; + + return alloc_pages(balloon_mapping_gfp_mask() | + gfp_mask | __GFP_NOMEMALLOC | __GFP_NOWARN, order); } -EXPORT_SYMBOL_GPL(balloon_page_alloc); +EXPORT_SYMBOL_GPL(balloon_pages_alloc); =20 /* * balloon_page_enqueue - inserts a new page into the balloon page list. @@ -155,6 +160,26 @@ void balloon_page_enqueue(struct balloon_dev_info *b_d= ev_info, EXPORT_SYMBOL_GPL(balloon_page_enqueue); =20 /* + * balloon_pages_enqueue - inserts continuous pages into the balloon page = list. + */ +void balloon_pages_enqueue(struct balloon_dev_info *b_dev_info, + struct page *page, unsigned int order) +{ + unsigned long flags, pfn, last_pfn; + + pfn =3D page_to_pfn(page); + last_pfn =3D pfn + (1 << order) - 1; + + spin_lock_irqsave(&b_dev_info->pages_lock, flags); + for (; pfn <=3D last_pfn; pfn++) { + page =3D pfn_to_page(pfn); + balloon_page_enqueue_one(b_dev_info, page); + } + spin_unlock_irqrestore(&b_dev_info->pages_lock, flags); +} +EXPORT_SYMBOL_GPL(balloon_pages_enqueue); + +/* * balloon_page_dequeue - removes a page from balloon's page list and retu= rns * its address to allow the driver to release the page. * @b_dev_info: balloon device decriptor where we will grab a page from. --=20 2.7.4 From nobody Sat Nov 15 11:54:34 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1594867437; cv=none; d=zohomail.com; s=zohoarc; b=S7E4jlr/u6AnL/9tuNf6sPUxy3viXmq2NigbXwpN/Kpq6+lzEkkWrHL6uOwUzOMWpDaZWVVZPRoxTY1uX7SHCK3LzTzzBtN4fqF6JGPwLfHctplHe7S3+1YcCc0bPPS4HIYhkQbOWoIy5ua//B5SkmS5gQ12W/zFDyfxU4Ow2rI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1594867437; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To; bh=cZCg2XkIuk49pa3EqRYv7VtiF8ctad/Pe1JBIIwi35Y=; b=nCCt18N+0k1WtdjTBgytBqU+8dFp7AYavGbAl2cdgfrNlEbSJRZ6BMvH/V8j7eg2lKfDrNePXvJOuP6Jj+5EeRlL+tQxCMEElFuA30dOrvk6NwohLgHInSdpBR6mbPTejL2X+AJCy+NvwSnd3myNlqojpc/oBKrjPG4PMqtKBUo= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1594867437057782.2428030598531; Wed, 15 Jul 2020 19:43:57 -0700 (PDT) Received: from localhost ([::1]:41652 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jvtsJ-00074u-R3 for importer@patchew.org; Wed, 15 Jul 2020 22:43:55 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37108) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jvtrD-0005aa-1k for qemu-devel@nongnu.org; Wed, 15 Jul 2020 22:42:47 -0400 Received: from out4436.biz.mail.alibaba.com ([47.88.44.36]:28600) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jvtrB-00042k-4w for qemu-devel@nongnu.org; Wed, 15 Jul 2020 22:42:46 -0400 Received: from localhost(mailfrom:teawaterz@linux.alibaba.com fp:SMTPD_---0U2rWAKu_1594867354) by smtp.aliyun-inc.com(127.0.0.1); Thu, 16 Jul 2020 10:42:37 +0800 X-Alimail-AntiSpam: AC=PASS; BC=-1|-1; BR=01201311R131e4; CH=green; DM=||false|; DS=||; FP=0|-1|-1|-1|0|-1|-1|-1; HT=e01e01419; MF=teawaterz@linux.alibaba.com; NM=1; PH=DS; RN=11; SR=0; TI=SMTPD_---0U2rWAKu_1594867354; From: Hui Zhu To: mst@redhat.com, david@redhat.com, jasowang@redhat.com, akpm@linux-foundation.org, virtualization@lists.linux-foundation.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org, qemu-devel@nongnu.org, virtio-dev@lists.oasis-open.org Subject: [RFC for qemu v4 1/2] virtio_balloon: Add cont-pages and icvq Date: Thu, 16 Jul 2020 10:41:54 +0800 Message-Id: <1594867315-8626-5-git-send-email-teawater@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1594867315-8626-1-git-send-email-teawater@gmail.com> References: <1594867315-8626-1-git-send-email-teawater@gmail.com> Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=47.88.44.36; envelope-from=teawaterz@linux.alibaba.com; helo=out4436.biz.mail.alibaba.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/07/15 22:42:26 X-ACL-Warn: Detected OS = Linux 3.1-3.10 X-Spam_score_int: -71 X-Spam_score: -7.2 X-Spam_bar: ------- X-Spam_report: (-7.2 / 5.0 requ) BAYES_00=-1.9, DKIM_ADSP_CUSTOM_MED=0.001, FORGED_GMAIL_RCVD=1, FREEMAIL_FORGED_FROMDOMAIN=1, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=1, NML_ADSP_CUSTOM_MED=0.9, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=-1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, UNPARSEABLE_RELAY=0.001, USER_IN_DEF_SPF_WL=-7.5 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Hui Zhu , Hui Zhu Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This commit adds cont-pages option to virtio_balloon. virtio_balloon will open flags VIRTIO_BALLOON_F_CONT_PAGES with this option. And it add a vq icvq to inflate continuous pages. When VIRTIO_BALLOON_F_CONT_PAGES is set, try to get continuous pages from icvq and use madvise MADV_DONTNEED release the pages. Signed-off-by: Hui Zhu --- hw/virtio/virtio-balloon.c | 80 ++++++++++++++++-----= ---- include/hw/virtio/virtio-balloon.h | 2 +- include/standard-headers/linux/virtio_balloon.h | 1 + 3 files changed, 55 insertions(+), 28 deletions(-) diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c index a4729f7..d36a5c8 100644 --- a/hw/virtio/virtio-balloon.c +++ b/hw/virtio/virtio-balloon.c @@ -65,23 +65,26 @@ static bool virtio_balloon_pbp_matches(PartiallyBalloon= edPage *pbp, =20 static void balloon_inflate_page(VirtIOBalloon *balloon, MemoryRegion *mr, hwaddr mr_offset, + size_t size, PartiallyBalloonedPage *pbp) { void *addr =3D memory_region_get_ram_ptr(mr) + mr_offset; ram_addr_t rb_offset, rb_aligned_offset, base_gpa; RAMBlock *rb; size_t rb_page_size; - int subpages; + int subpages, pages_num; =20 /* XXX is there a better way to get to the RAMBlock than via a * host address? */ rb =3D qemu_ram_block_from_host(addr, false, &rb_offset); rb_page_size =3D qemu_ram_pagesize(rb); =20 + size &=3D ~(rb_page_size - 1); + if (rb_page_size =3D=3D BALLOON_PAGE_SIZE) { /* Easy case */ =20 - ram_block_discard_range(rb, rb_offset, rb_page_size); + ram_block_discard_range(rb, rb_offset, size); /* We ignore errors from ram_block_discard_range(), because it * has already reported them, and failing to discard a balloon * page is not fatal */ @@ -99,32 +102,38 @@ static void balloon_inflate_page(VirtIOBalloon *balloo= n, =20 rb_aligned_offset =3D QEMU_ALIGN_DOWN(rb_offset, rb_page_size); subpages =3D rb_page_size / BALLOON_PAGE_SIZE; - base_gpa =3D memory_region_get_ram_addr(mr) + mr_offset - - (rb_offset - rb_aligned_offset); =20 - if (pbp->bitmap && !virtio_balloon_pbp_matches(pbp, base_gpa)) { - /* We've partially ballooned part of a host page, but now - * we're trying to balloon part of a different one. Too hard, - * give up on the old partial page */ - virtio_balloon_pbp_free(pbp); - } + for (pages_num =3D size / BALLOON_PAGE_SIZE; + pages_num > 0; pages_num--) { + base_gpa =3D memory_region_get_ram_addr(mr) + mr_offset - + (rb_offset - rb_aligned_offset); =20 - if (!pbp->bitmap) { - virtio_balloon_pbp_alloc(pbp, base_gpa, subpages); - } + if (pbp->bitmap && !virtio_balloon_pbp_matches(pbp, base_gpa)) { + /* We've partially ballooned part of a host page, but now + * we're trying to balloon part of a different one. Too hard, + * give up on the old partial page */ + virtio_balloon_pbp_free(pbp); + } =20 - set_bit((rb_offset - rb_aligned_offset) / BALLOON_PAGE_SIZE, - pbp->bitmap); + if (!pbp->bitmap) { + virtio_balloon_pbp_alloc(pbp, base_gpa, subpages); + } =20 - if (bitmap_full(pbp->bitmap, subpages)) { - /* We've accumulated a full host page, we can actually discard - * it now */ + set_bit((rb_offset - rb_aligned_offset) / BALLOON_PAGE_SIZE, + pbp->bitmap); =20 - ram_block_discard_range(rb, rb_aligned_offset, rb_page_size); - /* We ignore errors from ram_block_discard_range(), because it - * has already reported them, and failing to discard a balloon - * page is not fatal */ - virtio_balloon_pbp_free(pbp); + if (bitmap_full(pbp->bitmap, subpages)) { + /* We've accumulated a full host page, we can actually discard + * it now */ + + ram_block_discard_range(rb, rb_aligned_offset, rb_page_size); + /* We ignore errors from ram_block_discard_range(), because it + * has already reported them, and failing to discard a balloon + * page is not fatal */ + virtio_balloon_pbp_free(pbp); + } + + mr_offset +=3D BALLOON_PAGE_SIZE; } } =20 @@ -340,12 +349,21 @@ static void virtio_balloon_handle_output(VirtIODevice= *vdev, VirtQueue *vq) while (iov_to_buf(elem->out_sg, elem->out_num, offset, &pfn, 4) = =3D=3D 4) { unsigned int p =3D virtio_ldl_p(vdev, &pfn); hwaddr pa; + unsigned int psize =3D BALLOON_PAGE_SIZE; =20 pa =3D (hwaddr) p << VIRTIO_BALLOON_PFN_SHIFT; offset +=3D 4; =20 - section =3D memory_region_find(get_system_memory(), pa, - BALLOON_PAGE_SIZE); + if (vq =3D=3D s->icvq) { + uint32_t psize_ptr; + if (iov_to_buf(elem->out_sg, elem->out_num, offset, &psize= _ptr, 4) !=3D 4) { + break; + } + psize =3D virtio_ldl_p(vdev, &psize_ptr); + offset +=3D 4; + } + + section =3D memory_region_find(get_system_memory(), pa, psize); if (!section.mr) { trace_virtio_balloon_bad_addr(pa); continue; @@ -361,9 +379,10 @@ static void virtio_balloon_handle_output(VirtIODevice = *vdev, VirtQueue *vq) trace_virtio_balloon_handle_output(memory_region_name(section.= mr), pa); if (!qemu_balloon_is_inhibited()) { - if (vq =3D=3D s->ivq) { + if (vq =3D=3D s->ivq || vq =3D=3D s->icvq) { balloon_inflate_page(s, section.mr, - section.offset_within_region, &pb= p); + section.offset_within_region, + psize, &pbp); } else if (vq =3D=3D s->dvq) { balloon_deflate_page(s, section.mr, section.offset_wit= hin_region); } else { @@ -816,6 +835,11 @@ static void virtio_balloon_device_realize(DeviceState = *dev, Error **errp) virtio_error(vdev, "iothread is missing"); } } + + if (virtio_has_feature(s->host_features, VIRTIO_BALLOON_F_CONT_PAGES))= { + s->icvq =3D virtio_add_queue(vdev, 128, virtio_balloon_handle_outp= ut); + } + reset_stats(s); } =20 @@ -916,6 +940,8 @@ static Property virtio_balloon_properties[] =3D { VIRTIO_BALLOON_F_DEFLATE_ON_OOM, false), DEFINE_PROP_BIT("free-page-hint", VirtIOBalloon, host_features, VIRTIO_BALLOON_F_FREE_PAGE_HINT, false), + DEFINE_PROP_BIT("cont-pages", VirtIOBalloon, host_features, + VIRTIO_BALLOON_F_CONT_PAGES, false), /* QEMU 4.0 accidentally changed the config size even when free-page-h= int * is disabled, resulting in QEMU 3.1 migration incompatibility. This * property retains this quirk for QEMU 4.1 machine types. diff --git a/include/hw/virtio/virtio-balloon.h b/include/hw/virtio/virtio-= balloon.h index d1c968d..6a2514d 100644 --- a/include/hw/virtio/virtio-balloon.h +++ b/include/hw/virtio/virtio-balloon.h @@ -42,7 +42,7 @@ enum virtio_balloon_free_page_report_status { =20 typedef struct VirtIOBalloon { VirtIODevice parent_obj; - VirtQueue *ivq, *dvq, *svq, *free_page_vq; + VirtQueue *ivq, *dvq, *svq, *free_page_vq, *icvq; uint32_t free_page_report_status; uint32_t num_pages; uint32_t actual; diff --git a/include/standard-headers/linux/virtio_balloon.h b/include/stan= dard-headers/linux/virtio_balloon.h index 9375ca2..033926c 100644 --- a/include/standard-headers/linux/virtio_balloon.h +++ b/include/standard-headers/linux/virtio_balloon.h @@ -36,6 +36,7 @@ #define VIRTIO_BALLOON_F_DEFLATE_ON_OOM 2 /* Deflate balloon on OOM */ #define VIRTIO_BALLOON_F_FREE_PAGE_HINT 3 /* VQ to report free pages */ #define VIRTIO_BALLOON_F_PAGE_POISON 4 /* Guest is using page poisoning */ +#define VIRTIO_BALLOON_F_CONT_PAGES 6 /* VQ to report continuous pages */ =20 /* Size of a PFN in the balloon interface. */ #define VIRTIO_BALLOON_PFN_SHIFT 12 --=20 2.7.4 From nobody Sat Nov 15 11:54:34 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1594867445; cv=none; d=zohomail.com; s=zohoarc; b=S9FM41axo+tiZDuw7l6EsQGBhIrkFjCCRKq5N8pvYVtfddCulQhWTLQr5masO/ahL9i7wqZeBFZk9nO76woVdnR8UcMcxTEEBMrMks1AnDjeMtx9x7yz9egQfYJvfjyMQV5KJYvNbCkilol7Y6VT18ReFZOIaSxYnAWk14bdsaI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1594867445; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To; bh=Yo/EITui3fJl1a4PocnOpuLzibtram7gUwfEqVQg94c=; b=FMzcyk8DJel98imZIfCWBQMK+euFOKfBMe+U9YmrbaOl+FMLUF+9Zv2zW6M1Iab8EJ0g3R9VsbOaWj7bwB6ljcYB/TQthm+kDF41F4v4+3FG4hCoImWf4tEmP/tOkUc5O9UyNUYqrxBkLabPzdptBeQrp55GV8TneIwy7J4eRw8= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1594867445406842.54853573429; Wed, 15 Jul 2020 19:44:05 -0700 (PDT) Received: from localhost ([::1]:42564 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jvtsR-0007S5-UK for importer@patchew.org; Wed, 15 Jul 2020 22:44:03 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37144) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jvtrK-0005mj-7r for qemu-devel@nongnu.org; Wed, 15 Jul 2020 22:42:54 -0400 Received: from out4436.biz.mail.alibaba.com ([47.88.44.36]:1107) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jvtrI-00046d-1I for qemu-devel@nongnu.org; Wed, 15 Jul 2020 22:42:53 -0400 Received: from localhost(mailfrom:teawaterz@linux.alibaba.com fp:SMTPD_---0U2rTvA2_1594867348) by smtp.aliyun-inc.com(127.0.0.1); Thu, 16 Jul 2020 10:42:32 +0800 X-Alimail-AntiSpam: AC=PASS; BC=-1|-1; BR=01201311R831e4; CH=green; DM=||false|; DS=||; FP=0|-1|-1|-1|0|-1|-1|-1; HT=e01e04407; MF=teawaterz@linux.alibaba.com; NM=1; PH=DS; RN=11; SR=0; TI=SMTPD_---0U2rTvA2_1594867348; From: Hui Zhu To: mst@redhat.com, david@redhat.com, jasowang@redhat.com, akpm@linux-foundation.org, virtualization@lists.linux-foundation.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org, qemu-devel@nongnu.org, virtio-dev@lists.oasis-open.org Subject: [RFC for Linux v4 2/2] virtio_balloon: Add deflate_cont_vq to deflate continuous pages Date: Thu, 16 Jul 2020 10:41:52 +0800 Message-Id: <1594867315-8626-3-git-send-email-teawater@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1594867315-8626-1-git-send-email-teawater@gmail.com> References: <1594867315-8626-1-git-send-email-teawater@gmail.com> Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=47.88.44.36; envelope-from=teawaterz@linux.alibaba.com; helo=out4436.biz.mail.alibaba.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/07/15 22:42:26 X-ACL-Warn: Detected OS = Linux 3.1-3.10 X-Spam_score_int: -71 X-Spam_score: -7.2 X-Spam_bar: ------- X-Spam_report: (-7.2 / 5.0 requ) BAYES_00=-1.9, DKIM_ADSP_CUSTOM_MED=0.001, FORGED_GMAIL_RCVD=1, FREEMAIL_FORGED_FROMDOMAIN=1, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=1, NML_ADSP_CUSTOM_MED=0.9, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=-1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, UNPARSEABLE_RELAY=0.001, USER_IN_DEF_SPF_WL=-7.5 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Hui Zhu , Hui Zhu Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This commit adds a vq deflate_cont_vq to deflate continuous pages. When VIRTIO_BALLOON_F_CONT_PAGES is set, call leak_balloon_cont to leak the balloon. leak_balloon_cont will call balloon_page_list_dequeue_cont get continuous pages from balloon and report them use deflate_cont_vq. Signed-off-by: Hui Zhu --- drivers/virtio/virtio_balloon.c | 73 ++++++++++++++++++++++++++++++++--= -- include/linux/balloon_compaction.h | 3 ++ mm/balloon_compaction.c | 76 ++++++++++++++++++++++++++++++++++= ++++ 3 files changed, 144 insertions(+), 8 deletions(-) diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloo= n.c index b89f566..258b3d9 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -44,6 +44,7 @@ =20 #define VIRTIO_BALLOON_INFLATE_MAX_ORDER min((int) (sizeof(__virtio32) * B= ITS_PER_BYTE - \ 1 - PAGE_SHIFT), (MAX_ORDER-1)) +#define VIRTIO_BALLOON_DEFLATE_MAX_PAGES_NUM (((__virtio32)~0U) >> PAGE_SH= IFT) =20 #ifdef CONFIG_BALLOON_COMPACTION static struct vfsmount *balloon_mnt; @@ -56,6 +57,7 @@ enum virtio_balloon_vq { VIRTIO_BALLOON_VQ_FREE_PAGE, VIRTIO_BALLOON_VQ_REPORTING, VIRTIO_BALLOON_VQ_INFLATE_CONT, + VIRTIO_BALLOON_VQ_DEFLATE_CONT, VIRTIO_BALLOON_VQ_MAX }; =20 @@ -65,7 +67,8 @@ enum virtio_balloon_config_read { =20 struct virtio_balloon { struct virtio_device *vdev; - struct virtqueue *inflate_vq, *deflate_vq, *stats_vq, *free_page_vq, *inf= late_cont_vq; + struct virtqueue *inflate_vq, *deflate_vq, *stats_vq, *free_page_vq, + *inflate_cont_vq, *deflate_cont_vq; =20 /* Balloon's own wq for cpu-intensive work items */ struct workqueue_struct *balloon_wq; @@ -215,6 +218,16 @@ static void set_page_pfns(struct virtio_balloon *vb, page_to_balloon_pfn(page) + i); } =20 +static void set_page_pfns_size(struct virtio_balloon *vb, + __virtio32 pfns[], struct page *page, + size_t size) +{ + /* Set the first pfn of the continuous pages. */ + pfns[0] =3D cpu_to_virtio32(vb->vdev, page_to_balloon_pfn(page)); + /* Set the size of the continuous pages. */ + pfns[1] =3D (__virtio32) size; +} + static void set_page_pfns_order(struct virtio_balloon *vb, __virtio32 pfns[], struct page *page, unsigned int order) @@ -222,10 +235,7 @@ static void set_page_pfns_order(struct virtio_balloon = *vb, if (order =3D=3D 0) return set_page_pfns(vb, pfns, page); =20 - /* Set the first pfn of the continuous pages. */ - pfns[0] =3D cpu_to_virtio32(vb->vdev, page_to_balloon_pfn(page)); - /* Set the size of the continuous pages. */ - pfns[1] =3D PAGE_SIZE << order; + set_page_pfns_size(vb, pfns, page, PAGE_SIZE << order); } =20 static unsigned fill_balloon(struct virtio_balloon *vb, size_t num) @@ -367,6 +377,42 @@ static unsigned leak_balloon(struct virtio_balloon *vb= , size_t num) return num_freed_pages; } =20 +static unsigned int leak_balloon_cont(struct virtio_balloon *vb, size_t nu= m) +{ + unsigned int num_freed_pages; + struct balloon_dev_info *vb_dev_info =3D &vb->vb_dev_info; + LIST_HEAD(pages); + size_t num_pages; + + mutex_lock(&vb->balloon_lock); + for (vb->num_pfns =3D 0, num_freed_pages =3D 0; + vb->num_pfns < ARRAY_SIZE(vb->pfns) && num_freed_pages < num; + vb->num_pfns +=3D 2, + num_freed_pages +=3D num_pages << (PAGE_SHIFT - VIRTIO_BALLOON_PFN_S= HIFT)) { + struct page *page; + + num_pages =3D balloon_page_list_dequeue_cont(vb_dev_info, &pages, &page, + min_t(size_t, + VIRTIO_BALLOON_DEFLATE_MAX_PAGES_NUM, + num - num_freed_pages)); + if (!num_pages) + break; + set_page_pfns_size(vb, vb->pfns + vb->num_pfns, page, num_pages << PAGE_= SHIFT); + } + vb->num_pages -=3D num_freed_pages; + + /* + * Note that if + * virtio_has_feature(vdev, VIRTIO_BALLOON_F_MUST_TELL_HOST); + * is true, we *have* to do it in this order + */ + if (vb->num_pfns !=3D 0) + tell_host(vb, vb->deflate_cont_vq); + release_pages_balloon(vb, &pages); + mutex_unlock(&vb->balloon_lock); + return num_freed_pages; +} + static inline void update_stat(struct virtio_balloon *vb, int idx, u16 tag, u64 val) { @@ -551,8 +597,12 @@ static void update_balloon_size_func(struct work_struc= t *work) =20 if (diff > 0) diff -=3D fill_balloon(vb, diff); - else - diff +=3D leak_balloon(vb, -diff); + else { + if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_CONT_PAGES)) + diff +=3D leak_balloon_cont(vb, -diff); + else + diff +=3D leak_balloon(vb, -diff); + } update_balloon_size(vb); =20 if (diff) @@ -587,6 +637,8 @@ static int init_vqs(struct virtio_balloon *vb) names[VIRTIO_BALLOON_VQ_REPORTING] =3D NULL; names[VIRTIO_BALLOON_VQ_INFLATE_CONT] =3D NULL; callbacks[VIRTIO_BALLOON_VQ_INFLATE_CONT] =3D NULL; + names[VIRTIO_BALLOON_VQ_DEFLATE_CONT] =3D NULL; + callbacks[VIRTIO_BALLOON_VQ_DEFLATE_CONT] =3D NULL; =20 if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ)) { names[VIRTIO_BALLOON_VQ_STATS] =3D "stats"; @@ -606,6 +658,8 @@ static int init_vqs(struct virtio_balloon *vb) if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_CONT_PAGES)) { names[VIRTIO_BALLOON_VQ_INFLATE_CONT] =3D "inflate_cont"; callbacks[VIRTIO_BALLOON_VQ_INFLATE_CONT] =3D balloon_ack; + names[VIRTIO_BALLOON_VQ_DEFLATE_CONT] =3D "deflate_cont"; + callbacks[VIRTIO_BALLOON_VQ_DEFLATE_CONT] =3D balloon_ack; } =20 err =3D vb->vdev->config->find_vqs(vb->vdev, VIRTIO_BALLOON_VQ_MAX, @@ -643,9 +697,12 @@ static int init_vqs(struct virtio_balloon *vb) if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_REPORTING)) vb->reporting_vq =3D vqs[VIRTIO_BALLOON_VQ_REPORTING]; =20 - if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_CONT_PAGES)) + if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_CONT_PAGES)) { vb->inflate_cont_vq =3D vqs[VIRTIO_BALLOON_VQ_INFLATE_CONT]; + vb->deflate_cont_vq + =3D vqs[VIRTIO_BALLOON_VQ_DEFLATE_CONT]; + } =20 return 0; } diff --git a/include/linux/balloon_compaction.h b/include/linux/balloon_com= paction.h index 8180bbf..7cb2a75 100644 --- a/include/linux/balloon_compaction.h +++ b/include/linux/balloon_compaction.h @@ -70,6 +70,9 @@ extern size_t balloon_page_list_enqueue(struct balloon_de= v_info *b_dev_info, struct list_head *pages); extern size_t balloon_page_list_dequeue(struct balloon_dev_info *b_dev_inf= o, struct list_head *pages, size_t n_req_pages); +extern size_t balloon_page_list_dequeue_cont(struct balloon_dev_info *b_de= v_info, + struct list_head *pages, struct page **first_page, + size_t max_req_pages); =20 static inline struct page *balloon_page_alloc(void) { diff --git a/mm/balloon_compaction.c b/mm/balloon_compaction.c index 397d0b9..ea7d91f 100644 --- a/mm/balloon_compaction.c +++ b/mm/balloon_compaction.c @@ -111,6 +111,82 @@ size_t balloon_page_list_dequeue(struct balloon_dev_in= fo *b_dev_info, } EXPORT_SYMBOL_GPL(balloon_page_list_dequeue); =20 +/** + * balloon_page_list_dequeue_cont() - removes continuous pages from balloo= n's page list + * and returns a list of the continuous pages. + * @b_dev_info: balloon device decriptor where we will grab a page from. + * @pages: pointer to the list of pages that would be returned to the call= er. + * @max_req_pages: max number of requested pages. + * + * Driver must call this function to properly de-allocate a previous enlis= ted + * balloon pages before definitively releasing it back to the guest system. + * This function tries to remove @max_req_pages continuous pages from the = ballooned + * pages and return them to the caller in the @pages list. + * + * Note that this function may fail to dequeue some pages even if the ball= oon + * isn't empty - since the page list can be temporarily empty due to compa= ction + * of isolated pages. + * + * Return: number of pages that were added to the @pages list. + */ +size_t balloon_page_list_dequeue_cont(struct balloon_dev_info *b_dev_info, + struct list_head *pages, struct page **first_page, + size_t max_req_pages) +{ + struct page *page, *tmp; + unsigned long flags, tail_pfn; + size_t n_pages =3D 0; + bool got_first =3D false; + + spin_lock_irqsave(&b_dev_info->pages_lock, flags); + list_for_each_entry_safe_reverse(page, tmp, &b_dev_info->pages, lru) { + unsigned long pfn; + + if (n_pages =3D=3D max_req_pages) + break; + + pfn =3D page_to_pfn(page); + + if (got_first && pfn !=3D tail_pfn + 1) + break; + + /* + * Block others from accessing the 'page' while we get around to + * establishing additional references and preparing the 'page' + * to be released by the balloon driver. + */ + if (!trylock_page(page)) { + if (!got_first) + continue; + else + break; + } + + if (IS_ENABLED(CONFIG_BALLOON_COMPACTION) && PageIsolated(page)) { + /* raced with isolation */ + unlock_page(page); + if (!got_first) + continue; + else + break; + } + balloon_page_delete(page); + __count_vm_event(BALLOON_DEFLATE); + list_add(&page->lru, pages); + unlock_page(page); + n_pages++; + tail_pfn =3D pfn; + if (!got_first) { + got_first =3D true; + *first_page =3D page; + } + } + spin_unlock_irqrestore(&b_dev_info->pages_lock, flags); + + return n_pages; +} +EXPORT_SYMBOL_GPL(balloon_page_list_dequeue_cont); + /* * balloon_pages_alloc - allocates a new page for insertion into the ballo= on * page list. --=20 2.7.4 From nobody Sat Nov 15 11:54:34 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1594867516; cv=none; d=zohomail.com; s=zohoarc; b=nve5T5m6CSu9nbBBYwjT+WvZzq2X4vnlv8yTVbH7Ysi8TWHzuscpz4vtU3mf768oIvTgOheQ1BemoAzgVvK9I0PA8jQs+1+ZuwOjewgvIU4epu2NWmknhmUqyNXS5DgWNe4zK+TcinfFhdAP/XJur/jcVB7x32eG5Q+PUF3unMc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1594867516; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To; bh=4uUfyzIHX5F8nhg7nCi52MdMV93XJEtQEkOKCnq7iuQ=; b=aq9l9mMfJRWRKk7UxTWgdtRgHG5izeUM6EanvrWDNJOxtWpOirVaCmS1e1rbkcCRY/Po82MUVLE2M4h9N3TZYeLiCA4Smt4Gp1Gj6QE6BoOqikdwqMVEq062u0oEYET+iVDJBjFYfNfD/X62E0t4pYw/2IJEM1Q+JeGyJylcBqQ= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1594867516721870.0119889394088; Wed, 15 Jul 2020 19:45:16 -0700 (PDT) Received: from localhost ([::1]:48368 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jvttb-0001Lp-Ic for importer@patchew.org; Wed, 15 Jul 2020 22:45:15 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37120) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jvtrE-0005cH-HI for qemu-devel@nongnu.org; Wed, 15 Jul 2020 22:42:48 -0400 Received: from out4436.biz.mail.alibaba.com ([47.88.44.36]:26625) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jvtrC-00043n-PW for qemu-devel@nongnu.org; Wed, 15 Jul 2020 22:42:48 -0400 Received: from localhost(mailfrom:teawaterz@linux.alibaba.com fp:SMTPD_---0U2rVPuE_1594867357) by smtp.aliyun-inc.com(127.0.0.1); Thu, 16 Jul 2020 10:42:39 +0800 X-Alimail-AntiSpam: AC=PASS; BC=-1|-1; BR=01201311R151e4; CH=green; DM=||false|; DS=||; FP=0|-1|-1|-1|0|-1|-1|-1; HT=e01f04427; MF=teawaterz@linux.alibaba.com; NM=1; PH=DS; RN=11; SR=0; TI=SMTPD_---0U2rVPuE_1594867357; From: Hui Zhu To: mst@redhat.com, david@redhat.com, jasowang@redhat.com, akpm@linux-foundation.org, virtualization@lists.linux-foundation.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org, qemu-devel@nongnu.org, virtio-dev@lists.oasis-open.org Subject: [RFC for qemu v4 2/2] virtio_balloon: Add dcvq to deflate continuous pages Date: Thu, 16 Jul 2020 10:41:55 +0800 Message-Id: <1594867315-8626-6-git-send-email-teawater@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1594867315-8626-1-git-send-email-teawater@gmail.com> References: <1594867315-8626-1-git-send-email-teawater@gmail.com> Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=47.88.44.36; envelope-from=teawaterz@linux.alibaba.com; helo=out4436.biz.mail.alibaba.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/07/15 22:42:26 X-ACL-Warn: Detected OS = Linux 3.1-3.10 X-Spam_score_int: -71 X-Spam_score: -7.2 X-Spam_bar: ------- X-Spam_report: (-7.2 / 5.0 requ) BAYES_00=-1.9, DKIM_ADSP_CUSTOM_MED=0.001, FORGED_GMAIL_RCVD=1, FREEMAIL_FORGED_FROMDOMAIN=1, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=1, NML_ADSP_CUSTOM_MED=0.9, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=-1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, UNPARSEABLE_RELAY=0.001, USER_IN_DEF_SPF_WL=-7.5 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Hui Zhu , Hui Zhu Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This commit adds a vq dcvq to deflate continuous pages. When VIRTIO_BALLOON_F_CONT_PAGES is set, try to get continuous pages from icvq and use madvise MADV_WILLNEED with the pages. Signed-off-by: Hui Zhu --- hw/virtio/virtio-balloon.c | 14 +++++++++----- include/hw/virtio/virtio-balloon.h | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c index d36a5c8..165adf7 100644 --- a/hw/virtio/virtio-balloon.c +++ b/hw/virtio/virtio-balloon.c @@ -138,7 +138,8 @@ static void balloon_inflate_page(VirtIOBalloon *balloon, } =20 static void balloon_deflate_page(VirtIOBalloon *balloon, - MemoryRegion *mr, hwaddr mr_offset) + MemoryRegion *mr, hwaddr mr_offset, + size_t size) { void *addr =3D memory_region_get_ram_ptr(mr) + mr_offset; ram_addr_t rb_offset; @@ -153,10 +154,11 @@ static void balloon_deflate_page(VirtIOBalloon *ballo= on, rb_page_size =3D qemu_ram_pagesize(rb); =20 host_addr =3D (void *)((uintptr_t)addr & ~(rb_page_size - 1)); + size &=3D ~(rb_page_size - 1); =20 /* When a page is deflated, we hint the whole host page it lives * on, since we can't do anything smaller */ - ret =3D qemu_madvise(host_addr, rb_page_size, QEMU_MADV_WILLNEED); + ret =3D qemu_madvise(host_addr, size, QEMU_MADV_WILLNEED); if (ret !=3D 0) { warn_report("Couldn't MADV_WILLNEED on balloon deflate: %s", strerror(errno)); @@ -354,7 +356,7 @@ static void virtio_balloon_handle_output(VirtIODevice *= vdev, VirtQueue *vq) pa =3D (hwaddr) p << VIRTIO_BALLOON_PFN_SHIFT; offset +=3D 4; =20 - if (vq =3D=3D s->icvq) { + if (vq =3D=3D s->icvq || vq =3D=3D s->dcvq) { uint32_t psize_ptr; if (iov_to_buf(elem->out_sg, elem->out_num, offset, &psize= _ptr, 4) !=3D 4) { break; @@ -383,8 +385,9 @@ static void virtio_balloon_handle_output(VirtIODevice *= vdev, VirtQueue *vq) balloon_inflate_page(s, section.mr, section.offset_within_region, psize, &pbp); - } else if (vq =3D=3D s->dvq) { - balloon_deflate_page(s, section.mr, section.offset_wit= hin_region); + } else if (vq =3D=3D s->dvq || vq =3D=3D s->dcvq) { + balloon_deflate_page(s, section.mr, section.offset_wit= hin_region, + psize); } else { g_assert_not_reached(); } @@ -838,6 +841,7 @@ static void virtio_balloon_device_realize(DeviceState *= dev, Error **errp) =20 if (virtio_has_feature(s->host_features, VIRTIO_BALLOON_F_CONT_PAGES))= { s->icvq =3D virtio_add_queue(vdev, 128, virtio_balloon_handle_outp= ut); + s->dcvq =3D virtio_add_queue(vdev, 128, virtio_balloon_handle_outp= ut); } =20 reset_stats(s); diff --git a/include/hw/virtio/virtio-balloon.h b/include/hw/virtio/virtio-= balloon.h index 6a2514d..848a7fb 100644 --- a/include/hw/virtio/virtio-balloon.h +++ b/include/hw/virtio/virtio-balloon.h @@ -42,7 +42,7 @@ enum virtio_balloon_free_page_report_status { =20 typedef struct VirtIOBalloon { VirtIODevice parent_obj; - VirtQueue *ivq, *dvq, *svq, *free_page_vq, *icvq; + VirtQueue *ivq, *dvq, *svq, *free_page_vq, *icvq, *dcvq; uint32_t free_page_report_status; uint32_t num_pages; uint32_t actual; --=20 2.7.4