OSDN Git Service

xfs: remove support for inlining data/extents into the inode fork
authorChristoph Hellwig <hch@lst.de>
Fri, 3 Nov 2017 17:34:45 +0000 (10:34 -0700)
committerDarrick J. Wong <darrick.wong@oracle.com>
Mon, 6 Nov 2017 19:53:40 +0000 (11:53 -0800)
Supporting a small bit of data inside the inode fork blows up the fork size
a lot, removing the 32 bytes of inline data halves the effective size of
the inode fork (and it still has a lot of unused padding left), and the
performance of a single kmalloc doesn't show up compared to the size to read
an inode or create one.

It also simplifies the fork management code a lot.

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

index 61d02b7..c5dbcae 100644 (file)
@@ -269,19 +269,14 @@ xfs_init_local_fork(
        if (zero_terminate)
                mem_size++;
 
-       if (size == 0)
-               ifp->if_u1.if_data = NULL;
-       else if (mem_size <= sizeof(ifp->if_u2.if_inline_data))
-               ifp->if_u1.if_data = ifp->if_u2.if_inline_data;
-       else {
+       if (size) {
                real_size = roundup(mem_size, 4);
                ifp->if_u1.if_data = kmem_alloc(real_size, KM_SLEEP | KM_NOFS);
-       }
-
-       if (size) {
                memcpy(ifp->if_u1.if_data, data, size);
                if (zero_terminate)
                        ifp->if_u1.if_data[size] = '\0';
+       } else {
+               ifp->if_u1.if_data = NULL;
        }
 
        ifp->if_bytes = size;
@@ -292,13 +287,6 @@ xfs_init_local_fork(
 
 /*
  * The file is in-lined in the on-disk inode.
- * If it fits into if_inline_data, then copy
- * it there, otherwise allocate a buffer for it
- * and copy the data there.  Either way, set
- * if_data to point at the data.
- * If we allocate a buffer for the data, make
- * sure that its size is a multiple of 4 and
- * record the real size in i_real_bytes.
  */
 STATIC int
 xfs_iformat_local(
@@ -328,9 +316,7 @@ xfs_iformat_local(
 
 /*
  * The file consists of a set of extents all of which fit into the on-disk
- * inode.  If there are few enough extents to fit into the if_inline_ext, then
- * copy them there.  Otherwise allocate a buffer for them and copy them into it.
- * Either way, set if_extents to point at the extents.
+ * inode.
  */
 STATIC int
 xfs_iformat_extents(
@@ -362,8 +348,6 @@ xfs_iformat_extents(
        ifp->if_real_bytes = 0;
        if (nex == 0)
                ifp->if_u1.if_extents = NULL;
-       else if (nex <= XFS_INLINE_EXTS)
-               ifp->if_u1.if_extents = ifp->if_u2.if_inline_ext;
        else
                xfs_iext_add(ifp, 0, nex);
 
@@ -618,26 +602,9 @@ xfs_idata_realloc(
        ASSERT(new_size >= 0);
 
        if (new_size == 0) {
-               if (ifp->if_u1.if_data != ifp->if_u2.if_inline_data) {
-                       kmem_free(ifp->if_u1.if_data);
-               }
+               kmem_free(ifp->if_u1.if_data);
                ifp->if_u1.if_data = NULL;
                real_size = 0;
-       } else if (new_size <= sizeof(ifp->if_u2.if_inline_data)) {
-               /*
-                * If the valid extents/data can fit in if_inline_ext/data,
-                * copy them from the malloc'd vector and free it.
-                */
-               if (ifp->if_u1.if_data == NULL) {
-                       ifp->if_u1.if_data = ifp->if_u2.if_inline_data;
-               } else if (ifp->if_u1.if_data != ifp->if_u2.if_inline_data) {
-                       ASSERT(ifp->if_real_bytes != 0);
-                       memcpy(ifp->if_u2.if_inline_data, ifp->if_u1.if_data,
-                             new_size);
-                       kmem_free(ifp->if_u1.if_data);
-                       ifp->if_u1.if_data = ifp->if_u2.if_inline_data;
-               }
-               real_size = 0;
        } else {
                /*
                 * Stuck with malloc/realloc.
@@ -651,7 +618,7 @@ xfs_idata_realloc(
                        ASSERT(ifp->if_real_bytes == 0);
                        ifp->if_u1.if_data = kmem_alloc(real_size,
                                                        KM_SLEEP | KM_NOFS);
-               } else if (ifp->if_u1.if_data != ifp->if_u2.if_inline_data) {
+               } else {
                        /*
                         * Only do the realloc if the underlying size
                         * is really changing.
@@ -662,12 +629,6 @@ xfs_idata_realloc(
                                                        real_size,
                                                        KM_SLEEP | KM_NOFS);
                        }
-               } else {
-                       ASSERT(ifp->if_real_bytes == 0);
-                       ifp->if_u1.if_data = kmem_alloc(real_size,
-                                                       KM_SLEEP | KM_NOFS);
-                       memcpy(ifp->if_u1.if_data, ifp->if_u2.if_inline_data,
-                               ifp->if_bytes);
                }
        }
        ifp->if_real_bytes = real_size;
@@ -695,8 +656,7 @@ xfs_idestroy_fork(
         * so check and free it up if we do.
         */
        if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
-               if ((ifp->if_u1.if_data != ifp->if_u2.if_inline_data) &&
-                   (ifp->if_u1.if_data != NULL)) {
+               if (ifp->if_u1.if_data != NULL) {
                        ASSERT(ifp->if_real_bytes != 0);
                        kmem_free(ifp->if_u1.if_data);
                        ifp->if_u1.if_data = NULL;
@@ -704,13 +664,11 @@ xfs_idestroy_fork(
                }
        } else if ((ifp->if_flags & XFS_IFEXTENTS) &&
                   ((ifp->if_flags & XFS_IFEXTIREC) ||
-                   ((ifp->if_u1.if_extents != NULL) &&
-                    (ifp->if_u1.if_extents != ifp->if_u2.if_inline_ext)))) {
+                   (ifp->if_u1.if_extents != NULL))) {
                ASSERT(ifp->if_real_bytes != 0);
                xfs_iext_destroy(ifp);
        }
-       ASSERT(ifp->if_u1.if_extents == NULL ||
-              ifp->if_u1.if_extents == ifp->if_u2.if_inline_ext);
+       ASSERT(ifp->if_u1.if_extents == NULL);
        ASSERT(ifp->if_real_bytes == 0);
        if (whichfork == XFS_ATTR_FORK) {
                kmem_zone_free(xfs_ifork_zone, ip->i_afp);
@@ -943,28 +901,14 @@ xfs_iext_add(
        ASSERT((idx >= 0) && (idx <= nextents));
        byte_diff = ext_diff * sizeof(xfs_bmbt_rec_t);
        new_size = ifp->if_bytes + byte_diff;
+
        /*
-        * If the new number of extents (nextents + ext_diff)
-        * fits inside the inode, then continue to use the inline
-        * extent buffer.
-        */
-       if (nextents + ext_diff <= XFS_INLINE_EXTS) {
-               if (idx < nextents) {
-                       memmove(&ifp->if_u2.if_inline_ext[idx + ext_diff],
-                               &ifp->if_u2.if_inline_ext[idx],
-                               (nextents - idx) * sizeof(xfs_bmbt_rec_t));
-                       memset(&ifp->if_u2.if_inline_ext[idx], 0, byte_diff);
-               }
-               ifp->if_u1.if_extents = ifp->if_u2.if_inline_ext;
-               ifp->if_real_bytes = 0;
-       }
-       /*
-        * Otherwise use a linear (direct) extent list.
+        * Use a linear (direct) extent list.
         * If the extents are currently inside the inode,
         * xfs_iext_realloc_direct will switch us from
         * inline to direct extent allocation mode.
         */
-       else if (nextents + ext_diff <= XFS_LINEAR_EXTS) {
+       if (nextents + ext_diff <= XFS_LINEAR_EXTS) {
                xfs_iext_realloc_direct(ifp, new_size);
                if (idx < nextents) {
                        memmove(&ifp->if_u1.if_extents[idx + ext_diff],
@@ -1172,44 +1116,11 @@ xfs_iext_remove(
                xfs_iext_remove_indirect(ifp, cur->idx, ext_diff);
        } else if (ifp->if_real_bytes) {
                xfs_iext_remove_direct(ifp, cur->idx, ext_diff);
-       } else {
-               xfs_iext_remove_inline(ifp, cur->idx, ext_diff);
        }
        ifp->if_bytes = new_size;
 }
 
 /*
- * This removes ext_diff extents from the inline buffer, beginning
- * at extent index idx.
- */
-void
-xfs_iext_remove_inline(
-       xfs_ifork_t     *ifp,           /* inode fork pointer */
-       xfs_extnum_t    idx,            /* index to begin removing exts */
-       int             ext_diff)       /* number of extents to remove */
-{
-       int             nextents;       /* number of extents in file */
-
-       ASSERT(!(ifp->if_flags & XFS_IFEXTIREC));
-       ASSERT(idx < XFS_INLINE_EXTS);
-       nextents = xfs_iext_count(ifp);
-       ASSERT(((nextents - ext_diff) > 0) &&
-               (nextents - ext_diff) < XFS_INLINE_EXTS);
-
-       if (idx + ext_diff < nextents) {
-               memmove(&ifp->if_u2.if_inline_ext[idx],
-                       &ifp->if_u2.if_inline_ext[idx + ext_diff],
-                       (nextents - (idx + ext_diff)) *
-                        sizeof(xfs_bmbt_rec_t));
-               memset(&ifp->if_u2.if_inline_ext[nextents - ext_diff],
-                       0, ext_diff * sizeof(xfs_bmbt_rec_t));
-       } else {
-               memset(&ifp->if_u2.if_inline_ext[idx], 0,
-                       ext_diff * sizeof(xfs_bmbt_rec_t));
-       }
-}
-
-/*
  * This removes ext_diff extents from a linear (direct) extent list,
  * beginning at extent index idx. If the extents are being removed
  * from the end of the list (ie. truncate) then we just need to re-
@@ -1351,16 +1262,7 @@ xfs_iext_realloc_direct(
        /* Free extent records */
        if (new_size == 0) {
                xfs_iext_destroy(ifp);
-       }
-       /* Resize direct extent list and zero any new bytes */
-       else if (ifp->if_real_bytes) {
-               /* Check if extents will fit inside the inode */
-               if (new_size <= XFS_INLINE_EXTS * sizeof(xfs_bmbt_rec_t)) {
-                       xfs_iext_direct_to_inline(ifp, new_size /
-                               (uint)sizeof(xfs_bmbt_rec_t));
-                       ifp->if_bytes = new_size;
-                       return;
-               }
+       } else {
                if (!is_power_of_2(new_size)){
                        rnew_size = roundup_pow_of_two(new_size);
                }
@@ -1375,64 +1277,11 @@ xfs_iext_realloc_direct(
                                rnew_size - ifp->if_real_bytes);
                }
        }
-       /* Switch from the inline extent buffer to a direct extent list */
-       else {
-               if (!is_power_of_2(new_size)) {
-                       rnew_size = roundup_pow_of_two(new_size);
-               }
-               xfs_iext_inline_to_direct(ifp, rnew_size);
-       }
        ifp->if_real_bytes = rnew_size;
        ifp->if_bytes = new_size;
 }
 
 /*
- * Switch from linear (direct) extent records to inline buffer.
- */
-void
-xfs_iext_direct_to_inline(
-       xfs_ifork_t     *ifp,           /* inode fork pointer */
-       xfs_extnum_t    nextents)       /* number of extents in file */
-{
-       ASSERT(ifp->if_flags & XFS_IFEXTENTS);
-       ASSERT(nextents <= XFS_INLINE_EXTS);
-       /*
-        * The inline buffer was zeroed when we switched
-        * from inline to direct extent allocation mode,
-        * so we don't need to clear it here.
-        */
-       memcpy(ifp->if_u2.if_inline_ext, ifp->if_u1.if_extents,
-               nextents * sizeof(xfs_bmbt_rec_t));
-       kmem_free(ifp->if_u1.if_extents);
-       ifp->if_u1.if_extents = ifp->if_u2.if_inline_ext;
-       ifp->if_real_bytes = 0;
-}
-
-/*
- * Switch from inline buffer to linear (direct) extent records.
- * new_size should already be rounded up to the next power of 2
- * by the caller (when appropriate), so use new_size as it is.
- * However, since new_size may be rounded up, we can't update
- * if_bytes here. It is the caller's responsibility to update
- * if_bytes upon return.
- */
-void
-xfs_iext_inline_to_direct(
-       xfs_ifork_t     *ifp,           /* inode fork pointer */
-       int             new_size)       /* number of extents in file */
-{
-       ifp->if_u1.if_extents = kmem_alloc(new_size, KM_NOFS);
-       memset(ifp->if_u1.if_extents, 0, new_size);
-       if (ifp->if_bytes) {
-               memcpy(ifp->if_u1.if_extents, ifp->if_u2.if_inline_ext,
-                       ifp->if_bytes);
-               memset(ifp->if_u2.if_inline_ext, 0, XFS_INLINE_EXTS *
-                       sizeof(xfs_bmbt_rec_t));
-       }
-       ifp->if_real_bytes = new_size;
-}
-
-/*
  * Resize an extent indirection array to new_size bytes.
  */
 STATIC void
@@ -1511,9 +1360,6 @@ xfs_iext_destroy(
                xfs_iext_irec_remove_all(ifp);
        } else if (ifp->if_real_bytes) {
                kmem_free(ifp->if_u1.if_extents);
-       } else if (ifp->if_bytes) {
-               memset(ifp->if_u2.if_inline_ext, 0, XFS_INLINE_EXTS *
-                       sizeof(xfs_bmbt_rec_t));
        }
        ifp->if_u1.if_extents = NULL;
        ifp->if_real_bytes = 0;
@@ -1708,8 +1554,6 @@ xfs_iext_irec_init(
 
        if (nextents == 0) {
                ifp->if_u1.if_extents = kmem_alloc(XFS_IEXT_BUFSZ, KM_NOFS);
-       } else if (!ifp->if_real_bytes) {
-               xfs_iext_inline_to_direct(ifp, XFS_IEXT_BUFSZ);
        } else if (ifp->if_real_bytes < XFS_IEXT_BUFSZ) {
                xfs_iext_realloc_direct(ifp, XFS_IEXT_BUFSZ);
        }
@@ -1829,9 +1673,6 @@ xfs_iext_irec_compact(
 
        if (nextents == 0) {
                xfs_iext_destroy(ifp);
-       } else if (nextents <= XFS_INLINE_EXTS) {
-               xfs_iext_indirect_to_direct(ifp);
-               xfs_iext_direct_to_inline(ifp, nextents);
        } else if (nextents <= XFS_LINEAR_EXTS) {
                xfs_iext_indirect_to_direct(ifp);
        } else if (nextents < (nlists * XFS_LINEAR_EXTS) >> 1) {
index d454161..cf9885a 100644 (file)
@@ -51,8 +51,6 @@ typedef struct xfs_ext_irec {
  */
 #define        XFS_IEXT_BUFSZ          4096
 #define        XFS_LINEAR_EXTS         (XFS_IEXT_BUFSZ / (uint)sizeof(xfs_bmbt_rec_t))
-#define        XFS_INLINE_EXTS         2
-#define        XFS_INLINE_DATA         32
 typedef struct xfs_ifork {
        int                     if_bytes;       /* bytes in if_u1 */
        int                     if_real_bytes;  /* bytes allocated in if_u1 */
@@ -64,12 +62,6 @@ typedef struct xfs_ifork {
                xfs_ext_irec_t  *if_ext_irec;   /* irec map file exts */
                char            *if_data;       /* inline file data */
        } if_u1;
-       union {
-               xfs_bmbt_rec_host_t if_inline_ext[XFS_INLINE_EXTS];
-                                               /* very small file extents */
-               char            if_inline_data[XFS_INLINE_DATA];
-                                               /* very small file data */
-       } if_u2;
 } xfs_ifork_t;
 
 /*
@@ -158,12 +150,9 @@ void               xfs_iext_add_indirect_multi(struct xfs_ifork *, int,
                                            xfs_extnum_t, int);
 void           xfs_iext_remove(struct xfs_inode *, struct xfs_iext_cursor *,
                        int, int);
-void           xfs_iext_remove_inline(struct xfs_ifork *, xfs_extnum_t, int);
 void           xfs_iext_remove_direct(struct xfs_ifork *, xfs_extnum_t, int);
 void           xfs_iext_remove_indirect(struct xfs_ifork *, xfs_extnum_t, int);
 void           xfs_iext_realloc_direct(struct xfs_ifork *, int);
-void           xfs_iext_direct_to_inline(struct xfs_ifork *, xfs_extnum_t);
-void           xfs_iext_inline_to_direct(struct xfs_ifork *, int);
 void           xfs_iext_destroy(struct xfs_ifork *);
 struct xfs_bmbt_rec_host *
                xfs_iext_bno_to_ext(struct xfs_ifork *, xfs_fileoff_t, int *);
index e748309..6d37ab4 100644 (file)
@@ -1709,7 +1709,6 @@ xfs_swap_extent_forks(
        xfs_filblks_t           aforkblks = 0;
        xfs_filblks_t           taforkblks = 0;
        xfs_extnum_t            junk;
-       xfs_extnum_t            nextents;
        uint64_t                tmp;
        int                     error;
 
@@ -1784,13 +1783,6 @@ xfs_swap_extent_forks(
 
        switch (ip->i_d.di_format) {
        case XFS_DINODE_FMT_EXTENTS:
-               /*
-                * If the extents fit in the inode, fix the pointer.  Otherwise
-                * it's already NULL or pointing to the extent.
-                */
-               nextents = xfs_iext_count(&ip->i_df);
-               if (nextents <= XFS_INLINE_EXTS)
-                       ifp->if_u1.if_extents = ifp->if_u2.if_inline_ext;
                (*src_log_flags) |= XFS_ILOG_DEXT;
                break;
        case XFS_DINODE_FMT_BTREE:
@@ -1802,13 +1794,6 @@ xfs_swap_extent_forks(
 
        switch (tip->i_d.di_format) {
        case XFS_DINODE_FMT_EXTENTS:
-               /*
-                * If the extents fit in the inode, fix the pointer.  Otherwise
-                * it's already NULL or pointing to the extent.
-                */
-               nextents = xfs_iext_count(&tip->i_df);
-               if (nextents <= XFS_INLINE_EXTS)
-                       tifp->if_u1.if_extents = tifp->if_u2.if_inline_ext;
                (*target_log_flags) |= XFS_ILOG_DEXT;
                break;
        case XFS_DINODE_FMT_BTREE: