summaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_icache.c
diff options
context:
space:
mode:
authorBrian Foster <bfoster@redhat.com>2014-07-24 11:44:28 +0200
committerDave Chinner <david@fromorbit.com>2014-07-24 11:44:28 +0200
commitf4526397928fff052f795713748f376a2bba1b5e (patch)
treeb705d85eb1370c092b497ae663ee5f14becfc116 /fs/xfs/xfs_icache.c
parentxfs: add scan owner field to xfs_eofblocks (diff)
downloadlinux-f4526397928fff052f795713748f376a2bba1b5e.tar.xz
linux-f4526397928fff052f795713748f376a2bba1b5e.zip
xfs: support a union-based filter for eofblocks scans
From: Brian Foster <bfoster@redhat.com> The eofblocks scan inode filter uses intersection logic by default. E.g., specifying both user and group quota ids filters out inodes that are not covered by both the specified user and group quotas. This is suitable for behavior exposed to userspace. Scans that are initiated from within the kernel might require more broad semantics, such as scanning all inodes under each quota associated with an inode to alleviate low free space conditions in each. Create the XFS_EOF_FLAGS_UNION flag to support a conditional union-based filtering algorithm for eofblocks scans. This flag is intentionally left out of the valid mask as it is not supported for scans initiated from userspace. Signed-off-by: Brian Foster <bfoster@redhat.com> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs/xfs_icache.c')
-rw-r--r--fs/xfs/xfs_icache.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index 6e522ff5a006..43452081b705 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -1203,6 +1203,30 @@ xfs_inode_match_id(
return 1;
}
+/*
+ * A union-based inode filtering algorithm. Process the inode if any of the
+ * criteria match. This is for global/internal scans only.
+ */
+STATIC int
+xfs_inode_match_id_union(
+ struct xfs_inode *ip,
+ struct xfs_eofblocks *eofb)
+{
+ if ((eofb->eof_flags & XFS_EOF_FLAGS_UID) &&
+ uid_eq(VFS_I(ip)->i_uid, eofb->eof_uid))
+ return 1;
+
+ if ((eofb->eof_flags & XFS_EOF_FLAGS_GID) &&
+ gid_eq(VFS_I(ip)->i_gid, eofb->eof_gid))
+ return 1;
+
+ if ((eofb->eof_flags & XFS_EOF_FLAGS_PRID) &&
+ xfs_get_projid(ip) == eofb->eof_prid)
+ return 1;
+
+ return 0;
+}
+
STATIC int
xfs_inode_free_eofblocks(
struct xfs_inode *ip,
@@ -1212,6 +1236,7 @@ xfs_inode_free_eofblocks(
int ret;
struct xfs_eofblocks *eofb = args;
bool need_iolock = true;
+ int match;
ASSERT(!eofb || (eofb && eofb->eof_scan_owner != 0));
@@ -1231,7 +1256,11 @@ xfs_inode_free_eofblocks(
return 0;
if (eofb) {
- if (!xfs_inode_match_id(ip, eofb))
+ if (eofb->eof_flags & XFS_EOF_FLAGS_UNION)
+ match = xfs_inode_match_id_union(ip, eofb);
+ else
+ match = xfs_inode_match_id(ip, eofb);
+ if (!match)
return 0;
/* skip the inode if the file size is too small */