From patchwork Thu Oct 19 06:59:37 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Hellwig X-Patchwork-Id: 10016087 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id F138B60215 for ; Thu, 19 Oct 2017 07:00:33 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E356A28C64 for ; Thu, 19 Oct 2017 07:00:33 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D847728CA3; Thu, 19 Oct 2017 07:00:33 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id F2F1528C64 for ; Thu, 19 Oct 2017 07:00:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751558AbdJSHAc (ORCPT ); Thu, 19 Oct 2017 03:00:32 -0400 Received: from bombadil.infradead.org ([65.50.211.133]:57031 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751490AbdJSHAc (ORCPT ); Thu, 19 Oct 2017 03:00:32 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20170209; h=References:In-Reply-To:Message-Id: Date:Subject:To:From:Sender:Reply-To:Cc:MIME-Version:Content-Type: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=iRBqIKE27MRN49ilHnji6vlPrM9D86cip0PiTpto/iM=; b=cNr4dvdN46+rNO9AXWzT5vY+i u0YRI0wnEcsTXFYDt66LevKlN2cBoFIAd05AnYZZkh20SOKgFJRJWMRs67FO8t4ot94Cybq2Eynkn /xjWF/XyJfMuo1h6caVueheSZkh8KF/R7MB2BAkf1maCTvOYLtMwyU7afn5QlLkK1ZwNdgaieVmaJ 7f54MGjaOO6ZHj5FJT5KcDFeHuooRBQtiNtO1N6/P8cXDYXxAU1+tctRzDUbnOJcaSAqGNUFKmQtv ZLZFq6SXYINHcTiPs11TvjefI7x+2HxMDXDrjFxSL7A4Bw+5CHTHHd49l3ZTRbl9n8emMhraLlbvo hACbHoVsQ==; Received: from 212095007233.public.telering.at ([212.95.7.233] helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.87 #1 (Red Hat Linux)) id 1e54oh-0005sa-1i for linux-xfs@vger.kernel.org; Thu, 19 Oct 2017 07:00:31 +0000 From: Christoph Hellwig To: linux-xfs@vger.kernel.org Subject: [PATCH 10/15] xfs: split xfs_bmap_shift_extents Date: Thu, 19 Oct 2017 08:59:37 +0200 Message-Id: <20171019065942.18813-11-hch@lst.de> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20171019065942.18813-1-hch@lst.de> References: <20171019065942.18813-1-hch@lst.de> X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html Sender: linux-xfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Have a separate helper for insert vs collapse, as this prepares us for simplifying the code in the next patches. Also changed the done output argument to a bool intead of int for both new functions. Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_bmap.c | 197 ++++++++++++++++++++++++++++++++--------------- fs/xfs/libxfs/xfs_bmap.h | 10 ++- fs/xfs/xfs_bmap_util.c | 14 ++-- 3 files changed, 148 insertions(+), 73 deletions(-) diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 89ea8a5235c0..7d3a38e69d28 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -5689,57 +5689,151 @@ xfs_bmse_shift_one( return xfs_rmap_map_extent(mp, dfops, ip, whichfork, &new); } -/* - * Shift extent records to the left/right to cover/create a hole. - * - * @stop_fsb specifies the file offset at which to stop shift and the - * file offset where we've left off is returned in @next_fsb. @offset_shift_fsb - * is the length by which each extent is shifted. If there is no hole to shift - * the extents into, this will be considered invalid operation and we abort - * immediately. - */ int -xfs_bmap_shift_extents( +xfs_bmap_collapse_extents( struct xfs_trans *tp, struct xfs_inode *ip, xfs_fileoff_t *next_fsb, xfs_fileoff_t offset_shift_fsb, - int *done, + bool *done, xfs_fileoff_t stop_fsb, xfs_fsblock_t *firstblock, - struct xfs_defer_ops *dfops, - enum shift_direction direction) + struct xfs_defer_ops *dfops) { - struct xfs_btree_cur *cur = NULL; - struct xfs_bmbt_irec got; - struct xfs_mount *mp = ip->i_mount; - struct xfs_ifork *ifp; - xfs_extnum_t current_ext; - xfs_extnum_t total_extents; - xfs_extnum_t stop_extent; - int error = 0; - int whichfork = XFS_DATA_FORK; - int logflags = 0; + int whichfork = XFS_DATA_FORK; + struct xfs_mount *mp = ip->i_mount; + struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); + struct xfs_btree_cur *cur = NULL; + struct xfs_bmbt_irec got; + xfs_extnum_t current_ext; + xfs_extnum_t total_extents; + xfs_extnum_t stop_extent; + int error = 0; + int logflags = 0; if (unlikely(XFS_TEST_ERROR( (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE), mp, XFS_ERRTAG_BMAPIFORMAT))) { - XFS_ERROR_REPORT("xfs_bmap_shift_extents", - XFS_ERRLEVEL_LOW, mp); + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp); return -EFSCORRUPTED; } if (XFS_FORCED_SHUTDOWN(mp)) return -EIO; - ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL)); - ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); - ASSERT(direction == SHIFT_LEFT || direction == SHIFT_RIGHT); + ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL)); + + if (!(ifp->if_flags & XFS_IFEXTENTS)) { + error = xfs_iread_extents(tp, ip, whichfork); + if (error) + return error; + } + + if (ifp->if_flags & XFS_IFBROOT) { + cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork); + cur->bc_private.b.firstblock = *firstblock; + cur->bc_private.b.dfops = dfops; + cur->bc_private.b.flags = 0; + } + + /* + * There may be delalloc extents in the data fork before the range we + * are collapsing out, so we cannot use the count of real extents here. + * Instead we have to calculate it from the incore fork. + */ + total_extents = xfs_iext_count(ifp); + if (total_extents == 0) { + *done = true; + goto del_cursor; + } + + /* + * Look up the extent index for the fsb where we start shifting. We can + * henceforth iterate with current_ext as extent list changes are locked + * out via ilock. + * + * If next_fsb lies in a hole beyond which there are no extents we are + * done. + */ + if (!xfs_iext_lookup_extent(ip, ifp, *next_fsb, ¤t_ext, &got)) { + *done = true; + goto del_cursor; + } + + stop_extent = total_extents; + if (current_ext >= stop_extent) { + error = -EIO; + goto del_cursor; + } + + error = xfs_bmse_shift_one(ip, whichfork, offset_shift_fsb, + ¤t_ext, &got, cur, &logflags, + SHIFT_LEFT, dfops); + if (error) + goto del_cursor; + /* + * If there was an extent merge during the shift, the extent + * count can change. Update the total and grade the next record. + */ + total_extents = xfs_iext_count(ifp); + stop_extent = total_extents; + if (current_ext == stop_extent) { + *done = true; + goto del_cursor; + } + xfs_iext_get_extent(ifp, current_ext, &got); + + if (!*done) + *next_fsb = got.br_startoff; + +del_cursor: + if (cur) + xfs_btree_del_cursor(cur, + error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); + + if (logflags) + xfs_trans_log_inode(tp, ip, logflags); + + return error; +} + +int +xfs_bmap_insert_extents( + struct xfs_trans *tp, + struct xfs_inode *ip, + xfs_fileoff_t *next_fsb, + xfs_fileoff_t offset_shift_fsb, + bool *done, + xfs_fileoff_t stop_fsb, + xfs_fsblock_t *firstblock, + struct xfs_defer_ops *dfops) +{ + int whichfork = XFS_DATA_FORK; + struct xfs_mount *mp = ip->i_mount; + struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); + struct xfs_btree_cur *cur = NULL; + struct xfs_bmbt_irec got, s; + xfs_extnum_t current_ext; + xfs_extnum_t total_extents; + xfs_extnum_t stop_extent; + int error = 0; + int logflags = 0; + + if (unlikely(XFS_TEST_ERROR( + (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && + XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE), + mp, XFS_ERRTAG_BMAPIFORMAT))) { + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp); + return -EFSCORRUPTED; + } + + if (XFS_FORCED_SHUTDOWN(mp)) + return -EIO; + + ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL)); - ifp = XFS_IFORK_PTR(ip, whichfork); if (!(ifp->if_flags & XFS_IFEXTENTS)) { - /* Read in all the extents */ error = xfs_iread_extents(tp, ip, whichfork); if (error) return error; @@ -5759,7 +5853,7 @@ xfs_bmap_shift_extents( */ total_extents = xfs_iext_count(ifp); if (total_extents == 0) { - *done = 1; + *done = true; goto del_cursor; } @@ -5767,12 +5861,10 @@ xfs_bmap_shift_extents( * In case of first right shift, we need to initialize next_fsb */ if (*next_fsb == NULLFSBLOCK) { - ASSERT(direction == SHIFT_RIGHT); - current_ext = total_extents - 1; xfs_iext_get_extent(ifp, current_ext, &got); if (stop_fsb > got.br_startoff) { - *done = 1; + *done = true; goto del_cursor; } *next_fsb = got.br_startoff; @@ -5787,46 +5879,27 @@ xfs_bmap_shift_extents( */ if (!xfs_iext_lookup_extent(ip, ifp, *next_fsb, ¤t_ext, &got)) { - *done = 1; + *done = true; goto del_cursor; } } /* Lookup the extent index at which we have to stop */ - if (direction == SHIFT_RIGHT) { - struct xfs_bmbt_irec s; - - xfs_iext_lookup_extent(ip, ifp, stop_fsb, &stop_extent, &s); - /* Make stop_extent exclusive of shift range */ - stop_extent--; - if (current_ext <= stop_extent) { - error = -EIO; - goto del_cursor; - } - } else { - stop_extent = total_extents; - if (current_ext >= stop_extent) { - error = -EIO; - goto del_cursor; - } + xfs_iext_lookup_extent(ip, ifp, stop_fsb, &stop_extent, &s); + /* Make stop_extent exclusive of shift range */ + stop_extent--; + if (current_ext <= stop_extent) { + error = -EIO; + goto del_cursor; } error = xfs_bmse_shift_one(ip, whichfork, offset_shift_fsb, ¤t_ext, &got, cur, &logflags, - direction, dfops); + SHIFT_RIGHT, dfops); if (error) goto del_cursor; - /* - * If there was an extent merge during the shift, the extent - * count can change. Update the total and grade the next record. - */ - if (direction == SHIFT_LEFT) { - total_extents = xfs_iext_count(ifp); - stop_extent = total_extents; - } - if (current_ext == stop_extent) { - *done = 1; + *done = true; goto del_cursor; } xfs_iext_get_extent(ifp, current_ext, &got); diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h index 985b1c26566a..f7ccf2de1a8c 100644 --- a/fs/xfs/libxfs/xfs_bmap.h +++ b/fs/xfs/libxfs/xfs_bmap.h @@ -227,10 +227,14 @@ int xfs_bmap_del_extent_delay(struct xfs_inode *ip, int whichfork, void xfs_bmap_del_extent_cow(struct xfs_inode *ip, xfs_extnum_t *idx, struct xfs_bmbt_irec *got, struct xfs_bmbt_irec *del); uint xfs_default_attroffset(struct xfs_inode *ip); -int xfs_bmap_shift_extents(struct xfs_trans *tp, struct xfs_inode *ip, +int xfs_bmap_collapse_extents(struct xfs_trans *tp, struct xfs_inode *ip, xfs_fileoff_t *next_fsb, xfs_fileoff_t offset_shift_fsb, - int *done, xfs_fileoff_t stop_fsb, xfs_fsblock_t *firstblock, - struct xfs_defer_ops *dfops, enum shift_direction direction); + bool *done, xfs_fileoff_t stop_fsb, xfs_fsblock_t *firstblock, + struct xfs_defer_ops *dfops); +int xfs_bmap_insert_extents(struct xfs_trans *tp, struct xfs_inode *ip, + xfs_fileoff_t *next_fsb, xfs_fileoff_t offset_shift_fsb, + bool *done, xfs_fileoff_t stop_fsb, xfs_fsblock_t *firstblock, + struct xfs_defer_ops *dfops); int xfs_bmap_split_extent(struct xfs_inode *ip, xfs_fileoff_t split_offset); int xfs_bmapi_reserve_delalloc(struct xfs_inode *ip, int whichfork, xfs_fileoff_t off, xfs_filblks_t len, xfs_filblks_t prealloc, diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 3273f083c496..034f3429ca8c 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -1322,7 +1322,6 @@ xfs_collapse_file_space( xfs_off_t offset, xfs_off_t len) { - int done = 0; struct xfs_mount *mp = ip->i_mount; struct xfs_trans *tp; int error; @@ -1332,6 +1331,7 @@ xfs_collapse_file_space( xfs_fileoff_t next_fsb = XFS_B_TO_FSB(mp, offset + len); xfs_fileoff_t shift_fsb = XFS_B_TO_FSB(mp, len); uint resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0); + bool done = false; ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL)); trace_xfs_collapse_file_space(ip); @@ -1359,9 +1359,8 @@ xfs_collapse_file_space( xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); xfs_defer_init(&dfops, &first_block); - error = xfs_bmap_shift_extents(tp, ip, &next_fsb, shift_fsb, - &done, stop_fsb, &first_block, &dfops, - SHIFT_LEFT); + error = xfs_bmap_collapse_extents(tp, ip, &next_fsb, shift_fsb, + &done, stop_fsb, &first_block, &dfops); if (error) goto out_bmap_cancel; @@ -1406,7 +1405,7 @@ xfs_insert_file_space( xfs_fileoff_t stop_fsb = XFS_B_TO_FSB(mp, offset); xfs_fileoff_t next_fsb = NULLFSBLOCK; xfs_fileoff_t shift_fsb = XFS_B_TO_FSB(mp, len); - int done = 0; + bool done = false; ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL)); trace_xfs_insert_file_space(ip); @@ -1433,9 +1432,8 @@ xfs_insert_file_space( xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); xfs_defer_init(&dfops, &first_block); - error = xfs_bmap_shift_extents(tp, ip, &next_fsb, shift_fsb, - &done, stop_fsb, &first_block, &dfops, - SHIFT_RIGHT); + error = xfs_bmap_insert_extents(tp, ip, &next_fsb, shift_fsb, + &done, stop_fsb, &first_block, &dfops); if (error) goto out_bmap_cancel;