diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-06-26 10:48:57 -0700 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-06-26 10:48:57 -0700 | 
| commit | f7976a6493b3f00c4d057a37d9e63c322154ef8c (patch) | |
| tree | 0f295581c6993306c76a711807c82dda19dd2df4 /fs/nfsd/nfsctl.c | |
| parent | c0a572d9d32fe1e95672f24e860776dba0750a38 (diff) | |
| parent | 75bfb70457a4c4c9f0095e39885382fc5049c5ce (diff) | |
Merge tag 'nfsd-6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux
Pull nfsd updates from Chuck Lever:
 - Clean-ups in the READ path in anticipation of MSG_SPLICE_PAGES
 - Better NUMA awareness when allocating pages and other objects
 - A number of minor clean-ups to XDR encoding
 - Elimination of a race when accepting a TCP socket
 - Numerous observability enhancements
* tag 'nfsd-6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux: (46 commits)
  nfsd: remove redundant assignments to variable len
  svcrdma: Fix stale comment
  NFSD: Distinguish per-net namespace initialization
  nfsd: move init of percpu reply_cache_stats counters back to nfsd_init_net
  SUNRPC: Address RCU warning in net/sunrpc/svc.c
  SUNRPC: Use sysfs_emit in place of strlcpy/sprintf
  SUNRPC: Remove transport class dprintk call sites
  SUNRPC: Fix comments for transport class registration
  svcrdma: Remove an unused argument from __svc_rdma_put_rw_ctxt()
  svcrdma: trace cc_release calls
  svcrdma: Convert "might sleep" comment into a code annotation
  NFSD: Add an nfsd4_encode_nfstime4() helper
  SUNRPC: Move initialization of rq_stime
  SUNRPC: Optimize page release in svc_rdma_sendto()
  svcrdma: Prevent page release when nothing was received
  svcrdma: Revert 2a1e4f21d841 ("svcrdma: Normalize Send page handling")
  SUNRPC: Revert 579900670ac7 ("svcrdma: Remove unused sc_pages field")
  SUNRPC: Revert cc93ce9529a6 ("svcrdma: Retain the page backing rq_res.head[0].iov_base")
  NFSD: add encoding of op_recall flag for write delegation
  NFSD: Add "official" reviewers for this subsystem
  ...
