xfs: prevent metadata files from being inactivated
authorDarrick J. Wong <djwong@kernel.org>
Mon, 22 Mar 2021 16:51:54 +0000 (09:51 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Thu, 25 Mar 2021 23:47:50 +0000 (16:47 -0700)
Files containing metadata (quota records, rt bitmap and summary info)
are fully managed by the filesystem, which means that all resource
cleanup must be explicit, not automatic.  This means that they should
never be subjected automatic to post-eof truncation, nor should they be
freed automatically even if the link count drops to zero.

In other words, xfs_inactive() should leave these files alone.  Add the
necessary predicate functions to make this happen.  This adds a second
layer of prevention for the kinds of fs corruption that was fixed by
commit f4c32e87de7d.  If we ever decide to support removing metadata
files, we should make all those metadata updates explicit.

Rearrange the order of #includes to fix compiler errors, since
xfs_mount.h is supposed to be included before xfs_inode.h

Followup-to: f4c32e87de7d ("xfs: fix realtime bitmap/summary file truncation when growing rt volume")
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
fs/xfs/libxfs/xfs_iext_tree.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_inode.h
fs/xfs/xfs_xattr.c

index b4164256993d86594d9a6da4dd8ba40b409f6583..773cf43494286c3b62dba031276efe96a83c0043 100644 (file)
@@ -8,9 +8,9 @@
 #include "xfs_format.h"
 #include "xfs_bit.h"
 #include "xfs_log_format.h"
-#include "xfs_inode.h"
 #include "xfs_trans_resv.h"
 #include "xfs_mount.h"
+#include "xfs_inode.h"
 #include "xfs_trace.h"
 
 /*
index f93370bd7b1e387f35fc16b32bf058cc83002e5d..12c79962f8c3ed4aaeef7511b40b18f48ef1ddf2 100644 (file)
@@ -1697,6 +1697,10 @@ xfs_inactive(
        if (mp->m_flags & XFS_MOUNT_RDONLY)
                return;
 
+       /* Metadata inodes require explicit resource cleanup. */
+       if (xfs_is_metadata_inode(ip))
+               return;
+
        /* Try to clean out the cow blocks if there are any. */
        if (xfs_inode_has_cow_data(ip))
                xfs_reflink_cancel_cow_range(ip, 0, NULLFILEOFF, true);
index 88ee4c3930ae702387b504090e41f5465286ca7c..c2c26f8f4a819b3323c3ef72f5823ec1797e3ffd 100644 (file)
@@ -185,6 +185,14 @@ static inline bool xfs_is_reflink_inode(struct xfs_inode *ip)
        return ip->i_d.di_flags2 & XFS_DIFLAG2_REFLINK;
 }
 
+static inline bool xfs_is_metadata_inode(struct xfs_inode *ip)
+{
+       struct xfs_mount        *mp = ip->i_mount;
+
+       return ip == mp->m_rbmip || ip == mp->m_rsumip ||
+               xfs_is_quota_inode(&mp->m_sb, ip->i_ino);
+}
+
 /*
  * Check if an inode has any data in the COW fork.  This might be often false
  * even for inodes with the reflink flag when there is no pending COW operation.
index 12be32f66dc1b18561e19cfba97fdb7eca2a1e5f..0d050f8829ef9cf71407e012c8411fe902f88bbf 100644 (file)
@@ -9,6 +9,8 @@
 #include "xfs_format.h"
 #include "xfs_log_format.h"
 #include "xfs_da_format.h"
+#include "xfs_trans_resv.h"
+#include "xfs_mount.h"
 #include "xfs_inode.h"
 #include "xfs_attr.h"
 #include "xfs_acl.h"