xfs: add bmapi nodiscard flag
authorBrian Foster <bfoster@redhat.com>
Wed, 9 May 2018 15:45:04 +0000 (08:45 -0700)
committerDarrick J. Wong <darrick.wong@oracle.com>
Thu, 10 May 2018 15:56:46 +0000 (08:56 -0700)
Freed extents are unconditionally discarded when online discard is
enabled. Define XFS_BMAPI_NODISCARD to allow callers to bypass
discards when unnecessary. For example, this will be useful for
eofblocks trimming.

This patch does not change behavior.

Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
fs/xfs/libxfs/xfs_alloc.c
fs/xfs/libxfs/xfs_alloc.h
fs/xfs/libxfs/xfs_bmap.c
fs/xfs/libxfs/xfs_bmap.h
fs/xfs/xfs_extfree_item.c
fs/xfs/xfs_trans.h
fs/xfs/xfs_trans_extfree.c

index 350ad20..5410635 100644 (file)
@@ -3009,18 +3009,20 @@ out:
  * after fixing up the freelist.
  */
 int                            /* error */
-xfs_free_extent(
+__xfs_free_extent(
        struct xfs_trans        *tp,    /* transaction pointer */
        xfs_fsblock_t           bno,    /* starting block number of extent */
        xfs_extlen_t            len,    /* length of extent */
        struct xfs_owner_info   *oinfo, /* extent owner */
-       enum xfs_ag_resv_type   type)   /* block reservation type */
+       enum xfs_ag_resv_type   type,   /* block reservation type */
+       bool                    skip_discard)
 {
        struct xfs_mount        *mp = tp->t_mountp;
        struct xfs_buf          *agbp;
        xfs_agnumber_t          agno = XFS_FSB_TO_AGNO(mp, bno);
        xfs_agblock_t           agbno = XFS_FSB_TO_AGBNO(mp, bno);
        int                     error;
+       unsigned int            busy_flags = 0;
 
        ASSERT(len != 0);
        ASSERT(type != XFS_AG_RESV_AGFL);
@@ -3044,7 +3046,9 @@ xfs_free_extent(
        if (error)
                goto err;
 
-       xfs_extent_busy_insert(tp, agno, agbno, len, 0);
+       if (skip_discard)
+               busy_flags |= XFS_EXTENT_BUSY_SKIP_DISCARD;
+       xfs_extent_busy_insert(tp, agno, agbno, len, busy_flags);
        return 0;
 
 err:
index 949e213..1dcac78 100644 (file)
@@ -191,12 +191,35 @@ xfs_alloc_vextent(
  * Free an extent.
  */
 int                            /* error */
-xfs_free_extent(
+__xfs_free_extent(
        struct xfs_trans        *tp,    /* transaction pointer */
        xfs_fsblock_t           bno,    /* starting block number of extent */
        xfs_extlen_t            len,    /* length of extent */
        struct xfs_owner_info   *oinfo, /* extent owner */
-       enum xfs_ag_resv_type   type);  /* block reservation type */
+       enum xfs_ag_resv_type   type,   /* block reservation type */
+       bool                    skip_discard);
+
+static inline int
+xfs_free_extent(
+       struct xfs_trans        *tp,
+       xfs_fsblock_t           bno,
+       xfs_extlen_t            len,
+       struct xfs_owner_info   *oinfo,
+       enum xfs_ag_resv_type   type)
+{
+       return __xfs_free_extent(tp, bno, len, oinfo, type, false);
+}
+
+static inline int
+xfs_free_extent_nodiscard(
+       struct xfs_trans        *tp,
+       xfs_fsblock_t           bno,
+       xfs_extlen_t            len,
+       struct xfs_owner_info   *oinfo,
+       enum xfs_ag_resv_type   type)
+{
+       return __xfs_free_extent(tp, bno, len, oinfo, type, true);
+}
 
 int                            /* error */
 xfs_alloc_lookup_le(
index 3e5e9a6..534ffb8 100644 (file)
@@ -544,12 +544,13 @@ xfs_bmap_validate_ret(
  * The list is maintained sorted (by block number).
  */
 void
-xfs_bmap_add_free(
+__xfs_bmap_add_free(
        struct xfs_mount                *mp,
        struct xfs_defer_ops            *dfops,
        xfs_fsblock_t                   bno,
        xfs_filblks_t                   len,
-       struct xfs_owner_info           *oinfo)
+       struct xfs_owner_info           *oinfo,
+       bool                            skip_discard)
 {
        struct xfs_extent_free_item     *new;           /* new element */
 #ifdef DEBUG
@@ -576,6 +577,7 @@ xfs_bmap_add_free(
                new->xefi_oinfo = *oinfo;
        else
                xfs_rmap_skip_owner_update(&new->xefi_oinfo);
+       new->xefi_skip_discard = skip_discard;
        trace_xfs_bmap_free_defer(mp, XFS_FSB_TO_AGNO(mp, bno), 0,
                        XFS_FSB_TO_AGBNO(mp, bno), len);
        xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_FREE, &new->xefi_list);
@@ -5106,9 +5108,16 @@ xfs_bmap_del_extent_real(
                        error = xfs_refcount_decrease_extent(mp, dfops, del);
                        if (error)
                                goto done;
-               } else
-                       xfs_bmap_add_free(mp, dfops, del->br_startblock,
+               } else {
+                       if (bflags & XFS_BMAPI_NODISCARD) {
+                               xfs_bmap_add_free_nodiscard(mp, dfops,
+                                       del->br_startblock, del->br_blockcount,
+                                       NULL);
+                       } else {
+                               xfs_bmap_add_free(mp, dfops, del->br_startblock,
                                        del->br_blockcount, NULL);
+                       }
+               }
        }
 
        /*
index 2b766b3..8d8946b 100644 (file)
@@ -68,6 +68,7 @@ struct xfs_extent_free_item
        xfs_extlen_t            xefi_blockcount;/* number of blocks in extent */
        struct list_head        xefi_list;
        struct xfs_owner_info   xefi_oinfo;     /* extent owner */
+       bool                    xefi_skip_discard;
 };
 
 #define        XFS_BMAP_MAX_NMAP       4
@@ -116,6 +117,9 @@ struct xfs_extent_free_item
 /* Only convert unwritten extents, don't allocate new blocks */
 #define XFS_BMAPI_CONVERT_ONLY 0x800
 
+/* Skip online discard of freed extents */
+#define XFS_BMAPI_NODISCARD    0x1000
+
 #define XFS_BMAPI_FLAGS \
        { XFS_BMAPI_ENTIRE,     "ENTIRE" }, \
        { XFS_BMAPI_METADATA,   "METADATA" }, \
@@ -128,7 +132,8 @@ struct xfs_extent_free_item
        { XFS_BMAPI_REMAP,      "REMAP" }, \
        { XFS_BMAPI_COWFORK,    "COWFORK" }, \
        { XFS_BMAPI_DELALLOC,   "DELALLOC" }, \
-       { XFS_BMAPI_CONVERT_ONLY, "CONVERT_ONLY" }
+       { XFS_BMAPI_CONVERT_ONLY, "CONVERT_ONLY" }, \
+       { XFS_BMAPI_NODISCARD,  "NODISCARD" }
 
 
 static inline int xfs_bmapi_aflag(int w)
@@ -192,9 +197,9 @@ void        xfs_trim_extent(struct xfs_bmbt_irec *irec, xfs_fileoff_t bno,
 void   xfs_trim_extent_eof(struct xfs_bmbt_irec *, struct xfs_inode *);
 int    xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd);
 void   xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork);
-void   xfs_bmap_add_free(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
+void   __xfs_bmap_add_free(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
                          xfs_fsblock_t bno, xfs_filblks_t len,
-                         struct xfs_owner_info *oinfo);
+                         struct xfs_owner_info *oinfo, bool skip_discard);
 void   xfs_bmap_compute_maxlevels(struct xfs_mount *mp, int whichfork);
 int    xfs_bmap_first_unused(struct xfs_trans *tp, struct xfs_inode *ip,
                xfs_extlen_t len, xfs_fileoff_t *unused, int whichfork);
@@ -240,6 +245,28 @@ int        xfs_bmapi_reserve_delalloc(struct xfs_inode *ip, int whichfork,
                struct xfs_bmbt_irec *got, struct xfs_iext_cursor *cur,
                int eof);
 
+static inline void
+xfs_bmap_add_free(
+       struct xfs_mount                *mp,
+       struct xfs_defer_ops            *dfops,
+       xfs_fsblock_t                   bno,
+       xfs_filblks_t                   len,
+       struct xfs_owner_info           *oinfo)
+{
+       __xfs_bmap_add_free(mp, dfops, bno, len, oinfo, false);
+}
+
+static inline void
+xfs_bmap_add_free_nodiscard(
+       struct xfs_mount                *mp,
+       struct xfs_defer_ops            *dfops,
+       xfs_fsblock_t                   bno,
+       xfs_filblks_t                   len,
+       struct xfs_owner_info           *oinfo)
+{
+       __xfs_bmap_add_free(mp, dfops, bno, len, oinfo, true);
+}
+
 enum xfs_bmap_intent_type {
        XFS_BMAP_MAP = 1,
        XFS_BMAP_UNMAP,
index 70b7d48..a889b55 100644 (file)
@@ -542,7 +542,7 @@ xfs_efi_recover(
        for (i = 0; i < efip->efi_format.efi_nextents; i++) {
                extp = &efip->efi_format.efi_extents[i];
                error = xfs_trans_free_extent(tp, efdp, extp->ext_start,
-                                             extp->ext_len, &oinfo);
+                                             extp->ext_len, &oinfo, false);
                if (error)
                        goto abort_error;
 
index a386d8a..29706b8 100644 (file)
@@ -235,7 +235,8 @@ struct xfs_efd_log_item     *xfs_trans_get_efd(struct xfs_trans *,
                                  uint);
 int            xfs_trans_free_extent(struct xfs_trans *,
                                      struct xfs_efd_log_item *, xfs_fsblock_t,
-                                     xfs_extlen_t, struct xfs_owner_info *);
+                                     xfs_extlen_t, struct xfs_owner_info *,
+                                     bool);
 int            xfs_trans_commit(struct xfs_trans *);
 int            xfs_trans_roll(struct xfs_trans **);
 int            xfs_trans_roll_inode(struct xfs_trans **, struct xfs_inode *);
index c60395e..28a1d5a 100644 (file)
@@ -68,7 +68,8 @@ xfs_trans_free_extent(
        struct xfs_efd_log_item *efdp,
        xfs_fsblock_t           start_block,
        xfs_extlen_t            ext_len,
-       struct xfs_owner_info   *oinfo)
+       struct xfs_owner_info   *oinfo,
+       bool                    skip_discard)
 {
        struct xfs_mount        *mp = tp->t_mountp;
        uint                    next_extent;
@@ -79,8 +80,12 @@ xfs_trans_free_extent(
 
        trace_xfs_bmap_free_deferred(tp->t_mountp, agno, 0, agbno, ext_len);
 
-       error = xfs_free_extent(tp, start_block, ext_len, oinfo,
-                       XFS_AG_RESV_NONE);
+       if (skip_discard)
+               error = xfs_free_extent_nodiscard(tp, start_block, ext_len,
+                                                 oinfo, XFS_AG_RESV_NONE);
+       else
+               error = xfs_free_extent(tp, start_block, ext_len, oinfo,
+                                       XFS_AG_RESV_NONE);
 
        /*
         * Mark the transaction dirty, even on error. This ensures the
@@ -195,7 +200,7 @@ xfs_extent_free_finish_item(
        error = xfs_trans_free_extent(tp, done_item,
                        free->xefi_startblock,
                        free->xefi_blockcount,
-                       &free->xefi_oinfo);
+                       &free->xefi_oinfo, free->xefi_skip_discard);
        kmem_free(free);
        return error;
 }