Linux NFS development
 help / color / mirror / Atom feed
* [PATCH 0/1] Mount option - force READDIRPLUS
@ 2025-03-12 19:46 Benjamin Coddington
  2025-03-12 19:46 ` [PATCH 1/1] NFS: New mount option force_rdirplus Benjamin Coddington
  0 siblings, 1 reply; 6+ messages in thread
From: Benjamin Coddington @ 2025-03-12 19:46 UTC (permalink / raw)
  To: Trond Myklebust, Anna Schumaker; +Cc: linux-nfs

After these two changes:

1a34c8c9a49e NFS: Support larger readdir buffers
and
85aa8ddc3818 NFS: Trigger the "ls -l" readdir heuristic sooner

.. we've disadvantaged/regressed some users workloads where the user is
forced to use NFSv3 (such that we cannot prime the dcache with d_type on
READDIR as we do for NFSv4), and where the workload is a search through a
large directory tree.  Previously, the smaller buffers and/or the larger
heuristic size worked to their advantage to optimize the client toward the
READDIRPLUS path.

We've been able to relieve some pain temporarily by putting a knob into
sysfs to allow them to set the operation to one of:

	- force READDIRPLUS
	- disable READDIRPLUS
	- use the default heurstic

That's exactly the solution they're looking for and we have most of that in
mount options today with the "rdirplus" and "nordirplus".  Missing only is
the option to force the client to always use READDIR plus.  What follows is
a patch to do that with a new mount option.  I'll follow this up with a man
page update to nfs-utils.

The global heuristic is always going to be wrong for some workloads and we
cannnot depend on something like a mount-wide option to always work well for
mixed workloads on the same mount.  A realistic long-term solution involves
allowing the applications to signal their intended behavior.

So, I am going to look at plumbing in a posix_fadvise() flag for
READDIRPLUS.  There's been some interest expressed already for other
filesystems[1].  I plan to send along patches for this and face the
discussions.  However, that work will take some time to filter up into the
utilities and into distros.  In the meantime, I hope we can add this simpler
mount option to help the folks that need the old behaviors in recent
kernels.

[1]: https://lore.kernel.org/linux-fsdevel/CAOQ4uxhBWV3DfqaE=reuPjh8w92wwujA6Abj=Gt0YvapR4m_1g@mail.gmail.com/

Benjamin Coddington (1):
  NFS: New mount option force_rdirplus

 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(-)


base-commit: 2408a807bfc3f738850ef5ad5e3fd59d66168996
-- 
2.47.0


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/1] NFS: New mount option force_rdirplus
  2025-03-12 19:46 [PATCH 0/1] Mount option - force READDIRPLUS Benjamin Coddington
@ 2025-03-12 19:46 ` Benjamin Coddington
  2025-03-12 22:48   ` Trond Myklebust
  2025-03-13 14:20   ` kernel test robot
  0 siblings, 2 replies; 6+ messages in thread
From: Benjamin Coddington @ 2025-03-12 19:46 UTC (permalink / raw)
  To: Trond Myklebust, Anna Schumaker; +Cc: linux-nfs

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@redhat.com>
---
 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


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/1] NFS: New mount option force_rdirplus
  2025-03-12 19:46 ` [PATCH 1/1] NFS: New mount option force_rdirplus Benjamin Coddington
@ 2025-03-12 22:48   ` Trond Myklebust
  2025-03-12 22:57     ` Benjamin Coddington
  2025-03-13 14:20   ` kernel test robot
  1 sibling, 1 reply; 6+ messages in thread
From: Trond Myklebust @ 2025-03-12 22:48 UTC (permalink / raw)
  To: anna@kernel.org, bcodding@redhat.com; +Cc: linux-nfs@vger.kernel.org

On Wed, 2025-03-12 at 15:46 -0400, Benjamin Coddington wrote:
> 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.

Could we perhaps convert rdirplus to be a string with an optional
payload? Does the "fs_param_can_be_empty" flag allow you to convert
rdirplus into something that can behave as currently if you just
specify '-ordirplus', but that would allow you to specify '-
ordirplus=force' if you wanted to always use readdirplus?



