From patchwork Mon Nov 16 07:08:35 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chandan Rajendra X-Patchwork-Id: 7621261 Return-Path: X-Original-To: patchwork-linux-btrfs@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id D9CC7BF90C for ; Mon, 16 Nov 2015 07:09:30 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id E62462054A for ; Mon, 16 Nov 2015 07:09:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id B478B205B5 for ; Mon, 16 Nov 2015 07:09:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751970AbbKPHJP (ORCPT ); Mon, 16 Nov 2015 02:09:15 -0500 Received: from e28smtp06.in.ibm.com ([122.248.162.6]:57305 "EHLO e28smtp06.in.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751919AbbKPHJL (ORCPT ); Mon, 16 Nov 2015 02:09:11 -0500 Received: from /spool/local by e28smtp06.in.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 16 Nov 2015 12:39:09 +0530 Received: from d28dlp03.in.ibm.com (9.184.220.128) by e28smtp06.in.ibm.com (192.168.1.136) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Mon, 16 Nov 2015 12:39:07 +0530 X-Helo: d28dlp03.in.ibm.com X-MailFrom: chandan@linux.vnet.ibm.com X-RcptTo: linux-btrfs@vger.kernel.org Received: from d28relay04.in.ibm.com (d28relay04.in.ibm.com [9.184.220.61]) by d28dlp03.in.ibm.com (Postfix) with ESMTP id 9BBD21258098 for ; Mon, 16 Nov 2015 12:39:14 +0530 (IST) Received: from d28av03.in.ibm.com (d28av03.in.ibm.com [9.184.220.65]) by d28relay04.in.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id tAG78w8r31654116 for ; Mon, 16 Nov 2015 12:38:59 +0530 Received: from d28av03.in.ibm.com (localhost [127.0.0.1]) by d28av03.in.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id tAG78uUB027319 for ; Mon, 16 Nov 2015 12:38:57 +0530 Received: from localhost.in.ibm.com ([9.124.35.170]) by d28av03.in.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id tAG78tLb027210; Mon, 16 Nov 2015 12:38:56 +0530 From: Chandan Rajendra To: linux-btrfs@vger.kernel.org Cc: Chandan Rajendra , jbacik@fb.com, clm@fb.com, bo.li.liu@oracle.com, dsterba@suse.cz, chandan@mykolab.com Subject: [RFC PATCH V12 08/14] Btrfs: subpagesize-blocksize: Deal with partial ordered extent allocations. Date: Mon, 16 Nov 2015 12:38:35 +0530 Message-Id: <1447657721-10025-9-git-send-email-chandan@linux.vnet.ibm.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1447657721-10025-1-git-send-email-chandan@linux.vnet.ibm.com> References: <1447657721-10025-1-git-send-email-chandan@linux.vnet.ibm.com> X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 15111607-0021-0000-0000-0000087C2B47 Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Spam-Status: No, score=-7.7 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP In subpagesize-blocksize scenario, extent allocations for only some of the dirty blocks of a page can succeed, while allocation for rest of the blocks can fail. This patch allows I/O against such pages to be submitted. Signed-off-by: Chandan Rajendra --- fs/btrfs/extent_io.c | 27 ++++++++++++++------------- fs/btrfs/inode.c | 39 ++++++++++++++++++++++++++------------- 2 files changed, 40 insertions(+), 26 deletions(-) diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 5931607..d5d9408 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -1942,17 +1942,23 @@ int extent_clear_unlock_delalloc(struct inode *inode, u64 start, u64 end, if (page_ops & PAGE_SET_PRIVATE2) SetPagePrivate2(pages[i]); + if (page_ops & PAGE_SET_ERROR) + SetPageError(pages[i]); + if (pages[i] == locked_page) { page_cache_release(pages[i]); continue; } - if (page_ops & PAGE_CLEAR_DIRTY) + + if ((page_ops & PAGE_CLEAR_DIRTY) + && !PagePrivate2(pages[i])) clear_page_dirty_for_io(pages[i]); - if (page_ops & PAGE_SET_WRITEBACK) + if ((page_ops & PAGE_SET_WRITEBACK) + && !PagePrivate2(pages[i])) set_page_writeback(pages[i]); - if (page_ops & PAGE_SET_ERROR) - SetPageError(pages[i]); - if (page_ops & PAGE_END_WRITEBACK) + + if ((page_ops & PAGE_END_WRITEBACK) + && !PagePrivate2(pages[i])) end_page_writeback(pages[i]); if (page_ops & PAGE_UNLOCK) unlock_page(pages[i]); @@ -2642,7 +2648,7 @@ int end_extent_writepage(struct page *page, int err, u64 start, u64 end) uptodate = 0; } - if (!uptodate) { + if (!uptodate || PageError(page)) { ClearPageUptodate(page); SetPageError(page); ret = ret < 0 ? ret : -EIO; @@ -3487,7 +3493,6 @@ static noinline_for_stack int writepage_delalloc(struct inode *inode, nr_written); /* File system has been set read-only */ if (ret) { - SetPageError(page); /* fill_delalloc should be return < 0 for error * but just in case, we use > 0 here meaning the * IO is started, so we don't want to return > 0 @@ -3719,7 +3724,6 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc, struct inode *inode = page->mapping->host; struct extent_page_data *epd = data; u64 start = page_offset(page); - u64 page_end = start + PAGE_CACHE_SIZE - 1; int ret; int nr = 0; size_t pg_offset = 0; @@ -3764,7 +3768,7 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc, ret = writepage_delalloc(inode, page, wbc, epd, start, &nr_written); if (ret == 1) goto done_unlocked; - if (ret) + if (ret && !PagePrivate2(page)) goto done; ret = __extent_writepage_io(inode, page, wbc, epd, @@ -3778,10 +3782,7 @@ done: set_page_writeback(page); end_page_writeback(page); } - if (PageError(page)) { - ret = ret < 0 ? ret : -EIO; - end_extent_writepage(page, ret, start, page_end); - } + unlock_page(page); return ret; diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 29d6c07..891d533 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -934,6 +934,8 @@ static noinline int cow_file_range(struct inode *inode, struct btrfs_key ins; struct extent_map *em; struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; + struct btrfs_ordered_extent *ordered; + unsigned long page_ops, extent_ops; int ret = 0; if (btrfs_is_free_space_inode(inode)) { @@ -978,8 +980,6 @@ static noinline int cow_file_range(struct inode *inode, btrfs_drop_extent_cache(inode, start, start + num_bytes - 1, 0); while (disk_num_bytes > 0) { - unsigned long op; - cur_alloc_size = disk_num_bytes; ret = btrfs_reserve_extent(root, cur_alloc_size, root->sectorsize, 0, alloc_hint, @@ -1032,7 +1032,7 @@ static noinline int cow_file_range(struct inode *inode, ret = btrfs_reloc_clone_csums(inode, start, cur_alloc_size); if (ret) - goto out_drop_extent_cache; + goto out_remove_ordered_extent; } if (disk_num_bytes < cur_alloc_size) @@ -1045,13 +1045,12 @@ static noinline int cow_file_range(struct inode *inode, * Do set the Private2 bit so we know this page was properly * setup for writepage */ - op = unlock ? PAGE_UNLOCK : 0; - op |= PAGE_SET_PRIVATE2; - + page_ops = unlock ? PAGE_UNLOCK : 0; + page_ops |= PAGE_SET_PRIVATE2; + extent_ops = EXTENT_LOCKED | EXTENT_DELALLOC; extent_clear_unlock_delalloc(inode, start, - start + ram_size - 1, locked_page, - EXTENT_LOCKED | EXTENT_DELALLOC, - op); + start + ram_size - 1, locked_page, + extent_ops, page_ops); disk_num_bytes -= cur_alloc_size; num_bytes -= cur_alloc_size; alloc_hint = ins.objectid + ins.offset; @@ -1060,16 +1059,30 @@ static noinline int cow_file_range(struct inode *inode, out: return ret; +out_remove_ordered_extent: + ordered = btrfs_lookup_ordered_extent(inode, start); + BUG_ON(!ordered); + btrfs_remove_ordered_extent(inode, ordered); + /* once for us */ + btrfs_put_ordered_extent(ordered); + /* once for the tree */ + btrfs_put_ordered_extent(ordered); + out_drop_extent_cache: btrfs_drop_extent_cache(inode, start, start + ram_size - 1, 0); + out_reserve: btrfs_free_reserved_extent(root, ins.objectid, ins.offset, 1); + out_unlock: + page_ops = unlock ? PAGE_UNLOCK : 0; + page_ops |= PAGE_CLEAR_DIRTY | PAGE_SET_WRITEBACK | PAGE_END_WRITEBACK + | PAGE_SET_ERROR; + extent_ops = EXTENT_LOCKED | EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING + | EXTENT_DEFRAG; + extent_clear_unlock_delalloc(inode, start, end, locked_page, - EXTENT_LOCKED | EXTENT_DO_ACCOUNTING | - EXTENT_DELALLOC | EXTENT_DEFRAG, - PAGE_UNLOCK | PAGE_CLEAR_DIRTY | - PAGE_SET_WRITEBACK | PAGE_END_WRITEBACK); + extent_ops, page_ops); goto out; }