summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2021-03-25 13:37:03 -0700
committerDarrick J. Wong <djwong@kernel.org>2021-03-25 17:08:24 -0700
commitdca33ac51e74b0511c2eeb86fed5b3341d496c5a (patch)
tree76fdce2dfe8733b6f24bb2fb30dd40aa49889f1e
parent5799c2fba9827f834f6cc1cd337317453cd80efc (diff)
xfs: add inode scan limits to the eofblocks ioctl
Allow callers of the userspace eofblocks ioctl to set a limit on the number of inodes to scan, and then plumb that through the interface. This removes a minor wart from the internal inode walk interface. Signed-off-by: Darrick J. Wong <djwong@kernel.org>
-rw-r--r--fs/xfs/libxfs/xfs_fs.h7
-rw-r--r--fs/xfs/xfs_icache.c7
-rw-r--r--fs/xfs/xfs_icache.h2
-rw-r--r--fs/xfs/xfs_ioctl.c9
4 files changed, 17 insertions, 8 deletions
diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
index 97d21a282db9..bb53bc68fb3c 100644
--- a/fs/xfs/libxfs/xfs_fs.h
+++ b/fs/xfs/libxfs/xfs_fs.h
@@ -524,7 +524,7 @@ struct xfs_fs_eofblocks {
uid_t eof_uid;
gid_t eof_gid;
prid_t eof_prid;
- __u32 pad32;
+ __u32 eof_limit;
__u64 eof_min_file_size;
__u64 pad64[12];
};
@@ -538,12 +538,15 @@ struct xfs_fs_eofblocks {
#define XFS_EOF_FLAGS_UNION (1 << 5) /* union filter algorithm;
* kernel only, not included in
* valid mask */
+#define XFS_EOF_FLAGS_LIMIT (1 << 6) /* scan this many inodes */
+
#define XFS_EOF_FLAGS_VALID \
(XFS_EOF_FLAGS_SYNC | \
XFS_EOF_FLAGS_UID | \
XFS_EOF_FLAGS_GID | \
XFS_EOF_FLAGS_PRID | \
- XFS_EOF_FLAGS_MINFILESIZE)
+ XFS_EOF_FLAGS_MINFILESIZE | \
+ XFS_EOF_FLAGS_LIMIT)
/*
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index d45166066847..5fc4a1b54f72 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -1054,7 +1054,7 @@ restart:
break;
cond_resched();
- if (tag == XFS_ICI_RECLAIM_TAG && eofb) {
+ if (eofb && (eofb->eof_flags & XFS_EOF_FLAGS_LIMIT)) {
eofb->nr_to_scan -= XFS_LOOKUP_BATCH;
if (eofb->nr_to_scan < 0)
break;
@@ -1256,7 +1256,10 @@ xfs_reclaim_inodes_nr(
struct xfs_mount *mp,
int nr_to_scan)
{
- struct xfs_eofblocks eofb = { .nr_to_scan = nr_to_scan };
+ struct xfs_eofblocks eofb = {
+ .eof_flags = XFS_EOF_FLAGS_LIMIT,
+ .nr_to_scan = nr_to_scan
+ };
/* kick background reclaimer and push the AIL */
xfs_reclaim_work_queue(mp);
diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h
index a1230ebcea3e..0f832fa95fd4 100644
--- a/fs/xfs/xfs_icache.h
+++ b/fs/xfs/xfs_icache.h
@@ -15,8 +15,6 @@ struct xfs_eofblocks {
kgid_t eof_gid;
prid_t eof_prid;
__u64 eof_min_file_size;
-
- /* Number of inodes to scan, currently limited to reclaim */
int nr_to_scan;
};
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 562b57b7a4a3..ac3192a433f9 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -2041,8 +2041,7 @@ xfs_fs_eofblocks_from_user(
if (src->eof_flags & ~XFS_EOF_FLAGS_VALID)
return -EINVAL;
- if (memchr_inv(&src->pad32, 0, sizeof(src->pad32)) ||
- memchr_inv(src->pad64, 0, sizeof(src->pad64)))
+ if (memchr_inv(src->pad64, 0, sizeof(src->pad64)))
return -EINVAL;
dst->eof_flags = src->eof_flags;
@@ -2062,6 +2061,12 @@ xfs_fs_eofblocks_from_user(
if (!gid_valid(dst->eof_gid))
return -EINVAL;
}
+
+ if (src->eof_flags & XFS_EOF_FLAGS_LIMIT)
+ dst->nr_to_scan = min_t(int, src->eof_limit, INT_MAX);
+ else if (src->eof_limit != 0)
+ return -EINVAL;
+
return 0;
}