mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 04:18:39 +08:00
NFS client updates for Linux 6.9
Highlights include: Bugfixes: - Fix for an Oops in the NFSv4.2 listxattr handler - Correct an incorrect buffer size in listxattr - Fix for an Oops in the pNFS flexfiles layout - Fix a refcount leak in NFS O_DIRECT writes - Fix missing locking in NFS O_DIRECT - Avoid an infinite loop in pnfs_update_layout - Fix an overflow in the RPC waitqueue queue length counter - Ensure that pNFS I/O is also protected by TLS when xprtsec is specified by the mount options - Fix a leaked folio lock in the netfs read code - Fix a potential deadlock in fscache - Allow setting the fscache uniquifier in NFSv4 - Fix an off by one in root_nfs_cat() - Fix another off by one in rpc_sockaddr2uaddr() - nfs4_do_open() can incorrectly trigger state recovery. - Various fixes for connection shutdown Features and cleanups: - Ensure that containers only see their own RPC and NFS stats - Enable nconnect for RDMA - Remove dead code from nfs_writepage_locked() - Various tracepoint additions to track EXCHANGE_ID, GETDEVICEINFO, and mount options. -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEESQctxSBg8JpV8KqEZwvnipYKAPIFAmX14K0ACgkQZwvnipYK APLCeg/7Bdah7158TdNxSQAHPo3jzDqZmc933eZC0H8C9whNlu6XIa9fyT6ZrsQr qkQ/ztSwsB6yp6vLPSnVdDh5KsndwrInTB874H8y6+8x+KwwuhSQ7Uy8epg5wrO0 kgiaRYSH7HB7EgUdNY14fHNXkA/DMLHz1F1aw2NVGCYmVCMg7kGV4wYCOH6bI2Ea Wu8amZce6D1AbktbdSZcEz2ricR3lGXjCUPMnzRCaSpUmdd2t7d/rsnjTeKU1gb4 p9zLlOZs9Xe2vMT0ZQI8SEI+Scze82LBy7ykSKyhOjOt4AurVpzQFAvK+3dFZoIq lzIHJwabBGNui26CR1k90ZqERLkkk+24i3ccT28HwhTqe5eM/qDCKOVQmuP0F1F8 QYsnIM+NnmPZveSGAMdOQwlGFQTyJbT5Na1blHTW2R2rjqBzgvfn8fR0vV4L5P7B 0J8ShmZKVkvb7mtJJhaaI4LF41ciCF8+I5zwpnYQi0tsX370XPNNFbzS3BmPUVFL k0uEMVfNy69PkaH4DJWQT9GoE3qiAamkO+EdAlPad6b8QMdJJZxXOmaUzL8YsCHV sX5ugsih/Hf5/+QFBCbHEy7G3oeeHsT80yO8nvGT+yy94bv4F+WcM/tviyRbKrls t5audBDNRfrAeUlqAQkXfFmAyqP2CGNr29oL62cXL2muFG7d7ys= =5n+X -----END PGP SIGNATURE----- Merge tag 'nfs-for-6.9-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs Pull NFS client updates from Trond Myklebust: "Highlights include: Bugfixes: - Fix for an Oops in the NFSv4.2 listxattr handler - Correct an incorrect buffer size in listxattr - Fix for an Oops in the pNFS flexfiles layout - Fix a refcount leak in NFS O_DIRECT writes - Fix missing locking in NFS O_DIRECT - Avoid an infinite loop in pnfs_update_layout - Fix an overflow in the RPC waitqueue queue length counter - Ensure that pNFS I/O is also protected by TLS when xprtsec is specified by the mount options - Fix a leaked folio lock in the netfs read code - Fix a potential deadlock in fscache - Allow setting the fscache uniquifier in NFSv4 - Fix an off by one in root_nfs_cat() - Fix another off by one in rpc_sockaddr2uaddr() - nfs4_do_open() can incorrectly trigger state recovery - Various fixes for connection shutdown Features and cleanups: - Ensure that containers only see their own RPC and NFS stats - Enable nconnect for RDMA - Remove dead code from nfs_writepage_locked() - Various tracepoint additions to track EXCHANGE_ID, GETDEVICEINFO, and mount options" * tag 'nfs-for-6.9-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (29 commits) nfs: fix panic when nfs4_ff_layout_prepare_ds() fails NFS: trace the uniquifier of fscache NFS: Read unlock folio on nfs_page_create_from_folio() error NFS: remove unused variable nfs_rpcstat nfs: fix UAF in direct writes nfs: properly protect nfs_direct_req fields NFS: enable nconnect for RDMA NFSv4: nfs4_do_open() is incorrectly triggering state recovery NFS: avoid infinite loop in pnfs_update_layout. NFS: remove sync_mode test from nfs_writepage_locked() NFSv4.1/pnfs: fix NFS with TLS in pnfs NFS: Fix an off by one in root_nfs_cat() nfs: make the rpc_stat per net namespace nfs: expose /proc/net/sunrpc/nfs in net namespaces sunrpc: add a struct rpc_stats arg to rpc_create_args nfs: remove unused NFS_CALL macro NFSv4.1: add tracepoint to trunked nfs4_exchange_id calls NFS: Fix nfs_netfs_issue_read() xarray locking for writeback interrupt SUNRPC: increase size of rpc_wait_queue.qlen from unsigned short to unsigned int nfs: fix regression in handling of fsc= option in NFSv4 ...
This commit is contained in:
commit
c1f10ac840
@ -73,14 +73,9 @@ const struct rpc_program nfs_program = {
|
||||
.number = NFS_PROGRAM,
|
||||
.nrvers = ARRAY_SIZE(nfs_version),
|
||||
.version = nfs_version,
|
||||
.stats = &nfs_rpcstat,
|
||||
.pipe_dir_name = NFS_PIPE_DIRNAME,
|
||||
};
|
||||
|
||||
struct rpc_stat nfs_rpcstat = {
|
||||
.program = &nfs_program
|
||||
};
|
||||
|
||||
static struct nfs_subversion *find_nfs_version(unsigned int version)
|
||||
{
|
||||
struct nfs_subversion *nfs;
|
||||
@ -502,6 +497,7 @@ int nfs_create_rpc_client(struct nfs_client *clp,
|
||||
const struct nfs_client_initdata *cl_init,
|
||||
rpc_authflavor_t flavor)
|
||||
{
|
||||
struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id);
|
||||
struct rpc_clnt *clnt = NULL;
|
||||
struct rpc_create_args args = {
|
||||
.net = clp->cl_net,
|
||||
@ -513,6 +509,7 @@ int nfs_create_rpc_client(struct nfs_client *clp,
|
||||
.servername = clp->cl_hostname,
|
||||
.nodename = cl_init->nodename,
|
||||
.program = &nfs_program,
|
||||
.stats = &nn->rpcstats,
|
||||
.version = clp->rpc_ops->version,
|
||||
.authflavor = flavor,
|
||||
.cred = cl_init->cred,
|
||||
@ -1182,6 +1179,8 @@ void nfs_clients_init(struct net *net)
|
||||
#endif
|
||||
spin_lock_init(&nn->nfs_client_lock);
|
||||
nn->boot_time = ktime_get_real();
|
||||
memset(&nn->rpcstats, 0, sizeof(nn->rpcstats));
|
||||
nn->rpcstats.program = &nfs_program;
|
||||
|
||||
nfs_netns_sysfs_setup(nn, net);
|
||||
}
|
||||
|
@ -181,7 +181,6 @@ static int nfs_delegation_claim_opens(struct inode *inode,
|
||||
struct nfs_open_context *ctx;
|
||||
struct nfs4_state_owner *sp;
|
||||
struct nfs4_state *state;
|
||||
unsigned int seq;
|
||||
int err;
|
||||
|
||||
again:
|
||||
@ -202,12 +201,9 @@ again:
|
||||
sp = state->owner;
|
||||
/* Block nfs4_proc_unlck */
|
||||
mutex_lock(&sp->so_delegreturn_mutex);
|
||||
seq = raw_seqcount_begin(&sp->so_reclaim_seqcount);
|
||||
err = nfs4_open_delegation_recall(ctx, state, stateid);
|
||||
if (!err)
|
||||
err = nfs_delegation_claim_locks(state, stateid);
|
||||
if (!err && read_seqcount_retry(&sp->so_reclaim_seqcount, seq))
|
||||
err = -EAGAIN;
|
||||
mutex_unlock(&sp->so_delegreturn_mutex);
|
||||
put_nfs_open_context(ctx);
|
||||
if (err != 0)
|
||||
|
@ -606,6 +606,7 @@ static void nfs_direct_commit_complete(struct nfs_commit_data *data)
|
||||
|
||||
trace_nfs_direct_commit_complete(dreq);
|
||||
|
||||
spin_lock(&dreq->lock);
|
||||
if (status < 0) {
|
||||
/* Errors in commit are fatal */
|
||||
dreq->error = status;
|
||||
@ -613,6 +614,7 @@ static void nfs_direct_commit_complete(struct nfs_commit_data *data)
|
||||
} else {
|
||||
status = dreq->error;
|
||||
}
|
||||
spin_unlock(&dreq->lock);
|
||||
|
||||
nfs_init_cinfo_from_dreq(&cinfo, dreq);
|
||||
|
||||
@ -625,7 +627,10 @@ static void nfs_direct_commit_complete(struct nfs_commit_data *data)
|
||||
spin_unlock(&dreq->lock);
|
||||
nfs_release_request(req);
|
||||
} else if (!nfs_write_match_verf(verf, req)) {
|
||||
dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
|
||||
spin_lock(&dreq->lock);
|
||||
if (dreq->flags == 0)
|
||||
dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
|
||||
spin_unlock(&dreq->lock);
|
||||
/*
|
||||
* Despite the reboot, the write was successful,
|
||||
* so reset wb_nio.
|
||||
@ -667,10 +672,17 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
|
||||
LIST_HEAD(mds_list);
|
||||
|
||||
nfs_init_cinfo_from_dreq(&cinfo, dreq);
|
||||
nfs_commit_begin(cinfo.mds);
|
||||
nfs_scan_commit(dreq->inode, &mds_list, &cinfo);
|
||||
res = nfs_generic_commit_list(dreq->inode, &mds_list, 0, &cinfo);
|
||||
if (res < 0) /* res == -ENOMEM */
|
||||
nfs_direct_write_reschedule(dreq);
|
||||
if (res < 0) { /* res == -ENOMEM */
|
||||
spin_lock(&dreq->lock);
|
||||
if (dreq->flags == 0)
|
||||
dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
|
||||
spin_unlock(&dreq->lock);
|
||||
}
|
||||
if (nfs_commit_end(cinfo.mds))
|
||||
nfs_direct_write_complete(dreq);
|
||||
}
|
||||
|
||||
static void nfs_direct_write_clear_reqs(struct nfs_direct_req *dreq)
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "../internal.h"
|
||||
#include "../nfs4session.h"
|
||||
#include "filelayout.h"
|
||||
#include "../nfs4trace.h"
|
||||
|
||||
#define NFSDBG_FACILITY NFSDBG_PNFS_LD
|
||||
|
||||
@ -172,6 +173,7 @@ nfs4_fl_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev,
|
||||
dsaddr->ds_list[i] = nfs4_pnfs_ds_add(&dsaddrs, gfp_flags);
|
||||
if (!dsaddr->ds_list[i])
|
||||
goto out_err_drain_dsaddrs;
|
||||
trace_fl_getdevinfo(server, &pdev->dev_id, dsaddr->ds_list[i]->ds_remotestr);
|
||||
|
||||
/* If DS was already in cache, free ds addrs */
|
||||
while (!list_empty(&dsaddrs)) {
|
||||
|
@ -2016,7 +2016,7 @@ static void ff_layout_cancel_io(struct pnfs_layout_segment *lseg)
|
||||
for (idx = 0; idx < flseg->mirror_array_cnt; idx++) {
|
||||
mirror = flseg->mirror_array[idx];
|
||||
mirror_ds = mirror->mirror_ds;
|
||||
if (!mirror_ds)
|
||||
if (IS_ERR_OR_NULL(mirror_ds))
|
||||
continue;
|
||||
ds = mirror->mirror_ds->ds;
|
||||
if (!ds)
|
||||
|
@ -652,6 +652,7 @@ static int nfs_fs_context_parse_param(struct fs_context *fc,
|
||||
ctx->fscache_uniq = NULL;
|
||||
break;
|
||||
case Opt_fscache:
|
||||
trace_nfs_mount_assign(param->key, param->string);
|
||||
ctx->options |= NFS_OPTION_FSCACHE;
|
||||
kfree(ctx->fscache_uniq);
|
||||
ctx->fscache_uniq = param->string;
|
||||
|
@ -301,11 +301,11 @@ static void nfs_netfs_issue_read(struct netfs_io_subrequest *sreq)
|
||||
struct inode *inode = sreq->rreq->inode;
|
||||
struct nfs_open_context *ctx = sreq->rreq->netfs_priv;
|
||||
struct page *page;
|
||||
unsigned long idx;
|
||||
int err;
|
||||
pgoff_t start = (sreq->start + sreq->transferred) >> PAGE_SHIFT;
|
||||
pgoff_t last = ((sreq->start + sreq->len -
|
||||
sreq->transferred - 1) >> PAGE_SHIFT);
|
||||
XA_STATE(xas, &sreq->rreq->mapping->i_pages, start);
|
||||
|
||||
nfs_pageio_init_read(&pgio, inode, false,
|
||||
&nfs_async_read_completion_ops);
|
||||
@ -316,19 +316,14 @@ static void nfs_netfs_issue_read(struct netfs_io_subrequest *sreq)
|
||||
|
||||
pgio.pg_netfs = netfs; /* used in completion */
|
||||
|
||||
xas_lock(&xas);
|
||||
xas_for_each(&xas, page, last) {
|
||||
xa_for_each_range(&sreq->rreq->mapping->i_pages, idx, page, start, last) {
|
||||
/* nfs_read_add_folio() may schedule() due to pNFS layout and other RPCs */
|
||||
xas_pause(&xas);
|
||||
xas_unlock(&xas);
|
||||
err = nfs_read_add_folio(&pgio, ctx, page_folio(page));
|
||||
if (err < 0) {
|
||||
netfs->error = err;
|
||||
goto out;
|
||||
}
|
||||
xas_lock(&xas);
|
||||
}
|
||||
xas_unlock(&xas);
|
||||
out:
|
||||
nfs_pageio_complete_read(&pgio);
|
||||
nfs_netfs_put(netfs);
|
||||
|
@ -2426,12 +2426,16 @@ EXPORT_SYMBOL_GPL(nfs_net_id);
|
||||
|
||||
static int nfs_net_init(struct net *net)
|
||||
{
|
||||
struct nfs_net *nn = net_generic(net, nfs_net_id);
|
||||
|
||||
nfs_clients_init(net);
|
||||
rpc_proc_register(net, &nn->rpcstats);
|
||||
return nfs_fs_proc_net_init(net);
|
||||
}
|
||||
|
||||
static void nfs_net_exit(struct net *net)
|
||||
{
|
||||
rpc_proc_unregister(net, "nfs");
|
||||
nfs_fs_proc_net_exit(net);
|
||||
nfs_clients_exit(net);
|
||||
}
|
||||
@ -2486,15 +2490,12 @@ static int __init init_nfs_fs(void)
|
||||
if (err)
|
||||
goto out1;
|
||||
|
||||
rpc_proc_register(&init_net, &nfs_rpcstat);
|
||||
|
||||
err = register_nfs_fs();
|
||||
if (err)
|
||||
goto out0;
|
||||
|
||||
return 0;
|
||||
out0:
|
||||
rpc_proc_unregister(&init_net, "nfs");
|
||||
nfs_destroy_directcache();
|
||||
out1:
|
||||
nfs_destroy_writepagecache();
|
||||
@ -2524,7 +2525,6 @@ static void __exit exit_nfs_fs(void)
|
||||
nfs_destroy_inodecache();
|
||||
nfs_destroy_nfspagecache();
|
||||
unregister_pernet_subsys(&nfs_net_ops);
|
||||
rpc_proc_unregister(&init_net, "nfs");
|
||||
unregister_nfs_fs();
|
||||
nfs_fs_proc_exit();
|
||||
nfsiod_stop();
|
||||
|
@ -449,8 +449,6 @@ int nfs_try_get_tree(struct fs_context *);
|
||||
int nfs_get_tree_common(struct fs_context *);
|
||||
void nfs_kill_super(struct super_block *);
|
||||
|
||||
extern struct rpc_stat nfs_rpcstat;
|
||||
|
||||
extern int __init register_nfs_fs(void);
|
||||
extern void __exit unregister_nfs_fs(void);
|
||||
extern bool nfs_sb_active(struct super_block *sb);
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <linux/nfs4.h>
|
||||
#include <net/net_namespace.h>
|
||||
#include <net/netns/generic.h>
|
||||
#include <linux/sunrpc/stats.h>
|
||||
|
||||
struct bl_dev_msg {
|
||||
int32_t status;
|
||||
@ -34,6 +35,7 @@ struct nfs_net {
|
||||
struct nfs_netns_client *nfs_client;
|
||||
spinlock_t nfs_client_lock;
|
||||
ktime_t boot_time;
|
||||
struct rpc_stat rpcstats;
|
||||
#ifdef CONFIG_PROC_FS
|
||||
struct proc_dir_entry *proc_nfsfs;
|
||||
#endif
|
||||
|
@ -111,6 +111,7 @@ struct nfs_client *nfs3_set_ds_client(struct nfs_server *mds_srv,
|
||||
cl_init.hostname = buf;
|
||||
|
||||
switch (ds_proto) {
|
||||
case XPRT_TRANSPORT_RDMA:
|
||||
case XPRT_TRANSPORT_TCP:
|
||||
case XPRT_TRANSPORT_TCP_TLS:
|
||||
if (mds_clp->cl_nconnect > 1)
|
||||
|
@ -55,11 +55,14 @@ int nfs42_proc_removexattr(struct inode *inode, const char *name);
|
||||
* They would be 7 bytes long in the eventual buffer ("user.x\0"), and
|
||||
* 8 bytes long XDR-encoded.
|
||||
*
|
||||
* Include the trailing eof word as well.
|
||||
* Include the trailing eof word as well and make the result a multiple
|
||||
* of 4 bytes.
|
||||
*/
|
||||
static inline u32 nfs42_listxattr_xdrsize(u32 buflen)
|
||||
{
|
||||
return ((buflen / (XATTR_USER_PREFIX_LEN + 2)) * 8) + 4;
|
||||
u32 size = 8 * buflen / (XATTR_USER_PREFIX_LEN + 2) + 4;
|
||||
|
||||
return (size + 3) & ~3;
|
||||
}
|
||||
#endif /* CONFIG_NFS_V4_2 */
|
||||
#endif /* __LINUX_FS_NFS_NFS4_2_H */
|
||||
|
@ -120,7 +120,6 @@ struct nfs4_state_owner {
|
||||
unsigned long so_flags;
|
||||
struct list_head so_states;
|
||||
struct nfs_seqid_counter so_seqid;
|
||||
seqcount_spinlock_t so_reclaim_seqcount;
|
||||
struct mutex so_delegreturn_mutex;
|
||||
};
|
||||
|
||||
|
@ -924,6 +924,7 @@ static int nfs4_set_client(struct nfs_server *server,
|
||||
else
|
||||
cl_init.max_connect = max_connect;
|
||||
switch (proto) {
|
||||
case XPRT_TRANSPORT_RDMA:
|
||||
case XPRT_TRANSPORT_TCP:
|
||||
case XPRT_TRANSPORT_TCP_TLS:
|
||||
cl_init.nconnect = nconnect;
|
||||
@ -1000,6 +1001,7 @@ struct nfs_client *nfs4_set_ds_client(struct nfs_server *mds_srv,
|
||||
cl_init.hostname = buf;
|
||||
|
||||
switch (ds_proto) {
|
||||
case XPRT_TRANSPORT_RDMA:
|
||||
case XPRT_TRANSPORT_TCP:
|
||||
case XPRT_TRANSPORT_TCP_TLS:
|
||||
if (mds_clp->cl_nconnect > 1) {
|
||||
|
@ -3069,10 +3069,8 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
|
||||
fmode_t acc_mode = _nfs4_ctx_to_accessmode(ctx);
|
||||
struct inode *dir = d_inode(opendata->dir);
|
||||
unsigned long dir_verifier;
|
||||
unsigned int seq;
|
||||
int ret;
|
||||
|
||||
seq = raw_seqcount_begin(&sp->so_reclaim_seqcount);
|
||||
dir_verifier = nfs_save_change_attribute(dir);
|
||||
|
||||
ret = _nfs4_proc_open(opendata, ctx);
|
||||
@ -3125,11 +3123,8 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
|
||||
if (ret != 0)
|
||||
goto out;
|
||||
|
||||
if (d_inode(dentry) == state->inode) {
|
||||
if (d_inode(dentry) == state->inode)
|
||||
nfs_inode_attach_open_context(ctx);
|
||||
if (read_seqcount_retry(&sp->so_reclaim_seqcount, seq))
|
||||
nfs4_schedule_stateid_recovery(server, state);
|
||||
}
|
||||
|
||||
out:
|
||||
if (!opendata->cancelled) {
|
||||
@ -8973,10 +8968,12 @@ try_again:
|
||||
return;
|
||||
|
||||
status = task->tk_status;
|
||||
if (status == 0)
|
||||
if (status == 0) {
|
||||
status = nfs4_detect_session_trunking(adata->clp,
|
||||
task->tk_msg.rpc_resp, xprt);
|
||||
|
||||
trace_nfs4_trunked_exchange_id(adata->clp,
|
||||
xprt->address_strings[RPC_DISPLAY_ADDR], status);
|
||||
}
|
||||
if (status == 0)
|
||||
rpc_clnt_xprt_switch_add_xprt(clnt, xprt);
|
||||
else if (status != -NFS4ERR_DELAY && rpc_clnt_xprt_switch_has_addr(clnt,
|
||||
@ -10618,29 +10615,33 @@ const struct nfs4_minor_version_ops *nfs_v4_minor_ops[] = {
|
||||
static ssize_t nfs4_listxattr(struct dentry *dentry, char *list, size_t size)
|
||||
{
|
||||
ssize_t error, error2, error3;
|
||||
size_t left = size;
|
||||
|
||||
error = generic_listxattr(dentry, list, size);
|
||||
error = generic_listxattr(dentry, list, left);
|
||||
if (error < 0)
|
||||
return error;
|
||||
if (list) {
|
||||
list += error;
|
||||
size -= error;
|
||||
left -= error;
|
||||
}
|
||||
|
||||
error2 = nfs4_listxattr_nfs4_label(d_inode(dentry), list, size);
|
||||
error2 = nfs4_listxattr_nfs4_label(d_inode(dentry), list, left);
|
||||
if (error2 < 0)
|
||||
return error2;
|
||||
|
||||
if (list) {
|
||||
list += error2;
|
||||
size -= error2;
|
||||
left -= error2;
|
||||
}
|
||||
|
||||
error3 = nfs4_listxattr_nfs4_user(d_inode(dentry), list, size);
|
||||
error3 = nfs4_listxattr_nfs4_user(d_inode(dentry), list, left);
|
||||
if (error3 < 0)
|
||||
return error3;
|
||||
|
||||
return error + error2 + error3;
|
||||
error += error2 + error3;
|
||||
if (size && error > size)
|
||||
return -ERANGE;
|
||||
return error;
|
||||
}
|
||||
|
||||
static void nfs4_enable_swap(struct inode *inode)
|
||||
|
@ -513,7 +513,6 @@ nfs4_alloc_state_owner(struct nfs_server *server,
|
||||
nfs4_init_seqid_counter(&sp->so_seqid);
|
||||
atomic_set(&sp->so_count, 1);
|
||||
INIT_LIST_HEAD(&sp->so_lru);
|
||||
seqcount_spinlock_init(&sp->so_reclaim_seqcount, &sp->so_lock);
|
||||
mutex_init(&sp->so_delegreturn_mutex);
|
||||
return sp;
|
||||
}
|
||||
@ -1667,7 +1666,6 @@ static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp,
|
||||
* server that doesn't support a grace period.
|
||||
*/
|
||||
spin_lock(&sp->so_lock);
|
||||
raw_write_seqcount_begin(&sp->so_reclaim_seqcount);
|
||||
restart:
|
||||
list_for_each_entry(state, &sp->so_states, open_states) {
|
||||
if (!test_and_clear_bit(ops->state_flag_bit, &state->flags))
|
||||
@ -1735,7 +1733,6 @@ restart:
|
||||
spin_lock(&sp->so_lock);
|
||||
goto restart;
|
||||
}
|
||||
raw_write_seqcount_end(&sp->so_reclaim_seqcount);
|
||||
spin_unlock(&sp->so_lock);
|
||||
#ifdef CONFIG_NFS_V4_2
|
||||
if (found_ssc_copy_state)
|
||||
@ -1745,7 +1742,6 @@ restart:
|
||||
out_err:
|
||||
nfs4_put_open_state(state);
|
||||
spin_lock(&sp->so_lock);
|
||||
raw_write_seqcount_end(&sp->so_reclaim_seqcount);
|
||||
spin_unlock(&sp->so_lock);
|
||||
return status;
|
||||
}
|
||||
@ -1928,9 +1924,12 @@ static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recov
|
||||
struct nfs_server *server;
|
||||
struct rb_node *pos;
|
||||
LIST_HEAD(freeme);
|
||||
int status = 0;
|
||||
int lost_locks = 0;
|
||||
int status;
|
||||
|
||||
status = nfs4_begin_drain_session(clp);
|
||||
if (status < 0)
|
||||
return status;
|
||||
restart:
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
|
||||
@ -2694,6 +2693,9 @@ static void nfs4_state_manager(struct nfs_client *clp)
|
||||
/* Detect expired delegations... */
|
||||
if (test_and_clear_bit(NFS4CLNT_DELEGATION_EXPIRED, &clp->cl_state)) {
|
||||
section = "detect expired delegations";
|
||||
status = nfs4_begin_drain_session(clp);
|
||||
if (status < 0)
|
||||
goto out_error;
|
||||
nfs_reap_expired_delegations(clp);
|
||||
continue;
|
||||
}
|
||||
|
@ -145,6 +145,7 @@ static int do_nfs4_mount(struct nfs_server *server,
|
||||
const char *export_path)
|
||||
{
|
||||
struct nfs_fs_context *root_ctx;
|
||||
struct nfs_fs_context *ctx;
|
||||
struct fs_context *root_fc;
|
||||
struct vfsmount *root_mnt;
|
||||
struct dentry *dentry;
|
||||
@ -157,6 +158,12 @@ static int do_nfs4_mount(struct nfs_server *server,
|
||||
.dirfd = -1,
|
||||
};
|
||||
|
||||
struct fs_parameter param_fsc = {
|
||||
.key = "fsc",
|
||||
.type = fs_value_is_string,
|
||||
.dirfd = -1,
|
||||
};
|
||||
|
||||
if (IS_ERR(server))
|
||||
return PTR_ERR(server);
|
||||
|
||||
@ -168,9 +175,26 @@ static int do_nfs4_mount(struct nfs_server *server,
|
||||
kfree(root_fc->source);
|
||||
root_fc->source = NULL;
|
||||
|
||||
ctx = nfs_fc2context(fc);
|
||||
root_ctx = nfs_fc2context(root_fc);
|
||||
root_ctx->internal = true;
|
||||
root_ctx->server = server;
|
||||
|
||||
if (ctx->fscache_uniq) {
|
||||
len = strlen(ctx->fscache_uniq);
|
||||
param_fsc.size = len;
|
||||
param_fsc.string = kmemdup_nul(ctx->fscache_uniq, len, GFP_KERNEL);
|
||||
if (param_fsc.string == NULL) {
|
||||
put_fs_context(root_fc);
|
||||
return -ENOMEM;
|
||||
}
|
||||
ret = vfs_parse_fs_param(root_fc, ¶m_fsc);
|
||||
kfree(param_fsc.string);
|
||||
if (ret < 0) {
|
||||
put_fs_context(root_fc);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
/* We leave export_path unset as it's not used to find the root. */
|
||||
|
||||
len = strlen(hostname) + 5;
|
||||
|
@ -28,4 +28,6 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(pnfs_mds_fallback_write_pagelist);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(ff_layout_read_error);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(ff_layout_write_error);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(ff_layout_commit_error);
|
||||
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(fl_getdevinfo);
|
||||
#endif
|
||||
|
@ -77,6 +77,36 @@ DEFINE_NFS4_CLIENTID_EVENT(nfs4_bind_conn_to_session);
|
||||
DEFINE_NFS4_CLIENTID_EVENT(nfs4_sequence);
|
||||
DEFINE_NFS4_CLIENTID_EVENT(nfs4_reclaim_complete);
|
||||
|
||||
TRACE_EVENT(nfs4_trunked_exchange_id,
|
||||
TP_PROTO(
|
||||
const struct nfs_client *clp,
|
||||
const char *addr,
|
||||
int error
|
||||
),
|
||||
|
||||
TP_ARGS(clp, addr, error),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(main_addr, clp->cl_hostname)
|
||||
__string(trunk_addr, addr)
|
||||
__field(unsigned long, error)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->error = error < 0 ? -error : 0;
|
||||
__assign_str(main_addr, clp->cl_hostname);
|
||||
__assign_str(trunk_addr, addr);
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"error=%ld (%s) main_addr=%s trunk_addr=%s",
|
||||
-__entry->error,
|
||||
show_nfs4_status(__entry->error),
|
||||
__get_str(main_addr),
|
||||
__get_str(trunk_addr)
|
||||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(nfs4_sequence_done,
|
||||
TP_PROTO(
|
||||
const struct nfs4_session *session,
|
||||
@ -1991,6 +2021,34 @@ DECLARE_EVENT_CLASS(nfs4_deviceid_status,
|
||||
DEFINE_PNFS_DEVICEID_STATUS(nfs4_getdeviceinfo);
|
||||
DEFINE_PNFS_DEVICEID_STATUS(nfs4_find_deviceid);
|
||||
|
||||
TRACE_EVENT(fl_getdevinfo,
|
||||
TP_PROTO(
|
||||
const struct nfs_server *server,
|
||||
const struct nfs4_deviceid *deviceid,
|
||||
char *ds_remotestr
|
||||
),
|
||||
TP_ARGS(server, deviceid, ds_remotestr),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(mds_addr, server->nfs_client->cl_hostname)
|
||||
__array(unsigned char, deviceid, NFS4_DEVICEID4_SIZE)
|
||||
__string(ds_ips, ds_remotestr)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(mds_addr, server->nfs_client->cl_hostname);
|
||||
__assign_str(ds_ips, ds_remotestr);
|
||||
memcpy(__entry->deviceid, deviceid->data,
|
||||
NFS4_DEVICEID4_SIZE);
|
||||
),
|
||||
TP_printk(
|
||||
"deviceid=%s, mds_addr=%s, ds_ips=%s",
|
||||
__print_hex(__entry->deviceid, NFS4_DEVICEID4_SIZE),
|
||||
__get_str(mds_addr),
|
||||
__get_str(ds_ips)
|
||||
)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(nfs4_flexfiles_io_event,
|
||||
TP_PROTO(
|
||||
const struct nfs_pgio_header *hdr
|
||||
|
@ -175,10 +175,10 @@ static int __init root_nfs_cat(char *dest, const char *src,
|
||||
size_t len = strlen(dest);
|
||||
|
||||
if (len && dest[len - 1] != ',')
|
||||
if (strlcat(dest, ",", destlen) > destlen)
|
||||
if (strlcat(dest, ",", destlen) >= destlen)
|
||||
return -1;
|
||||
|
||||
if (strlcat(dest, src, destlen) > destlen)
|
||||
if (strlcat(dest, src, destlen) >= destlen)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
@ -1999,6 +1999,14 @@ pnfs_update_layout(struct inode *ino,
|
||||
}
|
||||
|
||||
lookup_again:
|
||||
if (!nfs4_valid_open_stateid(ctx->state)) {
|
||||
trace_pnfs_update_layout(ino, pos, count,
|
||||
iomode, lo, lseg,
|
||||
PNFS_UPDATE_LAYOUT_INVALID_OPEN);
|
||||
lseg = ERR_PTR(-EIO);
|
||||
goto out;
|
||||
}
|
||||
|
||||
lseg = ERR_PTR(nfs4_client_recover_expired_lease(clp));
|
||||
if (IS_ERR(lseg))
|
||||
goto out;
|
||||
|
@ -919,6 +919,8 @@ static int _nfs4_pnfs_v4_ds_connect(struct nfs_server *mds_srv,
|
||||
dprintk("--> %s DS %s\n", __func__, ds->ds_remotestr);
|
||||
|
||||
list_for_each_entry(da, &ds->ds_addrs, da_node) {
|
||||
char servername[48];
|
||||
|
||||
dprintk("%s: DS %s: trying address %s\n",
|
||||
__func__, ds->ds_remotestr, da->da_remotestr);
|
||||
|
||||
@ -929,6 +931,7 @@ static int _nfs4_pnfs_v4_ds_connect(struct nfs_server *mds_srv,
|
||||
.dstaddr = (struct sockaddr *)&da->da_addr,
|
||||
.addrlen = da->da_addrlen,
|
||||
.servername = clp->cl_hostname,
|
||||
.xprtsec = clp->cl_xprtsec,
|
||||
};
|
||||
struct nfs4_add_xprt_data xprtdata = {
|
||||
.clp = clp,
|
||||
@ -938,10 +941,45 @@ static int _nfs4_pnfs_v4_ds_connect(struct nfs_server *mds_srv,
|
||||
.data = &xprtdata,
|
||||
};
|
||||
|
||||
if (da->da_transport != clp->cl_proto)
|
||||
if (da->da_transport != clp->cl_proto &&
|
||||
clp->cl_proto != XPRT_TRANSPORT_TCP_TLS)
|
||||
continue;
|
||||
if (da->da_transport == XPRT_TRANSPORT_TCP &&
|
||||
mds_srv->nfs_client->cl_proto ==
|
||||
XPRT_TRANSPORT_TCP_TLS) {
|
||||
struct sockaddr *addr =
|
||||
(struct sockaddr *)&da->da_addr;
|
||||
struct sockaddr_in *sin =
|
||||
(struct sockaddr_in *)&da->da_addr;
|
||||
struct sockaddr_in6 *sin6 =
|
||||
(struct sockaddr_in6 *)&da->da_addr;
|
||||
|
||||
/* for NFS with TLS we need to supply a correct
|
||||
* servername of the trunked transport, not the
|
||||
* servername of the main transport stored in
|
||||
* clp->cl_hostname. And set the protocol to
|
||||
* indicate to use TLS
|
||||
*/
|
||||
servername[0] = '\0';
|
||||
switch(addr->sa_family) {
|
||||
case AF_INET:
|
||||
snprintf(servername, sizeof(servername),
|
||||
"%pI4", &sin->sin_addr.s_addr);
|
||||
break;
|
||||
case AF_INET6:
|
||||
snprintf(servername, sizeof(servername),
|
||||
"%pI6", &sin6->sin6_addr);
|
||||
break;
|
||||
default:
|
||||
/* do not consider this address */
|
||||
continue;
|
||||
}
|
||||
xprt_args.ident = XPRT_TRANSPORT_TCP_TLS;
|
||||
xprt_args.servername = servername;
|
||||
}
|
||||
if (da->da_addr.ss_family != clp->cl_addr.ss_family)
|
||||
continue;
|
||||
|
||||
/**
|
||||
* Test this address for session trunking and
|
||||
* add as an alias
|
||||
@ -953,6 +991,10 @@ static int _nfs4_pnfs_v4_ds_connect(struct nfs_server *mds_srv,
|
||||
if (xprtdata.cred)
|
||||
put_cred(xprtdata.cred);
|
||||
} else {
|
||||
if (da->da_transport == XPRT_TRANSPORT_TCP &&
|
||||
mds_srv->nfs_client->cl_proto ==
|
||||
XPRT_TRANSPORT_TCP_TLS)
|
||||
da->da_transport = XPRT_TRANSPORT_TCP_TLS;
|
||||
clp = nfs4_set_ds_client(mds_srv,
|
||||
&da->da_addr,
|
||||
da->da_addrlen,
|
||||
|
@ -305,6 +305,8 @@ int nfs_read_add_folio(struct nfs_pageio_descriptor *pgio,
|
||||
new = nfs_page_create_from_folio(ctx, folio, 0, aligned_len);
|
||||
if (IS_ERR(new)) {
|
||||
error = PTR_ERR(new);
|
||||
if (nfs_netfs_folio_unlock(folio))
|
||||
folio_unlock(folio);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -516,8 +516,16 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
|
||||
else
|
||||
nfs_show_nfsv4_options(m, nfss, showdefaults);
|
||||
|
||||
if (nfss->options & NFS_OPTION_FSCACHE)
|
||||
if (nfss->options & NFS_OPTION_FSCACHE) {
|
||||
#ifdef CONFIG_NFS_FSCACHE
|
||||
if (nfss->fscache_uniq)
|
||||
seq_printf(m, ",fsc=%s", nfss->fscache_uniq);
|
||||
else
|
||||
seq_puts(m, ",fsc");
|
||||
#else
|
||||
seq_puts(m, ",fsc");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (nfss->options & NFS_OPTION_MIGRATION)
|
||||
seq_puts(m, ",migration");
|
||||
|
@ -667,10 +667,6 @@ static int nfs_writepage_locked(struct folio *folio,
|
||||
struct inode *inode = folio_file_mapping(folio)->host;
|
||||
int err;
|
||||
|
||||
if (wbc->sync_mode == WB_SYNC_NONE &&
|
||||
NFS_SERVER(inode)->write_congested)
|
||||
return AOP_WRITEPAGE_ACTIVATE;
|
||||
|
||||
nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGE);
|
||||
nfs_pageio_init_write(&pgio, inode, 0, false,
|
||||
&nfs_async_write_completion_ops);
|
||||
@ -1650,7 +1646,7 @@ static int wait_on_commit(struct nfs_mds_commit_info *cinfo)
|
||||
!atomic_read(&cinfo->rpcs_out));
|
||||
}
|
||||
|
||||
static void nfs_commit_begin(struct nfs_mds_commit_info *cinfo)
|
||||
void nfs_commit_begin(struct nfs_mds_commit_info *cinfo)
|
||||
{
|
||||
atomic_inc(&cinfo->rpcs_out);
|
||||
}
|
||||
|
@ -611,6 +611,7 @@ int nfs_wb_folio_cancel(struct inode *inode, struct folio *folio);
|
||||
extern int nfs_commit_inode(struct inode *, int);
|
||||
extern struct nfs_commit_data *nfs_commitdata_alloc(void);
|
||||
extern void nfs_commit_free(struct nfs_commit_data *data);
|
||||
void nfs_commit_begin(struct nfs_mds_commit_info *cinfo);
|
||||
bool nfs_commit_end(struct nfs_mds_commit_info *cinfo);
|
||||
|
||||
static inline bool nfs_have_writebacks(const struct inode *inode)
|
||||
|
@ -1820,13 +1820,6 @@ struct nfs_rpc_ops {
|
||||
void (*disable_swap)(struct inode *inode);
|
||||
};
|
||||
|
||||
/*
|
||||
* NFS_CALL(getattr, inode, (fattr));
|
||||
* into
|
||||
* NFS_PROTO(inode)->getattr(fattr);
|
||||
*/
|
||||
#define NFS_CALL(op, inode, args) NFS_PROTO(inode)->op args
|
||||
|
||||
/*
|
||||
* Function vectors etc. for the NFS client
|
||||
*/
|
||||
|
@ -139,6 +139,7 @@ struct rpc_create_args {
|
||||
const char *servername;
|
||||
const char *nodename;
|
||||
const struct rpc_program *program;
|
||||
struct rpc_stat *stats;
|
||||
u32 prognumber; /* overrides program->number */
|
||||
u32 version;
|
||||
rpc_authflavor_t authflavor;
|
||||
|
@ -197,7 +197,7 @@ struct rpc_wait_queue {
|
||||
unsigned char maxpriority; /* maximum priority (0 if queue is not a priority queue) */
|
||||
unsigned char priority; /* current priority */
|
||||
unsigned char nr; /* # tasks remaining for cookie */
|
||||
unsigned short qlen; /* total # tasks waiting in queue */
|
||||
unsigned int qlen; /* total # tasks waiting in queue */
|
||||
struct rpc_timer timer_list;
|
||||
#if IS_ENABLED(CONFIG_SUNRPC_DEBUG) || IS_ENABLED(CONFIG_TRACEPOINTS)
|
||||
const char * name;
|
||||
|
@ -152,6 +152,7 @@ struct rpc_xprt_ops {
|
||||
int (*prepare_request)(struct rpc_rqst *req,
|
||||
struct xdr_buf *buf);
|
||||
int (*send_request)(struct rpc_rqst *req);
|
||||
void (*abort_send_request)(struct rpc_rqst *req);
|
||||
void (*wait_for_reply_request)(struct rpc_task *task);
|
||||
void (*timer)(struct rpc_xprt *xprt, struct rpc_task *task);
|
||||
void (*release_request)(struct rpc_task *task);
|
||||
|
@ -639,6 +639,7 @@ TRACE_EVENT(rpc_stats_latency,
|
||||
__field(unsigned long, backlog)
|
||||
__field(unsigned long, rtt)
|
||||
__field(unsigned long, execute)
|
||||
__field(u32, xprt_id)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
@ -651,13 +652,16 @@ TRACE_EVENT(rpc_stats_latency,
|
||||
__entry->backlog = ktime_to_us(backlog);
|
||||
__entry->rtt = ktime_to_us(rtt);
|
||||
__entry->execute = ktime_to_us(execute);
|
||||
__entry->xprt_id = task->tk_xprt->id;
|
||||
),
|
||||
|
||||
TP_printk(SUNRPC_TRACE_TASK_SPECIFIER
|
||||
" xid=0x%08x %sv%d %s backlog=%lu rtt=%lu execute=%lu",
|
||||
" xid=0x%08x %sv%d %s backlog=%lu rtt=%lu execute=%lu"
|
||||
" xprt_id=%d",
|
||||
__entry->task_id, __entry->client_id, __entry->xid,
|
||||
__get_str(progname), __entry->version, __get_str(procname),
|
||||
__entry->backlog, __entry->rtt, __entry->execute)
|
||||
__entry->backlog, __entry->rtt, __entry->execute,
|
||||
__entry->xprt_id)
|
||||
);
|
||||
|
||||
TRACE_EVENT(rpc_xdr_overflow,
|
||||
|
@ -239,6 +239,7 @@ TRACE_DEFINE_ENUM(NFS4ERR_RESET_TO_PNFS);
|
||||
{ EHOSTDOWN, "EHOSTDOWN" }, \
|
||||
{ EPIPE, "EPIPE" }, \
|
||||
{ EPFNOSUPPORT, "EPFNOSUPPORT" }, \
|
||||
{ EINVAL, "EINVAL" }, \
|
||||
{ EPROTONOSUPPORT, "EPROTONOSUPPORT" }, \
|
||||
{ NFS4ERR_ACCESS, "ACCESS" }, \
|
||||
{ NFS4ERR_ATTRNOTSUPP, "ATTRNOTSUPP" }, \
|
||||
|
@ -284,10 +284,10 @@ char *rpc_sockaddr2uaddr(const struct sockaddr *sap, gfp_t gfp_flags)
|
||||
}
|
||||
|
||||
if (snprintf(portbuf, sizeof(portbuf),
|
||||
".%u.%u", port >> 8, port & 0xff) > (int)sizeof(portbuf))
|
||||
".%u.%u", port >> 8, port & 0xff) >= (int)sizeof(portbuf))
|
||||
return NULL;
|
||||
|
||||
if (strlcat(addrbuf, portbuf, sizeof(addrbuf)) > sizeof(addrbuf))
|
||||
if (strlcat(addrbuf, portbuf, sizeof(addrbuf)) >= sizeof(addrbuf))
|
||||
return NULL;
|
||||
|
||||
return kstrdup(addrbuf, gfp_flags);
|
||||
|
@ -405,7 +405,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args,
|
||||
clnt->cl_maxproc = version->nrprocs;
|
||||
clnt->cl_prog = args->prognumber ? : program->number;
|
||||
clnt->cl_vers = version->number;
|
||||
clnt->cl_stats = program->stats;
|
||||
clnt->cl_stats = args->stats ? : program->stats;
|
||||
clnt->cl_metrics = rpc_alloc_iostats(clnt);
|
||||
rpc_init_pipe_dir_head(&clnt->cl_pipedir_objects);
|
||||
err = -ENOMEM;
|
||||
@ -691,6 +691,7 @@ struct rpc_clnt *rpc_clone_client(struct rpc_clnt *clnt)
|
||||
.version = clnt->cl_vers,
|
||||
.authflavor = clnt->cl_auth->au_flavor,
|
||||
.cred = clnt->cl_cred,
|
||||
.stats = clnt->cl_stats,
|
||||
};
|
||||
return __rpc_clone_client(&args, clnt);
|
||||
}
|
||||
@ -713,6 +714,7 @@ rpc_clone_client_set_auth(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
|
||||
.version = clnt->cl_vers,
|
||||
.authflavor = flavor,
|
||||
.cred = clnt->cl_cred,
|
||||
.stats = clnt->cl_stats,
|
||||
};
|
||||
return __rpc_clone_client(&args, clnt);
|
||||
}
|
||||
@ -1068,6 +1070,7 @@ struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old,
|
||||
.version = vers,
|
||||
.authflavor = old->cl_auth->au_flavor,
|
||||
.cred = old->cl_cred,
|
||||
.stats = old->cl_stats,
|
||||
};
|
||||
struct rpc_clnt *clnt;
|
||||
int err;
|
||||
|
@ -1398,6 +1398,12 @@ xprt_request_dequeue_transmit_locked(struct rpc_task *task)
|
||||
if (!test_and_clear_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate))
|
||||
return;
|
||||
if (!list_empty(&req->rq_xmit)) {
|
||||
struct rpc_xprt *xprt = req->rq_xprt;
|
||||
|
||||
if (list_is_first(&req->rq_xmit, &xprt->xmit_queue) &&
|
||||
xprt->ops->abort_send_request)
|
||||
xprt->ops->abort_send_request(req);
|
||||
|
||||
list_del(&req->rq_xmit);
|
||||
if (!list_empty(&req->rq_xmit2)) {
|
||||
struct rpc_rqst *next = list_first_entry(&req->rq_xmit2,
|
||||
@ -1541,6 +1547,9 @@ xprt_request_transmit(struct rpc_rqst *req, struct rpc_task *snd_task)
|
||||
int is_retrans = RPC_WAS_SENT(task);
|
||||
int status;
|
||||
|
||||
if (test_bit(XPRT_CLOSE_WAIT, &xprt->state))
|
||||
return -ENOTCONN;
|
||||
|
||||
if (!req->rq_bytes_sent) {
|
||||
if (xprt_request_data_received(task)) {
|
||||
status = 0;
|
||||
|
@ -62,6 +62,7 @@
|
||||
#include "sunrpc.h"
|
||||
|
||||
static void xs_close(struct rpc_xprt *xprt);
|
||||
static void xs_reset_srcport(struct sock_xprt *transport);
|
||||
static void xs_set_srcport(struct sock_xprt *transport, struct socket *sock);
|
||||
static void xs_tcp_set_socket_timeouts(struct rpc_xprt *xprt,
|
||||
struct socket *sock);
|
||||
@ -883,6 +884,17 @@ static int xs_stream_prepare_request(struct rpc_rqst *req, struct xdr_buf *buf)
|
||||
return xdr_alloc_bvec(buf, rpc_task_gfp_mask());
|
||||
}
|
||||
|
||||
static void xs_stream_abort_send_request(struct rpc_rqst *req)
|
||||
{
|
||||
struct rpc_xprt *xprt = req->rq_xprt;
|
||||
struct sock_xprt *transport =
|
||||
container_of(xprt, struct sock_xprt, xprt);
|
||||
|
||||
if (transport->xmit.offset != 0 &&
|
||||
!test_bit(XPRT_CLOSE_WAIT, &xprt->state))
|
||||
xprt_force_disconnect(xprt);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if the previous message in the stream was aborted before it
|
||||
* could complete transmission.
|
||||
@ -1565,8 +1577,10 @@ static void xs_tcp_state_change(struct sock *sk)
|
||||
break;
|
||||
case TCP_CLOSE:
|
||||
if (test_and_clear_bit(XPRT_SOCK_CONNECTING,
|
||||
&transport->sock_state))
|
||||
&transport->sock_state)) {
|
||||
xs_reset_srcport(transport);
|
||||
xprt_clear_connecting(xprt);
|
||||
}
|
||||
clear_bit(XPRT_CLOSING, &xprt->state);
|
||||
/* Trigger the socket release */
|
||||
xs_run_error_worker(transport, XPRT_SOCK_WAKE_DISCONNECT);
|
||||
@ -1722,6 +1736,11 @@ static void xs_set_port(struct rpc_xprt *xprt, unsigned short port)
|
||||
xs_update_peer_port(xprt);
|
||||
}
|
||||
|
||||
static void xs_reset_srcport(struct sock_xprt *transport)
|
||||
{
|
||||
transport->srcport = 0;
|
||||
}
|
||||
|
||||
static void xs_set_srcport(struct sock_xprt *transport, struct socket *sock)
|
||||
{
|
||||
if (transport->srcport == 0 && transport->xprt.reuseport)
|
||||
@ -3012,6 +3031,7 @@ static const struct rpc_xprt_ops xs_local_ops = {
|
||||
.buf_free = rpc_free,
|
||||
.prepare_request = xs_stream_prepare_request,
|
||||
.send_request = xs_local_send_request,
|
||||
.abort_send_request = xs_stream_abort_send_request,
|
||||
.wait_for_reply_request = xprt_wait_for_reply_request_def,
|
||||
.close = xs_close,
|
||||
.destroy = xs_destroy,
|
||||
@ -3059,6 +3079,7 @@ static const struct rpc_xprt_ops xs_tcp_ops = {
|
||||
.buf_free = rpc_free,
|
||||
.prepare_request = xs_stream_prepare_request,
|
||||
.send_request = xs_tcp_send_request,
|
||||
.abort_send_request = xs_stream_abort_send_request,
|
||||
.wait_for_reply_request = xprt_wait_for_reply_request_def,
|
||||
.close = xs_tcp_shutdown,
|
||||
.destroy = xs_destroy,
|
||||
|
Loading…
Reference in New Issue
Block a user