xfs
[Top] [All Lists]

[PATCH 11/24] xfs: map an inode's offset to an exact physical block

To: david@xxxxxxxxxxxxx, darrick.wong@xxxxxxxxxx
Subject: [PATCH 11/24] xfs: map an inode's offset to an exact physical block
From: "Darrick J. Wong" <darrick.wong@xxxxxxxxxx>
Date: Wed, 29 Jul 2015 15:34:09 -0700
Cc: xfs@xxxxxxxxxxx
Delivered-to: xfs@xxxxxxxxxxx
In-reply-to: <20150729223258.17414.91354.stgit@xxxxxxxxxxxxxxxx>
References: <20150729223258.17414.91354.stgit@xxxxxxxxxxxxxxxx>
User-agent: StGit/0.17.1-dirty
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 <darrick.wong@xxxxxxxxxx>
---
 fs/xfs/libxfs/xfs_bmap.c |   21 +++++++++++++++++++++
 fs/xfs/libxfs/xfs_bmap.h |    3 +++
 2 files changed, 24 insertions(+)


diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index dfdd9e6..1297b94 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -3897,6 +3897,15 @@ STATIC int
 xfs_bmap_alloc(
        struct xfs_bmalloca     *ap)    /* bmap alloc argument struct */
 {
+       if (ap->flags & XFS_BMAPI_EXACT) {
+               trace_xfs_reflink_relink_blocks(ap->ip, *ap->firstblock,
+                               ap->length);
+               ap->blkno = *ap->firstblock;
+               ap->ip->i_d.di_nblocks += ap->length;
+               xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE);
+               return 0;
+       }
+
        if (XFS_IS_REALTIME_INODE(ap->ip) && ap->userdata)
                return xfs_bmap_rtalloc(ap);
        return xfs_bmap_btalloc(ap);
@@ -4519,6 +4528,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_EXACT));
+       if (flags & XFS_BMAPI_EXACT) {
+               ASSERT(!(flags & XFS_BMAPI_PREALLOC));
+               ASSERT(!(flags & XFS_BMAPI_CONVERT));
+       }
 
        if (unlikely(XFS_TEST_ERROR(
            (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
@@ -4568,6 +4583,12 @@ xfs_bmapi_write(
                wasdelay = !inhole && isnullstartblock(bma.got.br_startblock);
 
                /*
+                * Make sure we only reflink into a hole.
+                */
+               if (flags & XFS_BMAPI_EXACT)
+                       ASSERT(inhole);
+
+               /*
                 * First, deal with the hole before the allocated space
                 * that we found, if any.
                 */
diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h
index 674819f..34db107 100644
--- a/fs/xfs/libxfs/xfs_bmap.h
+++ b/fs/xfs/libxfs/xfs_bmap.h
@@ -110,6 +110,9 @@ typedef     struct xfs_bmap_free
  */
 #define XFS_BMAPI_CONVERT      0x040
 
+#define XFS_BMAPI_EXACT                0x080   /* Map the inode offset to the 
block */
+                                       /* ap->firstblock. Used for reflink. */
+
 #define XFS_BMAPI_FLAGS \
        { XFS_BMAPI_ENTIRE,     "ENTIRE" }, \
        { XFS_BMAPI_METADATA,   "METADATA" }, \

<Prev in Thread] Current Thread [Next in Thread>