xfs: reinitialise recycled VFS inode correctly
authorDave Chinner <dchinner@redhat.com>
Tue, 9 Feb 2016 05:54:58 +0000 (16:54 +1100)
committerDave Chinner <david@fromorbit.com>
Tue, 9 Feb 2016 05:54:58 +0000 (16:54 +1100)
We are going to keep certain on-disk information in the VFS inode
rather than in a separate XFS specific stucture, so we have to be
careful of the VFS code clearing that information when we
re-initialise reclaimable cached inodes during lookup. If we don't
do this, then we lose critical information from the inode and that
results in corruption being detected.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Dave Chinner <david@fromorbit.com>
fs/xfs/xfs_icache.c

index 7c26f8611891469615b7bce072761c9f2105ff60..9ca2865575ab2624150fd0e01198f904d747b544 100644 (file)
@@ -134,6 +134,26 @@ xfs_inode_free(
        call_rcu(&VFS_I(ip)->i_rcu, xfs_inode_free_callback);
 }
 
+/*
+ * When we recycle a reclaimable inode, we need to re-initialise the VFS inode
+ * part of the structure. This is made more complex by the fact we store
+ * information about the on-disk values in the VFS inode and so we can't just
+ * overwrite it's values unconditionally. Hence we save the parameters we
+ * need to retain across reinitialisation, and rewrite them into the VFS inode
+ * after resetting it's state even if resetting fails.
+ */
+static int
+xfs_reinit_inode(
+       struct xfs_mount        *mp,
+       struct inode            *inode)
+{
+       int             error;
+
+       error = inode_init_always(mp->m_super, inode);
+
+       return error;
+}
+
 /*
  * Check the validity of the inode we just found it the cache
  */
@@ -208,7 +228,7 @@ xfs_iget_cache_hit(
                spin_unlock(&ip->i_flags_lock);
                rcu_read_unlock();
 
-               error = inode_init_always(mp->m_super, inode);
+               error = xfs_reinit_inode(mp, inode);
                if (error) {
                        /*
                         * Re-initializing the inode failed, and we are in deep