Received: by 2002:ac0:8c8e:0:0:0:0:0 with SMTP id r14csp2429ima; Wed, 6 Feb 2019 15:58:10 -0800 (PST) X-Google-Smtp-Source: AHgI3IY8ils539YrZzXgOoSWLoCbOljKttDv5xII2rv4o8M5S7OWocyLPR3xWgvB5qJ8VzAg+Jh0 X-Received: by 2002:a62:2018:: with SMTP id g24mr13668618pfg.100.1549497490156; Wed, 06 Feb 2019 15:58:10 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1549497490; cv=none; d=google.com; s=arc-20160816; b=fZQaY34Y1GC8FA5REshM+v7PkkW+Nt4AHZfCxZdXmLSGJBR0Bxzxw6m3JrXgQDouUa RVMKarrhqMBJpPq2yytPJV2xxtcHK29RzSmdXdppCnFMn/IPWd4vOGQybxyGlLNze6Nv vMHWI2H8Q454U44gCiRdq0yQZ/Qy9tH9eGMBHuq/21zDCoAlQcudfaHXlVjDD0omEAdv h3MkH/TNfrTRr/1qraaOMx5wEdJXoWDZgVuywLUP2/uWXQNk3/4DHhQHRof7QH9mOE4t IgIf/nlUh/B01Y7aGllNBfecIfngVWAndEoinpq78x+A5RefbYtjQZf7pZnUvJh8qwu5 vj+w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from; bh=3cFMgb/nxYwqmGq4qg/P9OpklSsQlX+5KNK3YSshihQ=; b=eIisbM++fP7dMUlXUcgteclPQ0Z1dCPXoi8kV0Ll9F/3ahJh7uEDQoEhIfv6c3dUGM Z1bT6wKtKMpCM5E9FhxQjn6oDT6+TOdHH7eK5uNGS4tIAyMOkhiazzNtb7+IyKlAoZn9 o6AHeKoxdjT+9cCQyVR1YzcbYIODYIOPFTZsi7Xl/NZzHKNO1GLy0ZlzVFO/OcDAS+MS SgoHQlmCvNwGiHe9CAGzFVDE6SPsL/KhEuV0S2vOecjURTSh04KTV5+07J2W1RM8NexR lY1MAJ5GYP0QitDOXdw7zthFn9iuWnR1cL6iRH38V3HiGTwL6Y+W8X+Bm1OmO27j48uu /E1g== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=vmware.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e93si4907487plk.56.2019.02.06.15.57.43; Wed, 06 Feb 2019 15:58:10 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=vmware.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726869AbfBFX50 (ORCPT + 99 others); Wed, 6 Feb 2019 18:57:26 -0500 Received: from ex13-edg-ou-002.vmware.com ([208.91.0.190]:44318 "EHLO EX13-EDG-OU-002.vmware.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726401AbfBFX5Z (ORCPT ); Wed, 6 Feb 2019 18:57:25 -0500 Received: from sc9-mailhost3.vmware.com (10.113.161.73) by EX13-EDG-OU-002.vmware.com (10.113.208.156) with Microsoft SMTP Server id 15.0.1156.6; Wed, 6 Feb 2019 15:56:37 -0800 Received: from ubuntu.localdomain (unknown [10.33.115.182]) by sc9-mailhost3.vmware.com (Postfix) with ESMTP id BAB2C40FBF; Wed, 6 Feb 2019 15:57:11 -0800 (PST) From: Nadav Amit To: Greg Kroah-Hartman CC: Arnd Bergmann , , Julien Freche , Nadav Amit , "Michael S. Tsirkin" , Jason Wang , , Subject: [PATCH 3/6] mm/balloon_compaction: list interfaces Date: Wed, 6 Feb 2019 15:57:03 -0800 Message-ID: <20190206235706.4851-4-namit@vmware.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190206235706.4851-1-namit@vmware.com> References: <20190206235706.4851-1-namit@vmware.com> MIME-Version: 1.0 Content-Type: text/plain Received-SPF: None (EX13-EDG-OU-002.vmware.com: namit@vmware.com does not designate permitted sender hosts) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Introduce interfaces for ballooning enqueueing and dequeueing of a list of pages. These interfaces reduce the overhead of storing and restoring IRQs by batching the operations. In addition they do not panic if the list of pages is empty. Cc: "Michael S. Tsirkin" Cc: Jason Wang Cc: linux-mm@kvack.org Cc: virtualization@lists.linux-foundation.org Reviewed-by: Xavier Deguillard Signed-off-by: Nadav Amit --- include/linux/balloon_compaction.h | 4 + mm/balloon_compaction.c | 139 +++++++++++++++++++++-------- 2 files changed, 105 insertions(+), 38 deletions(-) diff --git a/include/linux/balloon_compaction.h b/include/linux/balloon_compaction.h index 53051f3d8f25..2c5a8e09e413 100644 --- a/include/linux/balloon_compaction.h +++ b/include/linux/balloon_compaction.h @@ -72,6 +72,10 @@ extern struct page *balloon_page_alloc(void); extern void balloon_page_enqueue(struct balloon_dev_info *b_dev_info, struct page *page); extern struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info); +extern void balloon_page_list_enqueue(struct balloon_dev_info *b_dev_info, + struct list_head *pages); +extern int balloon_page_list_dequeue(struct balloon_dev_info *b_dev_info, + struct list_head *pages, int n_req_pages); static inline void balloon_devinfo_init(struct balloon_dev_info *balloon) { diff --git a/mm/balloon_compaction.c b/mm/balloon_compaction.c index ef858d547e2d..b8e82864f82c 100644 --- a/mm/balloon_compaction.c +++ b/mm/balloon_compaction.c @@ -10,6 +10,100 @@ #include #include +static int balloon_page_enqueue_one(struct balloon_dev_info *b_dev_info, + struct page *page) +{ + /* + * Block others from accessing the 'page' when we get around to + * establishing additional references. We should be the only one + * holding a reference to the 'page' at this point. + */ + if (!trylock_page(page)) { + WARN_ONCE(1, "balloon inflation failed to enqueue page\n"); + return -EFAULT; + } + list_del(&page->lru); + balloon_page_insert(b_dev_info, page); + unlock_page(page); + __count_vm_event(BALLOON_INFLATE); + return 0; +} + +/** + * balloon_page_list_enqueue() - inserts a list of pages into the balloon page + * list. + * @b_dev_info: balloon device descriptor where we will insert a new page to + * @pages: pages to enqueue - allocated using balloon_page_alloc. + * + * Driver must call it to properly enqueue a balloon pages before definitively + * removing it from the guest system. + */ +void balloon_page_list_enqueue(struct balloon_dev_info *b_dev_info, + struct list_head *pages) +{ + struct page *page, *tmp; + unsigned long flags; + + spin_lock_irqsave(&b_dev_info->pages_lock, flags); + list_for_each_entry_safe(page, tmp, pages, lru) + balloon_page_enqueue_one(b_dev_info, page); + spin_unlock_irqrestore(&b_dev_info->pages_lock, flags); +} +EXPORT_SYMBOL_GPL(balloon_page_list_enqueue); + +/** + * balloon_page_list_dequeue() - removes pages from balloon's page list and + * returns a list of the 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 caller. + * @n_req_pages: number of requested pages. + * + * Driver must call it to properly de-allocate a previous enlisted balloon pages + * before definetively releasing it back to the guest system. This function + * tries to remove @n_req_pages from the ballooned pages and return it to the + * caller in the @pages list. + * + * Note that this function may fail to dequeue some pages temporarily empty due + * to compaction isolated pages. + * + * Return: number of pages that were added to the @pages list. + */ +int balloon_page_list_dequeue(struct balloon_dev_info *b_dev_info, + struct list_head *pages, int n_req_pages) +{ + struct page *page, *tmp; + unsigned long flags; + int n_pages = 0; + + spin_lock_irqsave(&b_dev_info->pages_lock, flags); + list_for_each_entry_safe(page, tmp, &b_dev_info->pages, lru) { + /* + * Block others from accessing the 'page' while we get around + * establishing additional references and preparing the 'page' + * to be released by the balloon driver. + */ + if (!trylock_page(page)) + continue; + + if (IS_ENABLED(CONFIG_BALLOON_COMPACTION) && + PageIsolated(page)) { + /* raced with isolation */ + unlock_page(page); + continue; + } + balloon_page_delete(page); + __count_vm_event(BALLOON_DEFLATE); + unlock_page(page); + list_add(&page->lru, pages); + if (++n_pages >= n_req_pages) + break; + } + spin_unlock_irqrestore(&b_dev_info->pages_lock, flags); + + return n_pages; +} +EXPORT_SYMBOL_GPL(balloon_page_list_dequeue); + /* * balloon_page_alloc - allocates a new page for insertion into the balloon * page list. @@ -43,17 +137,9 @@ void balloon_page_enqueue(struct balloon_dev_info *b_dev_info, { unsigned long flags; - /* - * Block others from accessing the 'page' when we get around to - * establishing additional references. We should be the only one - * holding a reference to the 'page' at this point. - */ - BUG_ON(!trylock_page(page)); spin_lock_irqsave(&b_dev_info->pages_lock, flags); - balloon_page_insert(b_dev_info, page); - __count_vm_event(BALLOON_INFLATE); + balloon_page_enqueue_one(b_dev_info, page); spin_unlock_irqrestore(&b_dev_info->pages_lock, flags); - unlock_page(page); } EXPORT_SYMBOL_GPL(balloon_page_enqueue); @@ -70,36 +156,13 @@ EXPORT_SYMBOL_GPL(balloon_page_enqueue); */ struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info) { - struct page *page, *tmp; unsigned long flags; - bool dequeued_page; + LIST_HEAD(pages); + int n_pages; - dequeued_page = false; - spin_lock_irqsave(&b_dev_info->pages_lock, flags); - list_for_each_entry_safe(page, tmp, &b_dev_info->pages, lru) { - /* - * Block others from accessing the 'page' while we get around - * establishing additional references and preparing the 'page' - * to be released by the balloon driver. - */ - if (trylock_page(page)) { -#ifdef CONFIG_BALLOON_COMPACTION - if (PageIsolated(page)) { - /* raced with isolation */ - unlock_page(page); - continue; - } -#endif - balloon_page_delete(page); - __count_vm_event(BALLOON_DEFLATE); - unlock_page(page); - dequeued_page = true; - break; - } - } - spin_unlock_irqrestore(&b_dev_info->pages_lock, flags); + n_pages = balloon_page_list_dequeue(b_dev_info, &pages, 1); - if (!dequeued_page) { + if (n_pages != 1) { /* * If we are unable to dequeue a balloon page because the page * list is empty and there is no isolated pages, then something @@ -112,9 +175,9 @@ struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info) !b_dev_info->isolated_pages)) BUG(); spin_unlock_irqrestore(&b_dev_info->pages_lock, flags); - page = NULL; + return NULL; } - return page; + return list_first_entry(&pages, struct page, lru); } EXPORT_SYMBOL_GPL(balloon_page_dequeue); -- 2.17.1