-- 
Trond Myklebust
Linux NFS client maintainer, Hammerspace
trond.myklebust@hammerspace.com



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/1] NFS: New mount option force_rdirplus
  2025-03-12 22:48   ` Trond Myklebust
@ 2025-03-12 22:57     ` Benjamin Coddington
  2025-03-12 23:03       ` Trond Myklebust
  0 siblings, 1 reply; 6+ messages in thread
From: Benjamin Coddington @ 2025-03-12 22:57 UTC (permalink / raw)
  To: Trond Myklebust; +Cc: anna, linux-nfs

On 12 Mar 2025, at 18:48, Trond Myklebust wrote:

> On Wed, 2025-03-12 at 15:46 -0400, Benjamin Coddington wrote:
>> 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.
>
> Could we perhaps convert rdirplus to be a string with an optional
> payload? Does the "fs_param_can_be_empty" flag allow you to convert
> rdirplus into something that can behave as currently if you just
> specify '-ordirplus', but that would allow you to specify '-
> ordirplus=force' if you wanted to always use readdirplus?

Yes, I think that's possible.  I originally started down that route, but
abandoned it after it appeared to be a bigger code diff because you have to
re-define the nordirplus option which we get for free with fsparam_flag_no.

I can send a v2 that way if it's preferred.

Ben


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/1] NFS: New mount option force_rdirplus
  2025-03-12 22:57     ` Benjamin Coddington
@ 2025-03-12 23:03       ` Trond Myklebust
  0 siblings, 0 replies; 6+ messages in thread
From: Trond Myklebust @ 2025-03-12 23:03 UTC (permalink / raw)
  To: bcodding@redhat.com; +Cc: anna@kernel.org, linux-nfs@vger.kernel.org

On Wed, 2025-03-12 at 18:57 -0400, Benjamin Coddington wrote:
> On 12 Mar 2025, at 18:48, Trond Myklebust wrote:
> 
> > On Wed, 2025-03-12 at 15:46 -0400, Benjamin Coddington wrote:
> > > 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.
> > 
> > Could we perhaps convert rdirplus to be a string with an optional
> > payload? Does the "fs_param_can_be_empty" flag allow you to convert
> > rdirplus into something that can behave as currently if you just
> > specify '-ordirplus', but that would allow you to specify '-
> > ordirplus=force' if you wanted to always use readdirplus?
> 
> Yes, I think that's possible.  I originally started down that route,
> but
> abandoned it after it appeared to be a bigger code diff because you
> have to
> re-define the nordirplus option which we get for free with
> fsparam_flag_no.
> 
> I can send a v2 that way if it's preferred.

To me that seems tidier, and easier to remember. It also allows you to
alias nordirplus as a 'rdirplus=none' option, should that be desirable.

-- 
Trond Myklebust
Linux NFS client maintainer, Hammerspace
trond.myklebust@hammerspace.com



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/1] NFS: New mount option force_rdirplus
  2025-03-12 19:46 ` [PATCH 1/1] NFS: New mount option force_rdirplus Benjamin Coddington
  2025-03-12 22:48   ` Trond Myklebust
@ 2025-03-13 14:20   ` kernel test robot
  1 sibling, 0 replies; 6+ messages in thread
From: kernel test robot @ 2025-03-13 14:20 UTC (permalink / raw)
  To: Benjamin Coddington, Trond Myklebust, Anna Schumaker
  Cc: llvm, oe-kbuild-all, linux-nfs

Hi Benjamin,

kernel test robot noticed the following build warnings:

[auto build test WARNING on 2408a807bfc3f738850ef5ad5e3fd59d66168996]

