The following commit has been merged in the master branch: commit 6860c981b9672324cb53b883cfda8d2ea1445ff1 Merge: 0570bc8b7c9b41deba6f61ac218922e7168ad648 d5b9216fd5114be4ed98ca9c1ecc5f164cd8cf5e Author: Linus Torvalds torvalds@linux-foundation.org Date: Thu Jul 18 14:32:33 2019 -0700
Merge tag 'nfs-for-5.3-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client updates from Trond Myklebust: "Highlights include:
Stable fixes:
- SUNRPC: Ensure bvecs are re-synced when we re-encode the RPC request
- Fix an Oops in ff_layout_track_ds_error due to a PTR_ERR() dereference
- Revert buggy NFS readdirplus optimisation
- NFSv4: Handle the special Linux file open access mode
- pnfs: Fix a problem where we gratuitously start doing I/O through the MDS
Features:
- Allow NFS client to set up multiple TCP connections to the server using a new 'nconnect=X' mount option. Queue length is used to balance load.
- Enhance statistics reporting to report on all transports when using multiple connections.
- Speed up SUNRPC by removing bh-safe spinlocks
- Add a mechanism to allow NFSv4 to request that containers set a unique per-host identifier for when the hostname is not set.
- Ensure NFSv4 updates the lease_time after a clientid update
Bugfixes and cleanup:
- Fix use-after-free in rpcrdma_post_recvs
- Fix a memory leak when nfs_match_client() is interrupted
- Fix buggy file access checking in NFSv4 open for execute
- disable unsupported client side deduplication
- Fix spurious client disconnections
- Fix occasional RDMA transport deadlock
- Various RDMA cleanups
- Various tracepoint fixes
- Fix the TCP callback channel to guarantee the server can actually send the number of callback requests that was negotiated at mount time"
* tag 'nfs-for-5.3-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (68 commits) pnfs/flexfiles: Add tracepoints for detecting pnfs fallback to MDS pnfs: Fix a problem where we gratuitously start doing I/O through the MDS SUNRPC: Optimise transport balancing code SUNRPC: Ensure the bvecs are reset when we re-encode the RPC request pnfs/flexfiles: Fix PTR_ERR() dereferences in ff_layout_track_ds_error NFSv4: Don't use the zero stateid with layoutget SUNRPC: Fix up backchannel slot table accounting SUNRPC: Fix initialisation of struct rpc_xprt_switch SUNRPC: Skip zero-refcount transports SUNRPC: Replace division by multiplication in calculation of queue length NFSv4: Validate the stateid before applying it to state recovery nfs4.0: Refetch lease_time after clientid update nfs4: Rename nfs41_setup_state_renewal nfs4: Make nfs4_proc_get_lease_time available for nfs4.0 nfs: Fix copy-and-paste error in debug message NFS: Replace 16 seq_printf() calls by seq_puts() NFS: Use seq_putc() in nfs_show_stats() Revert "NFS: readdirplus optimization by cache mechanism" (memleak) SUNRPC: Fix transport accounting when caller specifies an rpc_xprt NFS: Record task, client ID, and XID in xdr_status trace points ...
diff --combined fs/nfs/nfs4file.c index f4157eb1f69d,52dbd17e401e..96db471ca2e5 --- a/fs/nfs/nfs4file.c +++ b/fs/nfs/nfs4file.c @@@ -49,7 -49,7 +49,7 @@@ nfs4_file_open(struct inode *inode, str return err;
if ((openflags & O_ACCMODE) == 3) - openflags--; + return nfs_open(inode, filp);
/* We can't create new files here */ openflags &= ~(O_CREAT|O_EXCL); @@@ -129,13 -129,10 +129,13 @@@ nfs4_file_flush(struct file *file, fl_o }
#ifdef CONFIG_NFS_V4_2 -static ssize_t nfs4_copy_file_range(struct file *file_in, loff_t pos_in, - struct file *file_out, loff_t pos_out, - size_t count, unsigned int flags) +static ssize_t __nfs4_copy_file_range(struct file *file_in, loff_t pos_in, + struct file *file_out, loff_t pos_out, + size_t count, unsigned int flags) { + /* Only offload copy if superblock is the same */ + if (file_inode(file_in)->i_sb != file_inode(file_out)->i_sb) + return -EXDEV; if (!nfs_server_capable(file_inode(file_out), NFS_CAP_COPY)) return -EOPNOTSUPP; if (file_inode(file_in) == file_inode(file_out)) @@@ -143,20 -140,6 +143,20 @@@ return nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count); }
+static ssize_t nfs4_copy_file_range(struct file *file_in, loff_t pos_in, + struct file *file_out, loff_t pos_out, + size_t count, unsigned int flags) +{ + ssize_t ret; + + ret = __nfs4_copy_file_range(file_in, pos_in, file_out, pos_out, count, + flags); + if (ret == -EOPNOTSUPP || ret == -EXDEV) + ret = generic_copy_file_range(file_in, pos_in, file_out, + pos_out, count, flags); + return ret; +} + static loff_t nfs4_file_llseek(struct file *filep, loff_t offset, int whence) { loff_t ret; @@@ -204,7 -187,11 +204,11 @@@ static loff_t nfs42_remap_file_range(st bool same_inode = false; int ret;
- if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY)) + /* NFS does not support deduplication. */ + if (remap_flags & REMAP_FILE_DEDUP) + return -EOPNOTSUPP; + + if (remap_flags & ~REMAP_FILE_ADVISORY) return -EINVAL;
/* check alignment w.r.t. clone_blksize */ diff --combined net/sunrpc/debugfs.c index 707d7aab1546,105bea190a45..fd9bca242724 --- a/net/sunrpc/debugfs.c +++ b/net/sunrpc/debugfs.c @@@ -1,5 -1,5 +1,5 @@@ // SPDX-License-Identifier: GPL-2.0 - /** + /* * debugfs interface for sunrpc * * (c) 2014 Jeff Layton jlayton@primarydata.com @@@ -11,6 -11,7 +11,6 @@@ #include "netns.h"
static struct dentry *topdir; -static struct dentry *rpc_fault_dir; static struct dentry *rpc_clnt_dir; static struct dentry *rpc_xprt_dir;
@@@ -117,44 -118,64 +117,50 @@@ static const struct file_operations tas .release = tasks_release, };
+ static int do_xprt_debugfs(struct rpc_clnt *clnt, struct rpc_xprt *xprt, void *numv) + { + int len; + char name[24]; /* enough for "../../rpc_xprt/ + 8 hex digits + NULL */ + char link[9]; /* enough for 8 hex digits + NULL */ + int *nump = numv; + + if (IS_ERR_OR_NULL(xprt->debugfs)) + return 0; + len = snprintf(name, sizeof(name), "../../rpc_xprt/%s", + xprt->debugfs->d_name.name); + if (len > sizeof(name)) + return -1; + if (*nump == 0) + strcpy(link, "xprt"); + else { + len = snprintf(link, sizeof(link), "xprt%d", *nump); + if (len > sizeof(link)) + return -1; + } - if (!debugfs_create_symlink(link, clnt->cl_debugfs, name)) - return -1; ++ debugfs_create_symlink(link, clnt->cl_debugfs, name); + (*nump)++; + return 0; + } + void rpc_clnt_debugfs_register(struct rpc_clnt *clnt) { int len; - char name[24]; /* enough for "../../rpc_xprt/ + 8 hex digits + NULL */ - struct rpc_xprt *xprt; + char name[9]; /* enough for 8 hex digits + NULL */ + int xprtnum = 0;
- /* Already registered? */ - if (clnt->cl_debugfs || !rpc_clnt_dir) - return; - len = snprintf(name, sizeof(name), "%x", clnt->cl_clid); if (len >= sizeof(name)) return;
/* make the per-client dir */ clnt->cl_debugfs = debugfs_create_dir(name, rpc_clnt_dir); - if (!clnt->cl_debugfs) - return;
/* make tasks file */ - if (!debugfs_create_file("tasks", S_IFREG | 0400, clnt->cl_debugfs, - clnt, &tasks_fops)) - goto out_err; + debugfs_create_file("tasks", S_IFREG | 0400, clnt->cl_debugfs, clnt, + &tasks_fops);
- rcu_read_lock(); - xprt = rcu_dereference(clnt->cl_xprt); - /* no "debugfs" dentry? Don't bother with the symlink. */ - if (IS_ERR_OR_NULL(xprt->debugfs)) { - rcu_read_unlock(); - return; - } - len = snprintf(name, sizeof(name), "../../rpc_xprt/%s", - xprt->debugfs->d_name.name); - rcu_read_unlock(); - - if (len >= sizeof(name)) - if (rpc_clnt_iterate_for_each_xprt(clnt, do_xprt_debugfs, &xprtnum) < 0) -- goto out_err; - - debugfs_create_symlink("xprt", clnt->cl_debugfs, name); -- -- return; --out_err: -- debugfs_remove_recursive(clnt->cl_debugfs); -- clnt->cl_debugfs = NULL; ++ rpc_clnt_iterate_for_each_xprt(clnt, do_xprt_debugfs, &xprtnum); }
void @@@ -217,6 -238,9 +223,6 @@@ rpc_xprt_debugfs_register(struct rpc_xp static atomic_t cur_id; char name[9]; /* 8 hex digits + NULL term */
- if (!rpc_xprt_dir) - return; - id = (unsigned int)atomic_inc_return(&cur_id);
len = snprintf(name, sizeof(name), "%x", id); @@@ -225,10 -249,15 +231,10 @@@
/* make the per-client dir */ xprt->debugfs = debugfs_create_dir(name, rpc_xprt_dir); - if (!xprt->debugfs) - return;
/* make tasks file */ - if (!debugfs_create_file("info", S_IFREG | 0400, xprt->debugfs, - xprt, &xprt_info_fops)) { - debugfs_remove_recursive(xprt->debugfs); - xprt->debugfs = NULL; - } + debugfs_create_file("info", S_IFREG | 0400, xprt->debugfs, xprt, + &xprt_info_fops);
atomic_set(&xprt->inject_disconnect, rpc_inject_disconnect); } @@@ -291,11 -320,28 +297,11 @@@ static const struct file_operations fau .release = fault_release, };
-static struct dentry * -inject_fault_dir(struct dentry *topdir) -{ - struct dentry *faultdir; - - faultdir = debugfs_create_dir("inject_fault", topdir); - if (!faultdir) - return NULL; - - if (!debugfs_create_file("disconnect", S_IFREG | 0400, faultdir, - NULL, &fault_disconnect_fops)) - return NULL; - - return faultdir; -} - void __exit sunrpc_debugfs_exit(void) { debugfs_remove_recursive(topdir); topdir = NULL; - rpc_fault_dir = NULL; rpc_clnt_dir = NULL; rpc_xprt_dir = NULL; } @@@ -303,16 -349,26 +309,16 @@@ void __init sunrpc_debugfs_init(void) { - topdir = debugfs_create_dir("sunrpc", NULL); - if (!topdir) - return; + struct dentry *rpc_fault_dir;
- rpc_fault_dir = inject_fault_dir(topdir); - if (!rpc_fault_dir) - goto out_remove; + topdir = debugfs_create_dir("sunrpc", NULL);
rpc_clnt_dir = debugfs_create_dir("rpc_clnt", topdir); - if (!rpc_clnt_dir) - goto out_remove;
rpc_xprt_dir = debugfs_create_dir("rpc_xprt", topdir); - if (!rpc_xprt_dir) - goto out_remove;
- return; -out_remove: - debugfs_remove_recursive(topdir); - topdir = NULL; - rpc_fault_dir = NULL; - rpc_clnt_dir = NULL; + rpc_fault_dir = debugfs_create_dir("inject_fault", topdir); + + debugfs_create_file("disconnect", S_IFREG | 0400, rpc_fault_dir, NULL, + &fault_disconnect_fops); }
linux-merge@lists.open-mesh.org