There are certain users that wish to force the NFS client to choose READDIRPLUS over READDIR for a particular mount. Add a new kernel mount option "force_rdirplus" to carry that intent. Signed-off-by: Benjamin Coddington <bcodding@xxxxxxxxxx> --- fs/nfs/dir.c | 2 ++ fs/nfs/fs_context.c | 14 ++++++++++++-- include/linux/nfs_fs_sb.h | 1 + 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 2b04038b0e40..c9de0e474cf5 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -666,6 +666,8 @@ static bool nfs_use_readdirplus(struct inode *dir, struct dir_context *ctx, { if (!nfs_server_capable(dir, NFS_CAP_READDIRPLUS)) return false; + if (NFS_SERVER(dir)->flags && NFS_MOUNT_FORCE_RDIRPLUS) + return true; if (ctx->pos == 0 || cache_hits + cache_misses > NFS_READDIR_CACHE_USAGE_THRESHOLD) return true; diff --git a/fs/nfs/fs_context.c b/fs/nfs/fs_context.c index b069385eea17..3ba44b444031 100644 --- a/fs/nfs/fs_context.c +++ b/fs/nfs/fs_context.c @@ -72,6 +72,7 @@ enum nfs_param { Opt_posix, Opt_proto, Opt_rdirplus, + Opt_force_rdirplus, Opt_rdma, Opt_resvport, Opt_retrans, @@ -175,6 +176,7 @@ static const struct fs_parameter_spec nfs_fs_parameters[] = { fsparam_flag_no("posix", Opt_posix), fsparam_string("proto", Opt_proto), fsparam_flag_no("rdirplus", Opt_rdirplus), + fsparam_flag ("force_rdirplus", Opt_force_rdirplus), fsparam_flag ("rdma", Opt_rdma), fsparam_flag_no("resvport", Opt_resvport), fsparam_u32 ("retrans", Opt_retrans), @@ -636,10 +638,18 @@ static int nfs_fs_context_parse_param(struct fs_context *fc, ctx->flags &= ~NFS_MOUNT_NOACL; break; case Opt_rdirplus: - if (result.negated) + if (result.negated) { + if (ctx->flags && NFS_MOUNT_FORCE_RDIRPLUS) + return nfs_invalf(fc, "NFS: Cannot both force and disable READDIR PLUS"); ctx->flags |= NFS_MOUNT_NORDIRPLUS; - else + } else { ctx->flags &= ~NFS_MOUNT_NORDIRPLUS; + } + break; + case Opt_force_rdirplus: + if (ctx->flags && NFS_MOUNT_NORDIRPLUS) + return nfs_invalf(fc, "NFS: Cannot both force and disable READDIR PLUS"); + ctx->flags |= NFS_MOUNT_FORCE_RDIRPLUS; break; case Opt_sharecache: if (result.negated) diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index f00bfcee7120..3774b2235a1e 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h @@ -167,6 +167,7 @@ struct nfs_server { #define NFS_MOUNT_TRUNK_DISCOVERY 0x04000000 #define NFS_MOUNT_SHUTDOWN 0x08000000 #define NFS_MOUNT_NO_ALIGNWRITE 0x10000000 +#define NFS_MOUNT_FORCE_RDIRPLUS 0x20000000 unsigned int fattr_valid; /* Valid attributes */ unsigned int caps; /* server capabilities */ -- 2.47.0