From patchwork Fri Nov 20 15:30:06 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 11921125 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.0 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 CD2FDC56201 for ; Fri, 20 Nov 2020 15:30:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 822392245F for ; Fri, 20 Nov 2020 15:30:14 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=kernel.org header.i=@kernel.org header.b="1xJnaGHS" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728534AbgKTPaN (ORCPT ); Fri, 20 Nov 2020 10:30:13 -0500 Received: from mail.kernel.org ([198.145.29.99]:35132 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727335AbgKTPaN (ORCPT ); Fri, 20 Nov 2020 10:30:13 -0500 Received: from tleilax.com (68-20-15-154.lightspeed.rlghnc.sbcglobal.net [68.20.15.154]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id C5DB12245A; Fri, 20 Nov 2020 15:30:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1605886212; bh=ZrMmAoupCP1VvaDAEcXsjaQ5Si8IUlNucRxFMdE1MF0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=1xJnaGHSBEyylwUC23Rpied4/U1li3LgHSMaQFBTO62uYVoZBpNu0dLk6bULfUazc B2S63X7qxEt6Zp6Ig9vmPEkPJE3FFx9wXx/neQi9tzLOtrWMuBGl8PVMivB08USR6T 6x0kMgKxojOe2d15/IgtjhH67KF2OJHJvEb6if18= From: Jeff Layton To: ceph-devel@vger.kernel.org Cc: linux-cachefs@redhat.com, idryomov@redhat.com, dhowells@redhat.com Subject: [PATCH 5/5] ceph: add fscache writeback support Date: Fri, 20 Nov 2020 10:30:06 -0500 Message-Id: <20201120153006.304296-6-jlayton@kernel.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201120153006.304296-1-jlayton@kernel.org> References: <20201120153006.304296-1-jlayton@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org When updating the backing store from the pagecache (a'la writepage or writepages), write to the cache first. This allows us to keep caching files even when they are open for write. With this change we we can now re-enable CEPH_FSCACHE in Kconfig. Signed-off-by: Jeff Layton --- fs/ceph/Kconfig | 2 +- fs/ceph/addr.c | 64 +++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/fs/ceph/Kconfig b/fs/ceph/Kconfig index 77ad452337ee..94df854147d3 100644 --- a/fs/ceph/Kconfig +++ b/fs/ceph/Kconfig @@ -21,7 +21,7 @@ config CEPH_FS if CEPH_FS config CEPH_FSCACHE bool "Enable Ceph client caching support" - depends on CEPH_FS=m && FSCACHE_OLD || CEPH_FS=y && FSCACHE_OLD=y + depends on CEPH_FS=m && FSCACHE || CEPH_FS=y && FSCACHE=y help Choose Y here to enable persistent, read-only local caching support for Ceph clients using FS-Cache diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index ea17ee7d7218..3bd9a2922e4f 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -5,7 +5,6 @@ #include #include #include -#include /* generic_writepages */ #include #include #include @@ -391,6 +390,39 @@ static void ceph_readahead(struct readahead_control *ractl) netfs_readahead(ractl, &ceph_readahead_netfs_ops, (void *)(uintptr_t)got); } +#ifdef CONFIG_CEPH_FSCACHE +static void ceph_fscache_write_terminated(void *priv, ssize_t error) +{ + struct inode *inode = priv; + + if (IS_ERR_VALUE(error) && error != -ENOBUFS) + ceph_fscache_invalidate(inode, 0); +} + +static void ceph_fscache_write_to_cache(struct inode *inode, u64 off, u64 len) +{ + struct ceph_inode_info *ci = ceph_inode(inode); + struct fscache_cookie *cookie = ceph_fscache_cookie(ci); + + fscache_write_to_cache(cookie, inode->i_mapping, off, len, i_size_read(inode), + ceph_fscache_write_terminated, inode); +} + +static inline bool CephTestSetPageFsCache(struct page *page) +{ + return TestSetPageFsCache(page); +} +#else +static inline void ceph_fscache_write_to_cache(struct inode *inode, u64 off, u64 len) +{ +} + +static inline bool CephTestSetPageFsCache(struct page *page) +{ + return false; +} +#endif /* CONFIG_CEPH_FSCACHE */ + struct ceph_writeback_ctl { loff_t i_size; @@ -544,16 +576,17 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) CONGESTION_ON_THRESH(fsc->mount_options->congestion_kb)) set_bdi_congested(inode_to_bdi(inode), BLK_RW_ASYNC); - set_page_writeback(page); req = ceph_osdc_new_request(osdc, &ci->i_layout, ceph_vino(inode), page_off, &len, 0, 1, CEPH_OSD_OP_WRITE, CEPH_OSD_FLAG_WRITE, snapc, ceph_wbc.truncate_seq, ceph_wbc.truncate_size, true); - if (IS_ERR(req)) { - redirty_page_for_writepage(wbc, page); - end_page_writeback(page); + if (IS_ERR(req)) return PTR_ERR(req); - } + + set_page_writeback(page); + if (CephTestSetPageFsCache(page)) + BUG(); + ceph_fscache_write_to_cache(inode, page_off, len); /* it may be a short write due to an object boundary */ WARN_ON_ONCE(len > PAGE_SIZE); @@ -612,6 +645,9 @@ static int ceph_writepage(struct page *page, struct writeback_control *wbc) struct inode *inode = page->mapping->host; BUG_ON(!inode); ihold(inode); + + ceph_wait_on_page_fscache(page); + err = writepage_nounlock(page, wbc); if (err == -ERESTARTSYS) { /* direct memory reclaimer was killed by SIGKILL. return 0 @@ -856,7 +892,7 @@ static int ceph_writepages_start(struct address_space *mapping, unlock_page(page); break; } - if (PageWriteback(page)) { + if (PageWriteback(page) || PageFsCache(page)) { if (wbc->sync_mode == WB_SYNC_NONE) { dout("%p under writeback\n", page); unlock_page(page); @@ -864,6 +900,7 @@ static int ceph_writepages_start(struct address_space *mapping, } dout("waiting on writeback %p\n", page); wait_on_page_writeback(page); + ceph_wait_on_page_fscache(page); } if (!clear_page_dirty_for_io(page)) { @@ -996,9 +1033,19 @@ static int ceph_writepages_start(struct address_space *mapping, op_idx = 0; for (i = 0; i < locked_pages; i++) { u64 cur_offset = page_offset(pages[i]); + /* + * Discontinuity in page range? Ceph can handle that by just passing + * multiple extents in the write op. + */ if (offset + len != cur_offset) { + /* If it's full, stop here */ if (op_idx + 1 == req->r_num_ops) break; + + /* Kick off an fscache write with what we have so far. */ + ceph_fscache_write_to_cache(inode, offset, len); + + /* Start a new extent */ osd_req_op_extent_dup_last(req, op_idx, cur_offset - offset); dout("writepages got pages at %llu~%llu\n", @@ -1015,8 +1062,11 @@ static int ceph_writepages_start(struct address_space *mapping, } set_page_writeback(pages[i]); + if (CephTestSetPageFsCache(pages[i])) + BUG(); len += PAGE_SIZE; } + ceph_fscache_write_to_cache(inode, offset, len); if (ceph_wbc.size_stable) { len = min(len, ceph_wbc.i_size - offset);