]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: support allocating delayed extents in CoW fork
authorDarrick J. Wong <darrick.wong@oracle.com>
Tue, 25 Oct 2016 01:38:27 +0000 (12:38 +1100)
committerDave Chinner <david@fromorbit.com>
Tue, 25 Oct 2016 01:38:27 +0000 (12:38 +1100)
Source kernel commit: 60b4984fc3924bff292ec46b95a3e98b34b8e259

Modify xfs_bmap_add_extent_delay_real() so that we can convert delayed
allocation extents in the CoW fork to real allocations, and wire this
up all the way back to xfs_iomap_write_allocate().  In a subsequent
patch, we'll modify the writepage handler to call this.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
libxfs/xfs_bmap.c

index b936d1eaa094d07d08129fd7a4813d5c76c24fa7..5b3f63d741b64c6436462d5d6e3308fbd5553b3b 100644 (file)
@@ -133,7 +133,8 @@ xfs_bmbt_lookup_ge(
  */
 static inline bool xfs_bmap_needs_btree(struct xfs_inode *ip, int whichfork)
 {
-       return XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
+       return whichfork != XFS_COW_FORK &&
+               XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
                XFS_IFORK_NEXTENTS(ip, whichfork) >
                        XFS_IFORK_MAXEXT(ip, whichfork);
 }
@@ -143,7 +144,8 @@ static inline bool xfs_bmap_needs_btree(struct xfs_inode *ip, int whichfork)
  */
 static inline bool xfs_bmap_wants_extents(struct xfs_inode *ip, int whichfork)
 {
-       return XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE &&
+       return whichfork != XFS_COW_FORK &&
+               XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE &&
                XFS_IFORK_NEXTENTS(ip, whichfork) <=
                        XFS_IFORK_MAXEXT(ip, whichfork);
 }
@@ -633,6 +635,7 @@ xfs_bmap_btree_to_extents(
 
        mp = ip->i_mount;
        ifp = XFS_IFORK_PTR(ip, whichfork);
+       ASSERT(whichfork != XFS_COW_FORK);
        ASSERT(ifp->if_flags & XFS_IFEXTENTS);
        ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE);
        rblock = ifp->if_broot;
@@ -699,6 +702,7 @@ xfs_bmap_extents_to_btree(
        xfs_bmbt_ptr_t          *pp;            /* root block address pointer */
 
        mp = ip->i_mount;
+       ASSERT(whichfork != XFS_COW_FORK);
        ifp = XFS_IFORK_PTR(ip, whichfork);
        ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS);
 
@@ -830,6 +834,7 @@ xfs_bmap_local_to_extents_empty(
 {
        struct xfs_ifork        *ifp = XFS_IFORK_PTR(ip, whichfork);
 
+       ASSERT(whichfork != XFS_COW_FORK);
        ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
        ASSERT(ifp->if_bytes == 0);
        ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) == 0);
@@ -1663,7 +1668,8 @@ xfs_bmap_one_block(
  */
 STATIC int                             /* error */
 xfs_bmap_add_extent_delay_real(
-       struct xfs_bmalloca     *bma)
+       struct xfs_bmalloca     *bma,
+       int                     whichfork)
 {
        struct xfs_bmbt_irec    *new = &bma->got;
        int                     diff;   /* temp value */
@@ -1682,10 +1688,13 @@ xfs_bmap_add_extent_delay_real(
        xfs_filblks_t           temp2=0;/* value for da_new calculations */
        int                     tmp_rval;       /* partial logging flags */
        struct xfs_mount        *mp;
-       int                     whichfork = XFS_DATA_FORK;
+       xfs_extnum_t            *nextents;
 
        mp = bma->ip->i_mount;
        ifp = XFS_IFORK_PTR(bma->ip, whichfork);
+       ASSERT(whichfork != XFS_ATTR_FORK);
+       nextents = (whichfork == XFS_COW_FORK ? &bma->ip->i_cnextents :
+                                               &bma->ip->i_d.di_nextents);
 
        ASSERT(bma->idx >= 0);
        ASSERT(bma->idx <= ifp->if_bytes / sizeof(struct xfs_bmbt_rec));
@@ -1699,6 +1708,9 @@ xfs_bmap_add_extent_delay_real(
 #define        RIGHT           r[1]
 #define        PREV            r[2]
 
+       if (whichfork == XFS_COW_FORK)
+               state |= BMAP_COWFORK;
+
        /*
         * Set up a bunch of variables to make the tests simpler.
         */
@@ -1785,7 +1797,7 @@ xfs_bmap_add_extent_delay_real(
                trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_);
 
                xfs_iext_remove(bma->ip, bma->idx + 1, 2, state);
-               bma->ip->i_d.di_nextents--;
+               (*nextents)--;
                if (bma->cur == NULL)
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
                else {
@@ -1887,7 +1899,7 @@ xfs_bmap_add_extent_delay_real(
                xfs_bmbt_set_startblock(ep, new->br_startblock);
                trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_);
 
-               bma->ip->i_d.di_nextents++;
+               (*nextents)++;
                if (bma->cur == NULL)
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
                else {
@@ -1957,7 +1969,7 @@ xfs_bmap_add_extent_delay_real(
                temp = PREV.br_blockcount - new->br_blockcount;
                xfs_bmbt_set_blockcount(ep, temp);
                xfs_iext_insert(bma->ip, bma->idx, 1, new, state);
-               bma->ip->i_d.di_nextents++;
+               (*nextents)++;
                if (bma->cur == NULL)
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
                else {
@@ -2041,7 +2053,7 @@ xfs_bmap_add_extent_delay_real(
                trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_);
                xfs_bmbt_set_blockcount(ep, temp);
                xfs_iext_insert(bma->ip, bma->idx + 1, 1, new, state);
-               bma->ip->i_d.di_nextents++;
+               (*nextents)++;
                if (bma->cur == NULL)
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
                else {
@@ -2110,7 +2122,7 @@ xfs_bmap_add_extent_delay_real(
                RIGHT.br_blockcount = temp2;
                /* insert LEFT (r[0]) and RIGHT (r[1]) at the same time */
                xfs_iext_insert(bma->ip, bma->idx + 1, 2, &LEFT, state);
-               bma->ip->i_d.di_nextents++;
+               (*nextents)++;
                if (bma->cur == NULL)
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
                else {
@@ -2208,7 +2220,8 @@ xfs_bmap_add_extent_delay_real(
 
        xfs_bmap_check_leaf_extents(bma->cur, bma->ip, whichfork);
 done:
-       bma->logflags |= rval;
+       if (whichfork != XFS_COW_FORK)
+               bma->logflags |= rval;
        return error;
 #undef LEFT
 #undef RIGHT
@@ -3853,7 +3866,8 @@ xfs_bmap_btalloc(
                ASSERT(nullfb || fb_agno == args.agno ||
                       (ap->dfops->dop_low && fb_agno < args.agno));
                ap->length = args.len;
-               ap->ip->i_d.di_nblocks += args.len;
+               if (!(ap->flags & XFS_BMAPI_COWFORK))
+                       ap->ip->i_d.di_nblocks += args.len;
                xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE);
                if (ap->wasdel)
                        ap->ip->i_delayed_blks -= args.len;
@@ -4248,8 +4262,7 @@ xfs_bmapi_allocate(
        struct xfs_bmalloca     *bma)
 {
        struct xfs_mount        *mp = bma->ip->i_mount;
-       int                     whichfork = (bma->flags & XFS_BMAPI_ATTRFORK) ?
-                                               XFS_ATTR_FORK : XFS_DATA_FORK;
+       int                     whichfork = xfs_bmapi_whichfork(bma->flags);
        struct xfs_ifork        *ifp = XFS_IFORK_PTR(bma->ip, whichfork);
        int                     tmp_logflags = 0;
        int                     error;
@@ -4344,7 +4357,7 @@ xfs_bmapi_allocate(
                bma->got.br_state = XFS_EXT_UNWRITTEN;
 
        if (bma->wasdel)
-               error = xfs_bmap_add_extent_delay_real(bma);
+               error = xfs_bmap_add_extent_delay_real(bma, whichfork);
        else
                error = xfs_bmap_add_extent_hole_real(bma, whichfork);
 
@@ -4498,8 +4511,7 @@ xfs_bmapi_write(
        orig_mval = mval;
        orig_nmap = *nmap;
 #endif
-       whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
-               XFS_ATTR_FORK : XFS_DATA_FORK;
+       whichfork = xfs_bmapi_whichfork(flags);
 
        ASSERT(*nmap >= 1);
        ASSERT(*nmap <= XFS_BMAP_MAX_NMAP);
@@ -4511,6 +4523,8 @@ xfs_bmapi_write(
        ASSERT(!(flags & XFS_BMAPI_REMAP) || whichfork == XFS_DATA_FORK);
        ASSERT(!(flags & XFS_BMAPI_PREALLOC) || !(flags & XFS_BMAPI_REMAP));
        ASSERT(!(flags & XFS_BMAPI_CONVERT) || !(flags & XFS_BMAPI_REMAP));
+       ASSERT(!(flags & XFS_BMAPI_PREALLOC) || whichfork != XFS_COW_FORK);
+       ASSERT(!(flags & XFS_BMAPI_CONVERT) || whichfork != XFS_COW_FORK);
 
        /* zeroing is for currently only for data extents, not metadata */
        ASSERT((flags & (XFS_BMAPI_METADATA | XFS_BMAPI_ZERO)) !=
@@ -4576,6 +4590,8 @@ xfs_bmapi_write(
                 */
                if (flags & XFS_BMAPI_REMAP)
                        ASSERT(inhole);
+               if (flags & XFS_BMAPI_COWFORK)
+                       ASSERT(!inhole);
 
                /*
                 * First, deal with the hole before the allocated space