url:    https://github.com/intel-lab-lkp/linux/commits/Benjamin-Coddington/NFS-New-mount-option-force_rdirplus/20250313-034816
base:   2408a807bfc3f738850ef5ad5e3fd59d66168996
patch link:    https://lore.kernel.org/r/4a471ab1bdea1052f45d894c967d0a6b6e38d4a6.1741806879.git.bcodding%40redhat.com
patch subject: [PATCH 1/1] NFS: New mount option force_rdirplus
config: i386-randconfig-003-20250313 (https://download.01.org/0day-ci/archive/20250313/202503132212.aPAVQklX-lkp@intel.com/config)
compiler: clang version 19.1.7 (https://github.com/llvm/llvm-project cd708029e0b2869e80abe31ddb175f7c35361f90)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250313/202503132212.aPAVQklX-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503132212.aPAVQklX-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> fs/nfs/fs_context.c:642:19: warning: use of logical '&&' with constant operand [-Wconstant-logical-operand]
     642 |                         if (ctx->flags && NFS_MOUNT_FORCE_RDIRPLUS)
         |                                        ^  ~~~~~~~~~~~~~~~~~~~~~~~~
   fs/nfs/fs_context.c:642:19: note: use '&' for a bitwise operation
     642 |                         if (ctx->flags && NFS_MOUNT_FORCE_RDIRPLUS)
         |                                        ^~
         |                                        &
   fs/nfs/fs_context.c:642:19: note: remove constant to silence this warning
     642 |                         if (ctx->flags && NFS_MOUNT_FORCE_RDIRPLUS)
         |                                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~
   fs/nfs/fs_context.c:650:18: warning: use of logical '&&' with constant operand [-Wconstant-logical-operand]
     650 |                 if (ctx->flags && NFS_MOUNT_NORDIRPLUS)
         |                                ^  ~~~~~~~~~~~~~~~~~~~~
   fs/nfs/fs_context.c:650:18: note: use '&' for a bitwise operation
     650 |                 if (ctx->flags && NFS_MOUNT_NORDIRPLUS)
         |                                ^~
         |                                &
   fs/nfs/fs_context.c:650:18: note: remove constant to silence this warning
     650 |                 if (ctx->flags && NFS_MOUNT_NORDIRPLUS)
         |                                ^~~~~~~~~~~~~~~~~~~~~~~
   2 warnings generated.
--
>> fs/nfs/dir.c:669:29: warning: use of logical '&&' with constant operand [-Wconstant-logical-operand]
     669 |         if (NFS_SERVER(dir)->flags && NFS_MOUNT_FORCE_RDIRPLUS)
         |                                    ^  ~~~~~~~~~~~~~~~~~~~~~~~~
   fs/nfs/dir.c:669:29: note: use '&' for a bitwise operation
     669 |         if (NFS_SERVER(dir)->flags && NFS_MOUNT_FORCE_RDIRPLUS)
         |                                    ^~
         |                                    &
   fs/nfs/dir.c:669:29: note: remove constant to silence this warning
     669 |         if (NFS_SERVER(dir)->flags && NFS_MOUNT_FORCE_RDIRPLUS)
         |                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~
   1 warning generated.


vim +642 fs/nfs/fs_context.c

   529	
   530	/*
   531	 * Parse a single mount parameter.
   532	 */
   533	static int nfs_fs_context_parse_param(struct fs_context *fc,
   534					      struct fs_parameter *param)
   535	{
   536		struct fs_parse_result result;
   537		struct nfs_fs_context *ctx = nfs_fc2context(fc);
   538		unsigned short protofamily, mountfamily;
   539		unsigned int len;
   540		int ret, opt;
   541	
   542		trace_nfs_mount_option(param);
   543	
   544		opt = fs_parse(fc, nfs_fs_parameters, param, &result);
   545		if (opt < 0)
   546			return (opt == -ENOPARAM && ctx->sloppy) ? 1 : opt;
   547	
   548		if (fc->security)
   549			ctx->has_sec_mnt_opts = 1;
   550	
   551		switch (opt) {
   552		case Opt_source:
   553			if (fc->source)
   554				return nfs_invalf(fc, "NFS: Multiple sources not supported");
   555			fc->source = param->string;
   556			param->string = NULL;
   557			break;
   558	
   559			/*
   560			 * boolean options:  foo/nofoo
   561			 */
   562		case Opt_soft:
   563			ctx->flags |= NFS_MOUNT_SOFT;
   564			ctx->flags &= ~NFS_MOUNT_SOFTERR;
   565			break;
   566		case Opt_softerr:
   567			ctx->flags |= NFS_MOUNT_SOFTERR | NFS_MOUNT_SOFTREVAL;
   568			ctx->flags &= ~NFS_MOUNT_SOFT;
   569			break;
   570		case Opt_hard:
   571			ctx->flags &= ~(NFS_MOUNT_SOFT |
   572					NFS_MOUNT_SOFTERR |
   573					NFS_MOUNT_SOFTREVAL);
   574			break;
   575		case Opt_softreval:
   576			if (result.negated)
   577				ctx->flags &= ~NFS_MOUNT_SOFTREVAL;
   578			else
   579				ctx->flags |= NFS_MOUNT_SOFTREVAL;
   580			break;
   581		case Opt_posix:
   582			if (result.negated)
   583				ctx->flags &= ~NFS_MOUNT_POSIX;
   584			else
   585				ctx->flags |= NFS_MOUNT_POSIX;
   586			break;
   587		case Opt_cto:
   588			if (result.negated)
   589				ctx->flags |= NFS_MOUNT_NOCTO;
   590			else
   591				ctx->flags &= ~NFS_MOUNT_NOCTO;
   592			break;
   593		case Opt_trunkdiscovery:
   594			if (result.negated)
   595				ctx->flags &= ~NFS_MOUNT_TRUNK_DISCOVERY;
   596			else
   597				ctx->flags |= NFS_MOUNT_TRUNK_DISCOVERY;
   598			break;
   599		case Opt_alignwrite:
   600			if (result.negated)
   601				ctx->flags |= NFS_MOUNT_NO_ALIGNWRITE;
   602			else
   603				ctx->flags &= ~NFS_MOUNT_NO_ALIGNWRITE;
   604			break;
   605		case Opt_ac:
   606			if (result.negated)
   607				ctx->flags |= NFS_MOUNT_NOAC;
   608			else
   609				ctx->flags &= ~NFS_MOUNT_NOAC;
   610			break;
   611		case Opt_lock:
   612			if (result.negated) {
   613				ctx->lock_status = NFS_LOCK_NOLOCK;
   614				ctx->flags |= NFS_MOUNT_NONLM;
   615				ctx->flags |= (NFS_MOUNT_LOCAL_FLOCK | NFS_MOUNT_LOCAL_FCNTL);
   616			} else {
   617				ctx->lock_status = NFS_LOCK_LOCK;
   618				ctx->flags &= ~NFS_MOUNT_NONLM;
   619				ctx->flags &= ~(NFS_MOUNT_LOCAL_FLOCK | NFS_MOUNT_LOCAL_FCNTL);
   620			}
   621			break;
   622		case Opt_udp:
   623			ctx->flags &= ~NFS_MOUNT_TCP;
   624			ctx->nfs_server.protocol = XPRT_TRANSPORT_UDP;
   625			break;
   626		case Opt_tcp:
   627		case Opt_rdma:
   628			ctx->flags |= NFS_MOUNT_TCP; /* for side protocols */
   629			ret = xprt_find_transport_ident(param->key);
   630			if (ret < 0)
   631				goto out_bad_transport;
   632			ctx->nfs_server.protocol = ret;
   633			break;
   634		case Opt_acl:
   635			if (result.negated)
   636				ctx->flags |= NFS_MOUNT_NOACL;
   637			else
   638				ctx->flags &= ~NFS_MOUNT_NOACL;
   639			break;
   640		case Opt_rdirplus:
   641			if (result.negated) {
 > 642				if (ctx->flags && NFS_MOUNT_FORCE_RDIRPLUS)
   643					return nfs_invalf(fc, "NFS: Cannot both force and disable READDIR PLUS");
   644				ctx->flags |= NFS_MOUNT_NORDIRPLUS;
   645			} else {
   646				ctx->flags &= ~NFS_MOUNT_NORDIRPLUS;
   647			}
   648			break;
   649		case Opt_force_rdirplus:
   650			if (ctx->flags && NFS_MOUNT_NORDIRPLUS)
   651				return nfs_invalf(fc, "NFS: Cannot both force and disable READDIR PLUS");
   652			ctx->flags |= NFS_MOUNT_FORCE_RDIRPLUS;
   653			break;
   654		case Opt_sharecache:
   655			if (result.negated)
   656				ctx->flags |= NFS_MOUNT_UNSHARED;
   657			else
   658				ctx->flags &= ~NFS_MOUNT_UNSHARED;
   659			break;
   660		case Opt_resvport:
   661			if (result.negated)
   662				ctx->flags |= NFS_MOUNT_NORESVPORT;
   663			else
   664				ctx->flags &= ~NFS_MOUNT_NORESVPORT;
   665			break;
   666		case Opt_fscache_flag:
   667			if (result.negated)
   668				ctx->options &= ~NFS_OPTION_FSCACHE;
   669			else
   670				ctx->options |= NFS_OPTION_FSCACHE;
   671			kfree(ctx->fscache_uniq);
   672			ctx->fscache_uniq = NULL;
   673			break;
   674		case Opt_fscache:
   675			trace_nfs_mount_assign(param->key, param->string);
   676			ctx->options |= NFS_OPTION_FSCACHE;
   677			kfree(ctx->fscache_uniq);
   678			ctx->fscache_uniq = param->string;
   679			param->string = NULL;
   680			break;
   681		case Opt_migration:
   682			if (result.negated)
   683				ctx->options &= ~NFS_OPTION_MIGRATION;
   684			else
   685				ctx->options |= NFS_OPTION_MIGRATION;
   686			break;
   687	
   688			/*
   689			 * options that take numeric values
   690			 */
   691		case Opt_port:
   692			if (result.uint_32 > USHRT_MAX)
   693				goto out_of_bounds;
   694			ctx->nfs_server.port = result.uint_32;
   695			break;
   696		case Opt_rsize:
   697			ctx->rsize = result.uint_32;
   698			break;
   699		case Opt_wsize:
   700			ctx->wsize = result.uint_32;
   701			break;
   702		case Opt_bsize:
   703			ctx->bsize = result.uint_32;
   704			break;
   705		case Opt_timeo:
   706			if (result.uint_32 < 1 || result.uint_32 > INT_MAX)
   707				goto out_of_bounds;
   708			ctx->timeo = result.uint_32;
   709			break;
   710		case Opt_retrans:
   711			if (result.uint_32 > INT_MAX)
   712				goto out_of_bounds;
   713			ctx->retrans = result.uint_32;
   714			break;
   715		case Opt_acregmin:
   716			ctx->acregmin = result.uint_32;
   717			break;
   718		case Opt_acregmax:
   719			ctx->acregmax = result.uint_32;
   720			break;
   721		case Opt_acdirmin:
   722			ctx->acdirmin = result.uint_32;
   723			break;
   724		case Opt_acdirmax:
   725			ctx->acdirmax = result.uint_32;
   726			break;
   727		case Opt_actimeo:
   728			ctx->acregmin = result.uint_32;
   729			ctx->acregmax = result.uint_32;
   730			ctx->acdirmin = result.uint_32;
   731			ctx->acdirmax = result.uint_32;
   732			break;
   733		case Opt_namelen:
   734			ctx->namlen = result.uint_32;
   735			break;
   736		case Opt_mountport:
   737			if (result.uint_32 > USHRT_MAX)
   738				goto out_of_bounds;
   739			ctx->mount_server.port = result.uint_32;
   740			break;
   741		case Opt_mountvers:
   742			if (result.uint_32 < NFS_MNT_VERSION ||
   743			    result.uint_32 > NFS_MNT3_VERSION)
   744				goto out_of_bounds;
   745			ctx->mount_server.version = result.uint_32;
   746			break;
   747		case Opt_minorversion:
   748			if (result.uint_32 > NFS4_MAX_MINOR_VERSION)
   749				goto out_of_bounds;
   750			ctx->minorversion = result.uint_32;
   751			break;
   752	
   753			/*
   754			 * options that take text values
   755			 */
   756		case Opt_v:
   757			ret = nfs_parse_version_string(fc, param->key + 1);
   758			if (ret < 0)
   759				return ret;
   760			break;
   761		case Opt_vers:
   762			if (!param->string)
   763				goto out_invalid_value;
   764			trace_nfs_mount_assign(param->key, param->string);
   765			ret = nfs_parse_version_string(fc, param->string);
   766			if (ret < 0)
   767				return ret;
   768			break;
   769		case Opt_sec:
   770			ret = nfs_parse_security_flavors(fc, param);
   771			if (ret < 0)
   772				return ret;
   773			break;
   774		case Opt_xprtsec:
   775			ret = nfs_parse_xprtsec_policy(fc, param);
   776			if (ret < 0)
   777				return ret;
   778			break;
   779	
   780		case Opt_proto:
   781			if (!param->string)
   782				goto out_invalid_value;
   783			trace_nfs_mount_assign(param->key, param->string);
   784			protofamily = AF_INET;
   785			switch (lookup_constant(nfs_xprt_protocol_tokens, param->string, -1)) {
   786			case Opt_xprt_udp6:
   787				protofamily = AF_INET6;
   788				fallthrough;
   789			case Opt_xprt_udp:
   790				ctx->flags &= ~NFS_MOUNT_TCP;
   791				ctx->nfs_server.protocol = XPRT_TRANSPORT_UDP;
   792				break;
   793			case Opt_xprt_tcp6:
   794				protofamily = AF_INET6;
   795				fallthrough;
   796			case Opt_xprt_tcp:
   797				ctx->flags |= NFS_MOUNT_TCP;
   798				ctx->nfs_server.protocol = XPRT_TRANSPORT_TCP;
   799				break;
   800			case Opt_xprt_rdma6:
   801				protofamily = AF_INET6;
   802				fallthrough;
   803			case Opt_xprt_rdma:
   804				/* vector side protocols to TCP */
   805				ctx->flags |= NFS_MOUNT_TCP;
   806				ret = xprt_find_transport_ident(param->string);
   807				if (ret < 0)
   808					goto out_bad_transport;
   809				ctx->nfs_server.protocol = ret;
   810				break;
   811			default:
   812				goto out_bad_transport;
   813			}
   814	
   815			ctx->protofamily = protofamily;
   816			break;
   817	
   818		case Opt_mountproto:
   819			if (!param->string)
   820				goto out_invalid_value;
   821			trace_nfs_mount_assign(param->key, param->string);
   822			mountfamily = AF_INET;
   823			switch (lookup_constant(nfs_xprt_protocol_tokens, param->string, -1)) {
   824			case Opt_xprt_udp6:
   825				mountfamily = AF_INET6;
   826				fallthrough;
   827			case Opt_xprt_udp:
   828				ctx->mount_server.protocol = XPRT_TRANSPORT_UDP;
   829				break;
   830			case Opt_xprt_tcp6:
   831				mountfamily = AF_INET6;
   832				fallthrough;
   833			case Opt_xprt_tcp:
   834				ctx->mount_server.protocol = XPRT_TRANSPORT_TCP;
   835				break;
   836			case Opt_xprt_rdma: /* not used for side protocols */
   837			default:
   838				goto out_bad_transport;
   839			}
   840			ctx->mountfamily = mountfamily;
   841			break;
   842	
   843		case Opt_addr:
   844			trace_nfs_mount_assign(param->key, param->string);
   845			len = rpc_pton(fc->net_ns, param->string, param->size,
   846				       &ctx->nfs_server.address,
   847				       sizeof(ctx->nfs_server._address));
   848			if (len == 0)
   849				goto out_invalid_address;
   850			ctx->nfs_server.addrlen = len;
   851			break;
   852		case Opt_clientaddr:
   853			trace_nfs_mount_assign(param->key, param->string);
   854			kfree(ctx->client_address);
   855			ctx->client_address = param->string;
   856			param->string = NULL;
   857			break;
   858		case Opt_mounthost:
   859			trace_nfs_mount_assign(param->key, param->string);
   860			kfree(ctx->mount_server.hostname);
   861			ctx->mount_server.hostname = param->string;
   862			param->string = NULL;
   863			break;
   864		case Opt_mountaddr:
   865			trace_nfs_mount_assign(param->key, param->string);
   866			len = rpc_pton(fc->net_ns, param->string, param->size,
   867				       &ctx->mount_server.address,
   868				       sizeof(ctx->mount_server._address));
   869			if (len == 0)
   870				goto out_invalid_address;
   871			ctx->mount_server.addrlen = len;
   872			break;
   873		case Opt_nconnect:
   874			trace_nfs_mount_assign(param->key, param->string);
   875			if (result.uint_32 < 1 || result.uint_32 > NFS_MAX_CONNECTIONS)
   876				goto out_of_bounds;
   877			ctx->nfs_server.nconnect = result.uint_32;
   878			break;
   879		case Opt_max_connect:
   880			trace_nfs_mount_assign(param->key, param->string);
   881			if (result.uint_32 < 1 || result.uint_32 > NFS_MAX_TRANSPORTS)
   882				goto out_of_bounds;
   883			ctx->nfs_server.max_connect = result.uint_32;
   884			break;
   885		case Opt_lookupcache:
   886			trace_nfs_mount_assign(param->key, param->string);
   887			switch (result.uint_32) {
   888			case Opt_lookupcache_all:
   889				ctx->flags &= ~(NFS_MOUNT_LOOKUP_CACHE_NONEG|NFS_MOUNT_LOOKUP_CACHE_NONE);
   890				break;
   891			case Opt_lookupcache_positive:
   892				ctx->flags &= ~NFS_MOUNT_LOOKUP_CACHE_NONE;
   893				ctx->flags |= NFS_MOUNT_LOOKUP_CACHE_NONEG;
   894				break;
   895			case Opt_lookupcache_none:
   896				ctx->flags |= NFS_MOUNT_LOOKUP_CACHE_NONEG|NFS_MOUNT_LOOKUP_CACHE_NONE;
   897				break;
   898			default:
   899				goto out_invalid_value;
   900			}
   901			break;
   902		case Opt_local_lock:
   903			trace_nfs_mount_assign(param->key, param->string);
   904			switch (result.uint_32) {
   905			case Opt_local_lock_all:
   906				ctx->flags |= (NFS_MOUNT_LOCAL_FLOCK |
   907					       NFS_MOUNT_LOCAL_FCNTL);
   908				break;
   909			case Opt_local_lock_flock:
   910				ctx->flags |= NFS_MOUNT_LOCAL_FLOCK;
   911				break;
   912			case Opt_local_lock_posix:
   913				ctx->flags |= NFS_MOUNT_LOCAL_FCNTL;
   914				break;
   915			case Opt_local_lock_none:
   916				ctx->flags &= ~(NFS_MOUNT_LOCAL_FLOCK |
   917						NFS_MOUNT_LOCAL_FCNTL);
   918				break;
   919			default:
   920				goto out_invalid_value;
   921			}
   922			break;
   923		case Opt_write:
   924			trace_nfs_mount_assign(param->key, param->string);
   925			switch (result.uint_32) {
   926			case Opt_write_lazy:
   927				ctx->flags &=
   928					~(NFS_MOUNT_WRITE_EAGER | NFS_MOUNT_WRITE_WAIT);
   929				break;
   930			case Opt_write_eager:
   931				ctx->flags |= NFS_MOUNT_WRITE_EAGER;
   932				ctx->flags &= ~NFS_MOUNT_WRITE_WAIT;
   933				break;
   934			case Opt_write_wait:
   935				ctx->flags |=
   936					NFS_MOUNT_WRITE_EAGER | NFS_MOUNT_WRITE_WAIT;
   937				break;
   938			default:
   939				goto out_invalid_value;
   940			}
   941			break;
   942	
   943			/*
   944			 * Special options
   945			 */
   946		case Opt_sloppy:
   947			ctx->sloppy = true;
   948			break;
   949		}
   950	
   951		return 0;
   952	
   953	out_invalid_value:
   954		return nfs_invalf(fc, "NFS: Bad mount option value specified");
   955	out_invalid_address:
   956		return nfs_invalf(fc, "NFS: Bad IP address specified");
   957	out_of_bounds:
   958		return nfs_invalf(fc, "NFS: Value for '%s' out of range", param->key);
   959	out_bad_transport:
   960		return nfs_invalf(fc, "NFS: Unrecognized transport protocol");
   961	}
   962	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2025-03-13 14:21 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-12 19:46 [PATCH 0/1] Mount option - force READDIRPLUS Benjamin Coddington
2025-03-12 19:46 ` [PATCH 1/1] NFS: New mount option force_rdirplus Benjamin Coddington
2025-03-12 22:48   ` Trond Myklebust
2025-03-12 22:57     ` Benjamin Coddington
2025-03-12 23:03       ` Trond Myklebust
2025-03-13 14:20   ` kernel test robot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox