From patchwork Wed Sep 16 17:38:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeffrey Layton X-Patchwork-Id: 11780293 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id F3A3F139F for ; Wed, 16 Sep 2020 17:40:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D800020738 for ; Wed, 16 Sep 2020 17:40:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1600278005; bh=NKPwYfkTayb562ch4wj6BLB2o+wJeNyJD02fPOTq5Fw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=wu/wvxWAp9C3RdjxyOHcGeCqF20S1sd93v1wbTsh2KMiuut+Va1PcDxyAVeV60dvN y7/qfe31H+k/EFKDQFmkpjKCa0r3oab3A4YBLfEI1XfXcE4ctBKl6JEdrCxqmJEw3t RXNbrFdP2Es0CHGLlGfoe8ReHMRTbZ3X4kMgJSnA= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727298AbgIPRj7 (ORCPT ); Wed, 16 Sep 2020 13:39:59 -0400 Received: from mail.kernel.org ([198.145.29.99]:52224 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727288AbgIPRi7 (ORCPT ); Wed, 16 Sep 2020 13:38:59 -0400 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 81A8520708; Wed, 16 Sep 2020 17:38:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1600277937; bh=NKPwYfkTayb562ch4wj6BLB2o+wJeNyJD02fPOTq5Fw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=FcVG05W2URtQZcGM4eimFBEmbECUq2Cg2Z7O2RoR9eEyW0I2zfSqSUheNfdbO++2H WUHeDgJmjCoDYh0k1AY8umvdcu94PimmW+0GEUuc2YXEmBIgUzB1MAWziocld6vWsP 2kavUDIR6cEjJKo3eLSpgJ8ui8pkCqzwBH5IO+7g= From: Jeff Layton To: ceph-devel@vger.kernel.org Cc: ukernel@gmail.com, idryomov@gmail.com Subject: [PATCH 1/5] ceph: break out writeback of incompatible snap context to separate function Date: Wed, 16 Sep 2020 13:38:50 -0400 Message-Id: <20200916173854.330265-2-jlayton@kernel.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200916173854.330265-1-jlayton@kernel.org> References: <20200916173854.330265-1-jlayton@kernel.org> MIME-Version: 1.0 Sender: ceph-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org When dirtying a page, we have to flush incompatible contexts. Move that into a separate function. Signed-off-by: Jeff Layton --- fs/ceph/addr.c | 96 +++++++++++++++++++++++++++++++------------------- 1 file changed, 60 insertions(+), 36 deletions(-) diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 7b1f3dad576f..c8e98fee8164 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -1298,40 +1298,34 @@ static int context_is_writeable_or_written(struct inode *inode, return ret; } -/* - * We are only allowed to write into/dirty the page if the page is - * clean, or already dirty within the same snap context. +/** + * ceph_find_incompatible - find an incompatible context and return it + * @inode: inode associated with page + * @page: page being dirtied * - * called with page locked. - * return success with page locked, - * or any failure (incl -EAGAIN) with page unlocked. + * Returns NULL on success, negative error code on error, and a snapc ref that should be + * waited on otherwise. */ -static int ceph_update_writeable_page(struct file *file, - loff_t pos, unsigned len, - struct page *page) +static struct ceph_snap_context * +ceph_find_incompatible(struct inode *inode, struct page *page) { - struct inode *inode = file_inode(file); struct ceph_fs_client *fsc = ceph_inode_to_client(inode); struct ceph_inode_info *ci = ceph_inode(inode); - loff_t page_off = pos & PAGE_MASK; - int pos_in_page = pos & ~PAGE_MASK; - int end_in_page = pos_in_page + len; - loff_t i_size; - int r; - struct ceph_snap_context *snapc, *oldest; if (READ_ONCE(fsc->mount_state) == CEPH_MOUNT_SHUTDOWN) { dout(" page %p forced umount\n", page); - unlock_page(page); - return -EIO; + return ERR_PTR(-EIO); } -retry_locked: - /* writepages currently holds page lock, but if we change that later, */ - wait_on_page_writeback(page); + for (;;) { + struct ceph_snap_context *snapc, *oldest; + + wait_on_page_writeback(page); + + snapc = page_snap_context(page); + if (!snapc || snapc == ci->i_head_snapc) + break; - snapc = page_snap_context(page); - if (snapc && snapc != ci->i_head_snapc) { /* * this page is already dirty in another (older) snap * context! is it writeable now? @@ -1346,26 +1340,56 @@ static int ceph_update_writeable_page(struct file *file, * be writeable or written */ snapc = ceph_get_snap_context(snapc); - unlock_page(page); - 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 == -ERESTARTSYS) - return r; - return -EAGAIN; + return snapc; } ceph_put_snap_context(oldest); /* yay, writeable, do it now (without dropping page lock) */ dout(" page %p snapc %p not current, but oldest\n", page, snapc); - if (!clear_page_dirty_for_io(page)) - goto retry_locked; - r = writepage_nounlock(page, NULL); - if (r < 0) + if (clear_page_dirty_for_io(page)) { + int r = writepage_nounlock(page, NULL); + if (r < 0) + return ERR_PTR(r); + } + } + return NULL; +} + +/* + * We are only allowed to write into/dirty the page if the page is + * clean, or already dirty within the same snap context. + * + * called with page locked. + * return success with page locked, + * or any failure (incl -EAGAIN) with page unlocked. + */ +static int ceph_update_writeable_page(struct file *file, + loff_t pos, unsigned len, + struct page *page) +{ + struct inode *inode = file_inode(file); + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_snap_context *snapc; + loff_t page_off = pos & PAGE_MASK; + int pos_in_page = pos & ~PAGE_MASK; + int end_in_page = pos_in_page + len; + loff_t i_size; + int r; + +retry_locked: + snapc = ceph_find_incompatible(inode, page); + if (snapc) { + if (IS_ERR(snapc)) { + r = PTR_ERR(snapc); goto fail_unlock; - goto retry_locked; + } + unlock_page(page); + 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 -EAGAIN; } if (PageUptodate(page)) { From patchwork Wed Sep 16 17:38:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeffrey Layton X-Patchwork-Id: 11780295 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4CA6F6CA for ; Wed, 16 Sep 2020 17:40:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 26ED720672 for ; Wed, 16 Sep 2020 17:40:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1600278014; bh=mCPIaWO4Vn8ZYNreZNFnuzE++GAUWvdp8VCShJCibPs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=x4Kr9ThfciBA4n4KTi4OSLgHu1DIHT1Fa5h8CUUK/5qoh9aj8v+mU5qUC243mP1WR vMdVCEaGnwWQ7pWI+2GVC6fS7WMWbqBY/95ThfVP6/znJaZ19Aod9/mbPfvYSWycAL HXT99QBLGAyEPk00kohkKLqTj522zzziuAO1yRoM= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727300AbgIPRkI (ORCPT ); Wed, 16 Sep 2020 13:40:08 -0400 Received: from mail.kernel.org ([198.145.29.99]:52240 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727289AbgIPRi6 (ORCPT ); Wed, 16 Sep 2020 13:38:58 -0400 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 1AAE920738; Wed, 16 Sep 2020 17:38:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1600277938; bh=mCPIaWO4Vn8ZYNreZNFnuzE++GAUWvdp8VCShJCibPs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ic8tQC6vkzKLh2T8BPWWSSUMH2nDE3e2yRr5jpSSelLK4bXMCqFMSr6ddolbHaYF+ DD5s3Bm4gI3S/G0wBXcu8mzaWv2wYW305zjlzbq0vGuC59bKUfhd+xvdLIG5IiJQ1Z NfNPQSJaZfI3GB0QR4XHb9DrPKAGcilyPYIYM4TE= From: Jeff Layton To: ceph-devel@vger.kernel.org Cc: ukernel@gmail.com, idryomov@gmail.com Subject: [PATCH 2/5] ceph: don't call ceph_update_writeable_page from page_mkwrite Date: Wed, 16 Sep 2020 13:38:51 -0400 Message-Id: <20200916173854.330265-3-jlayton@kernel.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200916173854.330265-1-jlayton@kernel.org> References: <20200916173854.330265-1-jlayton@kernel.org> MIME-Version: 1.0 Sender: ceph-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org page_mkwrite should only be called with Uptodate pages, so we should only need to flush incompatible snap contexts. Signed-off-by: Jeff Layton --- fs/ceph/addr.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index c8e98fee8164..02e286c30d44 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -1691,6 +1691,8 @@ static vm_fault_t ceph_page_mkwrite(struct vm_fault *vmf) inode_inc_iversion_raw(inode); do { + struct ceph_snap_context *snapc; + lock_page(page); if (page_mkwrite_check_truncate(page, inode) < 0) { @@ -1699,13 +1701,26 @@ static vm_fault_t ceph_page_mkwrite(struct vm_fault *vmf) break; } - err = ceph_update_writeable_page(vma->vm_file, off, len, page); - if (err >= 0) { + snapc = ceph_find_incompatible(inode, page); + if (!snapc) { /* success. we'll keep the page locked. */ set_page_dirty(page); ret = VM_FAULT_LOCKED; + break; } - } while (err == -EAGAIN); + + unlock_page(page); + + if (IS_ERR(snapc)) { + ret = VM_FAULT_SIGBUS; + break; + } + + ceph_queue_writeback(inode); + err = wait_event_killable(ci->i_cap_wq, + context_is_writeable_or_written(inode, snapc)); + ceph_put_snap_context(snapc); + } while (err == 0); if (ret == VM_FAULT_LOCKED || ci->i_inline_version != CEPH_INLINE_NONE) { From patchwork Wed Sep 16 17:38:52 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeffrey Layton X-Patchwork-Id: 11780291 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 04DCB139F for ; Wed, 16 Sep 2020 17:40:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DE17320738 for ; Wed, 16 Sep 2020 17:40:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1600278001; bh=jKY2L0+BIoKCnkrk12Tkp01kroUzXRO5lx7n1np0GtU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=rbgg2t0EEIlKtFgVrpQdJwFI4ASC1JTQsGgc6eAD68E3gTeq5EDhp85OU8z/XrrPN 4JqAvKWjz5oMsenUg+sLUMw2ACuzidBdVuEJExGu6hOcuL0RV2Qhb+AHwcuknqAkWq B/wp4cWXLtUjSD24p/TxQolDq3rl2JiDBC7IHnc0= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727291AbgIPRju (ORCPT ); Wed, 16 Sep 2020 13:39:50 -0400 Received: from mail.kernel.org ([198.145.29.99]:52260 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727290AbgIPRi7 (ORCPT ); Wed, 16 Sep 2020 13:38:59 -0400 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 A844B2076C; Wed, 16 Sep 2020 17:38:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1600277939; bh=jKY2L0+BIoKCnkrk12Tkp01kroUzXRO5lx7n1np0GtU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=tyawjpLjdhOjpzIcNDBSf28Qr0Y8M2hHoJfwLaSKFIqbymjNmsxPQniklnmUdVpEb Ej680Au/K8iW78ZP7vxEEBTwMpA7D1XTuhEbGrCu48uZX2YQgyxXa739RRZkzJMTEX jy15fhMMTjnMJ6u9FIahSk3JeAiiaCQAOgUECqxo= From: Jeff Layton To: ceph-devel@vger.kernel.org Cc: ukernel@gmail.com, idryomov@gmail.com Subject: [PATCH 3/5] ceph: fold ceph_sync_readpages into ceph_readpage Date: Wed, 16 Sep 2020 13:38:52 -0400 Message-Id: <20200916173854.330265-4-jlayton@kernel.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200916173854.330265-1-jlayton@kernel.org> References: <20200916173854.330265-1-jlayton@kernel.org> MIME-Version: 1.0 Sender: ceph-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org It's the only caller and this will make reorg easier. Signed-off-by: Jeff Layton --- fs/ceph/addr.c | 79 ++++++++++++++++---------------------------------- 1 file changed, 25 insertions(+), 54 deletions(-) diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 02e286c30d44..19de3e9ccafe 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -182,58 +182,15 @@ static int ceph_releasepage(struct page *page, gfp_t g) return !PagePrivate(page); } -/* - * Read some contiguous pages. If we cross a stripe boundary, shorten - * *plen. Return number of bytes read, or error. - */ -static int ceph_sync_readpages(struct ceph_fs_client *fsc, - struct ceph_vino vino, - struct ceph_file_layout *layout, - u64 off, u64 *plen, - u32 truncate_seq, u64 truncate_size, - struct page **pages, int num_pages, - int page_align) -{ - struct ceph_osd_client *osdc = &fsc->client->osdc; - struct ceph_osd_request *req; - int rc = 0; - - dout("readpages on ino %llx.%llx on %llu~%llu\n", vino.ino, - vino.snap, off, *plen); - req = ceph_osdc_new_request(osdc, layout, vino, off, plen, 0, 1, - CEPH_OSD_OP_READ, CEPH_OSD_FLAG_READ, - NULL, truncate_seq, truncate_size, - false); - if (IS_ERR(req)) - return PTR_ERR(req); - - /* it may be a short read due to an object boundary */ - osd_req_op_extent_osd_data_pages(req, 0, - pages, *plen, page_align, false, false); - - dout("readpages final extent is %llu~%llu (%llu bytes align %d)\n", - off, *plen, *plen, page_align); - - rc = ceph_osdc_start_request(osdc, req, false); - if (!rc) - rc = ceph_osdc_wait_request(osdc, req); - - ceph_update_read_latency(&fsc->mdsc->metric, req->r_start_latency, - req->r_end_latency, rc); - - ceph_osdc_put_request(req); - dout("readpages result %d\n", rc); - return rc; -} - -/* - * read a single page, without unlocking it. - */ +/* 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; @@ -260,12 +217,27 @@ static int ceph_do_readpage(struct file *filp, struct page *page) if (err == 0) return -EINPROGRESS; - dout("readpage inode %p file %p page %p index %lu\n", - inode, filp, page, page->index); - err = ceph_sync_readpages(fsc, ceph_vino(inode), - &ci->i_layout, off, &len, - ci->i_truncate_seq, ci->i_truncate_size, - &page, 1, 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) { @@ -283,7 +255,6 @@ static int ceph_do_readpage(struct file *filp, struct page *page) SetPageUptodate(page); ceph_readpage_to_fscache(inode, page); - out: return err < 0 ? err : 0; } From patchwork Wed Sep 16 17:38:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeffrey Layton X-Patchwork-Id: 11780289 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D6C49139F for ; Wed, 16 Sep 2020 17:39:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BBBDB20738 for ; Wed, 16 Sep 2020 17:39:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1600277988; bh=LZYKnj28NThBQRi+erHxwD7WsznzhEzi0+MczxXy6CM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=n5ZxONhg8Eaw2vdfQwJVpNdp8MuxPZH7cDXWgg9dH8oVT/qrRtv6JKpcwGDHjXKC2 3b3yKzFbrIPnA0zk+1utjtHTlNgfywurat+CTy65M8tLUimgtJinufDoWAL/SwU3j7 HCrqzfGN88AZVfch4c/NKKDVDJxDWwg3JaKS7yDk= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727214AbgIPRjn (ORCPT ); Wed, 16 Sep 2020 13:39:43 -0400 Received: from mail.kernel.org ([198.145.29.99]:52276 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727291AbgIPRjA (ORCPT ); Wed, 16 Sep 2020 13:39:00 -0400 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 40B9B2080C; Wed, 16 Sep 2020 17:38:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1600277939; bh=LZYKnj28NThBQRi+erHxwD7WsznzhEzi0+MczxXy6CM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=G0E5TJu+UDncZJZZ+pnNEI1rgCdogt38alglb9rDErTE01x1aRT5XPRvYVWIoFyHV /KvfjhrtxtcED17v9P1aCkvBL9+z1bZH3wO8L42buUPsUcUliwOtG2TAouCLoHqwFj Jm6pFWCmWySltQ/bMkaY0xCvzX3UjQtoBF/FqPss= From: Jeff Layton To: ceph-devel@vger.kernel.org Cc: ukernel@gmail.com, idryomov@gmail.com Subject: [PATCH 4/5] ceph: fold ceph_sync_writepages into writepage_nounlock Date: Wed, 16 Sep 2020 13:38:53 -0400 Message-Id: <20200916173854.330265-5-jlayton@kernel.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200916173854.330265-1-jlayton@kernel.org> References: <20200916173854.330265-1-jlayton@kernel.org> MIME-Version: 1.0 Sender: ceph-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org It's the only caller, and this will make it easier to refactor. Signed-off-by: Jeff Layton --- fs/ceph/addr.c | 93 +++++++++++++++++++------------------------------- 1 file changed, 35 insertions(+), 58 deletions(-) diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 19de3e9ccafe..a6c54cfc3fea 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -590,50 +590,6 @@ static u64 get_writepages_data_length(struct inode *inode, return end > start ? end - start : 0; } -/* - * do a synchronous write on N pages - */ -static int ceph_sync_writepages(struct ceph_fs_client *fsc, - struct ceph_vino vino, - struct ceph_file_layout *layout, - struct ceph_snap_context *snapc, - u64 off, u64 len, - u32 truncate_seq, u64 truncate_size, - struct timespec64 *mtime, - struct page **pages, int num_pages) -{ - struct ceph_osd_client *osdc = &fsc->client->osdc; - struct ceph_osd_request *req; - int rc = 0; - int page_align = off & ~PAGE_MASK; - - req = ceph_osdc_new_request(osdc, layout, vino, off, &len, 0, 1, - CEPH_OSD_OP_WRITE, CEPH_OSD_FLAG_WRITE, - snapc, truncate_seq, truncate_size, - true); - if (IS_ERR(req)) - return PTR_ERR(req); - - /* it may be a short write due to an object boundary */ - osd_req_op_extent_osd_data_pages(req, 0, pages, len, page_align, - false, false); - dout("writepages %llu~%llu (%llu bytes)\n", off, len, len); - - req->r_mtime = *mtime; - rc = ceph_osdc_start_request(osdc, req, true); - if (!rc) - rc = ceph_osdc_wait_request(osdc, req); - - ceph_update_write_latency(&fsc->mdsc->metric, req->r_start_latency, - req->r_end_latency, rc); - - ceph_osdc_put_request(req); - if (rc == 0) - rc = len; - dout("writepages result %d\n", rc); - return rc; -} - /* * Write a single page, but leave the page locked. * @@ -642,20 +598,19 @@ static int ceph_sync_writepages(struct ceph_fs_client *fsc, */ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) { - struct inode *inode; - struct ceph_inode_info *ci; - struct ceph_fs_client *fsc; + struct inode *inode = page->mapping->host; + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_fs_client *fsc = ceph_inode_to_client(inode); struct ceph_snap_context *snapc, *oldest; loff_t page_off = page_offset(page); - int err, len = PAGE_SIZE; + int err; + loff_t len = PAGE_SIZE; struct ceph_writeback_ctl ceph_wbc; + struct ceph_osd_client *osdc = &fsc->client->osdc; + struct ceph_osd_request *req; dout("writepage %p idx %lu\n", page, page->index); - inode = page->mapping->host; - ci = ceph_inode(inode); - fsc = ceph_inode_to_client(inode); - /* verify this is a writeable snap context */ snapc = page_snap_context(page); if (!snapc) { @@ -684,7 +639,7 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) if (ceph_wbc.i_size < page_off + len) len = ceph_wbc.i_size - page_off; - dout("writepage %p page %p index %lu on %llu~%u snapc %p seq %lld\n", + dout("writepage %p page %p index %lu on %llu~%llu snapc %p seq %lld\n", inode, page, page->index, page_off, len, snapc, snapc->seq); if (atomic_long_inc_return(&fsc->writeback_count) > @@ -692,11 +647,33 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) set_bdi_congested(inode_to_bdi(inode), BLK_RW_ASYNC); set_page_writeback(page); - err = ceph_sync_writepages(fsc, ceph_vino(inode), - &ci->i_layout, snapc, page_off, len, - ceph_wbc.truncate_seq, - ceph_wbc.truncate_size, - &inode->i_mtime, &page, 1); + 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); + return PTR_ERR(req); + } + + /* it may be a short write due to an object boundary */ + WARN_ON_ONCE(len > PAGE_SIZE); + osd_req_op_extent_osd_data_pages(req, 0, &page, len, 0, false, false); + dout("writepage %llu~%llu (%llu bytes)\n", page_off, len, len); + + req->r_mtime = inode->i_mtime; + err = ceph_osdc_start_request(osdc, req, true); + if (!err) + err = ceph_osdc_wait_request(osdc, req); + + ceph_update_write_latency(&fsc->mdsc->metric, req->r_start_latency, + req->r_end_latency, err); + + ceph_osdc_put_request(req); + if (err == 0) + err = len; + if (err < 0) { struct writeback_control tmp_wbc; if (!wbc) From patchwork Wed Sep 16 17:38:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeffrey Layton X-Patchwork-Id: 11780297 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DEA096CA for ; Wed, 16 Sep 2020 17:40:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C6A2F20738 for ; Wed, 16 Sep 2020 17:40:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1600278039; bh=LTIDt2NrL2coWN5soi5Nvk8Ep0rUn7wR8++EYLmk6HQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=pyVO7+wcRNPjJR7+qv2jt+NljsAGQiRPq19KkEe+DOf6EVJzA8bUT00VPHCh2S9Kk f9o2hNeUf82H2blaYT/5MzHqa6+Rb3P5o+oNSjIjwQGiVkECvBRHXxTFWU/sCXmFSG BseS01PADHlHyDvgtoG69bsw8mMPLbn67MloS9cw= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727306AbgIPRkT (ORCPT ); Wed, 16 Sep 2020 13:40:19 -0400 Received: from mail.kernel.org ([198.145.29.99]:53348 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727295AbgIPRjZ (ORCPT ); Wed, 16 Sep 2020 13:39:25 -0400 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 CD41C22207; Wed, 16 Sep 2020 17:38:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1600277940; bh=LTIDt2NrL2coWN5soi5Nvk8Ep0rUn7wR8++EYLmk6HQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=vHu276ovEaBbAg0gAnYQU9dEy2JjidWw/JQmr/KnP1oshIbOloxtZVFs5fqomh6/z Zimf/WiP4DZfMGj6phlxAbNRRvWzW7vQEbHV08ALyhbDo9jB2u7aUx10LFs/d5ETEh GNS92ZEfH8jgQ4yhD9Uw+7RdyrucRLiHpK4RqlXY= From: Jeff Layton To: ceph-devel@vger.kernel.org Cc: ukernel@gmail.com, idryomov@gmail.com Subject: [PATCH 5/5] ceph: fold ceph_update_writeable_page into ceph_write_begin Date: Wed, 16 Sep 2020 13:38:54 -0400 Message-Id: <20200916173854.330265-6-jlayton@kernel.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200916173854.330265-1-jlayton@kernel.org> References: <20200916173854.330265-1-jlayton@kernel.org> MIME-Version: 1.0 Sender: ceph-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org ...and reorganize the loop for better clarity. Signed-off-by: Jeff Layton --- fs/ceph/addr.c | 148 ++++++++++++++++++++++--------------------------- 1 file changed, 65 insertions(+), 83 deletions(-) diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index a6c54cfc3fea..89c4d8a9a5eb 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -1251,6 +1251,8 @@ static int context_is_writeable_or_written(struct inode *inode, * @inode: inode associated with page * @page: page being dirtied * + * We are only allowed to write into/dirty the page if the page is + * clean, or already dirty within the same snap context. * Returns NULL on success, negative error code on error, and a snapc ref that should be * waited on otherwise. */ @@ -1307,104 +1309,84 @@ ceph_find_incompatible(struct inode *inode, struct page *page) /* * We are only allowed to write into/dirty the page if the page is * clean, or already dirty within the same snap context. - * - * called with page locked. - * return success with page locked, - * or any failure (incl -EAGAIN) with page unlocked. */ -static int ceph_update_writeable_page(struct file *file, - loff_t pos, unsigned len, - struct page *page) +static int ceph_write_begin(struct file *file, struct address_space *mapping, + loff_t pos, unsigned len, unsigned flags, + struct page **pagep, void **fsdata) { struct inode *inode = file_inode(file); struct ceph_inode_info *ci = ceph_inode(inode); struct ceph_snap_context *snapc; - loff_t page_off = pos & PAGE_MASK; + struct page *page = NULL; + pgoff_t index = pos >> PAGE_SHIFT; int pos_in_page = pos & ~PAGE_MASK; - int end_in_page = pos_in_page + len; - loff_t i_size; - int r; + int r = 0; -retry_locked: - snapc = ceph_find_incompatible(inode, page); - if (snapc) { - if (IS_ERR(snapc)) { - r = PTR_ERR(snapc); - goto fail_unlock; + 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, 0); + if (!page) { + r = -ENOMEM; + break; } - unlock_page(page); - 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 -EAGAIN; - } - if (PageUptodate(page)) { - dout(" page %p already uptodate\n", page); - return 0; - } + snapc = ceph_find_incompatible(inode, page); + if (snapc) { + if (IS_ERR(snapc)) { + r = PTR_ERR(snapc); + break; + } + unlock_page(page); + ceph_queue_writeback(inode); + r = wait_event_killable(ci->i_cap_wq, + context_is_writeable_or_written(inode, snapc)); + ceph_put_snap_context(snapc); + put_page(page); + page = NULL; + if (r != 0) + break; + continue; + } - /* full page? */ - if (pos_in_page == 0 && len == PAGE_SIZE) - return 0; + if (PageUptodate(page)) { + dout(" page %p already uptodate\n", page); + break; + } - /* past end of file? */ - i_size = i_size_read(inode); - - if (page_off >= i_size || - (pos_in_page == 0 && (pos+len) >= i_size && - end_in_page - pos_in_page != PAGE_SIZE)) { - dout(" zeroing %p 0 - %d and %d - %d\n", - page, pos_in_page, end_in_page, (int)PAGE_SIZE); - zero_user_segments(page, - 0, pos_in_page, - end_in_page, PAGE_SIZE); - return 0; - } + /* + * 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 + */ + 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; + } - /* we need to read it. */ - r = ceph_do_readpage(file, page); - if (r < 0) { - if (r == -EINPROGRESS) - return -EAGAIN; - goto fail_unlock; + /* + * 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. + */ + r = ceph_do_readpage(file, page); + if (r != -EINPROGRESS) + break; } - goto retry_locked; -fail_unlock: - unlock_page(page); - return r; -} -/* - * We are only allowed to write into/dirty the page if the page is - * clean, or already dirty within the same snap context. - */ -static int ceph_write_begin(struct file *file, struct address_space *mapping, - loff_t pos, unsigned len, unsigned flags, - struct page **pagep, void **fsdata) -{ - struct inode *inode = file_inode(file); - struct page *page; - pgoff_t index = pos >> PAGE_SHIFT; - int r; - - do { - /* get a page */ - page = grab_cache_page_write_begin(mapping, index, 0); - if (!page) - return -ENOMEM; - - dout("write_begin file %p inode %p page %p %d~%d\n", file, - inode, page, (int)pos, (int)len); - - r = ceph_update_writeable_page(file, pos, len, page); - if (r < 0) + if (r < 0) { + if (page) { + unlock_page(page); put_page(page); - else - *pagep = page; - } while (r == -EAGAIN); - + } + } else { + *pagep = page; + } return r; }