]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: create a separate cow extent size hint for the allocator
authorDarrick J. Wong <darrick.wong@oracle.com>
Tue, 25 Oct 2016 01:43:42 +0000 (12:43 +1100)
committerDave Chinner <david@fromorbit.com>
Tue, 25 Oct 2016 01:43:42 +0000 (12:43 +1100)
Source kernel commit: f7ca35227253dc8244fd908140b06010e67a31e5

Create a per-inode extent size allocator hint for copy-on-write.  This
hint is separate from the existing extent size hint so that CoW can
take advantage of the fragmentation-reducing properties of extent size
hints without disabling delalloc for regular writes.

The extent size hint that's fed to the allocator during a copy on
write operation is the greater of the cowextsize and regular extsize
hint.

During reflink, if we're sharing the entire source file to the entire
destination file and the destination file doesn't already have a
cowextsize hint, propagate the source file's cowextsize hint to the
destination file.

Furthermore, zero the bulkstat buffer prior to setting the fields
so that we don't copy kernel memory contents into userspace.

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

index cb4639ad9c238ee8a4756e9f0d1e8d61271b31cb..a57821579b8496e0b32b86dc2b0f5aa51b314e05 100644 (file)
@@ -434,6 +434,7 @@ do { \
 #define xfs_rotorstep                          1
 #define xfs_bmap_rtalloc(a)                    (-ENOSYS)
 #define xfs_get_extsz_hint(ip)                 (0)
+#define xfs_get_cowextsz_hint(ip)              (0)
 #define xfs_inode_is_filestream(ip)            (0)
 #define xfs_filestream_lookup_ag(ip)           (0)
 #define xfs_filestream_new_ag(ip,ag)           (0)
index 5d00b5fa4fc39102665512f68c15c0fae855583a..74a205252044e304811c53ef2b17f12260165994 100644 (file)
@@ -3658,7 +3658,9 @@ xfs_bmap_btalloc(
        else if (mp->m_dalign)
                stripe_align = mp->m_dalign;
 
-       if (xfs_alloc_is_userdata(ap->datatype))
+       if (ap->flags & XFS_BMAPI_COWFORK)
+               align = xfs_get_cowextsz_hint(ap->ip);
+       else if (xfs_alloc_is_userdata(ap->datatype))
                align = xfs_get_extsz_hint(ap->ip);
        if (unlikely(align)) {
                error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev,
@@ -4184,7 +4186,10 @@ xfs_bmapi_reserve_delalloc(
                alen = XFS_FILBLKS_MIN(alen, got->br_startoff - aoff);
 
        /* Figure out the extent size, adjust alen */
-       extsz = xfs_get_extsz_hint(ip);
+       if (whichfork == XFS_COW_FORK)
+               extsz = xfs_get_cowextsz_hint(ip);
+       else
+               extsz = xfs_get_extsz_hint(ip);
        if (extsz) {
                error = xfs_bmap_extsize_align(mp, got, prev, extsz, rt, eof,
                                               1, 0, &aoff, &alen);
index 0392a0d368142223b08901c300679fa1920e6a2e..7bf61dc58133c649170eebce04d354fc4b43eee4 100644 (file)
@@ -901,7 +901,8 @@ typedef struct xfs_dinode {
        __be64          di_changecount; /* number of attribute changes */
        __be64          di_lsn;         /* flush sequence */
        __be64          di_flags2;      /* more random flags */
-       __u8            di_pad2[16];    /* more padding for future expansion */
+       __be32          di_cowextsize;  /* basic cow extent size for file */
+       __u8            di_pad2[12];    /* more padding for future expansion */
 
        /* fields only written to during inode creation */
        xfs_timestamp_t di_crtime;      /* time created */
index bb70066ee42b78ab443fe35cdc5ef79af689701a..df58c1c7e6c21d1656e9b5ed6abde85d19490b85 100644 (file)
@@ -302,7 +302,8 @@ typedef struct xfs_bstat {
 #define        bs_projid       bs_projid_lo    /* (previously just bs_projid)  */
        __u16           bs_forkoff;     /* inode fork offset in bytes   */
        __u16           bs_projid_hi;   /* higher part of project id    */
-       unsigned char   bs_pad[10];     /* pad space, unused            */
+       unsigned char   bs_pad[6];      /* pad space, unused            */
+       __u32           bs_cowextsize;  /* cow extent size              */
        __u32           bs_dmevmask;    /* DMIG event mask              */
        __u16           bs_dmstate;     /* DMIG state info              */
        __u16           bs_aextents;    /* attribute number of extents  */
index 036389d971cd8d3c7b3ac4fb5514b387001a1dca..beaa5299ee8740781ee145eb1b740d758d196159 100644 (file)
@@ -265,6 +265,7 @@ xfs_inode_from_disk(
                to->di_crtime.t_sec = be32_to_cpu(from->di_crtime.t_sec);
                to->di_crtime.t_nsec = be32_to_cpu(from->di_crtime.t_nsec);
                to->di_flags2 = be64_to_cpu(from->di_flags2);
+               to->di_cowextsize = be32_to_cpu(from->di_cowextsize);
        }
 }
 
@@ -314,7 +315,7 @@ xfs_inode_to_disk(
                to->di_crtime.t_sec = cpu_to_be32(from->di_crtime.t_sec);
                to->di_crtime.t_nsec = cpu_to_be32(from->di_crtime.t_nsec);
                to->di_flags2 = cpu_to_be64(from->di_flags2);
-
+               to->di_cowextsize = cpu_to_be32(from->di_cowextsize);
                to->di_ino = cpu_to_be64(ip->i_ino);
                to->di_lsn = cpu_to_be64(lsn);
                memset(to->di_pad2, 0, sizeof(to->di_pad2));
@@ -366,6 +367,7 @@ xfs_log_dinode_to_disk(
                to->di_crtime.t_sec = cpu_to_be32(from->di_crtime.t_sec);
                to->di_crtime.t_nsec = cpu_to_be32(from->di_crtime.t_nsec);
                to->di_flags2 = cpu_to_be64(from->di_flags2);
+               to->di_cowextsize = cpu_to_be32(from->di_cowextsize);
                to->di_ino = cpu_to_be64(from->di_ino);
                to->di_lsn = cpu_to_be64(from->di_lsn);
                memcpy(to->di_pad2, from->di_pad2, sizeof(to->di_pad2));
index 4ece9bf2f90cfe59d5c183a9cfe3c3d1a469622c..99f18218b22f02507824be766db19963d5bfd8b0 100644 (file)
@@ -47,6 +47,7 @@ struct xfs_icdinode {
        __uint16_t      di_flags;       /* random flags, XFS_DIFLAG_... */
 
        __uint64_t      di_flags2;      /* more random flags */
+       __uint32_t      di_cowextsize;  /* basic cow extent size for file */
 
        xfs_ictimestamp_t di_crtime;    /* time created */
 };
index 8bb250281b83755bd33cecb7a20cd9d8336ba8ab..cfd31a1bdbf8647384c707b115805a511509ed3c 100644 (file)
@@ -423,7 +423,8 @@ struct xfs_log_dinode {
        __uint64_t      di_changecount; /* number of attribute changes */
        xfs_lsn_t       di_lsn;         /* flush sequence */
        __uint64_t      di_flags2;      /* more random flags */
-       __uint8_t       di_pad2[16];    /* more padding for future expansion */
+       __uint32_t      di_cowextsize;  /* basic cow extent size for file */
+       __uint8_t       di_pad2[12];    /* more padding for future expansion */
 
        /* fields only written to during inode creation */
        xfs_ictimestamp_t di_crtime;    /* time created */