From patchwork Fri Jan 22 17:51:13 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 12040161 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.4 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 79DD1C433DB for ; Fri, 22 Jan 2021 17:57:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 30E5223AC9 for ; Fri, 22 Jan 2021 17:57:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728780AbhAVR4s (ORCPT ); Fri, 22 Jan 2021 12:56:48 -0500 Received: from mail.kernel.org ([198.145.29.99]:53836 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729404AbhAVRwD (ORCPT ); Fri, 22 Jan 2021 12:52:03 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 975CE23A9A; Fri, 22 Jan 2021 17:51:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1611337882; bh=7c4C0NGnd1ycQrjwFvqo5QhpKG7ptm/awGcqztQqlCk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=N3g9D5009TZiRfDlatB0eveoJ6x9PmEdzUnDdXYCrJ/gW6qkpsXdGCWTgmhfNFOuQ yzugITHigonLygkrGIn4HWtDHO9X9jcbBfmI5hUZ9qGNEBweh76aP/V6bCk5R94Mgp p3lfanhMdiNFT8Lgrh/YSA40M99dN4KbQxrxC98zA/eKs8TF/+wKA/8QPNC5mdNi1L 2HDXBUcmiE0bax87LxHJpTqEUMgmLY6BRsYSMBTuSUf0o+esBKVZ3cQVKWDIYZst8J JuOeijk/3oXRoGDdnJcE+RsImRQhcgwYTjGGAHA0wpdPzht+fpACGz4GD/Gaj2EWCl EqEc3HSCMaS8w== From: Jeff Layton To: ceph-devel@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org, dhowells@redhat.com, willy@infradead.org, linux-cachefs@redhat.com, linux-kernel@vger.kernel.org Subject: [RFC PATCH 1/6] ceph: disable old fscache readpage handling Date: Fri, 22 Jan 2021 12:51:13 -0500 Message-Id: <20210122175119.364381-2-jlayton@kernel.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210122175119.364381-1-jlayton@kernel.org> References: <20210122175119.364381-1-jlayton@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org With the new netfs read helper functions, we won't need a lot of this infrastructure as it handles a the pagecache itself. Rip out the read handling for now, and much of the old infrastructure that deals in individual pages. The cookie handling is mostly unchanged, however. Signed-off-by: Jeff Layton --- fs/ceph/addr.c | 31 +----------- fs/ceph/cache.c | 123 ------------------------------------------------ fs/ceph/cache.h | 91 +---------------------------------- fs/ceph/caps.c | 9 ---- 4 files changed, 3 insertions(+), 251 deletions(-) diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 26e66436f005..e267aa60c8b6 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -155,8 +155,6 @@ static void ceph_invalidatepage(struct page *page, unsigned int offset, return; } - ceph_invalidate_fscache_page(inode, page); - WARN_ON(!PageLocked(page)); if (!PagePrivate(page)) return; @@ -175,10 +173,6 @@ static int ceph_releasepage(struct page *page, gfp_t g) dout("%p releasepage %p idx %lu (%sdirty)\n", page->mapping->host, page, page->index, PageDirty(page) ? "" : "not "); - /* Can we release the page from the cache? */ - if (!ceph_release_fscache_page(page, g)) - return 0; - return !PagePrivate(page); } @@ -213,10 +207,6 @@ static int ceph_do_readpage(struct file *filp, struct page *page) return 0; } - err = ceph_readpage_from_fscache(inode, page); - if (err == 0) - return -EINPROGRESS; - dout("readpage ino %llx.%llx file %p off %llu len %llu page %p index %lu\n", vino.ino, vino.snap, filp, off, len, page, page->index); req = ceph_osdc_new_request(osdc, &ci->i_layout, vino, off, &len, 0, 1, @@ -241,7 +231,6 @@ static int ceph_do_readpage(struct file *filp, struct page *page) if (err == -ENOENT) err = 0; if (err < 0) { - ceph_fscache_readpage_cancel(inode, page); if (err == -EBLOCKLISTED) fsc->blocklisted = true; goto out; @@ -253,8 +242,6 @@ static int ceph_do_readpage(struct file *filp, struct page *page) flush_dcache_page(page); SetPageUptodate(page); - ceph_readpage_to_fscache(inode, page); - out: return err < 0 ? err : 0; } @@ -294,10 +281,8 @@ static void finish_read(struct ceph_osd_request *req) for (i = 0; i < num_pages; i++) { struct page *page = osd_data->pages[i]; - if (rc < 0 && rc != -ENOENT) { - ceph_fscache_readpage_cancel(inode, page); + if (rc < 0 && rc != -ENOENT) goto unlock; - } if (bytes < (int)PAGE_SIZE) { /* zero (remainder of) page */ int s = bytes < 0 ? 0 : bytes; @@ -307,7 +292,6 @@ static void finish_read(struct ceph_osd_request *req) page->index); flush_dcache_page(page); SetPageUptodate(page); - ceph_readpage_to_fscache(inode, page); unlock: unlock_page(page); put_page(page); @@ -408,7 +392,6 @@ static int start_read(struct inode *inode, struct ceph_rw_context *rw_ctx, page->index); if (add_to_page_cache_lru(page, &inode->i_data, page->index, GFP_KERNEL)) { - ceph_fscache_uncache_page(inode, page); put_page(page); dout("start_read %p add_to_page_cache failed %p\n", inode, page); @@ -440,10 +423,8 @@ static int start_read(struct inode *inode, struct ceph_rw_context *rw_ctx, return nr_pages; out_pages: - for (i = 0; i < nr_pages; ++i) { - ceph_fscache_readpage_cancel(inode, pages[i]); + for (i = 0; i < nr_pages; ++i) unlock_page(pages[i]); - } ceph_put_page_vector(pages, nr_pages, false); out_put: ceph_osdc_put_request(req); @@ -471,12 +452,6 @@ static int ceph_readpages(struct file *file, struct address_space *mapping, if (ceph_inode(inode)->i_inline_version != CEPH_INLINE_NONE) return -EINVAL; - rc = ceph_readpages_from_fscache(mapping->host, mapping, page_list, - &nr_pages); - - if (rc == 0) - goto out; - rw_ctx = ceph_find_rw_context(fi); max = fsc->mount_options->rsize >> PAGE_SHIFT; dout("readpages %p file %p ctx %p nr_pages %d max %d\n", @@ -487,8 +462,6 @@ static int ceph_readpages(struct file *file, struct address_space *mapping, goto out; } out: - ceph_fscache_readpages_cancel(inode, page_list); - dout("readpages %p file %p ret %d\n", inode, file, rc); return rc; } diff --git a/fs/ceph/cache.c b/fs/ceph/cache.c index 2f5cb6bc78e1..bd185faeeb8e 100644 --- a/fs/ceph/cache.c +++ b/fs/ceph/cache.c @@ -205,108 +205,6 @@ void ceph_fscache_file_set_cookie(struct inode *inode, struct file *filp) } } -static void ceph_readpage_from_fscache_complete(struct page *page, void *data, int error) -{ - if (!error) - SetPageUptodate(page); - - unlock_page(page); -} - -static inline bool cache_valid(struct ceph_inode_info *ci) -{ - return ci->i_fscache_gen == ci->i_rdcache_gen; -} - - -/* Atempt to read from the fscache, - * - * This function is called from the readpage_nounlock context. DO NOT attempt to - * unlock the page here (or in the callback). - */ -int ceph_readpage_from_fscache(struct inode *inode, struct page *page) -{ - struct ceph_inode_info *ci = ceph_inode(inode); - int ret; - - if (!cache_valid(ci)) - return -ENOBUFS; - - ret = fscache_read_or_alloc_page(ci->fscache, page, - ceph_readpage_from_fscache_complete, NULL, - GFP_KERNEL); - - switch (ret) { - case 0: /* Page found */ - dout("page read submitted\n"); - return 0; - case -ENOBUFS: /* Pages were not found, and can't be */ - case -ENODATA: /* Pages were not found */ - dout("page/inode not in cache\n"); - return ret; - default: - dout("%s: unknown error ret = %i\n", __func__, ret); - return ret; - } -} - -int ceph_readpages_from_fscache(struct inode *inode, - struct address_space *mapping, - struct list_head *pages, - unsigned *nr_pages) -{ - struct ceph_inode_info *ci = ceph_inode(inode); - int ret; - - if (!cache_valid(ci)) - return -ENOBUFS; - - ret = fscache_read_or_alloc_pages(ci->fscache, mapping, pages, nr_pages, - ceph_readpage_from_fscache_complete, - NULL, mapping_gfp_mask(mapping)); - - switch (ret) { - case 0: /* All pages found */ - dout("all-page read submitted\n"); - return 0; - case -ENOBUFS: /* Some pages were not found, and can't be */ - case -ENODATA: /* some pages were not found */ - dout("page/inode not in cache\n"); - return ret; - default: - dout("%s: unknown error ret = %i\n", __func__, ret); - return ret; - } -} - -void ceph_readpage_to_fscache(struct inode *inode, struct page *page) -{ - struct ceph_inode_info *ci = ceph_inode(inode); - int ret; - - if (!PageFsCache(page)) - return; - - if (!cache_valid(ci)) - return; - - ret = fscache_write_page(ci->fscache, page, i_size_read(inode), - GFP_KERNEL); - if (ret) - fscache_uncache_page(ci->fscache, page); -} - -void ceph_invalidate_fscache_page(struct inode* inode, struct page *page) -{ - struct ceph_inode_info *ci = ceph_inode(inode); - - if (!PageFsCache(page)) - return; - - fscache_wait_on_page_write(ci->fscache, page); - fscache_uncache_page(ci->fscache, page); -} - void ceph_fscache_unregister_fs(struct ceph_fs_client* fsc) { if (fscache_cookie_valid(fsc->fscache)) { @@ -329,24 +227,3 @@ void ceph_fscache_unregister_fs(struct ceph_fs_client* fsc) } fsc->fscache = NULL; } - -/* - * caller should hold CEPH_CAP_FILE_{RD,CACHE} - */ -void ceph_fscache_revalidate_cookie(struct ceph_inode_info *ci) -{ - if (cache_valid(ci)) - return; - - /* resue i_truncate_mutex. There should be no pending - * truncate while the caller holds CEPH_CAP_FILE_RD */ - mutex_lock(&ci->i_truncate_mutex); - if (!cache_valid(ci)) { - if (fscache_check_consistency(ci->fscache, &ci->i_vino)) - fscache_invalidate(ci->fscache); - spin_lock(&ci->i_ceph_lock); - ci->i_fscache_gen = ci->i_rdcache_gen; - spin_unlock(&ci->i_ceph_lock); - } - mutex_unlock(&ci->i_truncate_mutex); -} diff --git a/fs/ceph/cache.h b/fs/ceph/cache.h index 89dbdd1eb14a..10c21317b62f 100644 --- a/fs/ceph/cache.h +++ b/fs/ceph/cache.h @@ -29,13 +29,10 @@ int ceph_readpages_from_fscache(struct inode *inode, struct address_space *mapping, struct list_head *pages, unsigned *nr_pages); -void ceph_readpage_to_fscache(struct inode *inode, struct page *page); -void ceph_invalidate_fscache_page(struct inode* inode, struct page *page); static inline void ceph_fscache_inode_init(struct ceph_inode_info *ci) { ci->fscache = NULL; - ci->i_fscache_gen = 0; } static inline void ceph_fscache_invalidate(struct inode *inode) @@ -43,40 +40,6 @@ static inline void ceph_fscache_invalidate(struct inode *inode) fscache_invalidate(ceph_inode(inode)->fscache); } -static inline void ceph_fscache_uncache_page(struct inode *inode, - struct page *page) -{ - struct ceph_inode_info *ci = ceph_inode(inode); - return fscache_uncache_page(ci->fscache, page); -} - -static inline int ceph_release_fscache_page(struct page *page, gfp_t gfp) -{ - struct inode* inode = page->mapping->host; - struct ceph_inode_info *ci = ceph_inode(inode); - return fscache_maybe_release_page(ci->fscache, page, gfp); -} - -static inline void ceph_fscache_readpage_cancel(struct inode *inode, - struct page *page) -{ - struct ceph_inode_info *ci = ceph_inode(inode); - if (fscache_cookie_valid(ci->fscache) && PageFsCache(page)) - __fscache_uncache_page(ci->fscache, page); -} - -static inline void ceph_fscache_readpages_cancel(struct inode *inode, - struct list_head *pages) -{ - struct ceph_inode_info *ci = ceph_inode(inode); - return fscache_readpages_cancel(ci->fscache, pages); -} - -static inline void ceph_disable_fscache_readpage(struct ceph_inode_info *ci) -{ - ci->i_fscache_gen = ci->i_rdcache_gen - 1; -} - #else static inline int ceph_fscache_register(void) @@ -115,62 +78,10 @@ static inline void ceph_fscache_file_set_cookie(struct inode *inode, { } -static inline void ceph_fscache_revalidate_cookie(struct ceph_inode_info *ci) -{ -} - -static inline void ceph_fscache_uncache_page(struct inode *inode, - struct page *pages) -{ -} - -static inline int ceph_readpage_from_fscache(struct inode* inode, - struct page *page) -{ - return -ENOBUFS; -} - -static inline int ceph_readpages_from_fscache(struct inode *inode, - struct address_space *mapping, - struct list_head *pages, - unsigned *nr_pages) -{ - return -ENOBUFS; -} - -static inline void ceph_readpage_to_fscache(struct inode *inode, - struct page *page) -{ -} - static inline void ceph_fscache_invalidate(struct inode *inode) { } -static inline void ceph_invalidate_fscache_page(struct inode *inode, - struct page *page) -{ -} - -static inline int ceph_release_fscache_page(struct page *page, gfp_t gfp) -{ - return 1; -} - -static inline void ceph_fscache_readpage_cancel(struct inode *inode, - struct page *page) -{ -} - -static inline void ceph_fscache_readpages_cancel(struct inode *inode, - struct list_head *pages) -{ -} - -static inline void ceph_disable_fscache_readpage(struct ceph_inode_info *ci) -{ -} - #endif -#endif +#endif /* _CEPH_CACHE_H */ diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index abbf48fc6230..21ba949ca2c3 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -2730,10 +2730,6 @@ static int try_get_cap_refs(struct inode *inode, int need, int want, *got = need | want; else *got = need; - if (S_ISREG(inode->i_mode) && - (need & CEPH_CAP_FILE_RD) && - !(*got & CEPH_CAP_FILE_CACHE)) - ceph_disable_fscache_readpage(ci); ceph_take_cap_refs(ci, *got, true); ret = 1; } @@ -2983,11 +2979,6 @@ int ceph_get_caps(struct file *filp, int need, int want, } break; } - - if (S_ISREG(ci->vfs_inode.i_mode) && - (_got & CEPH_CAP_FILE_RD) && (_got & CEPH_CAP_FILE_CACHE)) - ceph_fscache_revalidate_cookie(ci); - *got = _got; return 0; } From patchwork Fri Jan 22 17:51:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 12040159 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.2 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A6ABDC433E6 for ; Fri, 22 Jan 2021 17:57:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5A3DB23ACA for ; Fri, 22 Jan 2021 17:57:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728818AbhAVR5I (ORCPT ); Fri, 22 Jan 2021 12:57:08 -0500 Received: from mail.kernel.org ([198.145.29.99]:53842 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729466AbhAVRwD (ORCPT ); Fri, 22 Jan 2021 12:52:03 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 7486723A9C; Fri, 22 Jan 2021 17:51:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1611337883; bh=x1lJQGM04EP7vdDpOg3XZRh7p/S7qixcDsgKzeM7VHE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=cgeYi17BYaz72pJfJRzXo5B8FqtZCB7ZgIWCKtkxGYlhLd4ecVOMeSpzWpQov/w7Q 2g5dp/aQ1Q3YXFu0mRH6SaSqo5/hVN5LY21FCbTJbT7lWWPco8GRYp2dYAtqiNMgS5 r3vP4aivhAT59DjBigNLlSPz9DYrhe+szb8xHs83tKQ6/cboaeNPChs3LuVf4WrE0K oTe9+2nW97R614lf9C71NBjcori4PijInVwyXZd4sYKUXyTWtLs2b16dQgAW22u7Om 2XZfA0OTD2XTqyd1515vuUxGX4KiXwMyHrLpbiF9QoSyDTw6rSwTQX5PLu44Y8PtXe xvIWzKp3r95OQ== From: Jeff Layton To: ceph-devel@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org, dhowells@redhat.com, willy@infradead.org, linux-cachefs@redhat.com, linux-kernel@vger.kernel.org Subject: [RFC PATCH 2/6] ceph: rework PageFsCache handling Date: Fri, 22 Jan 2021 12:51:14 -0500 Message-Id: <20210122175119.364381-3-jlayton@kernel.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210122175119.364381-1-jlayton@kernel.org> References: <20210122175119.364381-1-jlayton@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org With the new fscache API, the PageFsCache bit now indicates that the page is being written to the cache and shouldn't be modified or released until it's finished. Change releasepage and invalidatepage to wait on that bit before returning. Signed-off-by: Jeff Layton --- fs/ceph/addr.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index e267aa60c8b6..f554667e1e91 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -166,13 +166,19 @@ static void ceph_invalidatepage(struct page *page, unsigned int offset, ceph_put_snap_context(snapc); page->private = 0; ClearPagePrivate(page); + wait_on_page_fscache(page); } -static int ceph_releasepage(struct page *page, gfp_t g) +static int ceph_releasepage(struct page *page, gfp_t gfp_flags) { dout("%p releasepage %p idx %lu (%sdirty)\n", page->mapping->host, page, page->index, PageDirty(page) ? "" : "not "); + if (PageFsCache(page)) { + if (!(gfp_flags & __GFP_DIRECT_RECLAIM) || !(gfp_flags & __GFP_FS)) + return 0; + wait_on_page_fscache(page); + } return !PagePrivate(page); } From patchwork Fri Jan 22 17:51:15 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 12040149 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.2 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 04523C433DB for ; Fri, 22 Jan 2021 17:52:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C6C6623A7D for ; Fri, 22 Jan 2021 17:52:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729602AbhAVRwe (ORCPT ); Fri, 22 Jan 2021 12:52:34 -0500 Received: from mail.kernel.org ([198.145.29.99]:53852 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729481AbhAVRwE (ORCPT ); Fri, 22 Jan 2021 12:52:04 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 5002E23AA1; Fri, 22 Jan 2021 17:51:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1611337883; bh=yLO+A1ljIfqO/p2jKFSqSiZv9SibpfihSeI5YzB7Mq0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=kzh03ULZ551nNc3tCxjeqczVLHHfYMVA5OMJfwS3yvJN/LeW3vZJjP0mRlUAUB5W/ crh6N/QwkPHHgB1+HOOwD7GtJYzQ65CRIMvFhpOLMMvzmq+Sz/U6PJlUyQnCUcj666 df5D+zasEmkj0YqniXYbHP0I1LJHUmw14gB1k7gYWsRY58xeVr1YWlc0MdMq/WrVE/ +LT73p8lMJw89Y+7oOlTm73kKokopbBePXn87T2H3Mg53/UVAQUihfNXz8KsOdr2L3 292tebiJoDK0eX2kSmYyuswG6Qd3jF5VssddnruuFj7/+vzLSNRCXNcuLEWOfMmHK1 /rKMNY2t/m4yA== From: Jeff Layton To: ceph-devel@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org, dhowells@redhat.com, willy@infradead.org, linux-cachefs@redhat.com, linux-kernel@vger.kernel.org Subject: [RFC PATCH 3/6] ceph: fix invalidation Date: Fri, 22 Jan 2021 12:51:15 -0500 Message-Id: <20210122175119.364381-4-jlayton@kernel.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210122175119.364381-1-jlayton@kernel.org> References: <20210122175119.364381-1-jlayton@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Ensure that we invalidate the fscache whenever we go to invalidate the pagecache. Signed-off-by: Jeff Layton --- fs/ceph/caps.c | 1 + fs/ceph/inode.c | 1 + 2 files changed, 2 insertions(+) diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 21ba949ca2c3..0102221db7bf 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -1867,6 +1867,7 @@ static int try_nonblocking_invalidate(struct inode *inode) u32 invalidating_gen = ci->i_rdcache_gen; spin_unlock(&ci->i_ceph_lock); + ceph_fscache_invalidate(inode); invalidate_mapping_pages(&inode->i_data, 0, -1); spin_lock(&ci->i_ceph_lock); diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 5d20a620e96c..2d424b41a8b9 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -1863,6 +1863,7 @@ static void ceph_do_invalidate_pages(struct inode *inode) orig_gen = ci->i_rdcache_gen; spin_unlock(&ci->i_ceph_lock); + ceph_fscache_invalidate(inode); if (invalidate_inode_pages2(inode->i_mapping) < 0) { pr_err("invalidate_pages %p fails\n", inode); } From patchwork Fri Jan 22 17:51:16 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 12040183 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.2 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 33361C43333 for ; Fri, 22 Jan 2021 18:10:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1A0DC23AA1 for ; Fri, 22 Jan 2021 18:10:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729496AbhAVR6O (ORCPT ); Fri, 22 Jan 2021 12:58:14 -0500 Received: from mail.kernel.org ([198.145.29.99]:53910 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729591AbhAVRwh (ORCPT ); Fri, 22 Jan 2021 12:52:37 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 2DD2323AAA; Fri, 22 Jan 2021 17:51:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1611337884; bh=ZmC/Z8c2ub1C7KMD2cN83t8AzeiWrrEekRlNmXdgI38=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=E1YqlOEPWLh6RsaLKJW30ig0iwygO6rNHwEv0OrzmF1jk8OqJe/fkl3LhLs690LPK QDqntWzSA81dGZ/DVJOciw0+jnnVoaM5rp1dD1ed/1tIn4XEuxKb6EQaF5Ytxhl5Cs 8i9xsmf9pFVZf7P5xI8zuWhWi/2lsJzt2O8viGapcQsEVr3jlIQQs3HaLegnsD9HE5 +swGh42FWvg9qQESA00MMNmo8mgtRrHg01tdIktjcma26LYO2Xn2D6a0YcgPTcLQQg uCAK+fGa7REfU29sjST+D3mxBkANmV7IW9yAC3JowdWZUS5JhZgpss/j/nNLBdcuwg jwucEvoAq+WQA== From: Jeff Layton To: ceph-devel@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org, dhowells@redhat.com, willy@infradead.org, linux-cachefs@redhat.com, linux-kernel@vger.kernel.org Subject: [RFC PATCH 4/6] ceph: convert readpage to fscache read helper Date: Fri, 22 Jan 2021 12:51:16 -0500 Message-Id: <20210122175119.364381-5-jlayton@kernel.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210122175119.364381-1-jlayton@kernel.org> References: <20210122175119.364381-1-jlayton@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Have the ceph KConfig select NETFS_SUPPORT. Add a new netfs ops structure and the operations for it. Convert ceph_readpage to use the new netfs_readpage helper. Signed-off-by: Jeff Layton --- fs/ceph/Kconfig | 1 + fs/ceph/addr.c | 149 ++++++++++++++++++++++++++++++++++++++++++++---- fs/ceph/cache.h | 36 ++++++++++++ 3 files changed, 176 insertions(+), 10 deletions(-) diff --git a/fs/ceph/Kconfig b/fs/ceph/Kconfig index 471e40156065..94df854147d3 100644 --- a/fs/ceph/Kconfig +++ b/fs/ceph/Kconfig @@ -6,6 +6,7 @@ config CEPH_FS select LIBCRC32C select CRYPTO_AES select CRYPTO + select NETFS_SUPPORT default n help Choose Y or M here to include support for mounting the diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index f554667e1e91..986c9c56653f 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "super.h" #include "mds_client.h" @@ -182,6 +183,144 @@ static int ceph_releasepage(struct page *page, gfp_t gfp_flags) return !PagePrivate(page); } +static bool ceph_netfs_clamp_length(struct netfs_read_subrequest *subreq) +{ + struct inode *inode = subreq->rreq->mapping->host; + struct ceph_inode_info *ci = ceph_inode(inode); + u64 objno, objoff; + u32 xlen; + + /* Truncate the extent at the end of the current object */ + ceph_calc_file_object_mapping(&ci->i_layout, subreq->start, subreq->len, + &objno, &objoff, &xlen); + subreq->len = xlen; + return true; +} + +static void finish_netfs_read(struct ceph_osd_request *req) +{ + struct ceph_fs_client *fsc = ceph_inode_to_client(req->r_inode); + struct ceph_osd_data *osd_data = osd_req_op_extent_osd_data(req, 0); + struct netfs_read_subrequest *subreq = req->r_priv; + int num_pages; + int err = req->r_result; + + ceph_update_read_latency(&fsc->mdsc->metric, req->r_start_latency, + req->r_end_latency, err); + + dout("%s: result %d subreq->len=%zu i_size=%lld\n", __func__, req->r_result, + subreq->len, i_size_read(req->r_inode)); + + /* no object means success but no data */ + if (err == -ENOENT) + err = 0; + else if (err == -EBLOCKLISTED) + fsc->blocklisted = true; + + if (err >= 0 && err < subreq->len) + __set_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags); + + netfs_subreq_terminated(subreq, err); + + num_pages = calc_pages_for(osd_data->alignment, osd_data->length); + ceph_put_page_vector(osd_data->pages, num_pages, false); + iput(req->r_inode); +} + +static void ceph_netfs_issue_op(struct netfs_read_subrequest *subreq) +{ + struct netfs_read_request *rreq = subreq->rreq; + struct inode *inode = rreq->mapping->host; + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_fs_client *fsc = ceph_inode_to_client(inode); + struct ceph_osd_request *req = NULL; + struct ceph_vino vino = ceph_vino(inode); + struct iov_iter iter; + struct page **pages; + size_t page_off; + int err = 0; + u64 len = subreq->len; + + req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout, vino, subreq->start, &len, + 0, 1, CEPH_OSD_OP_READ, + CEPH_OSD_FLAG_READ | fsc->client->osdc.client->options->read_from_replica, + NULL, ci->i_truncate_seq, ci->i_truncate_size, false); + if (IS_ERR(req)) { + err = PTR_ERR(req); + goto out; + } + + dout("%s: pos=%llu orig_len=%zu len=%llu\n", __func__, subreq->start, subreq->len, len); + iov_iter_xarray(&iter, READ, &rreq->mapping->i_pages, subreq->start, len); + len = iov_iter_get_pages_alloc(&iter, &pages, len, &page_off); + if (len < 0) { + err = len; + dout("%s: iov_ter_get_pages_alloc returned %d\n", __func__, err); + goto out; + } + + /* should always give us a page-aligned read */ + WARN_ON_ONCE(page_off); + + osd_req_op_extent_osd_data_pages(req, 0, pages, len, 0, false, false); + req->r_callback = finish_netfs_read; + req->r_priv = subreq; + req->r_inode = inode; + ihold(inode); + + err = ceph_osdc_start_request(req->r_osdc, req, false); + if (err) + iput(inode); +out: + if (req) + ceph_osdc_put_request(req); + if (err) + netfs_subreq_terminated(subreq, err); + dout("%s: result %d\n", __func__, err); +} + +static void ceph_init_rreq(struct netfs_read_request *rreq, struct file *file) +{ +} + +const struct netfs_read_request_ops ceph_readpage_netfs_ops = { + .init_rreq = ceph_init_rreq, + .is_cache_enabled = ceph_is_cache_enabled, + .begin_cache_operation = ceph_begin_cache_operation, + .issue_op = ceph_netfs_issue_op, + .clamp_length = ceph_netfs_clamp_length, +}; + +/* read a single page, without unlocking it. */ +static int ceph_readpage(struct file *filp, struct page *page) +{ + struct inode *inode = file_inode(filp); + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_vino vino = ceph_vino(inode); + u64 off = page_offset(page); + u64 len = PAGE_SIZE; + + if (ci->i_inline_version != CEPH_INLINE_NONE) { + /* + * Uptodate inline data should have been added + * into page cache while getting Fcr caps. + */ + if (off == 0) { + unlock_page(page); + return -EINVAL; + } + zero_user_segment(page, 0, PAGE_SIZE); + SetPageUptodate(page); + unlock_page(page); + return 0; + } + + dout("readpage ino %llx.%llx file %p off %llu len %llu page %p index %lu\n", + vino.ino, vino.snap, filp, off, len, page, page->index); + + return netfs_readpage(filp, page, &ceph_readpage_netfs_ops, NULL); +} + /* read a single page, without unlocking it. */ static int ceph_do_readpage(struct file *filp, struct page *page) { @@ -252,16 +391,6 @@ static int ceph_do_readpage(struct file *filp, struct page *page) return err < 0 ? err : 0; } -static int ceph_readpage(struct file *filp, struct page *page) -{ - int r = ceph_do_readpage(filp, page); - if (r != -EINPROGRESS) - unlock_page(page); - else - r = 0; - return r; -} - /* * Finish an async read(ahead) op. */ diff --git a/fs/ceph/cache.h b/fs/ceph/cache.h index 10c21317b62f..1409d6149281 100644 --- a/fs/ceph/cache.h +++ b/fs/ceph/cache.h @@ -9,6 +9,8 @@ #ifndef _CEPH_CACHE_H #define _CEPH_CACHE_H +#include + #ifdef CONFIG_CEPH_FSCACHE extern struct fscache_netfs ceph_cache_netfs; @@ -35,11 +37,31 @@ static inline void ceph_fscache_inode_init(struct ceph_inode_info *ci) ci->fscache = NULL; } +static inline struct fscache_cookie *ceph_fscache_cookie(struct ceph_inode_info *ci) +{ + return ci->fscache; +} + static inline void ceph_fscache_invalidate(struct inode *inode) { fscache_invalidate(ceph_inode(inode)->fscache); } +static inline bool ceph_is_cache_enabled(struct inode *inode) +{ + struct fscache_cookie *cookie = ceph_fscache_cookie(ceph_inode(inode)); + + if (!cookie) + return false; + return fscache_cookie_enabled(cookie); +} + +static inline int ceph_begin_cache_operation(struct netfs_read_request *rreq) +{ + struct fscache_cookie *cookie = ceph_fscache_cookie(ceph_inode(rreq->inode)); + + return fscache_begin_read_operation(rreq, cookie); +} #else static inline int ceph_fscache_register(void) @@ -65,6 +87,11 @@ static inline void ceph_fscache_inode_init(struct ceph_inode_info *ci) { } +static inline struct fscache_cookie *ceph_fscache_cookie(struct ceph_inode_info *ci) +{ + return NULL; +} + static inline void ceph_fscache_register_inode_cookie(struct inode *inode) { } @@ -82,6 +109,15 @@ static inline void ceph_fscache_invalidate(struct inode *inode) { } +static inline bool ceph_is_cache_enabled(struct inode *inode) +{ + return false; +} + +static inline int ceph_begin_cache_operation(struct netfs_read_request *rreq) +{ + return -ENOBUFS; +} #endif #endif /* _CEPH_CACHE_H */ From patchwork Fri Jan 22 17:51:17 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 12040185 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.2 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 85F61C432C3 for ; Fri, 22 Jan 2021 18:10:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6122723A9C for ; Fri, 22 Jan 2021 18:10:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729285AbhAVR5j (ORCPT ); Fri, 22 Jan 2021 12:57:39 -0500 Received: from mail.kernel.org ([198.145.29.99]:53912 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729588AbhAVRwh (ORCPT ); Fri, 22 Jan 2021 12:52:37 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 0D44B23AAC; Fri, 22 Jan 2021 17:51:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1611337885; bh=XteU6WoIODT4ILm25/2DVaakb5xIuud8bxJnL10oc0I=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=d+yNe8hS5hwlDZXFiZ0OVvf0hKTARCyXm9CuYiJxlmmk1qSK02LwCoBfekbWBmJ0H Bzi9mrCuqOU//q6XUMUXnjXZN6Z8ZMRDsNbIKoWQ8aJ/5AEHo9C16uH5Netm+CmLzA l7dVXSoxw0OOpzM/AG0rbWWL3vJ9oBM6yuFYQHl4VVrBu2kiTqflg0yPdEB1GF5Ub5 hJVG1XtpvTUTjiVWaw1in/cQZ9lPvlmocxxHDUwoUlNgdqlZgoMYXCnPjlwRoRc8AO 0zgW9gUgZXk091PltjNA8jqZ3onRZfcis8ANrJEKIZ0El+uAkyonsBL1wYikhM73pr hcnIKJj5IdPpA== From: Jeff Layton To: ceph-devel@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org, dhowells@redhat.com, willy@infradead.org, linux-cachefs@redhat.com, linux-kernel@vger.kernel.org Subject: [RFC PATCH 5/6] ceph: plug write_begin into read helper Date: Fri, 22 Jan 2021 12:51:17 -0500 Message-Id: <20210122175119.364381-6-jlayton@kernel.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210122175119.364381-1-jlayton@kernel.org> References: <20210122175119.364381-1-jlayton@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Convert ceph_write_begin to use the netfs_write_begin helper. Most of the ops we need for it are already in place from the readpage conversion but we do add a new check_write_begin op since ceph needs to be able to vet whether there is an incompatible writeback already in flight before reading in the page. With this, we can also remove the old ceph_do_readpage helper. Signed-off-by: Jeff Layton --- fs/ceph/addr.c | 187 ++++++++++++++++--------------------------------- 1 file changed, 61 insertions(+), 126 deletions(-) diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 986c9c56653f..b3b58285a997 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -321,76 +321,6 @@ static int ceph_readpage(struct file *filp, struct page *page) return netfs_readpage(filp, page, &ceph_readpage_netfs_ops, NULL); } -/* read a single page, without unlocking it. */ -static int ceph_do_readpage(struct file *filp, struct page *page) -{ - struct inode *inode = file_inode(filp); - struct ceph_inode_info *ci = ceph_inode(inode); - struct ceph_fs_client *fsc = ceph_inode_to_client(inode); - struct ceph_osd_client *osdc = &fsc->client->osdc; - struct ceph_osd_request *req; - struct ceph_vino vino = ceph_vino(inode); - int err = 0; - u64 off = page_offset(page); - u64 len = PAGE_SIZE; - - if (off >= i_size_read(inode)) { - zero_user_segment(page, 0, PAGE_SIZE); - SetPageUptodate(page); - return 0; - } - - if (ci->i_inline_version != CEPH_INLINE_NONE) { - /* - * Uptodate inline data should have been added - * into page cache while getting Fcr caps. - */ - if (off == 0) - return -EINVAL; - zero_user_segment(page, 0, PAGE_SIZE); - SetPageUptodate(page); - return 0; - } - - dout("readpage ino %llx.%llx file %p off %llu len %llu page %p index %lu\n", - vino.ino, vino.snap, filp, off, len, page, page->index); - req = ceph_osdc_new_request(osdc, &ci->i_layout, vino, off, &len, 0, 1, - CEPH_OSD_OP_READ, CEPH_OSD_FLAG_READ, NULL, - ci->i_truncate_seq, ci->i_truncate_size, - false); - if (IS_ERR(req)) - return PTR_ERR(req); - - osd_req_op_extent_osd_data_pages(req, 0, &page, len, 0, false, false); - - err = ceph_osdc_start_request(osdc, req, false); - if (!err) - err = ceph_osdc_wait_request(osdc, req); - - ceph_update_read_latency(&fsc->mdsc->metric, req->r_start_latency, - req->r_end_latency, err); - - ceph_osdc_put_request(req); - dout("readpage result %d\n", err); - - if (err == -ENOENT) - err = 0; - if (err < 0) { - if (err == -EBLOCKLISTED) - fsc->blocklisted = true; - goto out; - } - if (err < PAGE_SIZE) - /* zero fill remainder of page */ - zero_user_segment(page, err, PAGE_SIZE); - else - flush_dcache_page(page); - - SetPageUptodate(page); -out: - return err < 0 ? err : 0; -} - /* * Finish an async read(ahead) op. */ @@ -1410,6 +1340,40 @@ ceph_find_incompatible(struct page *page) return NULL; } +static int ceph_netfs_check_write_begin(struct file *file, loff_t pos, unsigned int len, + struct page *page, void **_fsdata) +{ + struct inode *inode = file_inode(file); + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_snap_context *snapc; + + snapc = ceph_find_incompatible(page); + if (snapc) { + int r; + + unlock_page(page); + put_page(page); + if (IS_ERR(snapc)) + return PTR_ERR(snapc); + + ceph_queue_writeback(inode); + r = wait_event_killable(ci->i_cap_wq, + context_is_writeable_or_written(inode, snapc)); + ceph_put_snap_context(snapc); + return r == 0 ? -EAGAIN : r; + } + return 0; +} + +const struct netfs_read_request_ops ceph_netfs_write_begin_ops = { + .init_rreq = ceph_init_rreq, + .is_cache_enabled = ceph_is_cache_enabled, + .begin_cache_operation = ceph_begin_cache_operation, + .issue_op = ceph_netfs_issue_op, + .clamp_length = ceph_netfs_clamp_length, + .check_write_begin = ceph_netfs_check_write_begin, +}; + /* * We are only allowed to write into/dirty the page if the page is * clean, or already dirty within the same snap context. @@ -1420,75 +1384,46 @@ static int ceph_write_begin(struct file *file, struct address_space *mapping, { struct inode *inode = file_inode(file); struct ceph_inode_info *ci = ceph_inode(inode); - struct ceph_snap_context *snapc; struct page *page = NULL; pgoff_t index = pos >> PAGE_SHIFT; - int pos_in_page = pos & ~PAGE_MASK; - int r = 0; - - dout("write_begin file %p inode %p page %p %d~%d\n", file, inode, page, (int)pos, (int)len); - - for (;;) { - page = grab_cache_page_write_begin(mapping, index, flags); - if (!page) { - r = -ENOMEM; - break; - } - - snapc = ceph_find_incompatible(page); - if (snapc) { - if (IS_ERR(snapc)) { - r = PTR_ERR(snapc); - break; - } - unlock_page(page); - put_page(page); - page = NULL; - ceph_queue_writeback(inode); - r = wait_event_killable(ci->i_cap_wq, - context_is_writeable_or_written(inode, snapc)); - ceph_put_snap_context(snapc); - if (r != 0) - break; - continue; - } - - if (PageUptodate(page)) { - dout(" page %p already uptodate\n", page); - break; - } + int r; + if (ci->i_inline_version != CEPH_INLINE_NONE) { /* - * In some cases we don't need to read at all: - * - full page write - * - write that lies completely beyond EOF - * - write that covers the the page from start to EOF or beyond it + * In principle, we should never get here, as the inode should have been uninlined + * before we're allowed to write to the page (in write_iter or page_mkwrite). */ - if ((pos_in_page == 0 && len == PAGE_SIZE) || - (pos >= i_size_read(inode)) || - (pos_in_page == 0 && (pos + len) >= i_size_read(inode))) { - zero_user_segments(page, 0, pos_in_page, - pos_in_page + len, PAGE_SIZE); - break; - } + WARN_ONCE(1, "ceph: write_begin called on still-inlined inode!\n"); /* - * We need to read it. If we get back -EINPROGRESS, then the page was - * handed off to fscache and it will be unlocked when the read completes. - * Refind the page in that case so we can reacquire the page lock. Otherwise - * we got a hard error or the read was completed synchronously. + * Uptodate inline data should have been added + * into page cache while getting Fcr caps. */ - r = ceph_do_readpage(file, page); - if (r != -EINPROGRESS) - break; + if (index == 0) { + r = -EINVAL; + goto out; + } + + page = grab_cache_page_write_begin(mapping, index, flags); + if (!page) + return -ENOMEM; + + zero_user_segment(page, 0, PAGE_SIZE); + SetPageUptodate(page); + r = 0; + goto out; } + r = netfs_write_begin(file, inode->i_mapping, pos, len, 0, &page, NULL, + &ceph_netfs_write_begin_ops, NULL); +out: + if (r == 0) + wait_on_page_fscache(page); if (r < 0) { - if (page) { - unlock_page(page); + if (page) put_page(page); - } } else { + WARN_ON_ONCE(!PageLocked(page)); *pagep = page; } return r; From patchwork Fri Jan 22 17:51:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 12040163 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.4 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id F1DBCC433DB for ; Fri, 22 Jan 2021 17:59:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B8A9423A6A for ; Fri, 22 Jan 2021 17:59:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729566AbhAVR60 (ORCPT ); Fri, 22 Jan 2021 12:58:26 -0500 Received: from mail.kernel.org ([198.145.29.99]:53944 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729289AbhAVRxC (ORCPT ); Fri, 22 Jan 2021 12:53:02 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id E19B323AC0; Fri, 22 Jan 2021 17:51:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1611337886; bh=ydxEs9Whkod0VN9TjVjM1PoZcIsQiU4uGTvxkHheazk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=nO2QSxL9s3oYk4QBFS1ryuUZu9th3PcMqBCTfHZLteqwvagUcEgvm6n3f2gW0TtSO VnJMqwPCg5f/kvQ+1+tqYujtKTYKzVYPxF+6+pU9lfI1xLqzgMKdj31f2E0qaOPQW3 PhQYVCaoCRiZR8ACqZnsdZo6UplQjwcBWe2qfb/TFku/pVPy7tQzBi96MsD4Sw2ZeB OBTRXLRxh1U2htRpfjzb5At9E4gNDM+q+Y5ykSoFU5Fe7WQ35M/Rg3O4cbybrKVywl crcEf0Ya+KuwFdjWOhIEe8XKfQvfHO+R9dZvWF04v+b3Jn3YpPf04oL9/lA3mCdg4W P5j82NN2QGCrw== From: Jeff Layton To: ceph-devel@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org, dhowells@redhat.com, willy@infradead.org, linux-cachefs@redhat.com, linux-kernel@vger.kernel.org Subject: [RFC PATCH 6/6] ceph: convert ceph_readpages to ceph_readahead Date: Fri, 22 Jan 2021 12:51:18 -0500 Message-Id: <20210122175119.364381-7-jlayton@kernel.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210122175119.364381-1-jlayton@kernel.org> References: <20210122175119.364381-1-jlayton@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Convert ceph_readpages to ceph_readahead and make it use netfs_readahead. With this we can rip out a lot of the old readpage/readpages infrastructure. Signed-off-by: Jeff Layton --- fs/ceph/addr.c | 229 ++++++++----------------------------------------- 1 file changed, 34 insertions(+), 195 deletions(-) diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index b3b58285a997..d671c0cb1893 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -321,214 +321,53 @@ static int ceph_readpage(struct file *filp, struct page *page) return netfs_readpage(filp, page, &ceph_readpage_netfs_ops, NULL); } -/* - * Finish an async read(ahead) op. - */ -static void finish_read(struct ceph_osd_request *req) +static void ceph_readahead_cleanup(struct address_space *mapping, void *priv) { - struct inode *inode = req->r_inode; - struct ceph_fs_client *fsc = ceph_inode_to_client(inode); - struct ceph_osd_data *osd_data; - int rc = req->r_result <= 0 ? req->r_result : 0; - int bytes = req->r_result >= 0 ? req->r_result : 0; - int num_pages; - int i; - - dout("finish_read %p req %p rc %d bytes %d\n", inode, req, rc, bytes); - if (rc == -EBLOCKLISTED) - ceph_inode_to_client(inode)->blocklisted = true; - - /* unlock all pages, zeroing any data we didn't read */ - osd_data = osd_req_op_extent_osd_data(req, 0); - BUG_ON(osd_data->type != CEPH_OSD_DATA_TYPE_PAGES); - num_pages = calc_pages_for((u64)osd_data->alignment, - (u64)osd_data->length); - for (i = 0; i < num_pages; i++) { - struct page *page = osd_data->pages[i]; - - if (rc < 0 && rc != -ENOENT) - goto unlock; - if (bytes < (int)PAGE_SIZE) { - /* zero (remainder of) page */ - int s = bytes < 0 ? 0 : bytes; - zero_user_segment(page, s, PAGE_SIZE); - } - dout("finish_read %p uptodate %p idx %lu\n", inode, page, - page->index); - flush_dcache_page(page); - SetPageUptodate(page); -unlock: - unlock_page(page); - put_page(page); - bytes -= PAGE_SIZE; - } - - ceph_update_read_latency(&fsc->mdsc->metric, req->r_start_latency, - req->r_end_latency, rc); - - kfree(osd_data->pages); -} - -/* - * start an async read(ahead) operation. return nr_pages we submitted - * a read for on success, or negative error code. - */ -static int start_read(struct inode *inode, struct ceph_rw_context *rw_ctx, - struct list_head *page_list, int max) -{ - struct ceph_osd_client *osdc = - &ceph_inode_to_client(inode)->client->osdc; + struct inode *inode = mapping->host; struct ceph_inode_info *ci = ceph_inode(inode); - struct page *page = lru_to_page(page_list); - struct ceph_vino vino; - struct ceph_osd_request *req; - u64 off; - u64 len; - int i; - struct page **pages; - pgoff_t next_index; - int nr_pages = 0; - int got = 0; - int ret = 0; - - if (!rw_ctx) { - /* caller of readpages does not hold buffer and read caps - * (fadvise, madvise and readahead cases) */ - int want = CEPH_CAP_FILE_CACHE; - ret = ceph_try_get_caps(inode, CEPH_CAP_FILE_RD, want, - true, &got); - if (ret < 0) { - dout("start_read %p, error getting cap\n", inode); - } else if (!(got & want)) { - dout("start_read %p, no cache cap\n", inode); - ret = 0; - } - if (ret <= 0) { - if (got) - ceph_put_cap_refs(ci, got); - while (!list_empty(page_list)) { - page = lru_to_page(page_list); - list_del(&page->lru); - put_page(page); - } - return ret; - } - } - - off = (u64) page_offset(page); - - /* count pages */ - next_index = page->index; - list_for_each_entry_reverse(page, page_list, lru) { - if (page->index != next_index) - break; - nr_pages++; - next_index++; - if (max && nr_pages == max) - break; - } - len = nr_pages << PAGE_SHIFT; - dout("start_read %p nr_pages %d is %lld~%lld\n", inode, nr_pages, - off, len); - vino = ceph_vino(inode); - req = ceph_osdc_new_request(osdc, &ci->i_layout, vino, off, &len, - 0, 1, CEPH_OSD_OP_READ, - CEPH_OSD_FLAG_READ, NULL, - ci->i_truncate_seq, ci->i_truncate_size, - false); - if (IS_ERR(req)) { - ret = PTR_ERR(req); - goto out; - } - - /* build page vector */ - nr_pages = calc_pages_for(0, len); - pages = kmalloc_array(nr_pages, sizeof(*pages), GFP_KERNEL); - if (!pages) { - ret = -ENOMEM; - goto out_put; - } - for (i = 0; i < nr_pages; ++i) { - page = list_entry(page_list->prev, struct page, lru); - BUG_ON(PageLocked(page)); - list_del(&page->lru); - - dout("start_read %p adding %p idx %lu\n", inode, page, - page->index); - if (add_to_page_cache_lru(page, &inode->i_data, page->index, - GFP_KERNEL)) { - put_page(page); - dout("start_read %p add_to_page_cache failed %p\n", - inode, page); - nr_pages = i; - if (nr_pages > 0) { - len = nr_pages << PAGE_SHIFT; - osd_req_op_extent_update(req, 0, len); - break; - } - goto out_pages; - } - pages[i] = page; - } - osd_req_op_extent_osd_data_pages(req, 0, pages, len, 0, false, false); - req->r_callback = finish_read; - req->r_inode = inode; - - dout("start_read %p starting %p %lld~%lld\n", inode, req, off, len); - ret = ceph_osdc_start_request(osdc, req, false); - if (ret < 0) - goto out_pages; - ceph_osdc_put_request(req); + int got = (int)(uintptr_t)priv; - /* After adding locked pages to page cache, the inode holds cache cap. - * So we can drop our cap refs. */ if (got) ceph_put_cap_refs(ci, got); - - return nr_pages; - -out_pages: - for (i = 0; i < nr_pages; ++i) - unlock_page(pages[i]); - ceph_put_page_vector(pages, nr_pages, false); -out_put: - ceph_osdc_put_request(req); -out: - if (got) - ceph_put_cap_refs(ci, got); - return ret; } +const struct netfs_read_request_ops ceph_readahead_netfs_ops = { + .init_rreq = ceph_init_rreq, + .is_cache_enabled = ceph_is_cache_enabled, + .begin_cache_operation = ceph_begin_cache_operation, + .issue_op = ceph_netfs_issue_op, + .clamp_length = ceph_netfs_clamp_length, + .cleanup = ceph_readahead_cleanup, +}; - -/* - * Read multiple pages. Leave pages we don't read + unlock in page_list; - * the caller (VM) cleans them up. - */ -static int ceph_readpages(struct file *file, struct address_space *mapping, - struct list_head *page_list, unsigned nr_pages) +static void ceph_readahead(struct readahead_control *ractl) { - struct inode *inode = file_inode(file); - struct ceph_fs_client *fsc = ceph_inode_to_client(inode); - struct ceph_file_info *fi = file->private_data; + struct inode *inode = file_inode(ractl->file); + struct ceph_file_info *fi = ractl->file->private_data; struct ceph_rw_context *rw_ctx; - int rc = 0; - int max = 0; + int got = 0; + int ret = 0; if (ceph_inode(inode)->i_inline_version != CEPH_INLINE_NONE) - return -EINVAL; + return; rw_ctx = ceph_find_rw_context(fi); - max = fsc->mount_options->rsize >> PAGE_SHIFT; - dout("readpages %p file %p ctx %p nr_pages %d max %d\n", - inode, file, rw_ctx, nr_pages, max); - while (!list_empty(page_list)) { - rc = start_read(inode, rw_ctx, page_list, max); - if (rc < 0) - goto out; + if (!rw_ctx) { + /* + * readahead callers do not necessarily hold Fcb caps + * (e.g. fadvise, madvise). + */ + int want = CEPH_CAP_FILE_CACHE; + + ret = ceph_try_get_caps(inode, CEPH_CAP_FILE_RD, want, true, &got); + if (ret < 0) + dout("start_read %p, error getting cap\n", inode); + else if (!(got & want)) + dout("start_read %p, no cache cap\n", inode); + + if (ret <= 0) + return; } -out: - dout("readpages %p file %p ret %d\n", inode, file, rc); - return rc; + netfs_readahead(ractl, &ceph_readahead_netfs_ops, (void *)(uintptr_t)got); } struct ceph_writeback_ctl @@ -1481,7 +1320,7 @@ static ssize_t ceph_direct_io(struct kiocb *iocb, struct iov_iter *iter) const struct address_space_operations ceph_aops = { .readpage = ceph_readpage, - .readpages = ceph_readpages, + .readahead = ceph_readahead, .writepage = ceph_writepage, .writepages = ceph_writepages_start, .write_begin = ceph_write_begin,