aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorBrian Foster <bfoster@redhat.com>2014-07-24 05:44:28 -0400
committerDave Chinner <david@fromorbit.com>2014-07-24 05:44:28 -0400
commitf4526397928fff052f795713748f376a2bba1b5e (patch)
treeb705d85eb1370c092b497ae663ee5f14becfc116 /fs/xfs
parent5400da7dc0862d73523691038c044535f518a57f (diff)
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')
-rw-r--r--fs/xfs/xfs_fs.h3
-rw-r--r--fs/xfs/xfs_icache.c31
2 files changed, 33 insertions, 1 deletions
diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h
index d34703dbcb42..ffdabc687852 100644
--- a/fs/xfs/xfs_fs.h
+++ b/fs/xfs/xfs_fs.h
@@ -375,6 +375,9 @@ struct xfs_fs_eofblocks {
375#define XFS_EOF_FLAGS_GID (1 << 2) /* filter by gid */ 375#define XFS_EOF_FLAGS_GID (1 << 2) /* filter by gid */
376#define XFS_EOF_FLAGS_PRID (1 << 3) /* filter by project id */ 376#define XFS_EOF_FLAGS_PRID (1 << 3) /* filter by project id */
377#define XFS_EOF_FLAGS_MINFILESIZE (1 << 4) /* filter by min file size */ 377#define XFS_EOF_FLAGS_MINFILESIZE (1 << 4) /* filter by min file size */
378#define XFS_EOF_FLAGS_UNION (1 << 5) /* union filter algorithm;
379 * kernel only, not included in
380 * valid mask */
378#define XFS_EOF_FLAGS_VALID \ 381#define XFS_EOF_FLAGS_VALID \
379 (XFS_EOF_FLAGS_SYNC | \ 382 (XFS_EOF_FLAGS_SYNC | \
380 XFS_EOF_FLAGS_UID | \ 383 XFS_EOF_FLAGS_UID | \
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(
1203 return 1; 1203 return 1;
1204} 1204}
1205 1205
1206/*
1207 * A union-based inode filtering algorithm. Process the inode if any of the
1208 * criteria match. This is for global/internal scans only.
1209 */
1210STATIC int
1211xfs_inode_match_id_union(
1212 struct xfs_inode *ip,
1213 struct xfs_eofblocks *eofb)
1214{
1215 if ((eofb->eof_flags & XFS_EOF_FLAGS_UID) &&
1216 uid_eq(VFS_I(ip)->i_uid, eofb->eof_uid))
1217 return 1;
1218
1219 if ((eofb->eof_flags & XFS_EOF_FLAGS_GID) &&
1220 gid_eq(VFS_I(ip)->i_gid, eofb->eof_gid))
1221 return 1;
1222
1223 if ((eofb->eof_flags & XFS_EOF_FLAGS_PRID) &&
1224 xfs_get_projid(ip) == eofb->eof_prid)
1225 return 1;
1226
1227 return 0;
1228}
1229
1206STATIC int 1230STATIC int
1207xfs_inode_free_eofblocks( 1231xfs_inode_free_eofblocks(
1208 struct xfs_inode *ip, 1232 struct xfs_inode *ip,
@@ -1212,6 +1236,7 @@ xfs_inode_free_eofblocks(
1212 int ret; 1236 int ret;
1213 struct xfs_eofblocks *eofb = args; 1237 struct xfs_eofblocks *eofb = args;
1214 bool need_iolock = true; 1238 bool need_iolock = true;
1239 int match;
1215 1240
1216 ASSERT(!eofb || (eofb && eofb->eof_scan_owner != 0)); 1241 ASSERT(!eofb || (eofb && eofb->eof_scan_owner != 0));
1217 1242
@@ -1231,7 +1256,11 @@ xfs_inode_free_eofblocks(
1231 return 0; 1256 return 0;
1232 1257
1233 if (eofb) { 1258 if (eofb) {
1234 if (!xfs_inode_match_id(ip, eofb)) 1259 if (eofb->eof_flags & XFS_EOF_FLAGS_UNION)
1260 match = xfs_inode_match_id_union(ip, eofb);
1261 else
1262 match = xfs_inode_match_id(ip, eofb);
1263 if (!match)
1235 return 0; 1264 return 0;
1236 1265
1237 /* skip the inode if the file size is too small */ 1266 /* skip the inode if the file size is too small */