From: Darrick J. Wong <djwong@xxxxxxxxxx> 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@xxxxxxxxxx> --- fs/xfs/libxfs/xfs_fs.h | 7 +++++-- fs/xfs/xfs_icache.c | 7 +++++-- fs/xfs/xfs_icache.h | 2 -- fs/xfs/xfs_ioctl.c | 9 +++++++-- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h index 6fad140d4c8e..0b21d4b93072 100644 --- a/fs/xfs/libxfs/xfs_fs.h +++ b/fs/xfs/libxfs/xfs_fs.h @@ -523,7 +523,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]; }; @@ -537,12 +537,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 23b04cfa38f3..e8a2e1cf7577 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c @@ -1047,7 +1047,7 @@ xfs_inode_walk_ag( 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; @@ -1249,7 +1249,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 7f139ee442bf..b13869954846 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -2043,8 +2043,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; @@ -2064,6 +2063,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; }