Limiting nfs to 128kB of read ahead is performing poorly in high volume mounts. Add the rasize option to set the read ahead to a more suitable value. Signed-off-by: Thiago Rafael Becker <trbecker@xxxxxxxxx> --- fs/nfs/client.c | 3 +++ fs/nfs/fs_context.c | 11 ++++++++++- fs/nfs/internal.h | 1 + fs/nfs/nfs4client.c | 2 ++ fs/nfs/super.c | 2 ++ include/linux/nfs_fs_sb.h | 1 + include/uapi/linux/nfs4_mount.h | 1 + include/uapi/linux/nfs_mount.h | 1 + 8 files changed, 21 insertions(+), 1 deletion(-) diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 330f65727c45..042677cd82f5 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -713,6 +713,8 @@ static int nfs_init_server(struct nfs_server *server, server->rsize = nfs_block_size(ctx->rsize, NULL); if (ctx->wsize) server->wsize = nfs_block_size(ctx->wsize, NULL); + if (ctx->rasize) + server->rasize = ctx->rasize; server->acregmin = ctx->acregmin * HZ; server->acregmax = ctx->acregmax * HZ; @@ -869,6 +871,7 @@ void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *sour { target->flags = source->flags; target->rsize = source->rsize; + target->rasize = source->rasize; target->wsize = source->wsize; target->acregmin = source->acregmin; target->acregmax = source->acregmax; diff --git a/fs/nfs/fs_context.c b/fs/nfs/fs_context.c index d95c9a39bc70..8dcf14864d22 100644 --- a/fs/nfs/fs_context.c +++ b/fs/nfs/fs_context.c @@ -65,6 +65,7 @@ enum nfs_param { Opt_proto, Opt_rdirplus, Opt_rdma, + Opt_rasize, Opt_resvport, Opt_retrans, Opt_retry, @@ -162,6 +163,7 @@ static const struct fs_parameter_spec nfs_fs_parameters[] = { fsparam_u32 ("port", Opt_port), fsparam_flag_no("posix", Opt_posix), fsparam_string("proto", Opt_proto), + fsparam_u32 ("rasize", Opt_rasize), fsparam_flag_no("rdirplus", Opt_rdirplus), fsparam_flag ("rdma", Opt_rdma), fsparam_flag_no("resvport", Opt_resvport), @@ -476,7 +478,6 @@ static int nfs_fs_context_parse_param(struct fs_context *fc, int ret, opt; dfprintk(MOUNT, "NFS: parsing nfs mount option '%s'\n", param->key); - opt = fs_parse(fc, nfs_fs_parameters, param, &result); if (opt < 0) return ctx->sloppy ? 1 : opt; @@ -824,6 +825,9 @@ static int nfs_fs_context_parse_param(struct fs_context *fc, goto out_invalid_value; } break; + case Opt_rasize: + ctx->rasize = result.uint_32; + break; /* * Special options @@ -1012,6 +1016,7 @@ static int nfs23_parse_monolithic(struct fs_context *fc, ctx->flags |= extra_flags; ctx->rsize = data->rsize; ctx->wsize = data->wsize; + ctx->rasize = data->rasize; ctx->timeo = data->timeo; ctx->retrans = data->retrans; ctx->acregmin = data->acregmin; @@ -1145,6 +1150,7 @@ struct compat_nfs4_mount_data_v1 { compat_int_t proto; compat_int_t auth_flavourlen; compat_uptr_t auth_flavours; + compat_int_t rasize; }; static void nfs4_compat_mount_data_conv(struct nfs4_mount_data *data) @@ -1169,6 +1175,7 @@ static void nfs4_compat_mount_data_conv(struct nfs4_mount_data *data) data->timeo = compat->timeo; data->wsize = compat->wsize; data->rsize = compat->rsize; + data->rasize = compat->rasize; data->flags = compat->flags; data->version = compat->version; } @@ -1247,6 +1254,7 @@ static int nfs4_parse_monolithic(struct fs_context *fc, ctx->flags = data->flags & NFS4_MOUNT_FLAGMASK; ctx->rsize = data->rsize; ctx->wsize = data->wsize; + ctx->rasize = data->rasize; ctx->timeo = data->timeo; ctx->retrans = data->retrans; ctx->acregmin = data->acregmin; @@ -1508,6 +1516,7 @@ static int nfs_init_fs_context(struct fs_context *fc) ctx->flags = nfss->flags; ctx->rsize = nfss->rsize; ctx->wsize = nfss->wsize; + ctx->rasize = nfss->rasize; ctx->retrans = nfss->client->cl_timeout->to_retries; ctx->selected_flavor = nfss->client->cl_auth->au_flavor; ctx->acregmin = nfss->acregmin / HZ; diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index a36af04188c2..975f49a03de6 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -97,6 +97,7 @@ struct nfs_fs_context { unsigned short protofamily; unsigned short mountfamily; bool has_sec_mnt_opts; + unsigned int rasize; struct { union { diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index 28431acd1230..f3cb9e9ff656 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c @@ -1130,6 +1130,8 @@ static int nfs4_init_server(struct nfs_server *server, struct fs_context *fc) server->rsize = nfs_block_size(ctx->rsize, NULL); if (ctx->wsize) server->wsize = nfs_block_size(ctx->wsize, NULL); + if (ctx->rasize) + server->rasize = ctx->rasize; server->acregmin = ctx->acregmin * HZ; server->acregmax = ctx->acregmax * HZ; diff --git a/fs/nfs/super.c b/fs/nfs/super.c index fe58525cfed4..df5d27931ee6 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -456,6 +456,7 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, seq_printf(m, ",wsize=%u", nfss->wsize); if (nfss->bsize != 0) seq_printf(m, ",bsize=%u", nfss->bsize); + seq_printf(m, ",rasize=%lu", nfss->super->s_bdi->ra_pages * PAGE_SIZE); seq_printf(m, ",namlen=%u", nfss->namelen); if (nfss->acregmin != NFS_DEF_ACREGMIN*HZ || showdefaults) seq_printf(m, ",acregmin=%u", nfss->acregmin/HZ); @@ -1281,6 +1282,7 @@ int nfs_get_tree_common(struct fs_context *fc) if (error) goto error_splat_super; s->s_bdi->io_pages = server->rpages; + s->s_bdi->ra_pages = server->rasize / PAGE_SIZE; server->super = s; } diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index d71a0e90faeb..fe7469ce81e1 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h @@ -162,6 +162,7 @@ struct nfs_server { unsigned int rpages; /* read size (in pages) */ unsigned int wsize; /* write size */ unsigned int wpages; /* write size (in pages) */ + unsigned int rasize; /* read ahead size */ unsigned int wtmult; /* server disk block size */ unsigned int dtsize; /* readdir size */ unsigned short port; /* "port=" setting */ diff --git a/include/uapi/linux/nfs4_mount.h b/include/uapi/linux/nfs4_mount.h index d20bb869bb99..f9799fdccf06 100644 --- a/include/uapi/linux/nfs4_mount.h +++ b/include/uapi/linux/nfs4_mount.h @@ -54,6 +54,7 @@ struct nfs4_mount_data { /* Pseudo-flavours to use for authentication. See RFC2623 */ int auth_flavourlen; /* 1 */ int __user *auth_flavours; /* 1 */ + int rasize; /* 1 */ }; /* bits in the flags field */ diff --git a/include/uapi/linux/nfs_mount.h b/include/uapi/linux/nfs_mount.h index e3bcfc6aa3b0..0a5f40e986cf 100644 --- a/include/uapi/linux/nfs_mount.h +++ b/include/uapi/linux/nfs_mount.h @@ -44,6 +44,7 @@ struct nfs_mount_data { struct nfs3_fh root; /* 4 */ int pseudoflavor; /* 5 */ char context[NFS_MAX_CONTEXT_LEN + 1]; /* 6 */ + int rasize; /* 1 */ }; /* bits in the flags field visible to user space */ -- 2.31.1