From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id DDD0F7E86 for ; Thu, 25 Aug 2016 18:48:50 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id A28E6304039 for ; Thu, 25 Aug 2016 16:48:50 -0700 (PDT) Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id 1YFxJfG0AjGinLkD (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 25 Aug 2016 16:48:49 -0700 (PDT) Subject: [PATCH 21/71] xfs: map an inode's offset to an exact physical block From: "Darrick J. Wong" Date: Thu, 25 Aug 2016 16:48:45 -0700 Message-ID: <147216892521.4420.4118413366349909612.stgit@birch.djwong.org> In-Reply-To: <147216879156.4420.2446767701729565218.stgit@birch.djwong.org> References: <147216879156.4420.2446767701729565218.stgit@birch.djwong.org> MIME-Version: 1.0 List-Id: XFS Filesystem from SGI List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: xfs-bounces@oss.sgi.com Sender: xfs-bounces@oss.sgi.com To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-xfs@vger.kernel.org, xfs@oss.sgi.com Teach the bmap routine to know how to map a range of file blocks to a specific range of physical blocks, instead of simply allocating fresh blocks. This enables reflink to map a file to blocks that are already in use. Signed-off-by: Darrick J. Wong --- include/xfs_trace.h | 3 ++ libxfs/xfs_bmap.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_bmap.h | 10 +++++++- 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/include/xfs_trace.h b/include/xfs_trace.h index 0698280..cc0e960 100644 --- a/include/xfs_trace.h +++ b/include/xfs_trace.h @@ -259,6 +259,9 @@ #define trace_xfs_refcount_find_shared_result(...) ((void) 0) #define trace_xfs_refcount_find_shared_error(...) ((void) 0) +#define trace_xfs_bmap_remap_alloc(...) ((void) 0) +#define trace_xfs_bmap_remap_alloc_error(...) ((void) 0) + /* set c = c to avoid unused var warnings */ #define trace_xfs_perag_get(a,b,c,d) ((c) = (c)) #define trace_xfs_perag_get_tag(a,b,c,d) ((c) = (c)) diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c index 4045340..fab8182 100644 --- a/libxfs/xfs_bmap.c +++ b/libxfs/xfs_bmap.c @@ -3865,6 +3865,55 @@ xfs_bmap_btalloc( } /* + * For a remap operation, just "allocate" an extent at the address that the + * caller passed in, and ensure that the AGFL is the right size. The caller + * will then map the "allocated" extent into the file somewhere. + */ +STATIC int +xfs_bmap_remap_alloc( + struct xfs_bmalloca *ap) +{ + struct xfs_trans *tp = ap->tp; + struct xfs_mount *mp = tp->t_mountp; + xfs_agblock_t bno; + struct xfs_alloc_arg args; + int error; + + /* + * validate that the block number is legal - the enables us to detect + * and handle a silent filesystem corruption rather than crashing. + */ + memset(&args, 0, sizeof(struct xfs_alloc_arg)); + args.tp = ap->tp; + args.mp = ap->tp->t_mountp; + bno = *ap->firstblock; + args.agno = XFS_FSB_TO_AGNO(mp, bno); + ASSERT(args.agno < mp->m_sb.sb_agcount); + args.agbno = XFS_FSB_TO_AGBNO(mp, bno); + ASSERT(args.agbno < mp->m_sb.sb_agblocks); + + /* "Allocate" the extent from the range we passed in. */ + trace_xfs_bmap_remap_alloc(ap->ip, *ap->firstblock, ap->length); + ap->blkno = bno; + ap->ip->i_d.di_nblocks += ap->length; + xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE); + + /* Fix the freelist, like a real allocator does. */ + args.userdata = 1; + args.pag = xfs_perag_get(args.mp, args.agno); + ASSERT(args.pag); + + error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING); + if (error) + goto error0; +error0: + xfs_perag_put(args.pag); + if (error) + trace_xfs_bmap_remap_alloc_error(ap->ip, error, _RET_IP_); + return error; +} + +/* * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file. * It figures out where to ask the underlying allocator to put the new extent. */ @@ -3872,6 +3921,8 @@ STATIC int xfs_bmap_alloc( struct xfs_bmalloca *ap) /* bmap alloc argument struct */ { + if (ap->flags & XFS_BMAPI_REMAP) + return xfs_bmap_remap_alloc(ap); if (XFS_IS_REALTIME_INODE(ap->ip) && ap->userdata) return xfs_bmap_rtalloc(ap); return xfs_bmap_btalloc(ap); @@ -4508,6 +4559,12 @@ xfs_bmapi_write( ASSERT(len > 0); ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL); ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); + if (whichfork == XFS_ATTR_FORK) + ASSERT(!(flags & XFS_BMAPI_REMAP)); + if (flags & XFS_BMAPI_REMAP) { + ASSERT(!(flags & XFS_BMAPI_PREALLOC)); + ASSERT(!(flags & XFS_BMAPI_CONVERT)); + } /* zeroing is for currently only for data extents, not metadata */ ASSERT((flags & (XFS_BMAPI_METADATA | XFS_BMAPI_ZERO)) != @@ -4569,6 +4626,12 @@ xfs_bmapi_write( wasdelay = !inhole && isnullstartblock(bma.got.br_startblock); /* + * Make sure we only reflink into a hole. + */ + if (flags & XFS_BMAPI_REMAP) + ASSERT(inhole); + + /* * First, deal with the hole before the allocated space * that we found, if any. */ diff --git a/libxfs/xfs_bmap.h b/libxfs/xfs_bmap.h index c8160fe..42dc49e 100644 --- a/libxfs/xfs_bmap.h +++ b/libxfs/xfs_bmap.h @@ -97,6 +97,13 @@ struct xfs_extent_free_item */ #define XFS_BMAPI_ZERO 0x080 +/* + * Map the inode offset to the block given in ap->firstblock. Primarily + * used for reflink. The range must be in a hole, and this flag cannot be + * turned on with PREALLOC or CONVERT, and cannot be used on the attr fork. + */ +#define XFS_BMAPI_REMAP 0x100 + #define XFS_BMAPI_FLAGS \ { XFS_BMAPI_ENTIRE, "ENTIRE" }, \ { XFS_BMAPI_METADATA, "METADATA" }, \ @@ -105,7 +112,8 @@ struct xfs_extent_free_item { XFS_BMAPI_IGSTATE, "IGSTATE" }, \ { XFS_BMAPI_CONTIG, "CONTIG" }, \ { XFS_BMAPI_CONVERT, "CONVERT" }, \ - { XFS_BMAPI_ZERO, "ZERO" } + { XFS_BMAPI_ZERO, "ZERO" }, \ + { XFS_BMAPI_REMAP, "REMAP" } static inline int xfs_bmapi_aflag(int w) _______________________________________________ xfs mailing list xfs@oss.sgi.com http://oss.sgi.com/mailman/listinfo/xfs