mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-28 07:04:00 +08:00
NFS Client Updates for Linux 5.10
- Stable Fixes: - Wait for stateid updates after CLOSE/OPEN_DOWNGRADE # v5.4+ - Fix nfs_path in case of a rename retry - Support EXCHID4_FLAG_SUPP_FENCE_OPS v4.2 EXCHANGE_ID flag - New features and improvements: - Replace dprintk() calls with tracepoints - Make cache consistency bitmap dynamic - Added support for the NFS v4.2 READ_PLUS operation - Improvements to net namespace uniquifier - Other bugfixes and cleanups - Remove redundant clnt pointer - Don't update timeout values on connection resets - Remove redundant tracepoints - Various cleanups to comments - Fix oops when trying to use copy_file_range with v4.0 source server - Improvements to flexfiles mirrors - Add missing "local_lock=posix" mount option -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEnZ5MQTpR7cLU7KEp18tUv7ClQOsFAl+PJv0ACgkQ18tUv7Cl QOtB+hAAza4BwQSAZs0QbszPcoNV0f0qND99hWcJ2ad5KCr8S5eNYaMqB8G8lbS+ Ahuv6xRy69l2vjHvINXoSaSiXClYNAlAr5myiW0DqMLDpVV8VEMAhqgFJK97VpqQ AsbsdFwC4xAcQ+6nJ+IfK9f8AOYhvARkOP3171qkq0jX3Eq4j1IiQARn+JrGFZFL waC4UtVhCnx5z5pg7jyu7Ar4N0Xky72+Fm1EvRog4gndX2JbNNSkwavD33mWZ8iN 3q6DRq/AtEk9F4ttPwVeALvpNCBqjoGcNw5FCBil7x4V+xIbDI2FBhusKas3GzXm W2tyUuJMTGpA6ZjkyYDcg0jC8vKUiUpMWgT3oZoQ/6g7P4vPzB/XB/RQcAInMRjS /MhWZ3YNQmApnVCIZSwOa9+oNUc69dM0+vqmesLvvb/aNjzRnGwiJNiuWGyrwoGX 3SzpPUcJixa3+eKLi9uEHojKB+SuPIrB/HW4UYh/ZpOMyilVqUnX8RYbaK3qQ/gK Un++LjTmao9cXyjIDCiHJB630W01YSWXq1nwuSYkLuXCuALmmtgA4z8pm+4K+w+G SctETKVcD0qi3Yx5mFdU5A1dHXMB7nzYNaiRWYLvLO5qAR33nUPI4lV8rog2TUPe 2iW4n0j2YxnTlwR3QMPYJRndP7KeR5XvOoNuh3XpKRVbmbc7/A4= =6RM5 -----END PGP SIGNATURE----- Merge tag 'nfs-for-5.10-1' of git://git.linux-nfs.org/projects/anna/linux-nfs Pull NFS client updates from Anna Schumaker: "Stable Fixes: - Wait for stateid updates after CLOSE/OPEN_DOWNGRADE # v5.4+ - Fix nfs_path in case of a rename retry - Support EXCHID4_FLAG_SUPP_FENCE_OPS v4.2 EXCHANGE_ID flag New features and improvements: - Replace dprintk() calls with tracepoints - Make cache consistency bitmap dynamic - Added support for the NFS v4.2 READ_PLUS operation - Improvements to net namespace uniquifier Other bugfixes and cleanups: - Remove redundant clnt pointer - Don't update timeout values on connection resets - Remove redundant tracepoints - Various cleanups to comments - Fix oops when trying to use copy_file_range with v4.0 source server - Improvements to flexfiles mirrors - Add missing 'local_lock=posix' mount option" * tag 'nfs-for-5.10-1' of git://git.linux-nfs.org/projects/anna/linux-nfs: (55 commits) NFSv4.2: support EXCHGID4_FLAG_SUPP_FENCE_OPS 4.2 EXCHANGE_ID flag NFSv4: Fix up RCU annotations for struct nfs_netns_client NFS: Only reference user namespace from nfs4idmap struct instead of cred nfs: add missing "posix" local_lock constant table definition NFSv4: Use the net namespace uniquifier if it is set NFSv4: Clean up initialisation of uniquified client id strings NFS: Decode a full READ_PLUS reply SUNRPC: Add an xdr_align_data() function NFS: Add READ_PLUS hole segment decoding SUNRPC: Add the ability to expand holes in data pages SUNRPC: Split out _shift_data_right_tail() SUNRPC: Split out xdr_realign_pages() from xdr_align_pages() NFS: Add READ_PLUS data segment support NFS: Use xdr_page_pos() in NFSv4 decode_getacl() SUNRPC: Implement a xdr_page_pos() function SUNRPC: Split out a function for setting current page NFS: fix nfs_path in case of a rename retry fs: nfs: return per memcg count for xattr shrinkers NFSv4: Wait for stateid updates after CLOSE/OPEN_DOWNGRADE nfs: remove incorrect fallthrough label ...
This commit is contained in:
commit
59f0e7eb2f
@ -417,7 +417,7 @@ void nsm_release(struct nsm_handle *nsm)
|
||||
/*
|
||||
* XDR functions for NSM.
|
||||
*
|
||||
* See http://www.opengroup.org/ for details on the Network
|
||||
* See https://www.opengroup.org/ for details on the Network
|
||||
* Status Monitor wire protocol.
|
||||
*/
|
||||
|
||||
|
@ -94,6 +94,7 @@ enum {
|
||||
static const struct constant_table nfs_param_enums_local_lock[] = {
|
||||
{ "all", Opt_local_lock_all },
|
||||
{ "flock", Opt_local_lock_flock },
|
||||
{ "posix", Opt_local_lock_posix },
|
||||
{ "none", Opt_local_lock_none },
|
||||
{}
|
||||
};
|
||||
|
@ -32,9 +32,9 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ;
|
||||
/*
|
||||
* nfs_path - reconstruct the path given an arbitrary dentry
|
||||
* @base - used to return pointer to the end of devname part of path
|
||||
* @dentry - pointer to dentry
|
||||
* @dentry_in - pointer to dentry
|
||||
* @buffer - result buffer
|
||||
* @buflen - length of buffer
|
||||
* @buflen_in - length of buffer
|
||||
* @flags - options (see below)
|
||||
*
|
||||
* Helper function for constructing the server pathname
|
||||
@ -49,15 +49,19 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ;
|
||||
* the original device (export) name
|
||||
* (if unset, the original name is returned verbatim)
|
||||
*/
|
||||
char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen,
|
||||
unsigned flags)
|
||||
char *nfs_path(char **p, struct dentry *dentry_in, char *buffer,
|
||||
ssize_t buflen_in, unsigned flags)
|
||||
{
|
||||
char *end;
|
||||
int namelen;
|
||||
unsigned seq;
|
||||
const char *base;
|
||||
struct dentry *dentry;
|
||||
ssize_t buflen;
|
||||
|
||||
rename_retry:
|
||||
buflen = buflen_in;
|
||||
dentry = dentry_in;
|
||||
end = buffer+buflen;
|
||||
*--end = '\0';
|
||||
buflen--;
|
||||
|
@ -67,7 +67,6 @@ struct nfs4_xattr_bucket {
|
||||
|
||||
struct nfs4_xattr_cache {
|
||||
struct kref ref;
|
||||
spinlock_t hash_lock; /* protects hashtable and lru */
|
||||
struct nfs4_xattr_bucket buckets[NFS4_XATTR_HASH_SIZE];
|
||||
struct list_head lru;
|
||||
struct list_head dispose;
|
||||
@ -882,7 +881,7 @@ nfs4_xattr_cache_count(struct shrinker *shrink, struct shrink_control *sc)
|
||||
{
|
||||
unsigned long count;
|
||||
|
||||
count = list_lru_count(&nfs4_xattr_cache_lru);
|
||||
count = list_lru_shrink_count(&nfs4_xattr_cache_lru, sc);
|
||||
return vfs_pressure_ratio(count);
|
||||
}
|
||||
|
||||
@ -976,7 +975,7 @@ nfs4_xattr_entry_count(struct shrinker *shrink, struct shrink_control *sc)
|
||||
lru = (shrink == &nfs4_xattr_large_entry_shrinker) ?
|
||||
&nfs4_xattr_large_entry_lru : &nfs4_xattr_entry_lru;
|
||||
|
||||
count = list_lru_count(lru);
|
||||
count = list_lru_shrink_count(lru, sc);
|
||||
return vfs_pressure_ratio(count);
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,15 @@
|
||||
#define encode_deallocate_maxsz (op_encode_hdr_maxsz + \
|
||||
encode_fallocate_maxsz)
|
||||
#define decode_deallocate_maxsz (op_decode_hdr_maxsz)
|
||||
#define encode_read_plus_maxsz (op_encode_hdr_maxsz + \
|
||||
encode_stateid_maxsz + 3)
|
||||
#define NFS42_READ_PLUS_SEGMENT_SIZE (1 /* data_content4 */ + \
|
||||
2 /* data_info4.di_offset */ + \
|
||||
2 /* data_info4.di_length */)
|
||||
#define decode_read_plus_maxsz (op_decode_hdr_maxsz + \
|
||||
1 /* rpr_eof */ + \
|
||||
1 /* rpr_contents count */ + \
|
||||
2 * NFS42_READ_PLUS_SEGMENT_SIZE)
|
||||
#define encode_seek_maxsz (op_encode_hdr_maxsz + \
|
||||
encode_stateid_maxsz + \
|
||||
2 /* offset */ + \
|
||||
@ -128,6 +137,14 @@
|
||||
decode_putfh_maxsz + \
|
||||
decode_deallocate_maxsz + \
|
||||
decode_getattr_maxsz)
|
||||
#define NFS4_enc_read_plus_sz (compound_encode_hdr_maxsz + \
|
||||
encode_sequence_maxsz + \
|
||||
encode_putfh_maxsz + \
|
||||
encode_read_plus_maxsz)
|
||||
#define NFS4_dec_read_plus_sz (compound_decode_hdr_maxsz + \
|
||||
decode_sequence_maxsz + \
|
||||
decode_putfh_maxsz + \
|
||||
decode_read_plus_maxsz)
|
||||
#define NFS4_enc_seek_sz (compound_encode_hdr_maxsz + \
|
||||
encode_sequence_maxsz + \
|
||||
encode_putfh_maxsz + \
|
||||
@ -324,6 +341,16 @@ static void encode_deallocate(struct xdr_stream *xdr,
|
||||
encode_fallocate(xdr, args);
|
||||
}
|
||||
|
||||
static void encode_read_plus(struct xdr_stream *xdr,
|
||||
const struct nfs_pgio_args *args,
|
||||
struct compound_hdr *hdr)
|
||||
{
|
||||
encode_op_hdr(xdr, OP_READ_PLUS, decode_read_plus_maxsz, hdr);
|
||||
encode_nfs4_stateid(xdr, &args->stateid);
|
||||
encode_uint64(xdr, args->offset);
|
||||
encode_uint32(xdr, args->count);
|
||||
}
|
||||
|
||||
static void encode_seek(struct xdr_stream *xdr,
|
||||
const struct nfs42_seek_args *args,
|
||||
struct compound_hdr *hdr)
|
||||
@ -722,6 +749,28 @@ static void nfs4_xdr_enc_deallocate(struct rpc_rqst *req,
|
||||
encode_nops(&hdr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode READ_PLUS request
|
||||
*/
|
||||
static void nfs4_xdr_enc_read_plus(struct rpc_rqst *req,
|
||||
struct xdr_stream *xdr,
|
||||
const void *data)
|
||||
{
|
||||
const struct nfs_pgio_args *args = data;
|
||||
struct compound_hdr hdr = {
|
||||
.minorversion = nfs4_xdr_minorversion(&args->seq_args),
|
||||
};
|
||||
|
||||
encode_compound_hdr(xdr, req, &hdr);
|
||||
encode_sequence(xdr, &args->seq_args, &hdr);
|
||||
encode_putfh(xdr, args->fh, &hdr);
|
||||
encode_read_plus(xdr, args, &hdr);
|
||||
|
||||
rpc_prepare_reply_pages(req, args->pages, args->pgbase,
|
||||
args->count, hdr.replen);
|
||||
encode_nops(&hdr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode SEEK request
|
||||
*/
|
||||
@ -970,6 +1019,97 @@ static int decode_deallocate(struct xdr_stream *xdr, struct nfs42_falloc_res *re
|
||||
return decode_op_hdr(xdr, OP_DEALLOCATE);
|
||||
}
|
||||
|
||||
static int decode_read_plus_data(struct xdr_stream *xdr, struct nfs_pgio_res *res,
|
||||
uint32_t *eof)
|
||||
{
|
||||
uint32_t count, recvd;
|
||||
uint64_t offset;
|
||||
__be32 *p;
|
||||
|
||||
p = xdr_inline_decode(xdr, 8 + 4);
|
||||
if (unlikely(!p))
|
||||
return -EIO;
|
||||
|
||||
p = xdr_decode_hyper(p, &offset);
|
||||
count = be32_to_cpup(p);
|
||||
recvd = xdr_align_data(xdr, res->count, count);
|
||||
res->count += recvd;
|
||||
|
||||
if (count > recvd) {
|
||||
dprintk("NFS: server cheating in read reply: "
|
||||
"count %u > recvd %u\n", count, recvd);
|
||||
*eof = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decode_read_plus_hole(struct xdr_stream *xdr, struct nfs_pgio_res *res,
|
||||
uint32_t *eof)
|
||||
{
|
||||
uint64_t offset, length, recvd;
|
||||
__be32 *p;
|
||||
|
||||
p = xdr_inline_decode(xdr, 8 + 8);
|
||||
if (unlikely(!p))
|
||||
return -EIO;
|
||||
|
||||
p = xdr_decode_hyper(p, &offset);
|
||||
p = xdr_decode_hyper(p, &length);
|
||||
recvd = xdr_expand_hole(xdr, res->count, length);
|
||||
res->count += recvd;
|
||||
|
||||
if (recvd < length) {
|
||||
*eof = 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decode_read_plus(struct xdr_stream *xdr, struct nfs_pgio_res *res)
|
||||
{
|
||||
uint32_t eof, segments, type;
|
||||
int status, i;
|
||||
__be32 *p;
|
||||
|
||||
status = decode_op_hdr(xdr, OP_READ_PLUS);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
p = xdr_inline_decode(xdr, 4 + 4);
|
||||
if (unlikely(!p))
|
||||
return -EIO;
|
||||
|
||||
eof = be32_to_cpup(p++);
|
||||
segments = be32_to_cpup(p++);
|
||||
if (segments == 0)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < segments; i++) {
|
||||
p = xdr_inline_decode(xdr, 4);
|
||||
if (unlikely(!p))
|
||||
return -EIO;
|
||||
|
||||
type = be32_to_cpup(p++);
|
||||
if (type == NFS4_CONTENT_DATA)
|
||||
status = decode_read_plus_data(xdr, res, &eof);
|
||||
else if (type == NFS4_CONTENT_HOLE)
|
||||
status = decode_read_plus_hole(xdr, res, &eof);
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
if (status < 0)
|
||||
return status;
|
||||
if (status > 0)
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
res->eof = eof;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decode_seek(struct xdr_stream *xdr, struct nfs42_seek_res *res)
|
||||
{
|
||||
int status;
|
||||
@ -1146,6 +1286,33 @@ out:
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode READ_PLUS request
|
||||
*/
|
||||
static int nfs4_xdr_dec_read_plus(struct rpc_rqst *rqstp,
|
||||
struct xdr_stream *xdr,
|
||||
void *data)
|
||||
{
|
||||
struct nfs_pgio_res *res = data;
|
||||
struct compound_hdr hdr;
|
||||
int status;
|
||||
|
||||
status = decode_compound_hdr(xdr, &hdr);
|
||||
if (status)
|
||||
goto out;
|
||||
status = decode_sequence(xdr, &res->seq_res, rqstp);
|
||||
if (status)
|
||||
goto out;
|
||||
status = decode_putfh(xdr);
|
||||
if (status)
|
||||
goto out;
|
||||
status = decode_read_plus(xdr, res);
|
||||
if (!status)
|
||||
status = res->count;
|
||||
out:
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode SEEK request
|
||||
*/
|
||||
|
@ -599,6 +599,14 @@ static inline bool nfs4_stateid_is_newer(const nfs4_stateid *s1, const nfs4_stat
|
||||
return (s32)(be32_to_cpu(s1->seqid) - be32_to_cpu(s2->seqid)) > 0;
|
||||
}
|
||||
|
||||
static inline bool nfs4_stateid_is_next(const nfs4_stateid *s1, const nfs4_stateid *s2)
|
||||
{
|
||||
u32 seq1 = be32_to_cpu(s1->seqid);
|
||||
u32 seq2 = be32_to_cpu(s2->seqid);
|
||||
|
||||
return seq2 == seq1 + 1U || (seq2 == 1U && seq1 == 0xffffffffU);
|
||||
}
|
||||
|
||||
static inline bool nfs4_stateid_match_or_older(const nfs4_stateid *dst, const nfs4_stateid *src)
|
||||
{
|
||||
return nfs4_stateid_match_other(dst, src) &&
|
||||
|
@ -1045,6 +1045,8 @@ static int nfs4_server_common_setup(struct nfs_server *server,
|
||||
server->caps |= server->nfs_client->cl_mvops->init_caps;
|
||||
if (server->flags & NFS_MOUNT_NORDIRPLUS)
|
||||
server->caps &= ~NFS_CAP_READDIRPLUS;
|
||||
if (server->nfs_client->cl_proto == XPRT_TRANSPORT_RDMA)
|
||||
server->caps &= ~NFS_CAP_READ_PLUS;
|
||||
/*
|
||||
* Don't use NFS uid/gid mapping if we're using AUTH_SYS or lower
|
||||
* authentication.
|
||||
|
@ -145,7 +145,8 @@ static ssize_t __nfs4_copy_file_range(struct file *file_in, loff_t pos_in,
|
||||
/* Only offload copy if superblock is the same */
|
||||
if (file_in->f_op != &nfs4_file_operations)
|
||||
return -EXDEV;
|
||||
if (!nfs_server_capable(file_inode(file_out), NFS_CAP_COPY))
|
||||
if (!nfs_server_capable(file_inode(file_out), NFS_CAP_COPY) ||
|
||||
!nfs_server_capable(file_inode(file_in), NFS_CAP_COPY))
|
||||
return -EOPNOTSUPP;
|
||||
if (file_inode(file_in) == file_inode(file_out))
|
||||
return -EOPNOTSUPP;
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include <keys/user-type.h>
|
||||
#include <keys/request_key_auth-type.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/user_namespace.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "netns.h"
|
||||
@ -69,13 +70,13 @@ struct idmap {
|
||||
struct rpc_pipe *idmap_pipe;
|
||||
struct idmap_legacy_upcalldata *idmap_upcall_data;
|
||||
struct mutex idmap_mutex;
|
||||
const struct cred *cred;
|
||||
struct user_namespace *user_ns;
|
||||
};
|
||||
|
||||
static struct user_namespace *idmap_userns(const struct idmap *idmap)
|
||||
{
|
||||
if (idmap && idmap->cred)
|
||||
return idmap->cred->user_ns;
|
||||
if (idmap && idmap->user_ns)
|
||||
return idmap->user_ns;
|
||||
return &init_user_ns;
|
||||
}
|
||||
|
||||
@ -286,7 +287,7 @@ static struct key *nfs_idmap_request_key(const char *name, size_t namelen,
|
||||
if (ret < 0)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
if (!idmap->cred || idmap->cred->user_ns == &init_user_ns)
|
||||
if (!idmap->user_ns || idmap->user_ns == &init_user_ns)
|
||||
rkey = request_key(&key_type_id_resolver, desc, "");
|
||||
if (IS_ERR(rkey)) {
|
||||
mutex_lock(&idmap->idmap_mutex);
|
||||
@ -462,7 +463,7 @@ nfs_idmap_new(struct nfs_client *clp)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&idmap->idmap_mutex);
|
||||
idmap->cred = get_cred(clp->cl_rpcclient->cl_cred);
|
||||
idmap->user_ns = get_user_ns(clp->cl_rpcclient->cl_cred->user_ns);
|
||||
|
||||
rpc_init_pipe_dir_object(&idmap->idmap_pdo,
|
||||
&nfs_idmap_pipe_dir_object_ops,
|
||||
@ -486,7 +487,7 @@ nfs_idmap_new(struct nfs_client *clp)
|
||||
err_destroy_pipe:
|
||||
rpc_destroy_pipe_data(idmap->idmap_pipe);
|
||||
err:
|
||||
put_cred(idmap->cred);
|
||||
get_user_ns(idmap->user_ns);
|
||||
kfree(idmap);
|
||||
return error;
|
||||
}
|
||||
@ -503,7 +504,7 @@ nfs_idmap_delete(struct nfs_client *clp)
|
||||
&clp->cl_rpcclient->cl_pipedir_objects,
|
||||
&idmap->idmap_pdo);
|
||||
rpc_destroy_pipe_data(idmap->idmap_pipe);
|
||||
put_cred(idmap->cred);
|
||||
put_user_ns(idmap->user_ns);
|
||||
kfree(idmap);
|
||||
}
|
||||
|
||||
|
@ -63,6 +63,7 @@
|
||||
#include "callback.h"
|
||||
#include "pnfs.h"
|
||||
#include "netns.h"
|
||||
#include "sysfs.h"
|
||||
#include "nfs4idmap.h"
|
||||
#include "nfs4session.h"
|
||||
#include "fscache.h"
|
||||
@ -70,6 +71,10 @@
|
||||
|
||||
#include "nfs4trace.h"
|
||||
|
||||
#ifdef CONFIG_NFS_V4_2
|
||||
#include "nfs42.h"
|
||||
#endif /* CONFIG_NFS_V4_2 */
|
||||
|
||||
#define NFSDBG_FACILITY NFSDBG_PROC
|
||||
|
||||
#define NFS4_BITMASK_SZ 3
|
||||
@ -107,6 +112,9 @@ static int nfs41_test_stateid(struct nfs_server *, nfs4_stateid *,
|
||||
static int nfs41_free_stateid(struct nfs_server *, const nfs4_stateid *,
|
||||
const struct cred *, bool);
|
||||
#endif
|
||||
static void nfs4_bitmask_adjust(__u32 *bitmask, struct inode *inode,
|
||||
struct nfs_server *server,
|
||||
struct nfs4_label *label);
|
||||
|
||||
#ifdef CONFIG_NFS_V4_SECURITY_LABEL
|
||||
static inline struct nfs4_label *
|
||||
@ -1547,19 +1555,6 @@ static void nfs_state_log_update_open_stateid(struct nfs4_state *state)
|
||||
wake_up_all(&state->waitq);
|
||||
}
|
||||
|
||||
static void nfs_state_log_out_of_order_open_stateid(struct nfs4_state *state,
|
||||
const nfs4_stateid *stateid)
|
||||
{
|
||||
u32 state_seqid = be32_to_cpu(state->open_stateid.seqid);
|
||||
u32 stateid_seqid = be32_to_cpu(stateid->seqid);
|
||||
|
||||
if (stateid_seqid == state_seqid + 1U ||
|
||||
(stateid_seqid == 1U && state_seqid == 0xffffffffU))
|
||||
nfs_state_log_update_open_stateid(state);
|
||||
else
|
||||
set_bit(NFS_STATE_CHANGE_WAIT, &state->flags);
|
||||
}
|
||||
|
||||
static void nfs_test_and_clear_all_open_stateid(struct nfs4_state *state)
|
||||
{
|
||||
struct nfs_client *clp = state->owner->so_server->nfs_client;
|
||||
@ -1585,21 +1580,19 @@ static void nfs_test_and_clear_all_open_stateid(struct nfs4_state *state)
|
||||
* i.e. The stateid seqids have to be initialised to 1, and
|
||||
* are then incremented on every state transition.
|
||||
*/
|
||||
static bool nfs_need_update_open_stateid(struct nfs4_state *state,
|
||||
static bool nfs_stateid_is_sequential(struct nfs4_state *state,
|
||||
const nfs4_stateid *stateid)
|
||||
{
|
||||
if (test_bit(NFS_OPEN_STATE, &state->flags) == 0 ||
|
||||
!nfs4_stateid_match_other(stateid, &state->open_stateid)) {
|
||||
if (test_bit(NFS_OPEN_STATE, &state->flags)) {
|
||||
/* The common case - we're updating to a new sequence number */
|
||||
if (nfs4_stateid_match_other(stateid, &state->open_stateid) &&
|
||||
nfs4_stateid_is_next(&state->open_stateid, stateid)) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
/* This is the first OPEN in this generation */
|
||||
if (stateid->seqid == cpu_to_be32(1))
|
||||
nfs_state_log_update_open_stateid(state);
|
||||
else
|
||||
set_bit(NFS_STATE_CHANGE_WAIT, &state->flags);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (nfs4_stateid_is_newer(stateid, &state->open_stateid)) {
|
||||
nfs_state_log_out_of_order_open_stateid(state, stateid);
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -1673,16 +1666,16 @@ static void nfs_set_open_stateid_locked(struct nfs4_state *state,
|
||||
int status = 0;
|
||||
for (;;) {
|
||||
|
||||
if (!nfs_need_update_open_stateid(state, stateid))
|
||||
return;
|
||||
if (!test_bit(NFS_STATE_CHANGE_WAIT, &state->flags))
|
||||
if (nfs_stateid_is_sequential(state, stateid))
|
||||
break;
|
||||
|
||||
if (status)
|
||||
break;
|
||||
/* Rely on seqids for serialisation with NFSv4.0 */
|
||||
if (!nfs4_has_session(NFS_SERVER(state->inode)->nfs_client))
|
||||
break;
|
||||
|
||||
set_bit(NFS_STATE_CHANGE_WAIT, &state->flags);
|
||||
prepare_to_wait(&state->waitq, &wait, TASK_KILLABLE);
|
||||
/*
|
||||
* Ensure we process the state changes in the same order
|
||||
@ -1693,6 +1686,7 @@ static void nfs_set_open_stateid_locked(struct nfs4_state *state,
|
||||
spin_unlock(&state->owner->so_lock);
|
||||
rcu_read_unlock();
|
||||
trace_nfs4_open_stateid_update_wait(state->inode, stateid, 0);
|
||||
|
||||
if (!signal_pending(current)) {
|
||||
if (schedule_timeout(5*HZ) == 0)
|
||||
status = -EAGAIN;
|
||||
@ -3435,7 +3429,8 @@ static bool nfs4_refresh_open_old_stateid(nfs4_stateid *dst,
|
||||
__be32 seqid_open;
|
||||
u32 dst_seqid;
|
||||
bool ret;
|
||||
int seq;
|
||||
int seq, status = -EAGAIN;
|
||||
DEFINE_WAIT(wait);
|
||||
|
||||
for (;;) {
|
||||
ret = false;
|
||||
@ -3447,15 +3442,41 @@ static bool nfs4_refresh_open_old_stateid(nfs4_stateid *dst,
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
write_seqlock(&state->seqlock);
|
||||
seqid_open = state->open_stateid.seqid;
|
||||
if (read_seqretry(&state->seqlock, seq))
|
||||
continue;
|
||||
|
||||
dst_seqid = be32_to_cpu(dst->seqid);
|
||||
if ((s32)(dst_seqid - be32_to_cpu(seqid_open)) >= 0)
|
||||
dst->seqid = cpu_to_be32(dst_seqid + 1);
|
||||
else
|
||||
|
||||
/* Did another OPEN bump the state's seqid? try again: */
|
||||
if ((s32)(be32_to_cpu(seqid_open) - dst_seqid) > 0) {
|
||||
dst->seqid = seqid_open;
|
||||
write_sequnlock(&state->seqlock);
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
|
||||
/* server says we're behind but we haven't seen the update yet */
|
||||
set_bit(NFS_STATE_CHANGE_WAIT, &state->flags);
|
||||
prepare_to_wait(&state->waitq, &wait, TASK_KILLABLE);
|
||||
write_sequnlock(&state->seqlock);
|
||||
trace_nfs4_close_stateid_update_wait(state->inode, dst, 0);
|
||||
|
||||
if (signal_pending(current))
|
||||
status = -EINTR;
|
||||
else
|
||||
if (schedule_timeout(5*HZ) != 0)
|
||||
status = 0;
|
||||
|
||||
finish_wait(&state->waitq, &wait);
|
||||
|
||||
if (!status)
|
||||
continue;
|
||||
if (status == -EINTR)
|
||||
break;
|
||||
|
||||
/* we slept the whole 5 seconds, we must have lost a seqid */
|
||||
dst->seqid = cpu_to_be32(dst_seqid + 1);
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
@ -3632,9 +3653,10 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
|
||||
|
||||
if (calldata->arg.fmode == 0 || calldata->arg.fmode == FMODE_READ) {
|
||||
/* Close-to-open cache consistency revalidation */
|
||||
if (!nfs4_have_delegation(inode, FMODE_READ))
|
||||
if (!nfs4_have_delegation(inode, FMODE_READ)) {
|
||||
calldata->arg.bitmask = NFS_SERVER(inode)->cache_consistency_bitmask;
|
||||
else
|
||||
nfs4_bitmask_adjust(calldata->arg.bitmask, inode, NFS_SERVER(inode), NULL);
|
||||
} else
|
||||
calldata->arg.bitmask = NULL;
|
||||
}
|
||||
|
||||
@ -5255,28 +5277,60 @@ static bool nfs4_read_stateid_changed(struct rpc_task *task,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool nfs4_read_plus_not_supported(struct rpc_task *task,
|
||||
struct nfs_pgio_header *hdr)
|
||||
{
|
||||
struct nfs_server *server = NFS_SERVER(hdr->inode);
|
||||
struct rpc_message *msg = &task->tk_msg;
|
||||
|
||||
if (msg->rpc_proc == &nfs4_procedures[NFSPROC4_CLNT_READ_PLUS] &&
|
||||
server->caps & NFS_CAP_READ_PLUS && task->tk_status == -ENOTSUPP) {
|
||||
server->caps &= ~NFS_CAP_READ_PLUS;
|
||||
msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ];
|
||||
rpc_restart_call_prepare(task);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int nfs4_read_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
|
||||
{
|
||||
|
||||
dprintk("--> %s\n", __func__);
|
||||
|
||||
if (!nfs4_sequence_done(task, &hdr->res.seq_res))
|
||||
return -EAGAIN;
|
||||
if (nfs4_read_stateid_changed(task, &hdr->args))
|
||||
return -EAGAIN;
|
||||
if (nfs4_read_plus_not_supported(task, hdr))
|
||||
return -EAGAIN;
|
||||
if (task->tk_status > 0)
|
||||
nfs_invalidate_atime(hdr->inode);
|
||||
return hdr->pgio_done_cb ? hdr->pgio_done_cb(task, hdr) :
|
||||
nfs4_read_done_cb(task, hdr);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NFS_V4_2
|
||||
static void nfs42_read_plus_support(struct nfs_server *server, struct rpc_message *msg)
|
||||
{
|
||||
if (server->caps & NFS_CAP_READ_PLUS)
|
||||
msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ_PLUS];
|
||||
else
|
||||
msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ];
|
||||
}
|
||||
#else
|
||||
static void nfs42_read_plus_support(struct nfs_server *server, struct rpc_message *msg)
|
||||
{
|
||||
msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ];
|
||||
}
|
||||
#endif /* CONFIG_NFS_V4_2 */
|
||||
|
||||
static void nfs4_proc_read_setup(struct nfs_pgio_header *hdr,
|
||||
struct rpc_message *msg)
|
||||
{
|
||||
hdr->timestamp = jiffies;
|
||||
if (!hdr->pgio_done_cb)
|
||||
hdr->pgio_done_cb = nfs4_read_done_cb;
|
||||
msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ];
|
||||
nfs42_read_plus_support(NFS_SERVER(hdr->inode), msg);
|
||||
nfs4_init_sequence(&hdr->args.seq_args, &hdr->res.seq_res, 0, 0);
|
||||
}
|
||||
|
||||
@ -5360,6 +5414,38 @@ bool nfs4_write_need_cache_consistency_data(struct nfs_pgio_header *hdr)
|
||||
return nfs4_have_delegation(hdr->inode, FMODE_READ) == 0;
|
||||
}
|
||||
|
||||
static void nfs4_bitmask_adjust(__u32 *bitmask, struct inode *inode,
|
||||
struct nfs_server *server,
|
||||
struct nfs4_label *label)
|
||||
{
|
||||
|
||||
unsigned long cache_validity = READ_ONCE(NFS_I(inode)->cache_validity);
|
||||
|
||||
if ((cache_validity & NFS_INO_INVALID_DATA) ||
|
||||
(cache_validity & NFS_INO_REVAL_PAGECACHE) ||
|
||||
(cache_validity & NFS_INO_REVAL_FORCED) ||
|
||||
(cache_validity & NFS_INO_INVALID_OTHER))
|
||||
nfs4_bitmap_copy_adjust(bitmask, nfs4_bitmask(server, label), inode);
|
||||
|
||||
if (cache_validity & NFS_INO_INVALID_ATIME)
|
||||
bitmask[1] |= FATTR4_WORD1_TIME_ACCESS;
|
||||
if (cache_validity & NFS_INO_INVALID_ACCESS)
|
||||
bitmask[0] |= FATTR4_WORD1_MODE | FATTR4_WORD1_OWNER |
|
||||
FATTR4_WORD1_OWNER_GROUP;
|
||||
if (cache_validity & NFS_INO_INVALID_ACL)
|
||||
bitmask[0] |= FATTR4_WORD0_ACL;
|
||||
if (cache_validity & NFS_INO_INVALID_LABEL)
|
||||
bitmask[2] |= FATTR4_WORD2_SECURITY_LABEL;
|
||||
if (cache_validity & NFS_INO_INVALID_CTIME)
|
||||
bitmask[0] |= FATTR4_WORD0_CHANGE;
|
||||
if (cache_validity & NFS_INO_INVALID_MTIME)
|
||||
bitmask[1] |= FATTR4_WORD1_TIME_MODIFY;
|
||||
if (cache_validity & NFS_INO_INVALID_SIZE)
|
||||
bitmask[0] |= FATTR4_WORD0_SIZE;
|
||||
if (cache_validity & NFS_INO_INVALID_BLOCKS)
|
||||
bitmask[1] |= FATTR4_WORD1_SPACE_USED;
|
||||
}
|
||||
|
||||
static void nfs4_proc_write_setup(struct nfs_pgio_header *hdr,
|
||||
struct rpc_message *msg,
|
||||
struct rpc_clnt **clnt)
|
||||
@ -5369,8 +5455,10 @@ static void nfs4_proc_write_setup(struct nfs_pgio_header *hdr,
|
||||
if (!nfs4_write_need_cache_consistency_data(hdr)) {
|
||||
hdr->args.bitmask = NULL;
|
||||
hdr->res.fattr = NULL;
|
||||
} else
|
||||
} else {
|
||||
hdr->args.bitmask = server->cache_consistency_bitmask;
|
||||
nfs4_bitmask_adjust(hdr->args.bitmask, hdr->inode, server, NULL);
|
||||
}
|
||||
|
||||
if (!hdr->pgio_done_cb)
|
||||
hdr->pgio_done_cb = nfs4_write_done_cb;
|
||||
@ -6006,9 +6094,34 @@ static void nfs4_init_boot_verifier(const struct nfs_client *clp,
|
||||
memcpy(bootverf->data, verf, sizeof(bootverf->data));
|
||||
}
|
||||
|
||||
static size_t
|
||||
nfs4_get_uniquifier(struct nfs_client *clp, char *buf, size_t buflen)
|
||||
{
|
||||
struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id);
|
||||
struct nfs_netns_client *nn_clp = nn->nfs_client;
|
||||
const char *id;
|
||||
|
||||
buf[0] = '\0';
|
||||
|
||||
if (nn_clp) {
|
||||
rcu_read_lock();
|
||||
id = rcu_dereference(nn_clp->identifier);
|
||||
if (id)
|
||||
strscpy(buf, id, buflen);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
if (nfs4_client_id_uniquifier[0] != '\0' && buf[0] == '\0')
|
||||
strscpy(buf, nfs4_client_id_uniquifier, buflen);
|
||||
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
static int
|
||||
nfs4_init_nonuniform_client_string(struct nfs_client *clp)
|
||||
{
|
||||
char buf[NFS4_CLIENT_ID_UNIQ_LEN];
|
||||
size_t buflen;
|
||||
size_t len;
|
||||
char *str;
|
||||
|
||||
@ -6022,8 +6135,11 @@ nfs4_init_nonuniform_client_string(struct nfs_client *clp)
|
||||
strlen(rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR)) +
|
||||
1;
|
||||
rcu_read_unlock();
|
||||
if (nfs4_client_id_uniquifier[0] != '\0')
|
||||
len += strlen(nfs4_client_id_uniquifier) + 1;
|
||||
|
||||
buflen = nfs4_get_uniquifier(clp, buf, sizeof(buf));
|
||||
if (buflen)
|
||||
len += buflen + 1;
|
||||
|
||||
if (len > NFS4_OPAQUE_LIMIT + 1)
|
||||
return -EINVAL;
|
||||
|
||||
@ -6037,10 +6153,9 @@ nfs4_init_nonuniform_client_string(struct nfs_client *clp)
|
||||
return -ENOMEM;
|
||||
|
||||
rcu_read_lock();
|
||||
if (nfs4_client_id_uniquifier[0] != '\0')
|
||||
if (buflen)
|
||||
scnprintf(str, len, "Linux NFSv4.0 %s/%s/%s",
|
||||
clp->cl_rpcclient->cl_nodename,
|
||||
nfs4_client_id_uniquifier,
|
||||
clp->cl_rpcclient->cl_nodename, buf,
|
||||
rpc_peeraddr2str(clp->cl_rpcclient,
|
||||
RPC_DISPLAY_ADDR));
|
||||
else
|
||||
@ -6054,51 +6169,24 @@ nfs4_init_nonuniform_client_string(struct nfs_client *clp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nfs4_init_uniquifier_client_string(struct nfs_client *clp)
|
||||
{
|
||||
size_t len;
|
||||
char *str;
|
||||
|
||||
len = 10 + 10 + 1 + 10 + 1 +
|
||||
strlen(nfs4_client_id_uniquifier) + 1 +
|
||||
strlen(clp->cl_rpcclient->cl_nodename) + 1;
|
||||
|
||||
if (len > NFS4_OPAQUE_LIMIT + 1)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Since this string is allocated at mount time, and held until the
|
||||
* nfs_client is destroyed, we can use GFP_KERNEL here w/o worrying
|
||||
* about a memory-reclaim deadlock.
|
||||
*/
|
||||
str = kmalloc(len, GFP_KERNEL);
|
||||
if (!str)
|
||||
return -ENOMEM;
|
||||
|
||||
scnprintf(str, len, "Linux NFSv%u.%u %s/%s",
|
||||
clp->rpc_ops->version, clp->cl_minorversion,
|
||||
nfs4_client_id_uniquifier,
|
||||
clp->cl_rpcclient->cl_nodename);
|
||||
clp->cl_owner_id = str;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nfs4_init_uniform_client_string(struct nfs_client *clp)
|
||||
{
|
||||
char buf[NFS4_CLIENT_ID_UNIQ_LEN];
|
||||
size_t buflen;
|
||||
size_t len;
|
||||
char *str;
|
||||
|
||||
if (clp->cl_owner_id != NULL)
|
||||
return 0;
|
||||
|
||||
if (nfs4_client_id_uniquifier[0] != '\0')
|
||||
return nfs4_init_uniquifier_client_string(clp);
|
||||
|
||||
len = 10 + 10 + 1 + 10 + 1 +
|
||||
strlen(clp->cl_rpcclient->cl_nodename) + 1;
|
||||
|
||||
buflen = nfs4_get_uniquifier(clp, buf, sizeof(buf));
|
||||
if (buflen)
|
||||
len += buflen + 1;
|
||||
|
||||
if (len > NFS4_OPAQUE_LIMIT + 1)
|
||||
return -EINVAL;
|
||||
|
||||
@ -6111,9 +6199,14 @@ nfs4_init_uniform_client_string(struct nfs_client *clp)
|
||||
if (!str)
|
||||
return -ENOMEM;
|
||||
|
||||
scnprintf(str, len, "Linux NFSv%u.%u %s",
|
||||
clp->rpc_ops->version, clp->cl_minorversion,
|
||||
clp->cl_rpcclient->cl_nodename);
|
||||
if (buflen)
|
||||
scnprintf(str, len, "Linux NFSv%u.%u %s/%s",
|
||||
clp->rpc_ops->version, clp->cl_minorversion,
|
||||
buf, clp->cl_rpcclient->cl_nodename);
|
||||
else
|
||||
scnprintf(str, len, "Linux NFSv%u.%u %s",
|
||||
clp->rpc_ops->version, clp->cl_minorversion,
|
||||
clp->cl_rpcclient->cl_nodename);
|
||||
clp->cl_owner_id = str;
|
||||
return 0;
|
||||
}
|
||||
@ -6406,6 +6499,7 @@ static int _nfs4_proc_delegreturn(struct inode *inode, const struct cred *cred,
|
||||
data->args.fhandle = &data->fh;
|
||||
data->args.stateid = &data->stateid;
|
||||
data->args.bitmask = server->cache_consistency_bitmask;
|
||||
nfs4_bitmask_adjust(data->args.bitmask, inode, server, NULL);
|
||||
nfs_copy_fh(&data->fh, NFS_FH(inode));
|
||||
nfs4_stateid_copy(&data->stateid, stateid);
|
||||
data->res.fattr = &data->fattr;
|
||||
@ -7440,7 +7534,7 @@ nfs4_listxattr_nfs4_label(struct inode *inode, char *list, size_t list_len)
|
||||
|
||||
if (nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL)) {
|
||||
len = security_inode_listsecurity(inode, list, list_len);
|
||||
if (list_len && len > list_len)
|
||||
if (len >= 0 && list_len && len > list_len)
|
||||
return -ERANGE;
|
||||
}
|
||||
return len;
|
||||
@ -8039,9 +8133,11 @@ int nfs4_proc_secinfo(struct inode *dir, const struct qstr *name,
|
||||
* both PNFS and NON_PNFS flags set, and not having one of NON_PNFS, PNFS, or
|
||||
* DS flags set.
|
||||
*/
|
||||
static int nfs4_check_cl_exchange_flags(u32 flags)
|
||||
static int nfs4_check_cl_exchange_flags(u32 flags, u32 version)
|
||||
{
|
||||
if (flags & ~EXCHGID4_FLAG_MASK_R)
|
||||
if (version >= 2 && (flags & ~EXCHGID4_2_FLAG_MASK_R))
|
||||
goto out_inval;
|
||||
else if (version < 2 && (flags & ~EXCHGID4_FLAG_MASK_R))
|
||||
goto out_inval;
|
||||
if ((flags & EXCHGID4_FLAG_USE_PNFS_MDS) &&
|
||||
(flags & EXCHGID4_FLAG_USE_NON_PNFS))
|
||||
@ -8454,7 +8550,8 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, const struct cred *cre
|
||||
if (status != 0)
|
||||
goto out;
|
||||
|
||||
status = nfs4_check_cl_exchange_flags(resp->flags);
|
||||
status = nfs4_check_cl_exchange_flags(resp->flags,
|
||||
clp->cl_mvops->minor_version);
|
||||
if (status != 0)
|
||||
goto out;
|
||||
|
||||
@ -9693,7 +9790,6 @@ _nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle,
|
||||
.rpc_argp = &args,
|
||||
.rpc_resp = &res,
|
||||
};
|
||||
struct rpc_clnt *clnt = server->client;
|
||||
struct nfs4_call_sync_data data = {
|
||||
.seq_server = server,
|
||||
.seq_args = &args.seq_args,
|
||||
@ -9710,8 +9806,7 @@ _nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle,
|
||||
int status;
|
||||
|
||||
if (use_integrity) {
|
||||
clnt = server->nfs_client->cl_rpcclient;
|
||||
task_setup.rpc_client = clnt;
|
||||
task_setup.rpc_client = server->nfs_client->cl_rpcclient;
|
||||
|
||||
cred = nfs4_get_clid_cred(server->nfs_client);
|
||||
msg.rpc_cred = cred;
|
||||
@ -10165,7 +10260,8 @@ static const struct nfs4_minor_version_ops nfs_v4_2_minor_ops = {
|
||||
| NFS_CAP_SEEK
|
||||
| NFS_CAP_LAYOUTSTATS
|
||||
| NFS_CAP_CLONE
|
||||
| NFS_CAP_LAYOUTERROR,
|
||||
| NFS_CAP_LAYOUTERROR
|
||||
| NFS_CAP_READ_PLUS,
|
||||
.init_client = nfs41_init_client,
|
||||
.shutdown_client = nfs41_shutdown_client,
|
||||
.match_stateid = nfs41_match_stateid,
|
||||
|
@ -1511,6 +1511,7 @@ DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_setattr);
|
||||
DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_delegreturn);
|
||||
DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_open_stateid_update);
|
||||
DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_open_stateid_update_wait);
|
||||
DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_close_stateid_update_wait);
|
||||
|
||||
DECLARE_EVENT_CLASS(nfs4_getattr_event,
|
||||
TP_PROTO(
|
||||
|
@ -5308,7 +5308,6 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
|
||||
uint32_t attrlen,
|
||||
bitmap[3] = {0};
|
||||
int status;
|
||||
unsigned int pg_offset;
|
||||
|
||||
res->acl_len = 0;
|
||||
if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
|
||||
@ -5316,9 +5315,6 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
|
||||
|
||||
xdr_enter_page(xdr, xdr->buf->page_len);
|
||||
|
||||
/* Calculate the offset of the page data */
|
||||
pg_offset = xdr->buf->head[0].iov_len;
|
||||
|
||||
if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
|
||||
goto out;
|
||||
if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
|
||||
@ -5331,7 +5327,7 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
|
||||
/* The bitmap (xdr len + bitmaps) and the attr xdr len words
|
||||
* are stored with the acl data to handle the problem of
|
||||
* variable length bitmaps.*/
|
||||
res->acl_data_offset = xdr_stream_pos(xdr) - pg_offset;
|
||||
res->acl_data_offset = xdr_page_pos(xdr);
|
||||
res->acl_len = attrlen;
|
||||
|
||||
/* Check for receive buffer overflow */
|
||||
@ -7619,6 +7615,7 @@ const struct rpc_procinfo nfs4_procedures[] = {
|
||||
PROC42(SETXATTR, enc_setxattr, dec_setxattr),
|
||||
PROC42(LISTXATTRS, enc_listxattrs, dec_listxattrs),
|
||||
PROC42(REMOVEXATTR, enc_removexattr, dec_removexattr),
|
||||
PROC42(READ_PLUS, enc_read_plus, dec_read_plus),
|
||||
};
|
||||
|
||||
static unsigned int nfs_version4_counts[ARRAY_SIZE(nfs4_procedures)];
|
||||
|
@ -902,7 +902,7 @@ restart:
|
||||
}
|
||||
|
||||
/*
|
||||
* Called by the state manger to remove all layouts established under an
|
||||
* Called by the state manager to remove all layouts established under an
|
||||
* expired lease.
|
||||
*/
|
||||
void
|
||||
|
@ -889,7 +889,7 @@ static struct nfs_server *nfs_try_mount_request(struct fs_context *fc)
|
||||
default:
|
||||
if (rpcauth_get_gssinfo(flavor, &info) != 0)
|
||||
continue;
|
||||
/* Fallthrough */
|
||||
break;
|
||||
}
|
||||
dfprintk(MOUNT, "NFS: attempting to use auth flavor %u\n", flavor);
|
||||
ctx->selected_flavor = flavor;
|
||||
|
@ -79,7 +79,12 @@ static ssize_t nfs_netns_identifier_show(struct kobject *kobj,
|
||||
struct nfs_netns_client *c = container_of(kobj,
|
||||
struct nfs_netns_client,
|
||||
kobject);
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n", c->identifier);
|
||||
ssize_t ret;
|
||||
|
||||
rcu_read_lock();
|
||||
ret = scnprintf(buf, PAGE_SIZE, "%s\n", rcu_dereference(c->identifier));
|
||||
rcu_read_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Strip trailing '\n' */
|
||||
@ -107,7 +112,7 @@ static ssize_t nfs_netns_identifier_store(struct kobject *kobj,
|
||||
p = kmemdup_nul(buf, len, GFP_KERNEL);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
old = xchg(&c->identifier, p);
|
||||
old = rcu_dereference_protected(xchg(&c->identifier, (char __rcu *)p), 1);
|
||||
if (old) {
|
||||
synchronize_rcu();
|
||||
kfree(old);
|
||||
@ -121,7 +126,7 @@ static void nfs_netns_client_release(struct kobject *kobj)
|
||||
struct nfs_netns_client,
|
||||
kobject);
|
||||
|
||||
kfree(c->identifier);
|
||||
kfree(rcu_dereference_raw(c->identifier));
|
||||
kfree(c);
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
struct nfs_netns_client {
|
||||
struct kobject kobject;
|
||||
struct net *net;
|
||||
const char *identifier;
|
||||
const char __rcu *identifier;
|
||||
};
|
||||
|
||||
extern struct kobject *nfs_client_kobj;
|
||||
|
@ -551,13 +551,13 @@ enum {
|
||||
|
||||
NFSPROC4_CLNT_LOOKUPP,
|
||||
NFSPROC4_CLNT_LAYOUTERROR,
|
||||
|
||||
NFSPROC4_CLNT_COPY_NOTIFY,
|
||||
|
||||
NFSPROC4_CLNT_GETXATTR,
|
||||
NFSPROC4_CLNT_SETXATTR,
|
||||
NFSPROC4_CLNT_LISTXATTRS,
|
||||
NFSPROC4_CLNT_REMOVEXATTR,
|
||||
NFSPROC4_CLNT_READ_PLUS,
|
||||
};
|
||||
|
||||
/* nfs41 types */
|
||||
|
@ -287,5 +287,6 @@ struct nfs_server {
|
||||
#define NFS_CAP_LAYOUTERROR (1U << 26)
|
||||
#define NFS_CAP_COPY_NOTIFY (1U << 27)
|
||||
#define NFS_CAP_XATTR (1U << 28)
|
||||
#define NFS_CAP_READ_PLUS (1U << 29)
|
||||
|
||||
#endif
|
||||
|
@ -525,7 +525,7 @@ struct nfs_closeargs {
|
||||
struct nfs_seqid * seqid;
|
||||
fmode_t fmode;
|
||||
u32 share_access;
|
||||
const u32 * bitmask;
|
||||
u32 * bitmask;
|
||||
struct nfs4_layoutreturn_args *lr_args;
|
||||
};
|
||||
|
||||
@ -608,7 +608,7 @@ struct nfs4_delegreturnargs {
|
||||
struct nfs4_sequence_args seq_args;
|
||||
const struct nfs_fh *fhandle;
|
||||
const nfs4_stateid *stateid;
|
||||
const u32 * bitmask;
|
||||
u32 * bitmask;
|
||||
struct nfs4_layoutreturn_args *lr_args;
|
||||
};
|
||||
|
||||
@ -648,7 +648,7 @@ struct nfs_pgio_args {
|
||||
union {
|
||||
unsigned int replen; /* used by read */
|
||||
struct {
|
||||
const u32 * bitmask; /* used by write */
|
||||
u32 * bitmask; /* used by write */
|
||||
enum nfs3_stable_how stable; /* used by write */
|
||||
};
|
||||
};
|
||||
@ -657,7 +657,7 @@ struct nfs_pgio_args {
|
||||
struct nfs_pgio_res {
|
||||
struct nfs4_sequence_res seq_res;
|
||||
struct nfs_fattr * fattr;
|
||||
__u32 count;
|
||||
__u64 count;
|
||||
__u32 op_status;
|
||||
union {
|
||||
struct {
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
NetApp provides this source code under the GPL v2 License.
|
||||
The GPL v2 license is available at
|
||||
http://opensource.org/licenses/gpl-license.php.
|
||||
https://opensource.org/licenses/gpl-license.php.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
|
@ -45,7 +45,8 @@
|
||||
*/
|
||||
struct cache_head {
|
||||
struct hlist_node cache_list;
|
||||
time64_t expiry_time; /* After time time, don't use the data */
|
||||
time64_t expiry_time; /* After time expiry_time, don't use
|
||||
* the data */
|
||||
time64_t last_refresh; /* If CACHE_PENDING, this is when upcall was
|
||||
* sent, else this is when update was
|
||||
* received, though it is alway set to
|
||||
|
@ -143,7 +143,7 @@ typedef __be32 rpc_fraghdr;
|
||||
/*
|
||||
* Well-known netids. See:
|
||||
*
|
||||
* http://www.iana.org/assignments/rpc-netids/rpc-netids.xhtml
|
||||
* https://www.iana.org/assignments/rpc-netids/rpc-netids.xhtml
|
||||
*/
|
||||
#define RPCBIND_NETID_UDP "udp"
|
||||
#define RPCBIND_NETID_TCP "tcp"
|
||||
|
@ -240,6 +240,7 @@ extern int xdr_restrict_buflen(struct xdr_stream *xdr, int newbuflen);
|
||||
extern void xdr_write_pages(struct xdr_stream *xdr, struct page **pages,
|
||||
unsigned int base, unsigned int len);
|
||||
extern unsigned int xdr_stream_pos(const struct xdr_stream *xdr);
|
||||
extern unsigned int xdr_page_pos(const struct xdr_stream *xdr);
|
||||
extern void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf,
|
||||
__be32 *p, struct rpc_rqst *rqst);
|
||||
extern void xdr_init_decode_pages(struct xdr_stream *xdr, struct xdr_buf *buf,
|
||||
@ -249,6 +250,8 @@ extern __be32 *xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes);
|
||||
extern unsigned int xdr_read_pages(struct xdr_stream *xdr, unsigned int len);
|
||||
extern void xdr_enter_page(struct xdr_stream *xdr, unsigned int len);
|
||||
extern int xdr_process_buf(struct xdr_buf *buf, unsigned int offset, unsigned int len, int (*actor)(struct scatterlist *, void *), void *data);
|
||||
extern uint64_t xdr_align_data(struct xdr_stream *, uint64_t, uint32_t);
|
||||
extern uint64_t xdr_expand_hole(struct xdr_stream *, uint64_t, uint64_t);
|
||||
|
||||
/**
|
||||
* xdr_stream_remaining - Return the number of bytes remaining in the stream
|
||||
|
@ -424,7 +424,6 @@ DEFINE_CONN_EVENT(connect);
|
||||
DEFINE_CONN_EVENT(disconnect);
|
||||
|
||||
DEFINE_RXPRT_EVENT(xprtrdma_op_inject_dsc);
|
||||
DEFINE_RXPRT_EVENT(xprtrdma_op_setport);
|
||||
|
||||
TRACE_EVENT(xprtrdma_op_connect,
|
||||
TP_PROTO(
|
||||
@ -1188,68 +1187,6 @@ TRACE_EVENT(xprtrdma_decode_seg,
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
** Allocation/release of rpcrdma_reqs and rpcrdma_reps
|
||||
**/
|
||||
|
||||
TRACE_EVENT(xprtrdma_op_allocate,
|
||||
TP_PROTO(
|
||||
const struct rpc_task *task,
|
||||
const struct rpcrdma_req *req
|
||||
),
|
||||
|
||||
TP_ARGS(task, req),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned int, task_id)
|
||||
__field(unsigned int, client_id)
|
||||
__field(const void *, req)
|
||||
__field(size_t, callsize)
|
||||
__field(size_t, rcvsize)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->task_id = task->tk_pid;
|
||||
__entry->client_id = task->tk_client->cl_clid;
|
||||
__entry->req = req;
|
||||
__entry->callsize = task->tk_rqstp->rq_callsize;
|
||||
__entry->rcvsize = task->tk_rqstp->rq_rcvsize;
|
||||
),
|
||||
|
||||
TP_printk("task:%u@%u req=%p (%zu, %zu)",
|
||||
__entry->task_id, __entry->client_id,
|
||||
__entry->req, __entry->callsize, __entry->rcvsize
|
||||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(xprtrdma_op_free,
|
||||
TP_PROTO(
|
||||
const struct rpc_task *task,
|
||||
const struct rpcrdma_req *req
|
||||
),
|
||||
|
||||
TP_ARGS(task, req),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned int, task_id)
|
||||
__field(unsigned int, client_id)
|
||||
__field(const void *, req)
|
||||
__field(const void *, rep)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->task_id = task->tk_pid;
|
||||
__entry->client_id = task->tk_client->cl_clid;
|
||||
__entry->req = req;
|
||||
__entry->rep = req->rl_reply;
|
||||
),
|
||||
|
||||
TP_printk("task:%u@%u req=%p rep=%p",
|
||||
__entry->task_id, __entry->client_id,
|
||||
__entry->req, __entry->rep
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
** Callback events
|
||||
**/
|
||||
|
@ -259,8 +259,10 @@ DECLARE_EVENT_CLASS(rpc_task_status,
|
||||
TP_ARGS(task))
|
||||
|
||||
DEFINE_RPC_STATUS_EVENT(call);
|
||||
DEFINE_RPC_STATUS_EVENT(bind);
|
||||
DEFINE_RPC_STATUS_EVENT(connect);
|
||||
DEFINE_RPC_STATUS_EVENT(timeout);
|
||||
DEFINE_RPC_STATUS_EVENT(retry_refresh);
|
||||
DEFINE_RPC_STATUS_EVENT(refresh);
|
||||
|
||||
TRACE_EVENT(rpc_request,
|
||||
TP_PROTO(const struct rpc_task *task),
|
||||
@ -385,7 +387,10 @@ DECLARE_EVENT_CLASS(rpc_task_running,
|
||||
|
||||
DEFINE_RPC_RUNNING_EVENT(begin);
|
||||
DEFINE_RPC_RUNNING_EVENT(run_action);
|
||||
DEFINE_RPC_RUNNING_EVENT(sync_sleep);
|
||||
DEFINE_RPC_RUNNING_EVENT(sync_wake);
|
||||
DEFINE_RPC_RUNNING_EVENT(complete);
|
||||
DEFINE_RPC_RUNNING_EVENT(timeout);
|
||||
DEFINE_RPC_RUNNING_EVENT(signalled);
|
||||
DEFINE_RPC_RUNNING_EVENT(end);
|
||||
|
||||
@ -517,6 +522,49 @@ DEFINE_RPC_REPLY_EVENT(stale_creds);
|
||||
DEFINE_RPC_REPLY_EVENT(bad_creds);
|
||||
DEFINE_RPC_REPLY_EVENT(auth_tooweak);
|
||||
|
||||
#define DEFINE_RPCB_ERROR_EVENT(name) \
|
||||
DEFINE_EVENT(rpc_reply_event, rpcb_##name##_err, \
|
||||
TP_PROTO( \
|
||||
const struct rpc_task *task \
|
||||
), \
|
||||
TP_ARGS(task))
|
||||
|
||||
DEFINE_RPCB_ERROR_EVENT(prog_unavail);
|
||||
DEFINE_RPCB_ERROR_EVENT(timeout);
|
||||
DEFINE_RPCB_ERROR_EVENT(bind_version);
|
||||
DEFINE_RPCB_ERROR_EVENT(unreachable);
|
||||
DEFINE_RPCB_ERROR_EVENT(unrecognized);
|
||||
|
||||
TRACE_EVENT(rpc_buf_alloc,
|
||||
TP_PROTO(
|
||||
const struct rpc_task *task,
|
||||
int status
|
||||
),
|
||||
|
||||
TP_ARGS(task, status),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned int, task_id)
|
||||
__field(unsigned int, client_id)
|
||||
__field(size_t, callsize)
|
||||
__field(size_t, recvsize)
|
||||
__field(int, status)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->task_id = task->tk_pid;
|
||||
__entry->client_id = task->tk_client->cl_clid;
|
||||
__entry->callsize = task->tk_rqstp->rq_callsize;
|
||||
__entry->recvsize = task->tk_rqstp->rq_rcvsize;
|
||||
__entry->status = status;
|
||||
),
|
||||
|
||||
TP_printk("task:%u@%u callsize=%zu recvsize=%zu status=%d",
|
||||
__entry->task_id, __entry->client_id,
|
||||
__entry->callsize, __entry->recvsize, __entry->status
|
||||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(rpc_call_rpcerror,
|
||||
TP_PROTO(
|
||||
const struct rpc_task *task,
|
||||
@ -868,6 +916,34 @@ DEFINE_RPC_SOCKET_EVENT_DONE(rpc_socket_reset_connection);
|
||||
DEFINE_RPC_SOCKET_EVENT(rpc_socket_close);
|
||||
DEFINE_RPC_SOCKET_EVENT(rpc_socket_shutdown);
|
||||
|
||||
TRACE_EVENT(rpc_socket_nospace,
|
||||
TP_PROTO(
|
||||
const struct rpc_rqst *rqst,
|
||||
const struct sock_xprt *transport
|
||||
),
|
||||
|
||||
TP_ARGS(rqst, transport),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned int, task_id)
|
||||
__field(unsigned int, client_id)
|
||||
__field(unsigned int, total)
|
||||
__field(unsigned int, remaining)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->task_id = rqst->rq_task->tk_pid;
|
||||
__entry->client_id = rqst->rq_task->tk_client->cl_clid;
|
||||
__entry->total = rqst->rq_slen;
|
||||
__entry->remaining = rqst->rq_slen - transport->xmit.offset;
|
||||
),
|
||||
|
||||
TP_printk("task:%u@%u total=%u remaining=%u",
|
||||
__entry->task_id, __entry->client_id,
|
||||
__entry->total, __entry->remaining
|
||||
)
|
||||
);
|
||||
|
||||
TRACE_DEFINE_ENUM(XPRT_LOCKED);
|
||||
TRACE_DEFINE_ENUM(XPRT_CONNECTED);
|
||||
TRACE_DEFINE_ENUM(XPRT_CONNECTING);
|
||||
@ -925,6 +1001,7 @@ DECLARE_EVENT_CLASS(rpc_xprt_lifetime_class,
|
||||
TP_ARGS(xprt))
|
||||
|
||||
DEFINE_RPC_XPRT_LIFETIME_EVENT(create);
|
||||
DEFINE_RPC_XPRT_LIFETIME_EVENT(connect);
|
||||
DEFINE_RPC_XPRT_LIFETIME_EVENT(disconnect_auto);
|
||||
DEFINE_RPC_XPRT_LIFETIME_EVENT(disconnect_done);
|
||||
DEFINE_RPC_XPRT_LIFETIME_EVENT(disconnect_force);
|
||||
@ -969,7 +1046,6 @@ DECLARE_EVENT_CLASS(rpc_xprt_event,
|
||||
|
||||
DEFINE_RPC_XPRT_EVENT(timer);
|
||||
DEFINE_RPC_XPRT_EVENT(lookup_rqst);
|
||||
DEFINE_RPC_XPRT_EVENT(complete_rqst);
|
||||
|
||||
TRACE_EVENT(xprt_transmit,
|
||||
TP_PROTO(
|
||||
@ -1002,37 +1078,6 @@ TRACE_EVENT(xprt_transmit,
|
||||
__entry->seqno, __entry->status)
|
||||
);
|
||||
|
||||
TRACE_EVENT(xprt_enq_xmit,
|
||||
TP_PROTO(
|
||||
const struct rpc_task *task,
|
||||
int stage
|
||||
),
|
||||
|
||||
TP_ARGS(task, stage),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned int, task_id)
|
||||
__field(unsigned int, client_id)
|
||||
__field(u32, xid)
|
||||
__field(u32, seqno)
|
||||
__field(int, stage)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->task_id = task->tk_pid;
|
||||
__entry->client_id = task->tk_client ?
|
||||
task->tk_client->cl_clid : -1;
|
||||
__entry->xid = be32_to_cpu(task->tk_rqstp->rq_xid);
|
||||
__entry->seqno = task->tk_rqstp->rq_seqno;
|
||||
__entry->stage = stage;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"task:%u@%u xid=0x%08x seqno=%u stage=%d",
|
||||
__entry->task_id, __entry->client_id, __entry->xid,
|
||||
__entry->seqno, __entry->stage)
|
||||
);
|
||||
|
||||
TRACE_EVENT(xprt_ping,
|
||||
TP_PROTO(const struct rpc_xprt *xprt, int status),
|
||||
|
||||
@ -1095,6 +1140,7 @@ DECLARE_EVENT_CLASS(xprt_writelock_event,
|
||||
|
||||
DEFINE_WRITELOCK_EVENT(reserve_xprt);
|
||||
DEFINE_WRITELOCK_EVENT(release_xprt);
|
||||
DEFINE_WRITELOCK_EVENT(transmit_queued);
|
||||
|
||||
DECLARE_EVENT_CLASS(xprt_cong_event,
|
||||
TP_PROTO(
|
||||
@ -1147,6 +1193,30 @@ DEFINE_CONG_EVENT(release_cong);
|
||||
DEFINE_CONG_EVENT(get_cong);
|
||||
DEFINE_CONG_EVENT(put_cong);
|
||||
|
||||
TRACE_EVENT(xprt_reserve,
|
||||
TP_PROTO(
|
||||
const struct rpc_rqst *rqst
|
||||
),
|
||||
|
||||
TP_ARGS(rqst),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned int, task_id)
|
||||
__field(unsigned int, client_id)
|
||||
__field(u32, xid)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->task_id = rqst->rq_task->tk_pid;
|
||||
__entry->client_id = rqst->rq_task->tk_client->cl_clid;
|
||||
__entry->xid = be32_to_cpu(rqst->rq_xid);
|
||||
),
|
||||
|
||||
TP_printk("task:%u@%u xid=0x%08x",
|
||||
__entry->task_id, __entry->client_id, __entry->xid
|
||||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(xs_stream_read_data,
|
||||
TP_PROTO(struct rpc_xprt *xprt, ssize_t err, size_t total),
|
||||
|
||||
@ -1202,6 +1272,156 @@ TRACE_EVENT(xs_stream_read_request,
|
||||
__entry->copied, __entry->reclen, __entry->offset)
|
||||
);
|
||||
|
||||
TRACE_EVENT(rpcb_getport,
|
||||
TP_PROTO(
|
||||
const struct rpc_clnt *clnt,
|
||||
const struct rpc_task *task,
|
||||
unsigned int bind_version
|
||||
),
|
||||
|
||||
TP_ARGS(clnt, task, bind_version),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned int, task_id)
|
||||
__field(unsigned int, client_id)
|
||||
__field(unsigned int, program)
|
||||
__field(unsigned int, version)
|
||||
__field(int, protocol)
|
||||
__field(unsigned int, bind_version)
|
||||
__string(servername, task->tk_xprt->servername)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->task_id = task->tk_pid;
|
||||
__entry->client_id = clnt->cl_clid;
|
||||
__entry->program = clnt->cl_prog;
|
||||
__entry->version = clnt->cl_vers;
|
||||
__entry->protocol = task->tk_xprt->prot;
|
||||
__entry->bind_version = bind_version;
|
||||
__assign_str(servername, task->tk_xprt->servername);
|
||||
),
|
||||
|
||||
TP_printk("task:%u@%u server=%s program=%u version=%u protocol=%d bind_version=%u",
|
||||
__entry->task_id, __entry->client_id, __get_str(servername),
|
||||
__entry->program, __entry->version, __entry->protocol,
|
||||
__entry->bind_version
|
||||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(rpcb_setport,
|
||||
TP_PROTO(
|
||||
const struct rpc_task *task,
|
||||
int status,
|
||||
unsigned short port
|
||||
),
|
||||
|
||||
TP_ARGS(task, status, port),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned int, task_id)
|
||||
__field(unsigned int, client_id)
|
||||
__field(int, status)
|
||||
__field(unsigned short, port)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->task_id = task->tk_pid;
|
||||
__entry->client_id = task->tk_client->cl_clid;
|
||||
__entry->status = status;
|
||||
__entry->port = port;
|
||||
),
|
||||
|
||||
TP_printk("task:%u@%u status=%d port=%u",
|
||||
__entry->task_id, __entry->client_id,
|
||||
__entry->status, __entry->port
|
||||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(pmap_register,
|
||||
TP_PROTO(
|
||||
u32 program,
|
||||
u32 version,
|
||||
int protocol,
|
||||
unsigned short port
|
||||
),
|
||||
|
||||
TP_ARGS(program, version, protocol, port),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned int, program)
|
||||
__field(unsigned int, version)
|
||||
__field(int, protocol)
|
||||
__field(unsigned int, port)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->program = program;
|
||||
__entry->version = version;
|
||||
__entry->protocol = protocol;
|
||||
__entry->port = port;
|
||||
),
|
||||
|
||||
TP_printk("program=%u version=%u protocol=%d port=%u",
|
||||
__entry->program, __entry->version,
|
||||
__entry->protocol, __entry->port
|
||||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(rpcb_register,
|
||||
TP_PROTO(
|
||||
u32 program,
|
||||
u32 version,
|
||||
const char *addr,
|
||||
const char *netid
|
||||
),
|
||||
|
||||
TP_ARGS(program, version, addr, netid),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned int, program)
|
||||
__field(unsigned int, version)
|
||||
__string(addr, addr)
|
||||
__string(netid, netid)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->program = program;
|
||||
__entry->version = version;
|
||||
__assign_str(addr, addr);
|
||||
__assign_str(netid, netid);
|
||||
),
|
||||
|
||||
TP_printk("program=%u version=%u addr=%s netid=%s",
|
||||
__entry->program, __entry->version,
|
||||
__get_str(addr), __get_str(netid)
|
||||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(rpcb_unregister,
|
||||
TP_PROTO(
|
||||
u32 program,
|
||||
u32 version,
|
||||
const char *netid
|
||||
),
|
||||
|
||||
TP_ARGS(program, version, netid),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned int, program)
|
||||
__field(unsigned int, version)
|
||||
__string(netid, netid)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->program = program;
|
||||
__entry->version = version;
|
||||
__assign_str(netid, netid);
|
||||
),
|
||||
|
||||
TP_printk("program=%u version=%u netid=%s",
|
||||
__entry->program, __entry->version, __get_str(netid)
|
||||
)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(svc_xdr_buf_class,
|
||||
TP_PROTO(
|
||||
|
@ -139,6 +139,8 @@
|
||||
|
||||
#define EXCHGID4_FLAG_UPD_CONFIRMED_REC_A 0x40000000
|
||||
#define EXCHGID4_FLAG_CONFIRMED_R 0x80000000
|
||||
|
||||
#define EXCHGID4_FLAG_SUPP_FENCE_OPS 0x00000004
|
||||
/*
|
||||
* Since the validity of these bits depends on whether
|
||||
* they're set in the argument or response, have separate
|
||||
@ -146,6 +148,7 @@
|
||||
*/
|
||||
#define EXCHGID4_FLAG_MASK_A 0x40070103
|
||||
#define EXCHGID4_FLAG_MASK_R 0x80070103
|
||||
#define EXCHGID4_2_FLAG_MASK_R 0x80070107
|
||||
|
||||
#define SEQ4_STATUS_CB_PATH_DOWN 0x00000001
|
||||
#define SEQ4_STATUS_CB_GSS_CONTEXTS_EXPIRING 0x00000002
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
NetApp provides this source code under the GPL v2 License.
|
||||
The GPL v2 license is available at
|
||||
http://opensource.org/licenses/gpl-license.php.
|
||||
https://opensource.org/licenses/gpl-license.php.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
|
@ -47,10 +47,6 @@
|
||||
# define RPCDBG_FACILITY RPCDBG_CALL
|
||||
#endif
|
||||
|
||||
#define dprint_status(t) \
|
||||
dprintk("RPC: %5u %s (status %d)\n", t->tk_pid, \
|
||||
__func__, t->tk_status)
|
||||
|
||||
/*
|
||||
* All RPC clients are linked into this list
|
||||
*/
|
||||
@ -1639,10 +1635,6 @@ call_start(struct rpc_task *task)
|
||||
int idx = task->tk_msg.rpc_proc->p_statidx;
|
||||
|
||||
trace_rpc_request(task);
|
||||
dprintk("RPC: %5u call_start %s%d proc %s (%s)\n", task->tk_pid,
|
||||
clnt->cl_program->name, clnt->cl_vers,
|
||||
rpc_proc_name(task),
|
||||
(RPC_IS_ASYNC(task) ? "async" : "sync"));
|
||||
|
||||
/* Increment call count (version might not be valid for ping) */
|
||||
if (clnt->cl_program->version[clnt->cl_vers])
|
||||
@ -1658,8 +1650,6 @@ call_start(struct rpc_task *task)
|
||||
static void
|
||||
call_reserve(struct rpc_task *task)
|
||||
{
|
||||
dprint_status(task);
|
||||
|
||||
task->tk_status = 0;
|
||||
task->tk_action = call_reserveresult;
|
||||
xprt_reserve(task);
|
||||
@ -1675,8 +1665,6 @@ call_reserveresult(struct rpc_task *task)
|
||||
{
|
||||
int status = task->tk_status;
|
||||
|
||||
dprint_status(task);
|
||||
|
||||
/*
|
||||
* After a call to xprt_reserve(), we must have either
|
||||
* a request slot or else an error status.
|
||||
@ -1717,8 +1705,6 @@ call_reserveresult(struct rpc_task *task)
|
||||
static void
|
||||
call_retry_reserve(struct rpc_task *task)
|
||||
{
|
||||
dprint_status(task);
|
||||
|
||||
task->tk_status = 0;
|
||||
task->tk_action = call_reserveresult;
|
||||
xprt_retry_reserve(task);
|
||||
@ -1730,8 +1716,6 @@ call_retry_reserve(struct rpc_task *task)
|
||||
static void
|
||||
call_refresh(struct rpc_task *task)
|
||||
{
|
||||
dprint_status(task);
|
||||
|
||||
task->tk_action = call_refreshresult;
|
||||
task->tk_status = 0;
|
||||
task->tk_client->cl_stats->rpcauthrefresh++;
|
||||
@ -1746,8 +1730,6 @@ call_refreshresult(struct rpc_task *task)
|
||||
{
|
||||
int status = task->tk_status;
|
||||
|
||||
dprint_status(task);
|
||||
|
||||
task->tk_status = 0;
|
||||
task->tk_action = call_refresh;
|
||||
switch (status) {
|
||||
@ -1770,12 +1752,10 @@ call_refreshresult(struct rpc_task *task)
|
||||
if (!task->tk_cred_retry)
|
||||
break;
|
||||
task->tk_cred_retry--;
|
||||
dprintk("RPC: %5u %s: retry refresh creds\n",
|
||||
task->tk_pid, __func__);
|
||||
trace_rpc_retry_refresh_status(task);
|
||||
return;
|
||||
}
|
||||
dprintk("RPC: %5u %s: refresh creds failed with error %d\n",
|
||||
task->tk_pid, __func__, status);
|
||||
trace_rpc_refresh_status(task);
|
||||
rpc_call_rpcerror(task, status);
|
||||
}
|
||||
|
||||
@ -1792,8 +1772,6 @@ call_allocate(struct rpc_task *task)
|
||||
const struct rpc_procinfo *proc = task->tk_msg.rpc_proc;
|
||||
int status;
|
||||
|
||||
dprint_status(task);
|
||||
|
||||
task->tk_status = 0;
|
||||
task->tk_action = call_encode;
|
||||
|
||||
@ -1823,6 +1801,7 @@ call_allocate(struct rpc_task *task)
|
||||
req->rq_rcvsize <<= 2;
|
||||
|
||||
status = xprt->ops->buf_alloc(task);
|
||||
trace_rpc_buf_alloc(task, status);
|
||||
xprt_inject_disconnect(xprt);
|
||||
if (status == 0)
|
||||
return;
|
||||
@ -1831,8 +1810,6 @@ call_allocate(struct rpc_task *task)
|
||||
return;
|
||||
}
|
||||
|
||||
dprintk("RPC: %5u rpc_buffer allocation failed\n", task->tk_pid);
|
||||
|
||||
if (RPC_IS_ASYNC(task) || !fatal_signal_pending(current)) {
|
||||
task->tk_action = call_allocate;
|
||||
rpc_delay(task, HZ>>4);
|
||||
@ -1883,7 +1860,7 @@ call_encode(struct rpc_task *task)
|
||||
{
|
||||
if (!rpc_task_need_encode(task))
|
||||
goto out;
|
||||
dprint_status(task);
|
||||
|
||||
/* Dequeue task from the receive queue while we're encoding */
|
||||
xprt_request_dequeue_xprt(task);
|
||||
/* Encode here so that rpcsec_gss can use correct sequence number. */
|
||||
@ -1902,8 +1879,7 @@ call_encode(struct rpc_task *task)
|
||||
} else {
|
||||
task->tk_action = call_refresh;
|
||||
task->tk_cred_retry--;
|
||||
dprintk("RPC: %5u %s: retry refresh creds\n",
|
||||
task->tk_pid, __func__);
|
||||
trace_rpc_retry_refresh_status(task);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -1960,8 +1936,6 @@ call_bind(struct rpc_task *task)
|
||||
return;
|
||||
}
|
||||
|
||||
dprint_status(task);
|
||||
|
||||
task->tk_action = call_bind_status;
|
||||
if (!xprt_prepare_transmit(task))
|
||||
return;
|
||||
@ -1983,8 +1957,6 @@ call_bind_status(struct rpc_task *task)
|
||||
return;
|
||||
}
|
||||
|
||||
dprint_status(task);
|
||||
trace_rpc_bind_status(task);
|
||||
if (task->tk_status >= 0)
|
||||
goto out_next;
|
||||
if (xprt_bound(xprt)) {
|
||||
@ -1994,12 +1966,10 @@ call_bind_status(struct rpc_task *task)
|
||||
|
||||
switch (task->tk_status) {
|
||||
case -ENOMEM:
|
||||
dprintk("RPC: %5u rpcbind out of memory\n", task->tk_pid);
|
||||
rpc_delay(task, HZ >> 2);
|
||||
goto retry_timeout;
|
||||
case -EACCES:
|
||||
dprintk("RPC: %5u remote rpcbind: RPC program/version "
|
||||
"unavailable\n", task->tk_pid);
|
||||
trace_rpcb_prog_unavail_err(task);
|
||||
/* fail immediately if this is an RPC ping */
|
||||
if (task->tk_msg.rpc_proc->p_proc == 0) {
|
||||
status = -EOPNOTSUPP;
|
||||
@ -2016,17 +1986,14 @@ call_bind_status(struct rpc_task *task)
|
||||
case -EAGAIN:
|
||||
goto retry_timeout;
|
||||
case -ETIMEDOUT:
|
||||
dprintk("RPC: %5u rpcbind request timed out\n",
|
||||
task->tk_pid);
|
||||
trace_rpcb_timeout_err(task);
|
||||
goto retry_timeout;
|
||||
case -EPFNOSUPPORT:
|
||||
/* server doesn't support any rpcbind version we know of */
|
||||
dprintk("RPC: %5u unrecognized remote rpcbind service\n",
|
||||
task->tk_pid);
|
||||
trace_rpcb_bind_version_err(task);
|
||||
break;
|
||||
case -EPROTONOSUPPORT:
|
||||
dprintk("RPC: %5u remote rpcbind version unavailable, retrying\n",
|
||||
task->tk_pid);
|
||||
trace_rpcb_bind_version_err(task);
|
||||
goto retry_timeout;
|
||||
case -ECONNREFUSED: /* connection problems */
|
||||
case -ECONNRESET:
|
||||
@ -2037,8 +2004,7 @@ call_bind_status(struct rpc_task *task)
|
||||
case -EHOSTUNREACH:
|
||||
case -ENETUNREACH:
|
||||
case -EPIPE:
|
||||
dprintk("RPC: %5u remote rpcbind unreachable: %d\n",
|
||||
task->tk_pid, task->tk_status);
|
||||
trace_rpcb_unreachable_err(task);
|
||||
if (!RPC_IS_SOFTCONN(task)) {
|
||||
rpc_delay(task, 5*HZ);
|
||||
goto retry_timeout;
|
||||
@ -2046,8 +2012,7 @@ call_bind_status(struct rpc_task *task)
|
||||
status = task->tk_status;
|
||||
break;
|
||||
default:
|
||||
dprintk("RPC: %5u unrecognized rpcbind error (%d)\n",
|
||||
task->tk_pid, -task->tk_status);
|
||||
trace_rpcb_unrecognized_err(task);
|
||||
}
|
||||
|
||||
rpc_call_rpcerror(task, status);
|
||||
@ -2079,10 +2044,6 @@ call_connect(struct rpc_task *task)
|
||||
return;
|
||||
}
|
||||
|
||||
dprintk("RPC: %5u call_connect xprt %p %s connected\n",
|
||||
task->tk_pid, xprt,
|
||||
(xprt_connected(xprt) ? "is" : "is not"));
|
||||
|
||||
task->tk_action = call_connect_status;
|
||||
if (task->tk_status < 0)
|
||||
return;
|
||||
@ -2110,7 +2071,6 @@ call_connect_status(struct rpc_task *task)
|
||||
return;
|
||||
}
|
||||
|
||||
dprint_status(task);
|
||||
trace_rpc_connect_status(task);
|
||||
|
||||
if (task->tk_status == 0) {
|
||||
@ -2178,8 +2138,6 @@ call_transmit(struct rpc_task *task)
|
||||
return;
|
||||
}
|
||||
|
||||
dprint_status(task);
|
||||
|
||||
task->tk_action = call_transmit_status;
|
||||
if (!xprt_prepare_transmit(task))
|
||||
return;
|
||||
@ -2214,7 +2172,6 @@ call_transmit_status(struct rpc_task *task)
|
||||
|
||||
switch (task->tk_status) {
|
||||
default:
|
||||
dprint_status(task);
|
||||
break;
|
||||
case -EBADMSG:
|
||||
task->tk_status = 0;
|
||||
@ -2296,8 +2253,6 @@ call_bc_transmit_status(struct rpc_task *task)
|
||||
if (rpc_task_transmitted(task))
|
||||
task->tk_status = 0;
|
||||
|
||||
dprint_status(task);
|
||||
|
||||
switch (task->tk_status) {
|
||||
case 0:
|
||||
/* Success */
|
||||
@ -2357,8 +2312,6 @@ call_status(struct rpc_task *task)
|
||||
if (!task->tk_msg.rpc_proc->p_proc)
|
||||
trace_xprt_ping(task->tk_xprt, task->tk_status);
|
||||
|
||||
dprint_status(task);
|
||||
|
||||
status = task->tk_status;
|
||||
if (status >= 0) {
|
||||
task->tk_action = call_decode;
|
||||
@ -2405,7 +2358,8 @@ call_status(struct rpc_task *task)
|
||||
goto out_exit;
|
||||
}
|
||||
task->tk_action = call_encode;
|
||||
rpc_check_timeout(task);
|
||||
if (status != -ECONNRESET && status != -ECONNABORTED)
|
||||
rpc_check_timeout(task);
|
||||
return;
|
||||
out_exit:
|
||||
rpc_call_rpcerror(task, status);
|
||||
@ -2433,7 +2387,7 @@ rpc_check_timeout(struct rpc_task *task)
|
||||
if (xprt_adjust_timeout(task->tk_rqstp) == 0)
|
||||
return;
|
||||
|
||||
dprintk("RPC: %5u call_timeout (major)\n", task->tk_pid);
|
||||
trace_rpc_timeout_status(task);
|
||||
task->tk_timeouts++;
|
||||
|
||||
if (RPC_IS_SOFTCONN(task) && !rpc_check_connected(task->tk_rqstp)) {
|
||||
@ -2492,8 +2446,6 @@ call_decode(struct rpc_task *task)
|
||||
struct xdr_stream xdr;
|
||||
int err;
|
||||
|
||||
dprint_status(task);
|
||||
|
||||
if (!task->tk_msg.rpc_proc->p_decode) {
|
||||
task->tk_action = rpc_exit_task;
|
||||
return;
|
||||
@ -2537,8 +2489,6 @@ out:
|
||||
case 0:
|
||||
task->tk_action = rpc_exit_task;
|
||||
task->tk_status = rpcauth_unwrap_resp(task, &xdr);
|
||||
dprintk("RPC: %5u %s result %d\n",
|
||||
task->tk_pid, __func__, task->tk_status);
|
||||
return;
|
||||
case -EAGAIN:
|
||||
task->tk_status = 0;
|
||||
|
@ -31,11 +31,9 @@
|
||||
#include <linux/sunrpc/sched.h>
|
||||
#include <linux/sunrpc/xprtsock.h>
|
||||
|
||||
#include "netns.h"
|
||||
#include <trace/events/sunrpc.h>
|
||||
|
||||
#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
|
||||
# define RPCDBG_FACILITY RPCDBG_BIND
|
||||
#endif
|
||||
#include "netns.h"
|
||||
|
||||
#define RPCBIND_SOCK_PATHNAME "/var/run/rpcbind.sock"
|
||||
|
||||
@ -216,10 +214,6 @@ static void rpcb_set_local(struct net *net, struct rpc_clnt *clnt,
|
||||
sn->rpcb_is_af_local = is_af_local ? 1 : 0;
|
||||
smp_wmb();
|
||||
sn->rpcb_users = 1;
|
||||
dprintk("RPC: created new rpcb local clients (rpcb_local_clnt: "
|
||||
"%p, rpcb_local_clnt4: %p) for net %x%s\n",
|
||||
sn->rpcb_local_clnt, sn->rpcb_local_clnt4,
|
||||
net->ns.inum, (net == &init_net) ? " (init_net)" : "");
|
||||
}
|
||||
|
||||
/*
|
||||
@ -261,19 +255,13 @@ static int rpcb_create_local_unix(struct net *net)
|
||||
*/
|
||||
clnt = rpc_create(&args);
|
||||
if (IS_ERR(clnt)) {
|
||||
dprintk("RPC: failed to create AF_LOCAL rpcbind "
|
||||
"client (errno %ld).\n", PTR_ERR(clnt));
|
||||
result = PTR_ERR(clnt);
|
||||
goto out;
|
||||
}
|
||||
|
||||
clnt4 = rpc_bind_new_program(clnt, &rpcb_program, RPCBVERS_4);
|
||||
if (IS_ERR(clnt4)) {
|
||||
dprintk("RPC: failed to bind second program to "
|
||||
"rpcbind v4 client (errno %ld).\n",
|
||||
PTR_ERR(clnt4));
|
||||
if (IS_ERR(clnt4))
|
||||
clnt4 = NULL;
|
||||
}
|
||||
|
||||
rpcb_set_local(net, clnt, clnt4, true);
|
||||
|
||||
@ -309,8 +297,6 @@ static int rpcb_create_local_net(struct net *net)
|
||||
|
||||
clnt = rpc_create(&args);
|
||||
if (IS_ERR(clnt)) {
|
||||
dprintk("RPC: failed to create local rpcbind "
|
||||
"client (errno %ld).\n", PTR_ERR(clnt));
|
||||
result = PTR_ERR(clnt);
|
||||
goto out;
|
||||
}
|
||||
@ -321,12 +307,8 @@ static int rpcb_create_local_net(struct net *net)
|
||||
* v4 upcalls.
|
||||
*/
|
||||
clnt4 = rpc_bind_new_program(clnt, &rpcb_program, RPCBVERS_4);
|
||||
if (IS_ERR(clnt4)) {
|
||||
dprintk("RPC: failed to bind second program to "
|
||||
"rpcbind v4 client (errno %ld).\n",
|
||||
PTR_ERR(clnt4));
|
||||
if (IS_ERR(clnt4))
|
||||
clnt4 = NULL;
|
||||
}
|
||||
|
||||
rpcb_set_local(net, clnt, clnt4, false);
|
||||
|
||||
@ -403,11 +385,8 @@ static int rpcb_register_call(struct sunrpc_net *sn, struct rpc_clnt *clnt, stru
|
||||
msg->rpc_resp = &result;
|
||||
|
||||
error = rpc_call_sync(clnt, msg, flags);
|
||||
if (error < 0) {
|
||||
dprintk("RPC: failed to contact local rpcbind "
|
||||
"server (errno %d).\n", -error);
|
||||
if (error < 0)
|
||||
return error;
|
||||
}
|
||||
|
||||
if (!result)
|
||||
return -EACCES;
|
||||
@ -461,9 +440,7 @@ int rpcb_register(struct net *net, u32 prog, u32 vers, int prot, unsigned short
|
||||
struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
|
||||
bool is_set = false;
|
||||
|
||||
dprintk("RPC: %sregistering (%u, %u, %d, %u) with local "
|
||||
"rpcbind\n", (port ? "" : "un"),
|
||||
prog, vers, prot, port);
|
||||
trace_pmap_register(prog, vers, prot, port);
|
||||
|
||||
msg.rpc_proc = &rpcb_procedures2[RPCBPROC_UNSET];
|
||||
if (port != 0) {
|
||||
@ -489,11 +466,6 @@ static int rpcb_register_inet4(struct sunrpc_net *sn,
|
||||
|
||||
map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL);
|
||||
|
||||
dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with "
|
||||
"local rpcbind\n", (port ? "" : "un"),
|
||||
map->r_prog, map->r_vers,
|
||||
map->r_addr, map->r_netid);
|
||||
|
||||
msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET];
|
||||
if (port != 0) {
|
||||
msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET];
|
||||
@ -520,11 +492,6 @@ static int rpcb_register_inet6(struct sunrpc_net *sn,
|
||||
|
||||
map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL);
|
||||
|
||||
dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with "
|
||||
"local rpcbind\n", (port ? "" : "un"),
|
||||
map->r_prog, map->r_vers,
|
||||
map->r_addr, map->r_netid);
|
||||
|
||||
msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET];
|
||||
if (port != 0) {
|
||||
msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET];
|
||||
@ -541,9 +508,7 @@ static int rpcb_unregister_all_protofamilies(struct sunrpc_net *sn,
|
||||
{
|
||||
struct rpcbind_args *map = msg->rpc_argp;
|
||||
|
||||
dprintk("RPC: unregistering [%u, %u, '%s'] with "
|
||||
"local rpcbind\n",
|
||||
map->r_prog, map->r_vers, map->r_netid);
|
||||
trace_rpcb_unregister(map->r_prog, map->r_vers, map->r_netid);
|
||||
|
||||
map->r_addr = "";
|
||||
msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET];
|
||||
@ -615,6 +580,8 @@ int rpcb_v4_register(struct net *net, const u32 program, const u32 version,
|
||||
if (address == NULL)
|
||||
return rpcb_unregister_all_protofamilies(sn, &msg);
|
||||
|
||||
trace_rpcb_register(map.r_prog, map.r_vers, map.r_addr, map.r_netid);
|
||||
|
||||
switch (address->sa_family) {
|
||||
case AF_INET:
|
||||
return rpcb_register_inet4(sn, address, &msg);
|
||||
@ -693,18 +660,12 @@ void rpcb_getport_async(struct rpc_task *task)
|
||||
rcu_read_unlock();
|
||||
xprt = xprt_get(task->tk_xprt);
|
||||
|
||||
dprintk("RPC: %5u %s(%s, %u, %u, %d)\n",
|
||||
task->tk_pid, __func__,
|
||||
xprt->servername, clnt->cl_prog, clnt->cl_vers, xprt->prot);
|
||||
|
||||
/* Put self on the wait queue to ensure we get notified if
|
||||
* some other task is already attempting to bind the port */
|
||||
rpc_sleep_on_timeout(&xprt->binding, task,
|
||||
NULL, jiffies + xprt->bind_timeout);
|
||||
|
||||
if (xprt_test_and_set_binding(xprt)) {
|
||||
dprintk("RPC: %5u %s: waiting for another binder\n",
|
||||
task->tk_pid, __func__);
|
||||
xprt_put(xprt);
|
||||
return;
|
||||
}
|
||||
@ -712,8 +673,6 @@ void rpcb_getport_async(struct rpc_task *task)
|
||||
/* Someone else may have bound if we slept */
|
||||
if (xprt_bound(xprt)) {
|
||||
status = 0;
|
||||
dprintk("RPC: %5u %s: already bound\n",
|
||||
task->tk_pid, __func__);
|
||||
goto bailout_nofree;
|
||||
}
|
||||
|
||||
@ -732,20 +691,15 @@ void rpcb_getport_async(struct rpc_task *task)
|
||||
break;
|
||||
default:
|
||||
status = -EAFNOSUPPORT;
|
||||
dprintk("RPC: %5u %s: bad address family\n",
|
||||
task->tk_pid, __func__);
|
||||
goto bailout_nofree;
|
||||
}
|
||||
if (proc == NULL) {
|
||||
xprt->bind_index = 0;
|
||||
status = -EPFNOSUPPORT;
|
||||
dprintk("RPC: %5u %s: no more getport versions available\n",
|
||||
task->tk_pid, __func__);
|
||||
goto bailout_nofree;
|
||||
}
|
||||
|
||||
dprintk("RPC: %5u %s: trying rpcbind version %u\n",
|
||||
task->tk_pid, __func__, bind_version);
|
||||
trace_rpcb_getport(clnt, task, bind_version);
|
||||
|
||||
rpcb_clnt = rpcb_create(xprt->xprt_net,
|
||||
clnt->cl_nodename,
|
||||
@ -754,16 +708,12 @@ void rpcb_getport_async(struct rpc_task *task)
|
||||
clnt->cl_cred);
|
||||
if (IS_ERR(rpcb_clnt)) {
|
||||
status = PTR_ERR(rpcb_clnt);
|
||||
dprintk("RPC: %5u %s: rpcb_create failed, error %ld\n",
|
||||
task->tk_pid, __func__, PTR_ERR(rpcb_clnt));
|
||||
goto bailout_nofree;
|
||||
}
|
||||
|
||||
map = kzalloc(sizeof(struct rpcbind_args), GFP_NOFS);
|
||||
if (!map) {
|
||||
status = -ENOMEM;
|
||||
dprintk("RPC: %5u %s: no memory available\n",
|
||||
task->tk_pid, __func__);
|
||||
goto bailout_release_client;
|
||||
}
|
||||
map->r_prog = clnt->cl_prog;
|
||||
@ -780,8 +730,6 @@ void rpcb_getport_async(struct rpc_task *task)
|
||||
map->r_addr = rpc_sockaddr2uaddr(sap, GFP_NOFS);
|
||||
if (!map->r_addr) {
|
||||
status = -ENOMEM;
|
||||
dprintk("RPC: %5u %s: no memory available\n",
|
||||
task->tk_pid, __func__);
|
||||
goto bailout_free_args;
|
||||
}
|
||||
map->r_owner = "";
|
||||
@ -818,34 +766,33 @@ static void rpcb_getport_done(struct rpc_task *child, void *data)
|
||||
{
|
||||
struct rpcbind_args *map = data;
|
||||
struct rpc_xprt *xprt = map->r_xprt;
|
||||
int status = child->tk_status;
|
||||
|
||||
map->r_status = child->tk_status;
|
||||
|
||||
/* Garbage reply: retry with a lesser rpcbind version */
|
||||
if (status == -EIO)
|
||||
status = -EPROTONOSUPPORT;
|
||||
if (map->r_status == -EIO)
|
||||
map->r_status = -EPROTONOSUPPORT;
|
||||
|
||||
/* rpcbind server doesn't support this rpcbind protocol version */
|
||||
if (status == -EPROTONOSUPPORT)
|
||||
if (map->r_status == -EPROTONOSUPPORT)
|
||||
xprt->bind_index++;
|
||||
|
||||
if (status < 0) {
|
||||
if (map->r_status < 0) {
|
||||
/* rpcbind server not available on remote host? */
|
||||
xprt->ops->set_port(xprt, 0);
|
||||
map->r_port = 0;
|
||||
|
||||
} else if (map->r_port == 0) {
|
||||
/* Requested RPC service wasn't registered on remote host */
|
||||
xprt->ops->set_port(xprt, 0);
|
||||
status = -EACCES;
|
||||
map->r_status = -EACCES;
|
||||
} else {
|
||||
/* Succeeded */
|
||||
xprt->ops->set_port(xprt, map->r_port);
|
||||
xprt_set_bound(xprt);
|
||||
status = 0;
|
||||
map->r_status = 0;
|
||||
}
|
||||
|
||||
dprintk("RPC: %5u rpcb_getport_done(status %d, port %u)\n",
|
||||
child->tk_pid, status, map->r_port);
|
||||
|
||||
map->r_status = status;
|
||||
trace_rpcb_setport(child, map->r_status, map->r_port);
|
||||
xprt->ops->set_port(xprt, map->r_port);
|
||||
if (map->r_port)
|
||||
xprt_set_bound(xprt);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -858,11 +805,6 @@ static void rpcb_enc_mapping(struct rpc_rqst *req, struct xdr_stream *xdr,
|
||||
const struct rpcbind_args *rpcb = data;
|
||||
__be32 *p;
|
||||
|
||||
dprintk("RPC: %5u encoding PMAP_%s call (%u, %u, %d, %u)\n",
|
||||
req->rq_task->tk_pid,
|
||||
req->rq_task->tk_msg.rpc_proc->p_name,
|
||||
rpcb->r_prog, rpcb->r_vers, rpcb->r_prot, rpcb->r_port);
|
||||
|
||||
p = xdr_reserve_space(xdr, RPCB_mappingargs_sz << 2);
|
||||
*p++ = cpu_to_be32(rpcb->r_prog);
|
||||
*p++ = cpu_to_be32(rpcb->r_vers);
|
||||
@ -884,8 +826,6 @@ static int rpcb_dec_getport(struct rpc_rqst *req, struct xdr_stream *xdr,
|
||||
return -EIO;
|
||||
|
||||
port = be32_to_cpup(p);
|
||||
dprintk("RPC: %5u PMAP_%s result: %lu\n", req->rq_task->tk_pid,
|
||||
req->rq_task->tk_msg.rpc_proc->p_name, port);
|
||||
if (unlikely(port > USHRT_MAX))
|
||||
return -EIO;
|
||||
|
||||
@ -906,11 +846,6 @@ static int rpcb_dec_set(struct rpc_rqst *req, struct xdr_stream *xdr,
|
||||
*boolp = 0;
|
||||
if (*p != xdr_zero)
|
||||
*boolp = 1;
|
||||
|
||||
dprintk("RPC: %5u RPCB_%s call %s\n",
|
||||
req->rq_task->tk_pid,
|
||||
req->rq_task->tk_msg.rpc_proc->p_name,
|
||||
(*boolp ? "succeeded" : "failed"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -935,12 +870,6 @@ static void rpcb_enc_getaddr(struct rpc_rqst *req, struct xdr_stream *xdr,
|
||||
const struct rpcbind_args *rpcb = data;
|
||||
__be32 *p;
|
||||
|
||||
dprintk("RPC: %5u encoding RPCB_%s call (%u, %u, '%s', '%s')\n",
|
||||
req->rq_task->tk_pid,
|
||||
req->rq_task->tk_msg.rpc_proc->p_name,
|
||||
rpcb->r_prog, rpcb->r_vers,
|
||||
rpcb->r_netid, rpcb->r_addr);
|
||||
|
||||
p = xdr_reserve_space(xdr, (RPCB_program_sz + RPCB_version_sz) << 2);
|
||||
*p++ = cpu_to_be32(rpcb->r_prog);
|
||||
*p = cpu_to_be32(rpcb->r_vers);
|
||||
@ -970,11 +899,8 @@ static int rpcb_dec_getaddr(struct rpc_rqst *req, struct xdr_stream *xdr,
|
||||
* If the returned universal address is a null string,
|
||||
* the requested RPC service was not registered.
|
||||
*/
|
||||
if (len == 0) {
|
||||
dprintk("RPC: %5u RPCB reply: program not registered\n",
|
||||
req->rq_task->tk_pid);
|
||||
if (len == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (unlikely(len > RPCBIND_MAXUADDRLEN))
|
||||
goto out_fail;
|
||||
@ -982,8 +908,6 @@ static int rpcb_dec_getaddr(struct rpc_rqst *req, struct xdr_stream *xdr,
|
||||
p = xdr_inline_decode(xdr, len);
|
||||
if (unlikely(p == NULL))
|
||||
goto out_fail;
|
||||
dprintk("RPC: %5u RPCB_%s reply: %*pE\n", req->rq_task->tk_pid,
|
||||
req->rq_task->tk_msg.rpc_proc->p_name, len, (char *)p);
|
||||
|
||||
if (rpc_uaddr2sockaddr(req->rq_xprt->xprt_net, (char *)p, len,
|
||||
sap, sizeof(address)) == 0)
|
||||
@ -993,9 +917,6 @@ static int rpcb_dec_getaddr(struct rpc_rqst *req, struct xdr_stream *xdr,
|
||||
return 0;
|
||||
|
||||
out_fail:
|
||||
dprintk("RPC: %5u malformed RPCB_%s reply\n",
|
||||
req->rq_task->tk_pid,
|
||||
req->rq_task->tk_msg.rpc_proc->p_name);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
@ -27,10 +27,6 @@
|
||||
|
||||
#include "sunrpc.h"
|
||||
|
||||
#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
|
||||
#define RPCDBG_FACILITY RPCDBG_SCHED
|
||||
#endif
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include <trace/events/sunrpc.h>
|
||||
|
||||
@ -85,7 +81,6 @@ __rpc_disable_timer(struct rpc_wait_queue *queue, struct rpc_task *task)
|
||||
{
|
||||
if (list_empty(&task->u.tk_wait.timer_list))
|
||||
return;
|
||||
dprintk("RPC: %5u disabling timer\n", task->tk_pid);
|
||||
task->tk_timeout = 0;
|
||||
list_del(&task->u.tk_wait.timer_list);
|
||||
if (list_empty(&queue->timer_list.list))
|
||||
@ -111,9 +106,6 @@ static void
|
||||
__rpc_add_timer(struct rpc_wait_queue *queue, struct rpc_task *task,
|
||||
unsigned long timeout)
|
||||
{
|
||||
dprintk("RPC: %5u setting alarm for %u ms\n",
|
||||
task->tk_pid, jiffies_to_msecs(timeout - jiffies));
|
||||
|
||||
task->tk_timeout = timeout;
|
||||
if (list_empty(&queue->timer_list.list) || time_before(timeout, queue->timer_list.expires))
|
||||
rpc_set_queue_timer(queue, timeout);
|
||||
@ -216,9 +208,6 @@ static void __rpc_add_wait_queue(struct rpc_wait_queue *queue,
|
||||
/* barrier matches the read in rpc_wake_up_task_queue_locked() */
|
||||
smp_wmb();
|
||||
rpc_set_queued(task);
|
||||
|
||||
dprintk("RPC: %5u added to queue %p \"%s\"\n",
|
||||
task->tk_pid, queue, rpc_qname(queue));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -241,8 +230,6 @@ static void __rpc_remove_wait_queue(struct rpc_wait_queue *queue, struct rpc_tas
|
||||
else
|
||||
list_del(&task->u.tk_wait.list);
|
||||
queue->qlen--;
|
||||
dprintk("RPC: %5u removed from queue %p \"%s\"\n",
|
||||
task->tk_pid, queue, rpc_qname(queue));
|
||||
}
|
||||
|
||||
static void __rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const char *qname, unsigned char nr_queues)
|
||||
@ -382,13 +369,9 @@ static void __rpc_do_sleep_on_priority(struct rpc_wait_queue *q,
|
||||
struct rpc_task *task,
|
||||
unsigned char queue_priority)
|
||||
{
|
||||
dprintk("RPC: %5u sleep_on(queue \"%s\" time %lu)\n",
|
||||
task->tk_pid, rpc_qname(q), jiffies);
|
||||
|
||||
trace_rpc_task_sleep(task, q);
|
||||
|
||||
__rpc_add_wait_queue(q, task, queue_priority);
|
||||
|
||||
}
|
||||
|
||||
static void __rpc_sleep_on_priority(struct rpc_wait_queue *q,
|
||||
@ -510,9 +493,6 @@ static void __rpc_do_wake_up_task_on_wq(struct workqueue_struct *wq,
|
||||
struct rpc_wait_queue *queue,
|
||||
struct rpc_task *task)
|
||||
{
|
||||
dprintk("RPC: %5u __rpc_wake_up_task (now %lu)\n",
|
||||
task->tk_pid, jiffies);
|
||||
|
||||
/* Has the task been executed yet? If not, we cannot wake it up! */
|
||||
if (!RPC_IS_ACTIVATED(task)) {
|
||||
printk(KERN_ERR "RPC: Inactive task (%p) being woken up!\n", task);
|
||||
@ -524,8 +504,6 @@ static void __rpc_do_wake_up_task_on_wq(struct workqueue_struct *wq,
|
||||
__rpc_remove_wait_queue(queue, task);
|
||||
|
||||
rpc_make_runnable(wq, task);
|
||||
|
||||
dprintk("RPC: __rpc_wake_up_task done\n");
|
||||
}
|
||||
|
||||
/*
|
||||
@ -663,8 +641,6 @@ struct rpc_task *rpc_wake_up_first_on_wq(struct workqueue_struct *wq,
|
||||
{
|
||||
struct rpc_task *task = NULL;
|
||||
|
||||
dprintk("RPC: wake_up_first(%p \"%s\")\n",
|
||||
queue, rpc_qname(queue));
|
||||
spin_lock(&queue->lock);
|
||||
task = __rpc_find_next_queued(queue);
|
||||
if (task != NULL)
|
||||
@ -770,7 +746,7 @@ static void __rpc_queue_timer_fn(struct work_struct *work)
|
||||
list_for_each_entry_safe(task, n, &queue->timer_list.list, u.tk_wait.timer_list) {
|
||||
timeo = task->tk_timeout;
|
||||
if (time_after_eq(now, timeo)) {
|
||||
dprintk("RPC: %5u timeout\n", task->tk_pid);
|
||||
trace_rpc_task_timeout(task, task->tk_action);
|
||||
task->tk_status = -ETIMEDOUT;
|
||||
rpc_wake_up_task_queue_locked(queue, task);
|
||||
continue;
|
||||
@ -885,9 +861,6 @@ static void __rpc_execute(struct rpc_task *task)
|
||||
int task_is_async = RPC_IS_ASYNC(task);
|
||||
int status = 0;
|
||||
|
||||
dprintk("RPC: %5u __rpc_execute flags=0x%x\n",
|
||||
task->tk_pid, task->tk_flags);
|
||||
|
||||
WARN_ON_ONCE(RPC_IS_QUEUED(task));
|
||||
if (RPC_IS_QUEUED(task))
|
||||
return;
|
||||
@ -947,7 +920,7 @@ static void __rpc_execute(struct rpc_task *task)
|
||||
return;
|
||||
|
||||
/* sync task: sleep here */
|
||||
dprintk("RPC: %5u sync task going to sleep\n", task->tk_pid);
|
||||
trace_rpc_task_sync_sleep(task, task->tk_action);
|
||||
status = out_of_line_wait_on_bit(&task->tk_runstate,
|
||||
RPC_TASK_QUEUED, rpc_wait_bit_killable,
|
||||
TASK_KILLABLE);
|
||||
@ -963,11 +936,9 @@ static void __rpc_execute(struct rpc_task *task)
|
||||
task->tk_rpc_status = -ERESTARTSYS;
|
||||
rpc_exit(task, -ERESTARTSYS);
|
||||
}
|
||||
dprintk("RPC: %5u sync task resuming\n", task->tk_pid);
|
||||
trace_rpc_task_sync_wake(task, task->tk_action);
|
||||
}
|
||||
|
||||
dprintk("RPC: %5u return %d, status %d\n", task->tk_pid, status,
|
||||
task->tk_status);
|
||||
/* Release all resources associated with the task */
|
||||
rpc_release_task(task);
|
||||
}
|
||||
@ -1036,8 +1007,6 @@ int rpc_malloc(struct rpc_task *task)
|
||||
return -ENOMEM;
|
||||
|
||||
buf->len = size;
|
||||
dprintk("RPC: %5u allocated buffer of size %zu at %p\n",
|
||||
task->tk_pid, size, buf);
|
||||
rqst->rq_buffer = buf->data;
|
||||
rqst->rq_rbuffer = (char *)rqst->rq_buffer + rqst->rq_callsize;
|
||||
return 0;
|
||||
@ -1058,9 +1027,6 @@ void rpc_free(struct rpc_task *task)
|
||||
buf = container_of(buffer, struct rpc_buffer, data);
|
||||
size = buf->len;
|
||||
|
||||
dprintk("RPC: freeing buffer of size %zu at %p\n",
|
||||
size, buf);
|
||||
|
||||
if (size <= RPC_BUFFER_MAXSIZE)
|
||||
mempool_free(buf, rpc_buffer_mempool);
|
||||
else
|
||||
@ -1095,9 +1061,6 @@ static void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *ta
|
||||
task->tk_action = rpc_prepare_task;
|
||||
|
||||
rpc_init_task_statistics(task);
|
||||
|
||||
dprintk("RPC: new task initialized, procpid %u\n",
|
||||
task_pid_nr(current));
|
||||
}
|
||||
|
||||
static struct rpc_task *
|
||||
@ -1121,7 +1084,6 @@ struct rpc_task *rpc_new_task(const struct rpc_task_setup *setup_data)
|
||||
|
||||
rpc_init_task(task, setup_data);
|
||||
task->tk_flags |= flags;
|
||||
dprintk("RPC: allocated task %p\n", task);
|
||||
return task;
|
||||
}
|
||||
|
||||
@ -1151,10 +1113,8 @@ static void rpc_free_task(struct rpc_task *task)
|
||||
put_rpccred(task->tk_op_cred);
|
||||
rpc_release_calldata(task->tk_ops, task->tk_calldata);
|
||||
|
||||
if (tk_flags & RPC_TASK_DYNAMIC) {
|
||||
dprintk("RPC: %5u freeing task\n", task->tk_pid);
|
||||
if (tk_flags & RPC_TASK_DYNAMIC)
|
||||
mempool_free(task, rpc_task_mempool);
|
||||
}
|
||||
}
|
||||
|
||||
static void rpc_async_release(struct work_struct *work)
|
||||
@ -1208,8 +1168,6 @@ EXPORT_SYMBOL_GPL(rpc_put_task_async);
|
||||
|
||||
static void rpc_release_task(struct rpc_task *task)
|
||||
{
|
||||
dprintk("RPC: %5u release task\n", task->tk_pid);
|
||||
|
||||
WARN_ON_ONCE(RPC_IS_QUEUED(task));
|
||||
|
||||
rpc_release_resources_task(task);
|
||||
@ -1250,7 +1208,6 @@ static int rpciod_start(void)
|
||||
/*
|
||||
* Create the rpciod thread and wait for it to start.
|
||||
*/
|
||||
dprintk("RPC: creating workqueue rpciod\n");
|
||||
wq = alloc_workqueue("rpciod", WQ_MEM_RECLAIM | WQ_UNBOUND, 0);
|
||||
if (!wq)
|
||||
goto out_failed;
|
||||
@ -1275,7 +1232,6 @@ static void rpciod_stop(void)
|
||||
|
||||
if (rpciod_workqueue == NULL)
|
||||
return;
|
||||
dprintk("RPC: destroying workqueue rpciod\n");
|
||||
|
||||
wq = rpciod_workqueue;
|
||||
rpciod_workqueue = NULL;
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
NetApp provides this source code under the GPL v2 License.
|
||||
The GPL v2 license is available at
|
||||
http://opensource.org/licenses/gpl-license.php.
|
||||
https://opensource.org/licenses/gpl-license.php.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
|
311
net/sunrpc/xdr.c
311
net/sunrpc/xdr.c
@ -19,6 +19,9 @@
|
||||
#include <linux/bvec.h>
|
||||
#include <trace/events/sunrpc.h>
|
||||
|
||||
static void _copy_to_pages(struct page **, size_t, const char *, size_t);
|
||||
|
||||
|
||||
/*
|
||||
* XDR functions for basic NFS types
|
||||
*/
|
||||
@ -201,6 +204,88 @@ EXPORT_SYMBOL_GPL(xdr_inline_pages);
|
||||
* Helper routines for doing 'memmove' like operations on a struct xdr_buf
|
||||
*/
|
||||
|
||||
/**
|
||||
* _shift_data_left_pages
|
||||
* @pages: vector of pages containing both the source and dest memory area.
|
||||
* @pgto_base: page vector address of destination
|
||||
* @pgfrom_base: page vector address of source
|
||||
* @len: number of bytes to copy
|
||||
*
|
||||
* Note: the addresses pgto_base and pgfrom_base are both calculated in
|
||||
* the same way:
|
||||
* if a memory area starts at byte 'base' in page 'pages[i]',
|
||||
* then its address is given as (i << PAGE_CACHE_SHIFT) + base
|
||||
* Alse note: pgto_base must be < pgfrom_base, but the memory areas
|
||||
* they point to may overlap.
|
||||
*/
|
||||
static void
|
||||
_shift_data_left_pages(struct page **pages, size_t pgto_base,
|
||||
size_t pgfrom_base, size_t len)
|
||||
{
|
||||
struct page **pgfrom, **pgto;
|
||||
char *vfrom, *vto;
|
||||
size_t copy;
|
||||
|
||||
BUG_ON(pgfrom_base <= pgto_base);
|
||||
|
||||
pgto = pages + (pgto_base >> PAGE_SHIFT);
|
||||
pgfrom = pages + (pgfrom_base >> PAGE_SHIFT);
|
||||
|
||||
pgto_base &= ~PAGE_MASK;
|
||||
pgfrom_base &= ~PAGE_MASK;
|
||||
|
||||
do {
|
||||
if (pgto_base >= PAGE_SIZE) {
|
||||
pgto_base = 0;
|
||||
pgto++;
|
||||
}
|
||||
if (pgfrom_base >= PAGE_SIZE){
|
||||
pgfrom_base = 0;
|
||||
pgfrom++;
|
||||
}
|
||||
|
||||
copy = len;
|
||||
if (copy > (PAGE_SIZE - pgto_base))
|
||||
copy = PAGE_SIZE - pgto_base;
|
||||
if (copy > (PAGE_SIZE - pgfrom_base))
|
||||
copy = PAGE_SIZE - pgfrom_base;
|
||||
|
||||
vto = kmap_atomic(*pgto);
|
||||
if (*pgto != *pgfrom) {
|
||||
vfrom = kmap_atomic(*pgfrom);
|
||||
memcpy(vto + pgto_base, vfrom + pgfrom_base, copy);
|
||||
kunmap_atomic(vfrom);
|
||||
} else
|
||||
memmove(vto + pgto_base, vto + pgfrom_base, copy);
|
||||
flush_dcache_page(*pgto);
|
||||
kunmap_atomic(vto);
|
||||
|
||||
pgto_base += copy;
|
||||
pgfrom_base += copy;
|
||||
|
||||
} while ((len -= copy) != 0);
|
||||
}
|
||||
|
||||
static void
|
||||
_shift_data_left_tail(struct xdr_buf *buf, unsigned int pgto, size_t len)
|
||||
{
|
||||
struct kvec *tail = buf->tail;
|
||||
|
||||
if (len > tail->iov_len)
|
||||
len = tail->iov_len;
|
||||
|
||||
_copy_to_pages(buf->pages,
|
||||
buf->page_base + pgto,
|
||||
(char *)tail->iov_base,
|
||||
len);
|
||||
tail->iov_len -= len;
|
||||
|
||||
if (tail->iov_len > 0)
|
||||
memmove((char *)tail->iov_base,
|
||||
tail->iov_base + len,
|
||||
tail->iov_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* _shift_data_right_pages
|
||||
* @pages: vector of pages containing both the source and dest memory area.
|
||||
@ -266,6 +351,46 @@ _shift_data_right_pages(struct page **pages, size_t pgto_base,
|
||||
} while ((len -= copy) != 0);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
_shift_data_right_tail(struct xdr_buf *buf, unsigned int pgfrom, size_t len)
|
||||
{
|
||||
struct kvec *tail = buf->tail;
|
||||
unsigned int tailbuf_len;
|
||||
unsigned int result = 0;
|
||||
size_t copy;
|
||||
|
||||
tailbuf_len = buf->buflen - buf->head->iov_len - buf->page_len;
|
||||
|
||||
/* Shift the tail first */
|
||||
if (tailbuf_len != 0) {
|
||||
unsigned int free_space = tailbuf_len - tail->iov_len;
|
||||
|
||||
if (len < free_space)
|
||||
free_space = len;
|
||||
if (len > free_space)
|
||||
len = free_space;
|
||||
|
||||
tail->iov_len += free_space;
|
||||
copy = len;
|
||||
|
||||
if (tail->iov_len > len) {
|
||||
char *p = (char *)tail->iov_base + len;
|
||||
memmove(p, tail->iov_base, tail->iov_len - free_space);
|
||||
result += tail->iov_len - free_space;
|
||||
} else
|
||||
copy = tail->iov_len;
|
||||
|
||||
/* Copy from the inlined pages into the tail */
|
||||
_copy_from_pages((char *)tail->iov_base,
|
||||
buf->pages,
|
||||
buf->page_base + pgfrom,
|
||||
copy);
|
||||
result += copy;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* _copy_to_pages
|
||||
* @pages: array of pages
|
||||
@ -350,6 +475,38 @@ _copy_from_pages(char *p, struct page **pages, size_t pgbase, size_t len)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(_copy_from_pages);
|
||||
|
||||
/**
|
||||
* _zero_pages
|
||||
* @pages: array of pages
|
||||
* @pgbase: beginning page vector address
|
||||
* @len: length
|
||||
*/
|
||||
static void
|
||||
_zero_pages(struct page **pages, size_t pgbase, size_t len)
|
||||
{
|
||||
struct page **page;
|
||||
char *vpage;
|
||||
size_t zero;
|
||||
|
||||
page = pages + (pgbase >> PAGE_SHIFT);
|
||||
pgbase &= ~PAGE_MASK;
|
||||
|
||||
do {
|
||||
zero = PAGE_SIZE - pgbase;
|
||||
if (zero > len)
|
||||
zero = len;
|
||||
|
||||
vpage = kmap_atomic(*page);
|
||||
memset(vpage + pgbase, 0, zero);
|
||||
kunmap_atomic(vpage);
|
||||
|
||||
flush_dcache_page(*page);
|
||||
pgbase = 0;
|
||||
page++;
|
||||
|
||||
} while ((len -= zero) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* xdr_shrink_bufhead
|
||||
* @buf: xdr_buf
|
||||
@ -446,39 +603,13 @@ xdr_shrink_bufhead(struct xdr_buf *buf, size_t len)
|
||||
static unsigned int
|
||||
xdr_shrink_pagelen(struct xdr_buf *buf, size_t len)
|
||||
{
|
||||
struct kvec *tail;
|
||||
size_t copy;
|
||||
unsigned int pglen = buf->page_len;
|
||||
unsigned int tailbuf_len;
|
||||
unsigned int result;
|
||||
|
||||
result = 0;
|
||||
tail = buf->tail;
|
||||
if (len > buf->page_len)
|
||||
len = buf-> page_len;
|
||||
tailbuf_len = buf->buflen - buf->head->iov_len - buf->page_len;
|
||||
|
||||
/* Shift the tail first */
|
||||
if (tailbuf_len != 0) {
|
||||
unsigned int free_space = tailbuf_len - tail->iov_len;
|
||||
|
||||
if (len < free_space)
|
||||
free_space = len;
|
||||
tail->iov_len += free_space;
|
||||
|
||||
copy = len;
|
||||
if (tail->iov_len > len) {
|
||||
char *p = (char *)tail->iov_base + len;
|
||||
memmove(p, tail->iov_base, tail->iov_len - len);
|
||||
result += tail->iov_len - len;
|
||||
} else
|
||||
copy = tail->iov_len;
|
||||
/* Copy from the inlined pages into the tail */
|
||||
_copy_from_pages((char *)tail->iov_base,
|
||||
buf->pages, buf->page_base + pglen - len,
|
||||
copy);
|
||||
result += copy;
|
||||
}
|
||||
result = _shift_data_right_tail(buf, pglen - len, len);
|
||||
buf->page_len -= len;
|
||||
buf->buflen -= len;
|
||||
/* Have we truncated the message? */
|
||||
@ -505,6 +636,19 @@ unsigned int xdr_stream_pos(const struct xdr_stream *xdr)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xdr_stream_pos);
|
||||
|
||||
/**
|
||||
* xdr_page_pos - Return the current offset from the start of the xdr pages
|
||||
* @xdr: pointer to struct xdr_stream
|
||||
*/
|
||||
unsigned int xdr_page_pos(const struct xdr_stream *xdr)
|
||||
{
|
||||
unsigned int pos = xdr_stream_pos(xdr);
|
||||
|
||||
WARN_ON(pos < xdr->buf->head[0].iov_len);
|
||||
return pos - xdr->buf->head[0].iov_len;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xdr_page_pos);
|
||||
|
||||
/**
|
||||
* xdr_init_encode - Initialize a struct xdr_stream for sending data.
|
||||
* @xdr: pointer to xdr_stream struct
|
||||
@ -825,6 +969,13 @@ static int xdr_set_page_base(struct xdr_stream *xdr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void xdr_set_page(struct xdr_stream *xdr, unsigned int base,
|
||||
unsigned int len)
|
||||
{
|
||||
if (xdr_set_page_base(xdr, base, len) < 0)
|
||||
xdr_set_iov(xdr, xdr->buf->tail, xdr->nwords << 2);
|
||||
}
|
||||
|
||||
static void xdr_set_next_page(struct xdr_stream *xdr)
|
||||
{
|
||||
unsigned int newbase;
|
||||
@ -832,8 +983,7 @@ static void xdr_set_next_page(struct xdr_stream *xdr)
|
||||
newbase = (1 + xdr->page_ptr - xdr->buf->pages) << PAGE_SHIFT;
|
||||
newbase -= xdr->buf->page_base;
|
||||
|
||||
if (xdr_set_page_base(xdr, newbase, PAGE_SIZE) < 0)
|
||||
xdr_set_iov(xdr, xdr->buf->tail, xdr->nwords << 2);
|
||||
xdr_set_page(xdr, newbase, PAGE_SIZE);
|
||||
}
|
||||
|
||||
static bool xdr_set_next_buffer(struct xdr_stream *xdr)
|
||||
@ -841,8 +991,7 @@ static bool xdr_set_next_buffer(struct xdr_stream *xdr)
|
||||
if (xdr->page_ptr != NULL)
|
||||
xdr_set_next_page(xdr);
|
||||
else if (xdr->iov == xdr->buf->head) {
|
||||
if (xdr_set_page_base(xdr, 0, PAGE_SIZE) < 0)
|
||||
xdr_set_iov(xdr, xdr->buf->tail, xdr->nwords << 2);
|
||||
xdr_set_page(xdr, 0, PAGE_SIZE);
|
||||
}
|
||||
return xdr->p != xdr->end;
|
||||
}
|
||||
@ -979,10 +1128,25 @@ out_overflow:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xdr_inline_decode);
|
||||
|
||||
static void xdr_realign_pages(struct xdr_stream *xdr)
|
||||
{
|
||||
struct xdr_buf *buf = xdr->buf;
|
||||
struct kvec *iov = buf->head;
|
||||
unsigned int cur = xdr_stream_pos(xdr);
|
||||
unsigned int copied, offset;
|
||||
|
||||
/* Realign pages to current pointer position */
|
||||
if (iov->iov_len > cur) {
|
||||
offset = iov->iov_len - cur;
|
||||
copied = xdr_shrink_bufhead(buf, offset);
|
||||
trace_rpc_xdr_alignment(xdr, offset, copied);
|
||||
xdr->nwords = XDR_QUADLEN(buf->len - cur);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int xdr_align_pages(struct xdr_stream *xdr, unsigned int len)
|
||||
{
|
||||
struct xdr_buf *buf = xdr->buf;
|
||||
struct kvec *iov;
|
||||
unsigned int nwords = XDR_QUADLEN(len);
|
||||
unsigned int cur = xdr_stream_pos(xdr);
|
||||
unsigned int copied, offset;
|
||||
@ -990,15 +1154,7 @@ static unsigned int xdr_align_pages(struct xdr_stream *xdr, unsigned int len)
|
||||
if (xdr->nwords == 0)
|
||||
return 0;
|
||||
|
||||
/* Realign pages to current pointer position */
|
||||
iov = buf->head;
|
||||
if (iov->iov_len > cur) {
|
||||
offset = iov->iov_len - cur;
|
||||
copied = xdr_shrink_bufhead(buf, offset);
|
||||
trace_rpc_xdr_alignment(xdr, offset, copied);
|
||||
xdr->nwords = XDR_QUADLEN(buf->len - cur);
|
||||
}
|
||||
|
||||
xdr_realign_pages(xdr);
|
||||
if (nwords > xdr->nwords) {
|
||||
nwords = xdr->nwords;
|
||||
len = nwords << 2;
|
||||
@ -1057,6 +1213,79 @@ unsigned int xdr_read_pages(struct xdr_stream *xdr, unsigned int len)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xdr_read_pages);
|
||||
|
||||
uint64_t xdr_align_data(struct xdr_stream *xdr, uint64_t offset, uint32_t length)
|
||||
{
|
||||
struct xdr_buf *buf = xdr->buf;
|
||||
unsigned int from, bytes;
|
||||
unsigned int shift = 0;
|
||||
|
||||
if ((offset + length) < offset ||
|
||||
(offset + length) > buf->page_len)
|
||||
length = buf->page_len - offset;
|
||||
|
||||
xdr_realign_pages(xdr);
|
||||
from = xdr_page_pos(xdr);
|
||||
bytes = xdr->nwords << 2;
|
||||
if (length < bytes)
|
||||
bytes = length;
|
||||
|
||||
/* Move page data to the left */
|
||||
if (from > offset) {
|
||||
shift = min_t(unsigned int, bytes, buf->page_len - from);
|
||||
_shift_data_left_pages(buf->pages,
|
||||
buf->page_base + offset,
|
||||
buf->page_base + from,
|
||||
shift);
|
||||
bytes -= shift;
|
||||
|
||||
/* Move tail data into the pages, if necessary */
|
||||
if (bytes > 0)
|
||||
_shift_data_left_tail(buf, offset + shift, bytes);
|
||||
}
|
||||
|
||||
xdr->nwords -= XDR_QUADLEN(length);
|
||||
xdr_set_page(xdr, from + length, PAGE_SIZE);
|
||||
return length;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xdr_align_data);
|
||||
|
||||
uint64_t xdr_expand_hole(struct xdr_stream *xdr, uint64_t offset, uint64_t length)
|
||||
{
|
||||
struct xdr_buf *buf = xdr->buf;
|
||||
unsigned int bytes;
|
||||
unsigned int from;
|
||||
unsigned int truncated = 0;
|
||||
|
||||
if ((offset + length) < offset ||
|
||||
(offset + length) > buf->page_len)
|
||||
length = buf->page_len - offset;
|
||||
|
||||
xdr_realign_pages(xdr);
|
||||
from = xdr_page_pos(xdr);
|
||||
bytes = xdr->nwords << 2;
|
||||
|
||||
if (offset + length + bytes > buf->page_len) {
|
||||
unsigned int shift = (offset + length + bytes) - buf->page_len;
|
||||
unsigned int res = _shift_data_right_tail(buf, from + bytes - shift, shift);
|
||||
truncated = shift - res;
|
||||
xdr->nwords -= XDR_QUADLEN(truncated);
|
||||
bytes -= shift;
|
||||
}
|
||||
|
||||
/* Now move the page data over and zero pages */
|
||||
if (bytes > 0)
|
||||
_shift_data_right_pages(buf->pages,
|
||||
buf->page_base + offset + length,
|
||||
buf->page_base + from,
|
||||
bytes);
|
||||
_zero_pages(buf->pages, buf->page_base + offset, length);
|
||||
|
||||
buf->len += length - (from - offset) - truncated;
|
||||
xdr_set_page(xdr, offset + length, PAGE_SIZE);
|
||||
return length;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xdr_expand_hole);
|
||||
|
||||
/**
|
||||
* xdr_enter_page - decode data from the XDR page
|
||||
* @xdr: pointer to xdr_stream struct
|
||||
|
@ -834,8 +834,7 @@ void xprt_connect(struct rpc_task *task)
|
||||
{
|
||||
struct rpc_xprt *xprt = task->tk_rqstp->rq_xprt;
|
||||
|
||||
dprintk("RPC: %5u xprt_connect xprt %p %s connected\n", task->tk_pid,
|
||||
xprt, (xprt_connected(xprt) ? "is" : "is not"));
|
||||
trace_xprt_connect(xprt);
|
||||
|
||||
if (!xprt_bound(xprt)) {
|
||||
task->tk_status = -EAGAIN;
|
||||
@ -1131,8 +1130,6 @@ void xprt_complete_rqst(struct rpc_task *task, int copied)
|
||||
struct rpc_rqst *req = task->tk_rqstp;
|
||||
struct rpc_xprt *xprt = req->rq_xprt;
|
||||
|
||||
trace_xprt_complete_rqst(xprt, req->rq_xid, copied);
|
||||
|
||||
xprt->stat.recvs++;
|
||||
|
||||
req->rq_private_buf.len = copied;
|
||||
@ -1269,7 +1266,6 @@ xprt_request_enqueue_transmit(struct rpc_task *task)
|
||||
/* Note: req is added _before_ pos */
|
||||
list_add_tail(&req->rq_xmit, &pos->rq_xmit);
|
||||
INIT_LIST_HEAD(&req->rq_xmit2);
|
||||
trace_xprt_enq_xmit(task, 1);
|
||||
goto out;
|
||||
}
|
||||
} else if (RPC_IS_SWAPPER(task)) {
|
||||
@ -1281,7 +1277,6 @@ xprt_request_enqueue_transmit(struct rpc_task *task)
|
||||
/* Note: req is added _before_ pos */
|
||||
list_add_tail(&req->rq_xmit, &pos->rq_xmit);
|
||||
INIT_LIST_HEAD(&req->rq_xmit2);
|
||||
trace_xprt_enq_xmit(task, 2);
|
||||
goto out;
|
||||
}
|
||||
} else if (!req->rq_seqno) {
|
||||
@ -1290,13 +1285,11 @@ xprt_request_enqueue_transmit(struct rpc_task *task)
|
||||
continue;
|
||||
list_add_tail(&req->rq_xmit2, &pos->rq_xmit2);
|
||||
INIT_LIST_HEAD(&req->rq_xmit);
|
||||
trace_xprt_enq_xmit(task, 3);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
list_add_tail(&req->rq_xmit, &xprt->xmit_queue);
|
||||
INIT_LIST_HEAD(&req->rq_xmit2);
|
||||
trace_xprt_enq_xmit(task, 4);
|
||||
out:
|
||||
set_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate);
|
||||
spin_unlock(&xprt->queue_lock);
|
||||
@ -1414,9 +1407,9 @@ bool xprt_prepare_transmit(struct rpc_task *task)
|
||||
struct rpc_rqst *req = task->tk_rqstp;
|
||||
struct rpc_xprt *xprt = req->rq_xprt;
|
||||
|
||||
dprintk("RPC: %5u xprt_prepare_transmit\n", task->tk_pid);
|
||||
|
||||
if (!xprt_lock_write(xprt, task)) {
|
||||
trace_xprt_transmit_queued(xprt, task);
|
||||
|
||||
/* Race breaker: someone may have transmitted us */
|
||||
if (!test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate))
|
||||
rpc_wake_up_queued_task_set_status(&xprt->sending,
|
||||
@ -1520,10 +1513,13 @@ xprt_transmit(struct rpc_task *task)
|
||||
{
|
||||
struct rpc_rqst *next, *req = task->tk_rqstp;
|
||||
struct rpc_xprt *xprt = req->rq_xprt;
|
||||
int status;
|
||||
int counter, status;
|
||||
|
||||
spin_lock(&xprt->queue_lock);
|
||||
counter = 0;
|
||||
while (!list_empty(&xprt->xmit_queue)) {
|
||||
if (++counter == 20)
|
||||
break;
|
||||
next = list_first_entry(&xprt->xmit_queue,
|
||||
struct rpc_rqst, rq_xmit);
|
||||
xprt_pin_rqst(next);
|
||||
@ -1531,7 +1527,6 @@ xprt_transmit(struct rpc_task *task)
|
||||
status = xprt_request_transmit(next, task);
|
||||
if (status == -EBADMSG && next != req)
|
||||
status = 0;
|
||||
cond_resched();
|
||||
spin_lock(&xprt->queue_lock);
|
||||
xprt_unpin_rqst(next);
|
||||
if (status == 0) {
|
||||
@ -1747,8 +1742,8 @@ xprt_request_init(struct rpc_task *task)
|
||||
req->rq_rcv_buf.bvec = NULL;
|
||||
req->rq_release_snd_buf = NULL;
|
||||
xprt_init_majortimeo(task, req);
|
||||
dprintk("RPC: %5u reserved req %p xid %08x\n", task->tk_pid,
|
||||
req, ntohl(req->rq_xid));
|
||||
|
||||
trace_xprt_reserve(req);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1838,7 +1833,6 @@ void xprt_release(struct rpc_task *task)
|
||||
if (req->rq_release_snd_buf)
|
||||
req->rq_release_snd_buf(req);
|
||||
|
||||
dprintk("RPC: %5u release request %p\n", task->tk_pid, req);
|
||||
if (likely(!bc_prealloc(req)))
|
||||
xprt->ops->free_slot(xprt, req);
|
||||
else
|
||||
|
@ -124,7 +124,7 @@ int frwr_mr_init(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr *mr)
|
||||
if (IS_ERR(frmr))
|
||||
goto out_mr_err;
|
||||
|
||||
sg = kcalloc(depth, sizeof(*sg), GFP_NOFS);
|
||||
sg = kmalloc_array(depth, sizeof(*sg), GFP_NOFS);
|
||||
if (!sg)
|
||||
goto out_list_err;
|
||||
|
||||
|
@ -413,9 +413,6 @@ xprt_rdma_set_port(struct rpc_xprt *xprt, u16 port)
|
||||
kfree(xprt->address_strings[RPC_DISPLAY_HEX_PORT]);
|
||||
snprintf(buf, sizeof(buf), "%4hx", port);
|
||||
xprt->address_strings[RPC_DISPLAY_HEX_PORT] = kstrdup(buf, GFP_KERNEL);
|
||||
|
||||
trace_xprtrdma_op_setport(container_of(xprt, struct rpcrdma_xprt,
|
||||
rx_xprt));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -586,11 +583,9 @@ xprt_rdma_allocate(struct rpc_task *task)
|
||||
|
||||
rqst->rq_buffer = rdmab_data(req->rl_sendbuf);
|
||||
rqst->rq_rbuffer = rdmab_data(req->rl_recvbuf);
|
||||
trace_xprtrdma_op_allocate(task, req);
|
||||
return 0;
|
||||
|
||||
out_fail:
|
||||
trace_xprtrdma_op_allocate(task, NULL);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -607,8 +602,6 @@ xprt_rdma_free(struct rpc_task *task)
|
||||
struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(rqst->rq_xprt);
|
||||
struct rpcrdma_req *req = rpcr_to_rdmar(rqst);
|
||||
|
||||
trace_xprtrdma_op_free(task, req);
|
||||
|
||||
if (!list_empty(&req->rl_registered))
|
||||
frwr_unmap_sync(r_xprt, req);
|
||||
|
||||
|
@ -762,10 +762,7 @@ static int xs_nospace(struct rpc_rqst *req)
|
||||
struct sock *sk = transport->inet;
|
||||
int ret = -EAGAIN;
|
||||
|
||||
dprintk("RPC: %5u xmit incomplete (%u left of %u)\n",
|
||||
req->rq_task->tk_pid,
|
||||
req->rq_slen - transport->xmit.offset,
|
||||
req->rq_slen);
|
||||
trace_rpc_socket_nospace(req, transport);
|
||||
|
||||
/* Protect against races with write_space */
|
||||
spin_lock(&xprt->transport_lock);
|
||||
|
Loading…
Reference in New Issue
Block a user