From patchwork Wed Jan 11 17:54:07 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Brian Foster X-Patchwork-Id: 9510897 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 65F4F6075C for ; Wed, 11 Jan 2017 17:55:19 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4FDCC2860B for ; Wed, 11 Jan 2017 17:55:19 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 436FB2862E; Wed, 11 Jan 2017 17:55:19 +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.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI 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 BDC132860B for ; Wed, 11 Jan 2017 17:55:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S937680AbdAKRyW (ORCPT ); Wed, 11 Jan 2017 12:54:22 -0500 Received: from mx1.redhat.com ([209.132.183.28]:59868 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1765680AbdAKRyS (ORCPT ); Wed, 11 Jan 2017 12:54:18 -0500 Received: from smtp.corp.redhat.com (int-mx16.intmail.prod.int.phx2.redhat.com [10.5.11.28]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 35FA6C008AE5 for ; Wed, 11 Jan 2017 17:54:11 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-20.bos.redhat.com [10.18.41.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id 068942DB52 for ; Wed, 11 Jan 2017 17:54:10 +0000 (UTC) Received: by bfoster.bfoster (Postfix, from userid 1000) id 9337B122F75; Wed, 11 Jan 2017 12:54:09 -0500 (EST) From: Brian Foster To: linux-xfs@vger.kernel.org Subject: [PATCH v2 3/5] xfs: reuse iomap delalloc code for COW fork reservation Date: Wed, 11 Jan 2017 12:54:07 -0500 Message-Id: <1484157249-464-4-git-send-email-bfoster@redhat.com> In-Reply-To: <1484157249-464-1-git-send-email-bfoster@redhat.com> References: <1484157249-464-1-git-send-email-bfoster@redhat.com> X-Scanned-By: MIMEDefang 2.74 on 10.5.11.28 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Wed, 11 Jan 2017 17:54:11 +0000 (UTC) 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 COW fork reservation (delayed allocation) is implemented in xfs_reflink_reserve_cow() and is generally based on the traditional data fork delalloc logic in xfs_file_iomap_begin_delay(). In preparation for further changes to implement more aggressive COW fork preallocation, refactor the COW reservation code to reuse xfs_file_iomap_begin_delay() for data fork allocation as well as COW fork reservation. This patch does not change behavior. Signed-off-by: Brian Foster --- fs/xfs/xfs_iomap.c | 74 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 19 deletions(-) diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 8791ed5..19b7eb0 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -527,9 +527,8 @@ xfs_iomap_prealloc_size( * inode data and COW forks. If an existing data extent is shared, determine * whether COW fork reservation is necessary. * - * The 'found' parameter indicates whether a writable mapping was found. If the - * mapping is shared, a COW reservation is performed for the corresponding - * range. + * The 'found' parameter indicates whether a writable mapping was found. If a + * shared mapping exists, found is set only if COW reservation exists as well. */ static int xfs_iomap_search_extents( @@ -540,12 +539,14 @@ xfs_iomap_search_extents( int *eof, int *idx, struct xfs_bmbt_irec *got, + bool *shared, bool *found) /* found usable extent */ { struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); int error = 0; + bool trimmed; - *found = false; + *shared = *found = false; /* * Look up a preexisting extent directly into imap. Set got for the @@ -556,17 +557,37 @@ xfs_iomap_search_extents( *got = *imap; return 0; } + if (!xfs_is_reflink_inode(ip)) { + *found = true; + return 0; + } - if (xfs_is_reflink_inode(ip)) { - bool shared; - - xfs_trim_extent(imap, offset_fsb, end_fsb - offset_fsb); - error = xfs_reflink_reserve_cow(ip, imap, &shared); - if (error) - return error; + /* + * Found a data extent but we don't know if it is shared. If an extent + * exists in the cow fork, assume that it is. Use got for this lookup as + * imap must retain the data mapping. + */ + xfs_trim_extent(imap, offset_fsb, end_fsb - offset_fsb); + ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK); + *eof = !xfs_iext_lookup_extent(ip, ifp, offset_fsb, idx, got); + if (!*eof && got->br_startoff <= imap->br_startoff) { + trace_xfs_reflink_cow_found(ip, got); + xfs_trim_extent(imap, got->br_startoff, got->br_blockcount); + *found = true; + return 0; } - *found = true; + /* + * There is no existing cow fork extent. We have to explicitly check if + * the data extent is shared to determine whether COW fork reservation + * is required to map the data extent. Trim the mapping to the next + * (un)shared boundary at the same time. + */ + error = xfs_reflink_trim_around_shared(ip, imap, shared, &trimmed); + if (error) + return error; + if (!*shared) + *found = true; return error; } @@ -587,11 +608,13 @@ xfs_file_iomap_begin_delay( xfs_fileoff_t maxbytes_fsb = XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes); int error = 0, eof = 0; + int fork = XFS_DATA_FORK; struct xfs_bmbt_irec imap; struct xfs_bmbt_irec got; xfs_extnum_t idx; xfs_fsblock_t prealloc_blocks = 0; bool found; + bool shared; ASSERT(!XFS_IS_REALTIME_INODE(ip)); ASSERT(!xfs_get_extsz_hint(ip)); @@ -620,16 +643,20 @@ xfs_file_iomap_begin_delay( /* * Search for preexisting extents. If an existing data extent is shared, - * this will perform COW fork reservation. + * switch to the COW fork for COW reservation. */ error = xfs_iomap_search_extents(ip, offset_fsb, end_fsb, &imap, &eof, - &idx, &got, &found); + &idx, &got, &shared, &found); if (error) goto out_unlock; if (found) { trace_xfs_iomap_found(ip, offset, count, 0, &imap); goto done; } + if (shared) { + end_fsb = imap.br_startoff + imap.br_blockcount; + fork = XFS_COW_FORK; + } error = xfs_qm_dqattach_locked(ip, 0); if (error) @@ -645,9 +672,10 @@ xfs_file_iomap_begin_delay( * the lower level functions are updated. */ count = min_t(loff_t, count, 1024 * PAGE_SIZE); - end_fsb = min(XFS_B_TO_FSB(mp, offset + count), maxbytes_fsb); + end_fsb = min(end_fsb, XFS_B_TO_FSB(mp, offset + count)); + xfs_trim_extent(&imap, offset_fsb, end_fsb - offset_fsb); - if (eof) { + if (eof && fork == XFS_DATA_FORK) { prealloc_blocks = xfs_iomap_prealloc_size(ip, offset, count, idx); if (prealloc_blocks) { xfs_extlen_t align; @@ -669,7 +697,7 @@ xfs_file_iomap_begin_delay( } retry: - error = xfs_bmapi_reserve_delalloc(ip, XFS_DATA_FORK, offset_fsb, + error = xfs_bmapi_reserve_delalloc(ip, fork, offset_fsb, end_fsb - offset_fsb, prealloc_blocks, &got, &idx, eof); switch (error) { case 0: @@ -687,8 +715,16 @@ xfs_file_iomap_begin_delay( goto out_unlock; } - trace_xfs_iomap_alloc(ip, offset, count, 0, &got); - imap = got; + /* + * For the data fork, the iomap mapping is simply the extent that was + * returned from the delalloc request. Otherwise, use imap as it refers + * to the data fork but is trimmed according to the shared state. + */ + if (fork == XFS_DATA_FORK) { + trace_xfs_iomap_alloc(ip, offset, count, 0, &got); + imap = got; + } else + trace_xfs_reflink_cow_alloc(ip, &got); done: if (isnullstartblock(imap.br_startblock)) imap.br_startblock = DELAYSTARTBLOCK;