From patchwork Mon Dec 12 18:15:37 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Edward Shishkin X-Patchwork-Id: 9470999 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 5008D60476 for ; Mon, 12 Dec 2016 18:18:13 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 40C3B27F8C for ; Mon, 12 Dec 2016 18:18:13 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3571128509; Mon, 12 Dec 2016 18:18:13 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.3 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AD56C27F8C for ; Mon, 12 Dec 2016 18:18:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751993AbcLLSSL (ORCPT ); Mon, 12 Dec 2016 13:18:11 -0500 Received: from mail-wm0-f68.google.com ([74.125.82.68]:34223 "EHLO mail-wm0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751792AbcLLSSK (ORCPT ); Mon, 12 Dec 2016 13:18:10 -0500 Received: by mail-wm0-f68.google.com with SMTP id g23so12978315wme.1 for ; Mon, 12 Dec 2016 10:18:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=RLjk49IicRYT1Bafufc0RkefOpTZ6WvEfiUHs1qDsRM=; b=o7sq40n3ICR0PTkx+k5a3CwZJqREZwGMBmiZYrWy5zUto+EPlTkJwQTqry98eI7ZB7 IMJ3VzdNPenNW3A12wZLT8jEoLZYOhYbBkkKyP1e2txevvKwgctaDH0suXbXTOR88htT eJGtVyUE341U2V/fvNJUP8vmA7ib/aoVtZOKMBbt9yPpnb0bQNVEl178YUlb7aV13wcn iFfuqNOpcBLJP62eSUkzQJOZ1+WzAAmJVKisSk/FtzFUTMLXh2xrROnhIq0xISg46tZT ua+9btc9vA2y+XQFSS9Y4+fO9Po6s8uz/hBhTzISyIBVcHPAyOXUO2hzNmRazFa4ec5i yMzQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=RLjk49IicRYT1Bafufc0RkefOpTZ6WvEfiUHs1qDsRM=; b=LpYRJI4ZPCg6eaOHWEruNcZ/SCsePsineo1PuLGC7ggoPqKPoOw2h0Aw8FqP8sLZN4 9yZUQm4zSl+MGKr5kkmRURvuVpLJ+Y4BsHhoi5BZnruYe6lH1klkcb+uLsxaICj82/DB qQPOkfz4Vvh/fj1EcAZx6+E7ZZwNKlkPz4PM45d9OwYaeB52hYuibGv+obKeUQ2lw5mW clmGpYFaKmpMw6l7eMWS8sHzh9DFwUxLpGUtzoeRezbuJEwQEAPP5EwStjc//XhYu1FV VHkNnoV3YQELCvdhxoNVaAB6OaN2pVoSKdyjQYfjr2M2nxOO+fQfbYLZj3w/9mwEWt5O 06nA== X-Gm-Message-State: AKaTC02mu9CzK7qMCuqpsKwNE8rSpDUSiwcXoqpCRfrDF9c+UxWU9pOti3JMgtWIJNlMvQ== X-Received: by 10.28.151.136 with SMTP id z130mr11423339wmd.126.1481566688894; Mon, 12 Dec 2016 10:18:08 -0800 (PST) Received: from zeta.huawei.com (h-213.61.75.66.host.de.colt.net. [213.61.75.66]) by smtp.gmail.com with ESMTPSA id kp5sm58432667wjb.8.2016.12.12.10.18.07 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 12 Dec 2016 10:18:08 -0800 (PST) From: edward.shishkin@gmail.com To: Eric Van Hensbergen , V9FS Developers Mailing List , Linux Filesystem Development List Cc: QEMU Developers Mailing List , ZhangWei , Claudio Fontana , Greg Kurz , Alexander Graf , Eduard Shishkin Subject: [PATCH 2/7] 9p: v9fs new readpages. Date: Mon, 12 Dec 2016 19:15:37 +0100 Message-Id: <1481566542-25894-2-git-send-email-edward.shishkin@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1481566542-25894-1-git-send-email-edward.shishkin@gmail.com> References: <1481566542-25894-1-git-send-email-edward.shishkin@gmail.com> Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Eduard Shishkin Modify v9fs private ->readpages() method of address_space operations for merging pages into long 9p messages. Signed-off-by: Eduard Shishkin --- fs/9p/vfs_addr.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 155 insertions(+), 1 deletion(-) diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c index e871886..4ad248e 100644 --- a/fs/9p/vfs_addr.c +++ b/fs/9p/vfs_addr.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -99,6 +100,148 @@ static int v9fs_vfs_readpage(struct file *filp, struct page *page) return v9fs_fid_readpage(filp->private_data, page); } +/* + * Context for "fast readpages" + */ +struct v9fs_readpages_ctx { + struct file *filp; + struct address_space *mapping; + pgoff_t start_index; /* index of the first page with actual data */ + char *buf; /* buffer with actual data */ + int len; /* length of the actual data */ + int num_pages; /* maximal data chunk (in pages) that can be + passed per transmission */ +}; + +static int init_readpages_ctx(struct v9fs_readpages_ctx *ctx, + struct file *filp, + struct address_space *mapping, + int num_pages) +{ + memset(ctx, 0, sizeof(*ctx)); + ctx->buf = kmalloc(num_pages << PAGE_SHIFT, GFP_USER); + if (!ctx->buf) + return -ENOMEM; + ctx->filp = filp; + ctx->mapping = mapping; + ctx->num_pages = num_pages; + return 0; +} + +static void done_readpages_ctx(struct v9fs_readpages_ctx *ctx) +{ + kfree(ctx->buf); +} + +static int receive_buffer(struct file *filp, + char *buf, + off_t offset, /* offset in the file */ + int len, + int *err) +{ + struct kvec kvec; + struct iov_iter iter; + + kvec.iov_base = buf; + kvec.iov_len = len; + iov_iter_kvec(&iter, READ | ITER_KVEC, &kvec, 1, len); + + return p9_client_read(filp->private_data, offset, &iter, err); +} + +static int fast_filler(struct v9fs_readpages_ctx *ctx, struct page *page) +{ + int err; + int ret = 0; + char *kdata; + int to_page; + off_t off_in_buf; + struct inode *inode = page->mapping->host; + + BUG_ON(!PageLocked(page)); + /* + * first, validate the buffer + */ + if (page->index < ctx->start_index || + ctx->start_index + ctx->num_pages < page->index) { + /* + * No actual data in the buffer, + * so actualize it + */ + ret = receive_buffer(ctx->filp, + ctx->buf, + page_offset(page), + ctx->num_pages << PAGE_SHIFT, + &err); + if (err) { + printk("failed to receive buffer off=%llu (%d)\n", + (unsigned long long)page_offset(page), + err); + ret = err; + goto done; + } + ctx->start_index = page->index; + ctx->len = ret; + ret = 0; + } + /* + * fill the page with buffer's data + */ + off_in_buf = (page->index - ctx->start_index) << PAGE_SHIFT; + if (off_in_buf >= ctx->len) { + /* + * No actual data to fill the page with + */ + ret = -1; + goto done; + } + to_page = ctx->len - off_in_buf; + if (to_page >= PAGE_SIZE) + to_page = PAGE_SIZE; + + kdata = kmap_atomic(page); + memcpy(kdata, ctx->buf + off_in_buf, to_page); + memset(kdata + to_page, 0, PAGE_SIZE - to_page); + kunmap_atomic(kdata); + + flush_dcache_page(page); + SetPageUptodate(page); + v9fs_readpage_to_fscache(inode, page); + done: + unlock_page(page); + return ret; +} + +/** + * Try to read pages by groups. For every such group we issue only one + * read request to the server. + * @num_pages: maximal chunk of data (in pages) that can be passed per + * such request + */ +static int v9fs_readpages_tryfast(struct file *filp, + struct address_space *mapping, + struct list_head *pages, + int num_pages) +{ + int ret; + struct v9fs_readpages_ctx ctx; + + ret = init_readpages_ctx(&ctx, filp, mapping, num_pages); + if (ret) + /* + * Can not allocate resources for the fast path, + * so do it by slow way + */ + return read_cache_pages(mapping, pages, + (void *)v9fs_vfs_readpage, filp); + + else + ret = read_cache_pages(mapping, pages, + (void *)fast_filler, &ctx); + done_readpages_ctx(&ctx); + return ret; +} + /** * v9fs_vfs_readpages - read a set of pages from 9P * @@ -114,6 +257,7 @@ static int v9fs_vfs_readpages(struct file *filp, struct address_space *mapping, { int ret = 0; struct inode *inode; + struct v9fs_flush_set *fset; inode = mapping->host; p9_debug(P9_DEBUG_VFS, "inode: %p file: %p\n", inode, filp); @@ -122,7 +266,17 @@ static int v9fs_vfs_readpages(struct file *filp, struct address_space *mapping, if (ret == 0) return ret; - ret = read_cache_pages(mapping, pages, (void *)v9fs_vfs_readpage, filp); + fset = v9fs_inode2v9ses(mapping->host)->flush; + if (!fset) + /* + * Do it by slow way + */ + ret = read_cache_pages(mapping, pages, + (void *)v9fs_vfs_readpage, filp); + else + ret = v9fs_readpages_tryfast(filp, mapping, + pages, fset->num_pages); + p9_debug(P9_DEBUG_VFS, " = %d\n", ret); return ret; }