summaryrefslogtreecommitdiff
path: root/fs/xfs/xfs_icache.c
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2021-05-31 11:31:57 -0700
committerDarrick J. Wong <djwong@kernel.org>2021-06-03 15:56:02 -0700
commit1ad2cfe0a57031505df682dc1e26922d9d43737f (patch)
treebd07e251745427f767a77f5dc9666eea27b545e4 /fs/xfs/xfs_icache.c
parent977ec4ddf0b75b30afa443cf71ae80e20f501b15 (diff)
xfs: move the quotaoff dqrele inode walk into xfs_icache.c
The only external caller of xfs_inode_walk* happens in quotaoff, when we want to walk all the incore inodes to detach the dquots. Move this code to xfs_icache.c so that we can hide xfs_inode_walk as the starting step in more cleanups of inode walks. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Dave Chinner <dchinner@redhat.com>
Diffstat (limited to 'fs/xfs/xfs_icache.c')
-rw-r--r--fs/xfs/xfs_icache.c65
1 files changed, 64 insertions, 1 deletions
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index 3c81daca0e9a..e2edbcf7a528 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -27,6 +27,18 @@
#include <linux/iversion.h>
/*
+ * Private inode cache walk flags for struct xfs_eofblocks. Must not coincide
+ * with XFS_EOF_FLAGS_*.
+ */
+#define XFS_ICWALK_FLAG_DROP_UDQUOT (1U << 31)
+#define XFS_ICWALK_FLAG_DROP_GDQUOT (1U << 30)
+#define XFS_ICWALK_FLAG_DROP_PDQUOT (1U << 29)
+
+#define XFS_ICWALK_PRIVATE_FLAGS (XFS_ICWALK_FLAG_DROP_UDQUOT | \
+ XFS_ICWALK_FLAG_DROP_GDQUOT | \
+ XFS_ICWALK_FLAG_DROP_PDQUOT)
+
+/*
* Allocate and initialise an xfs_inode.
*/
struct xfs_inode *
@@ -890,7 +902,7 @@ xfs_inode_walk_get_perag(
* Call the @execute function on all incore inodes matching the radix tree
* @tag.
*/
-int
+static int
xfs_inode_walk(
struct xfs_mount *mp,
int iter_flags,
@@ -915,7 +927,58 @@ xfs_inode_walk(
}
}
return last_error;
+ BUILD_BUG_ON(XFS_ICWALK_PRIVATE_FLAGS & XFS_EOF_FLAGS_VALID);
+}
+
+#ifdef CONFIG_XFS_QUOTA
+/* Drop this inode's dquots. */
+static int
+xfs_dqrele_inode(
+ struct xfs_inode *ip,
+ void *priv)
+{
+ struct xfs_eofblocks *eofb = priv;
+
+ xfs_ilock(ip, XFS_ILOCK_EXCL);
+ if (eofb->eof_flags & XFS_ICWALK_FLAG_DROP_UDQUOT) {
+ xfs_qm_dqrele(ip->i_udquot);
+ ip->i_udquot = NULL;
+ }
+ if (eofb->eof_flags & XFS_ICWALK_FLAG_DROP_GDQUOT) {
+ xfs_qm_dqrele(ip->i_gdquot);
+ ip->i_gdquot = NULL;
+ }
+ if (eofb->eof_flags & XFS_ICWALK_FLAG_DROP_PDQUOT) {
+ xfs_qm_dqrele(ip->i_pdquot);
+ ip->i_pdquot = NULL;
+ }
+ xfs_iunlock(ip, XFS_ILOCK_EXCL);
+ return 0;
+}
+
+/*
+ * Detach all dquots from incore inodes if we can. The caller must already
+ * have dropped the relevant XFS_[UGP]QUOTA_ACTIVE flags so that dquots will
+ * not get reattached.
+ */
+int
+xfs_dqrele_all_inodes(
+ struct xfs_mount *mp,
+ unsigned int qflags)
+{
+ struct xfs_eofblocks eofb = { .eof_flags = 0 };
+
+ if (qflags & XFS_UQUOTA_ACCT)
+ eofb.eof_flags |= XFS_ICWALK_FLAG_DROP_UDQUOT;
+ if (qflags & XFS_GQUOTA_ACCT)
+ eofb.eof_flags |= XFS_ICWALK_FLAG_DROP_GDQUOT;
+ if (qflags & XFS_PQUOTA_ACCT)
+ eofb.eof_flags |= XFS_ICWALK_FLAG_DROP_PDQUOT;
+
+ return xfs_inode_walk(mp, XFS_INODE_WALK_INEW_WAIT, xfs_dqrele_inode,
+ &eofb, XFS_ICI_NO_TAG);
}
+#endif /* CONFIG_XFS_QUOTA */
/*
* Grab the inode for reclaim exclusively.