Diffstat (limited to 'fs/nfsd/nfsctl.c')
| -rw-r--r-- | fs/nfsd/nfsctl.c | 116 | 
1 files changed, 78 insertions, 38 deletions
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index b4fd7a7062d5..1b8b1aab9a15 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -25,6 +25,7 @@  #include "netns.h"  #include "pnfs.h"  #include "filecache.h" +#include "trace.h"  /*   *	We have a single directory with several nodes in it. @@ -109,12 +110,12 @@ static ssize_t nfsctl_transaction_write(struct file *file, const char __user *bu  	if (IS_ERR(data))  		return PTR_ERR(data); -	rv =  write_op[ino](file, data, size); -	if (rv >= 0) { -		simple_transaction_set(file, rv); -		rv = size; -	} -	return rv; +	rv = write_op[ino](file, data, size); +	if (rv < 0) +		return rv; + +	simple_transaction_set(file, rv); +	return size;  }  static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos) @@ -230,6 +231,7 @@ static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size)  	if (rpc_pton(net, fo_path, size, sap, salen) == 0)  		return -EINVAL; +	trace_nfsd_ctl_unlock_ip(net, buf);  	return nlmsvc_unlock_all_by_ip(sap);  } @@ -263,7 +265,7 @@ static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size)  	fo_path = buf;  	if (qword_get(&buf, fo_path, size) < 0)  		return -EINVAL; - +	trace_nfsd_ctl_unlock_fs(netns(file), fo_path);  	error = kern_path(fo_path, 0, &path);  	if (error)  		return error; @@ -324,7 +326,7 @@ static ssize_t write_filehandle(struct file *file, char *buf, size_t size)  	len = qword_get(&mesg, dname, size);  	if (len <= 0)  		return -EINVAL; -	 +  	path = dname+len+1;  	len = qword_get(&mesg, path, size);  	if (len <= 0) @@ -338,15 +340,17 @@ static ssize_t write_filehandle(struct file *file, char *buf, size_t size)  		return -EINVAL;  	maxsize = min(maxsize, NFS3_FHSIZE); -	if (qword_get(&mesg, mesg, size)>0) +	if (qword_get(&mesg, mesg, size) > 0)  		return -EINVAL; +	trace_nfsd_ctl_filehandle(netns(file), dname, path, maxsize); +  	/* we have all the words, they are in buf.. */  	dom = unix_domain_find(dname);  	if (!dom)  		return -ENOMEM; -	len = exp_rootfh(netns(file), dom, path, &fh,  maxsize); +	len = exp_rootfh(netns(file), dom, path, &fh, maxsize);  	auth_domain_put(dom);  	if (len)  		return len; @@ -399,6 +403,7 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size)  			return rv;  		if (newthreads < 0)  			return -EINVAL; +		trace_nfsd_ctl_threads(net, newthreads);  		rv = nfsd_svc(newthreads, net, file->f_cred);  		if (rv < 0)  			return rv; @@ -418,8 +423,8 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size)   * OR   *   * Input: - * 			buf:		C string containing whitespace- - * 					separated unsigned integer values + *			buf:		C string containing whitespace- + *					separated unsigned integer values   *					representing the number of NFSD   *					threads to start in each pool   *			size:		non-zero length of C string in @buf @@ -471,6 +476,7 @@ static ssize_t write_pool_threads(struct file *file, char *buf, size_t size)  			rv = -EINVAL;  			if (nthreads[i] < 0)  				goto out_free; +			trace_nfsd_ctl_pool_threads(net, i, nthreads[i]);  		}  		rv = nfsd_set_nrthreads(i, nthreads, net);  		if (rv) @@ -526,7 +532,7 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size)  	char *sep;  	struct nfsd_net *nn = net_generic(netns(file), nfsd_net_id); -	if (size>0) { +	if (size > 0) {  		if (nn->nfsd_serv)  			/* Cannot change versions without updating  			 * nn->nfsd_serv->sv_xdrsize, and reallocing @@ -536,6 +542,7 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size)  		if (buf[size-1] != '\n')  			return -EINVAL;  		buf[size-1] = 0; +		trace_nfsd_ctl_version(netns(file), buf);  		vers = mesg;  		len = qword_get(&mesg, vers, size); @@ -637,11 +644,11 @@ out:   * OR   *   * Input: - * 			buf:		C string containing whitespace- - * 					separated positive or negative - * 					integer values representing NFS - * 					protocol versions to enable ("+n") - * 					or disable ("-n") + *			buf:		C string containing whitespace- + *					separated positive or negative + *					integer values representing NFS + *					protocol versions to enable ("+n") + *					or disable ("-n")   *			size:		non-zero length of C string in @buf   * Output:   *	On success:	status of zero or more protocol versions has @@ -689,6 +696,7 @@ static ssize_t __write_ports_addfd(char *buf, struct net *net, const struct cred  	err = get_int(&mesg, &fd);  	if (err != 0 || fd < 0)  		return -EINVAL; +	trace_nfsd_ctl_ports_addfd(net, fd);  	err = nfsd_create_serv(net);  	if (err != 0) @@ -705,7 +713,7 @@ static ssize_t __write_ports_addfd(char *buf, struct net *net, const struct cred  }  /* - * A transport listener is added by writing it's transport name and + * A transport listener is added by writing its transport name and   * a port number.   */  static ssize_t __write_ports_addxprt(char *buf, struct net *net, const struct cred *cred) @@ -720,6 +728,7 @@ static ssize_t __write_ports_addxprt(char *buf, struct net *net, const struct cr  	if (port < 1 || port > USHRT_MAX)  		return -EINVAL; +	trace_nfsd_ctl_ports_addxprt(net, transport, port);  	err = nfsd_create_serv(net);  	if (err != 0) @@ -832,9 +841,9 @@ int nfsd_max_blksize;   * OR   *   * Input: - * 			buf:		C string containing an unsigned - * 					integer value representing the new - * 					NFS blksize + *			buf:		C string containing an unsigned + *					integer value representing the new + *					NFS blksize   *			size:		non-zero length of C string in @buf   * Output:   *	On success:	passed-in buffer filled with '\n'-terminated C string @@ -853,6 +862,8 @@ static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)  		int rv = get_int(&mesg, &bsize);  		if (rv)  			return rv; +		trace_nfsd_ctl_maxblksize(netns(file), bsize); +  		/* force bsize into allowed range and  		 * required alignment.  		 */ @@ -881,9 +892,9 @@ static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)   * OR   *   * Input: - * 			buf:		C string containing an unsigned - * 					integer value representing the new - * 					number of max connections + *			buf:		C string containing an unsigned + *					integer value representing the new + *					number of max connections   *			size:		non-zero length of C string in @buf   * Output:   *	On success:	passed-in buffer filled with '\n'-terminated C string @@ -903,6 +914,7 @@ static ssize_t write_maxconn(struct file *file, char *buf, size_t size)  		if (rv)  			return rv; +		trace_nfsd_ctl_maxconn(netns(file), maxconn);  		nn->max_connections = maxconn;  	} @@ -913,6 +925,7 @@ static ssize_t write_maxconn(struct file *file, char *buf, size_t size)  static ssize_t __nfsd4_write_time(struct file *file, char *buf, size_t size,  				  time64_t *time, struct nfsd_net *nn)  { +	struct dentry *dentry = file_dentry(file);  	char *mesg = buf;  	int rv, i; @@ -922,6 +935,9 @@ static ssize_t __nfsd4_write_time(struct file *file, char *buf, size_t size,  		rv = get_int(&mesg, &i);  		if (rv)  			return rv; +		trace_nfsd_ctl_time(netns(file), dentry->d_name.name, +				    dentry->d_name.len, i); +  		/*  		 * Some sanity checking.  We don't have a reason for  		 * these particular numbers, but problems with the @@ -1014,6 +1030,7 @@ static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size,  		len = qword_get(&mesg, recdir, size);  		if (len <= 0)  			return -EINVAL; +		trace_nfsd_ctl_recoverydir(netns(file), recdir);  		status = nfs4_reset_recoverydir(recdir);  		if (status) @@ -1065,7 +1082,7 @@ static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)   * OR   *   * Input: - * 			buf:		any value + *			buf:		any value   *			size:		non-zero length of C string in @buf   * Output:   *			passed-in buffer filled with "Y" or "N" with a newline @@ -1087,7 +1104,7 @@ static ssize_t write_v4_end_grace(struct file *file, char *buf, size_t size)  		case '1':  			if (!nn->nfsd_serv)  				return -EBUSY; -			nfsd4_end_grace(nn); +			trace_nfsd_end_grace(netns(file));  			break;  		default:  			return -EINVAL; @@ -1192,8 +1209,8 @@ static int __nfsd_symlink(struct inode *dir, struct dentry *dentry,   * @content is assumed to be a NUL-terminated string that lives   * longer than the symlink itself.   */ -static void nfsd_symlink(struct dentry *parent, const char *name, -			 const char *content) +static void _nfsd_symlink(struct dentry *parent, const char *name, +			  const char *content)  {  	struct inode *dir = parent->d_inode;  	struct dentry *dentry; @@ -1210,8 +1227,8 @@ out:  	inode_unlock(dir);  }  #else -static inline void nfsd_symlink(struct dentry *parent, const char *name, -				const char *content) +static inline void _nfsd_symlink(struct dentry *parent, const char *name, +				 const char *content)  {  } @@ -1389,8 +1406,8 @@ static int nfsd_fill_super(struct super_block *sb, struct fs_context *fc)  	ret = simple_fill_super(sb, 0x6e667364, nfsd_files);  	if (ret)  		return ret; -	nfsd_symlink(sb->s_root, "supported_krb5_enctypes", -		     "/proc/net/rpc/gss_krb5_enctypes"); +	_nfsd_symlink(sb->s_root, "supported_krb5_enctypes", +		      "/proc/net/rpc/gss_krb5_enctypes");  	dentry = nfsd_mkdir(sb->s_root, NULL, "clients");  	if (IS_ERR(dentry))  		return PTR_ERR(dentry); @@ -1477,7 +1494,17 @@ static int create_proc_exports_entry(void)  unsigned int nfsd_net_id; -static __net_init int nfsd_init_net(struct net *net) +/** + * nfsd_net_init - Prepare the nfsd_net portion of a new net namespace + * @net: a freshly-created network namespace + * + * This information stays around as long as the network namespace is + * alive whether or not there is an NFSD instance running in the + * namespace. + * + * Returns zero on success, or a negative errno otherwise. + */ +static __net_init int nfsd_net_init(struct net *net)  {  	int retval;  	struct nfsd_net *nn = net_generic(net, nfsd_net_id); @@ -1488,6 +1515,9 @@ static __net_init int nfsd_init_net(struct net *net)  	retval = nfsd_idmap_init(net);  	if (retval)  		goto out_idmap_error; +	retval = nfsd_net_reply_cache_init(nn); +	if (retval) +		goto out_repcache_error;  	nn->nfsd_versions = NULL;  	nn->nfsd4_minorversions = NULL;  	nfsd4_init_leases_net(nn); @@ -1496,22 +1526,32 @@ static __net_init int nfsd_init_net(struct net *net)  	return 0; +out_repcache_error: +	nfsd_idmap_shutdown(net);  out_idmap_error:  	nfsd_export_shutdown(net);  out_export_error:  	return retval;  } -static __net_exit void nfsd_exit_net(struct net *net) +/** + * nfsd_net_exit - Release the nfsd_net portion of a net namespace + * @net: a network namespace that is about to be destroyed + * + */ +static __net_exit void nfsd_net_exit(struct net *net)  { +	struct nfsd_net *nn = net_generic(net, nfsd_net_id); + +	nfsd_net_reply_cache_destroy(nn);  	nfsd_idmap_shutdown(net);  	nfsd_export_shutdown(net); -	nfsd_netns_free_versions(net_generic(net, nfsd_net_id)); +	nfsd_netns_free_versions(nn);  }  static struct pernet_operations nfsd_net_ops = { -	.init = nfsd_init_net, -	.exit = nfsd_exit_net, +	.init = nfsd_net_init, +	.exit = nfsd_net_exit,  	.id   = &nfsd_net_id,  	.size = sizeof(struct nfsd_net),  };  | 
