xfs: remove the di_dmevmask and di_dmstate fields from struct xfs_icdinode
authorChristoph Hellwig <hch@lst.de>
Mon, 29 Mar 2021 18:11:38 +0000 (11:11 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Wed, 7 Apr 2021 21:37:03 +0000 (14:37 -0700)
The legacy DMAPI fields were never set by upstream Linux XFS, and have no
way to be read using the kernel APIs.  So instead of bloating the in-core
inode for them just copy them from the on-disk inode into the log when
logging the inode.  The only caveat is that we need to make sure to zero
the fields for newly read or deleted inodes, which is solved using a new
flag in the inode.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
fs/xfs/libxfs/xfs_inode_buf.c
fs/xfs/libxfs/xfs_inode_buf.h
fs/xfs/xfs_inode.c
fs/xfs/xfs_inode.h
fs/xfs/xfs_inode_item.c
fs/xfs/xfs_log_recover.c

index af5ee8bd7e6ac9573c8762717087569289fac7a2..917a41828ffbe30fe15d5359deab8ad30c2880ee 100644 (file)
@@ -230,10 +230,11 @@ xfs_inode_from_disk(
        to->di_nblocks = be64_to_cpu(from->di_nblocks);
        to->di_extsize = be32_to_cpu(from->di_extsize);
        to->di_forkoff = from->di_forkoff;
-       to->di_dmevmask = be32_to_cpu(from->di_dmevmask);
-       to->di_dmstate  = be16_to_cpu(from->di_dmstate);
        to->di_flags    = be16_to_cpu(from->di_flags);
 
+       if (from->di_dmevmask || from->di_dmstate)
+               xfs_iflags_set(ip, XFS_IPRESERVE_DM_FIELDS);
+
        if (xfs_sb_version_has_v3inode(&ip->i_mount->m_sb)) {
                inode_set_iversion_queried(inode,
                                           be64_to_cpu(from->di_changecount));
@@ -311,8 +312,6 @@ xfs_inode_to_disk(
        to->di_anextents = cpu_to_be16(xfs_ifork_nextents(ip->i_afp));
        to->di_forkoff = from->di_forkoff;
        to->di_aformat = xfs_ifork_format(ip->i_afp);
-       to->di_dmevmask = cpu_to_be32(from->di_dmevmask);
-       to->di_dmstate = cpu_to_be16(from->di_dmstate);
        to->di_flags = cpu_to_be16(from->di_flags);
 
        if (xfs_sb_version_has_v3inode(&ip->i_mount->m_sb)) {
index b3097ea8b5336681c4b7c8e28dbbcb84925e7758..d7a019df05d647bb5d1e923926acff87c3220acb 100644 (file)
@@ -22,8 +22,6 @@ struct xfs_icdinode {
        xfs_rfsblock_t  di_nblocks;     /* # of direct & btree blocks used */
        xfs_extlen_t    di_extsize;     /* basic/minimum extent size for file */
        uint8_t         di_forkoff;     /* attr fork offs, <<3 for 64b align */
-       uint32_t        di_dmevmask;    /* DMIG event mask */
-       uint16_t        di_dmstate;     /* DMIG state info */
        uint16_t        di_flags;       /* random flags, XFS_DIFLAG_... */
 
        uint64_t        di_flags2;      /* more random flags */
index 8c164fe621548b552c7e2a3c481e4f0d7343cef4..9c8fd11a53622af7115536fd14474c658f3a2a9a 100644 (file)
@@ -840,8 +840,6 @@ xfs_init_new_inode(
        inode->i_ctime = tv;
 
        ip->i_d.di_extsize = 0;
-       ip->i_d.di_dmevmask = 0;
-       ip->i_d.di_dmstate = 0;
        ip->i_d.di_flags = 0;
 
        if (xfs_sb_version_has_v3inode(&mp->m_sb)) {
@@ -2615,9 +2613,10 @@ xfs_ifree(
        VFS_I(ip)->i_mode = 0;          /* mark incore inode as free */
        ip->i_d.di_flags = 0;
        ip->i_d.di_flags2 = ip->i_mount->m_ino_geo.new_diflags2;
-       ip->i_d.di_dmevmask = 0;
        ip->i_d.di_forkoff = 0;         /* mark the attr fork not in use */
        ip->i_df.if_format = XFS_DINODE_FMT_EXTENTS;
+       if (xfs_iflags_test(ip, XFS_IPRESERVE_DM_FIELDS))
+               xfs_iflags_clear(ip, XFS_IPRESERVE_DM_FIELDS);
 
        /* Don't attempt to replay owner changes for a deleted inode */
        spin_lock(&iip->ili_lock);
index 13f4cd2e1f4fc5495325d10e449568cb01a9c4fc..df514276747939a483640c8f1a47dc26b7a2b435 100644 (file)
@@ -222,6 +222,7 @@ static inline bool xfs_inode_has_bigtime(struct xfs_inode *ip)
 #define XFS_IRECLAIMABLE       (1 << 2) /* inode can be reclaimed */
 #define __XFS_INEW_BIT         3        /* inode has just been allocated */
 #define XFS_INEW               (1 << __XFS_INEW_BIT)
+#define XFS_IPRESERVE_DM_FIELDS        (1 << 4) /* has legacy DMAPI fields set */
 #define XFS_ITRUNCATED         (1 << 5) /* truncated down so flush-on-close */
 #define XFS_IDIRTY_RELEASE     (1 << 6) /* dirty release already seen */
 #define XFS_IFLUSHING          (1 << 7) /* inode is being flushed */
index 17e20a6d8b4e27a590096a0cf463e609c53f92b7..16e758a689217e1ef3a072b64335aec26695d8b9 100644 (file)
@@ -317,6 +317,33 @@ xfs_inode_to_log_dinode_ts(
        return its;
 }
 
+/*
+ * The legacy DMAPI fields are only present in the on-disk and in-log inodes,
+ * but not in the in-memory one.  But we are guaranteed to have an inode buffer
+ * in memory when logging an inode, so we can just copy it from the on-disk
+ * inode to the in-log inode here so that recovery of file system with these
+ * fields set to non-zero values doesn't lose them.  For all other cases we zero
+ * the fields.
+ */
+static void
+xfs_copy_dm_fields_to_log_dinode(
+       struct xfs_inode        *ip,
+       struct xfs_log_dinode   *to)
+{
+       struct xfs_dinode       *dip;
+
+       dip = xfs_buf_offset(ip->i_itemp->ili_item.li_buf,
+                            ip->i_imap.im_boffset);
+
+       if (xfs_iflags_test(ip, XFS_IPRESERVE_DM_FIELDS)) {
+               to->di_dmevmask = be32_to_cpu(dip->di_dmevmask);
+               to->di_dmstate = be16_to_cpu(dip->di_dmstate);
+       } else {
+               to->di_dmevmask = 0;
+               to->di_dmstate = 0;
+       }
+}
+
 static void
 xfs_inode_to_log_dinode(
        struct xfs_inode        *ip,
@@ -349,10 +376,10 @@ xfs_inode_to_log_dinode(
        to->di_anextents = xfs_ifork_nextents(ip->i_afp);
        to->di_forkoff = from->di_forkoff;
        to->di_aformat = xfs_ifork_format(ip->i_afp);
-       to->di_dmevmask = from->di_dmevmask;
-       to->di_dmstate = from->di_dmstate;
        to->di_flags = from->di_flags;
 
+       xfs_copy_dm_fields_to_log_dinode(ip, to);
+
        /* log a dummy value to ensure log structure is fully initialised */
        to->di_next_unlinked = NULLAGINO;
 
index 42a8c7da492aa8220b5e0f9b1d8585a777e878f6..e5dd1c0c2f03c46086f6c94613556c4725caedc5 100644 (file)
@@ -2696,12 +2696,6 @@ xlog_recover_process_one_iunlink(
        agino = be32_to_cpu(dip->di_next_unlinked);
        xfs_buf_relse(ibp);
 
-       /*
-        * Prevent any DMAPI event from being sent when the reference on
-        * the inode is dropped.
-        */
-       ip->i_d.di_dmevmask = 0;
-
        xfs_irele(ip);
        return agino;