Commit 911d137a authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'nfsd-5.5' of git://linux-nfs.org/~bfields/linux

Pull nfsd updates from Bruce Fields:
 "This is a relatively quiet cycle for nfsd, mainly various bugfixes.

  Possibly most interesting is Trond's fixes for some callback races
  that were due to my incomplete understanding of rpc client shutdown.
  Unfortunately at the last minute I've started noticing a new
  intermittent failure to send callbacks. As the logic seems basically
  correct, I'm leaving Trond's patches in for now, and hope to find a
  fix in the next week so I don't have to revert those patches"

* tag 'nfsd-5.5' of git://linux-nfs.org/~bfields/linux: (24 commits)
  nfsd: depend on CRYPTO_MD5 for legacy client tracking
  NFSD fixing possible null pointer derefering in copy offload
  nfsd: check for EBUSY from vfs_rmdir/vfs_unink.
  nfsd: Ensure CLONE persists data and metadata changes to the target file
  SUNRPC: Fix backchannel latency metrics
  nfsd: restore NFSv3 ACL support
  nfsd: v4 support requires CRYPTO_SHA256
  nfsd: Fix cld_net->cn_tfm initialization
  lockd: remove __KERNEL__ ifdefs
  sunrpc: remove __KERNEL__ ifdefs
  race in exportfs_decode_fh()
  nfsd: Drop LIST_HEAD where the variable it declares is never used.
  nfsd: document callback_wq serialization of callback code
  nfsd: mark cb path down on unknown errors
  nfsd: Fix races between nfsd4_cb_release() and nfsd4_shutdown_callback()
  nfsd: minor 4.1 callback cleanup
  SUNRPC: Fix svcauth_gss_proxy_init()
  SUNRPC: Trace gssproxy upcall results
  sunrpc: fix crash when cache_head become valid before update
  nfsd: remove private bin2hex implementation
  ...
parents fb9bf40c 38a2204f
...@@ -73,7 +73,8 @@ config NFSD_V4 ...@@ -73,7 +73,8 @@ config NFSD_V4
select NFSD_V3 select NFSD_V3
select FS_POSIX_ACL select FS_POSIX_ACL
select SUNRPC_GSS select SUNRPC_GSS
select CRYPTO select CRYPTO_MD5
select CRYPTO_SHA256
select GRACE_PERIOD select GRACE_PERIOD
help help
This option enables support in your system's NFS server for This option enables support in your system's NFS server for
......
...@@ -685,8 +685,6 @@ nfsd_file_cache_purge(struct net *net) ...@@ -685,8 +685,6 @@ nfsd_file_cache_purge(struct net *net)
void void
nfsd_file_cache_shutdown(void) nfsd_file_cache_shutdown(void)
{ {
LIST_HEAD(dispose);
set_bit(NFSD_FILE_SHUTDOWN, &nfsd_file_lru_flags); set_bit(NFSD_FILE_SHUTDOWN, &nfsd_file_lru_flags);
lease_unregister_notifier(&nfsd_file_lease_notifier); lease_unregister_notifier(&nfsd_file_lease_notifier);
......
...@@ -826,6 +826,31 @@ static int max_cb_time(struct net *net) ...@@ -826,6 +826,31 @@ static int max_cb_time(struct net *net)
return max(nn->nfsd4_lease/10, (time_t)1) * HZ; return max(nn->nfsd4_lease/10, (time_t)1) * HZ;
} }
static struct workqueue_struct *callback_wq;
static bool nfsd4_queue_cb(struct nfsd4_callback *cb)
{
return queue_work(callback_wq, &cb->cb_work);
}
static void nfsd41_cb_inflight_begin(struct nfs4_client *clp)
{
atomic_inc(&clp->cl_cb_inflight);
}
static void nfsd41_cb_inflight_end(struct nfs4_client *clp)
{
if (atomic_dec_and_test(&clp->cl_cb_inflight))
wake_up_var(&clp->cl_cb_inflight);
}
static void nfsd41_cb_inflight_wait_complete(struct nfs4_client *clp)
{
wait_var_event(&clp->cl_cb_inflight,
!atomic_read(&clp->cl_cb_inflight));
}
static const struct cred *get_backchannel_cred(struct nfs4_client *clp, struct rpc_clnt *client, struct nfsd4_session *ses) static const struct cred *get_backchannel_cred(struct nfs4_client *clp, struct rpc_clnt *client, struct nfsd4_session *ses)
{ {
if (clp->cl_minorversion == 0) { if (clp->cl_minorversion == 0) {
...@@ -937,14 +962,21 @@ static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata) ...@@ -937,14 +962,21 @@ static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata)
clp->cl_cb_state = NFSD4_CB_UP; clp->cl_cb_state = NFSD4_CB_UP;
} }
static void nfsd4_cb_probe_release(void *calldata)
{
struct nfs4_client *clp = container_of(calldata, struct nfs4_client, cl_cb_null);
nfsd41_cb_inflight_end(clp);
}
static const struct rpc_call_ops nfsd4_cb_probe_ops = { static const struct rpc_call_ops nfsd4_cb_probe_ops = {
/* XXX: release method to ensure we set the cb channel down if /* XXX: release method to ensure we set the cb channel down if
* necessary on early failure? */ * necessary on early failure? */
.rpc_call_done = nfsd4_cb_probe_done, .rpc_call_done = nfsd4_cb_probe_done,
.rpc_release = nfsd4_cb_probe_release,
}; };
static struct workqueue_struct *callback_wq;
/* /*
* Poke the callback thread to process any updates to the callback * Poke the callback thread to process any updates to the callback
* parameters, and send a null probe. * parameters, and send a null probe.
...@@ -975,9 +1007,12 @@ void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *conn) ...@@ -975,9 +1007,12 @@ void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *conn)
* If the slot is available, then mark it busy. Otherwise, set the * If the slot is available, then mark it busy. Otherwise, set the
* thread for sleeping on the callback RPC wait queue. * thread for sleeping on the callback RPC wait queue.
*/ */
static bool nfsd41_cb_get_slot(struct nfs4_client *clp, struct rpc_task *task) static bool nfsd41_cb_get_slot(struct nfsd4_callback *cb, struct rpc_task *task)
{ {
if (test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) { struct nfs4_client *clp = cb->cb_clp;
if (!cb->cb_holds_slot &&
test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) {
rpc_sleep_on(&clp->cl_cb_waitq, task, NULL); rpc_sleep_on(&clp->cl_cb_waitq, task, NULL);
/* Race breaker */ /* Race breaker */
if (test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) { if (test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) {
...@@ -986,9 +1021,31 @@ static bool nfsd41_cb_get_slot(struct nfs4_client *clp, struct rpc_task *task) ...@@ -986,9 +1021,31 @@ static bool nfsd41_cb_get_slot(struct nfs4_client *clp, struct rpc_task *task)
} }
rpc_wake_up_queued_task(&clp->cl_cb_waitq, task); rpc_wake_up_queued_task(&clp->cl_cb_waitq, task);
} }
cb->cb_holds_slot = true;
return true; return true;
} }
static void nfsd41_cb_release_slot(struct nfsd4_callback *cb)
{
struct nfs4_client *clp = cb->cb_clp;
if (cb->cb_holds_slot) {
cb->cb_holds_slot = false;
clear_bit(0, &clp->cl_cb_slot_busy);
rpc_wake_up_next(&clp->cl_cb_waitq);
}
}
static void nfsd41_destroy_cb(struct nfsd4_callback *cb)
{
struct nfs4_client *clp = cb->cb_clp;
nfsd41_cb_release_slot(cb);
if (cb->cb_ops && cb->cb_ops->release)
cb->cb_ops->release(cb);
nfsd41_cb_inflight_end(clp);
}
/* /*
* TODO: cb_sequence should support referring call lists, cachethis, multiple * TODO: cb_sequence should support referring call lists, cachethis, multiple
* slots, and mark callback channel down on communication errors. * slots, and mark callback channel down on communication errors.
...@@ -1005,11 +1062,8 @@ static void nfsd4_cb_prepare(struct rpc_task *task, void *calldata) ...@@ -1005,11 +1062,8 @@ static void nfsd4_cb_prepare(struct rpc_task *task, void *calldata)
*/ */
cb->cb_seq_status = 1; cb->cb_seq_status = 1;
cb->cb_status = 0; cb->cb_status = 0;
if (minorversion) { if (minorversion && !nfsd41_cb_get_slot(cb, task))
if (!cb->cb_holds_slot && !nfsd41_cb_get_slot(clp, task)) return;
return;
cb->cb_holds_slot = true;
}
rpc_call_start(task); rpc_call_start(task);
} }
...@@ -1072,13 +1126,12 @@ static bool nfsd4_cb_sequence_done(struct rpc_task *task, struct nfsd4_callback ...@@ -1072,13 +1126,12 @@ static bool nfsd4_cb_sequence_done(struct rpc_task *task, struct nfsd4_callback
} }
break; break;
default: default:
nfsd4_mark_cb_fault(cb->cb_clp, cb->cb_seq_status);
dprintk("%s: unprocessed error %d\n", __func__, dprintk("%s: unprocessed error %d\n", __func__,
cb->cb_seq_status); cb->cb_seq_status);
} }
cb->cb_holds_slot = false; nfsd41_cb_release_slot(cb);
clear_bit(0, &clp->cl_cb_slot_busy);
rpc_wake_up_next(&clp->cl_cb_waitq);
dprintk("%s: freed slot, new seqid=%d\n", __func__, dprintk("%s: freed slot, new seqid=%d\n", __func__,
clp->cl_cb_session->se_cb_seq_nr); clp->cl_cb_session->se_cb_seq_nr);
...@@ -1091,8 +1144,10 @@ static bool nfsd4_cb_sequence_done(struct rpc_task *task, struct nfsd4_callback ...@@ -1091,8 +1144,10 @@ static bool nfsd4_cb_sequence_done(struct rpc_task *task, struct nfsd4_callback
ret = false; ret = false;
goto out; goto out;
need_restart: need_restart:
task->tk_status = 0; if (!test_bit(NFSD4_CLIENT_CB_KILL, &clp->cl_flags)) {
cb->cb_need_restart = true; task->tk_status = 0;
cb->cb_need_restart = true;
}
return false; return false;
} }
...@@ -1134,9 +1189,9 @@ static void nfsd4_cb_release(void *calldata) ...@@ -1134,9 +1189,9 @@ static void nfsd4_cb_release(void *calldata)
struct nfsd4_callback *cb = calldata; struct nfsd4_callback *cb = calldata;
if (cb->cb_need_restart) if (cb->cb_need_restart)
nfsd4_run_cb(cb); nfsd4_queue_cb(cb);
else else
cb->cb_ops->release(cb); nfsd41_destroy_cb(cb);
} }
...@@ -1170,6 +1225,7 @@ void nfsd4_shutdown_callback(struct nfs4_client *clp) ...@@ -1170,6 +1225,7 @@ void nfsd4_shutdown_callback(struct nfs4_client *clp)
*/ */
nfsd4_run_cb(&clp->cl_cb_null); nfsd4_run_cb(&clp->cl_cb_null);
flush_workqueue(callback_wq); flush_workqueue(callback_wq);
nfsd41_cb_inflight_wait_complete(clp);
} }
/* requires cl_lock: */ /* requires cl_lock: */
...@@ -1187,6 +1243,12 @@ static struct nfsd4_conn * __nfsd4_find_backchannel(struct nfs4_client *clp) ...@@ -1187,6 +1243,12 @@ static struct nfsd4_conn * __nfsd4_find_backchannel(struct nfs4_client *clp)
return NULL; return NULL;
} }
/*
* Note there isn't a lot of locking in this code; instead we depend on
* the fact that it is run from the callback_wq, which won't run two
* work items at once. So, for example, callback_wq handles all access
* of cl_cb_client and all calls to rpc_create or rpc_shutdown_client.
*/
static void nfsd4_process_cb_update(struct nfsd4_callback *cb) static void nfsd4_process_cb_update(struct nfsd4_callback *cb)
{ {
struct nfs4_cb_conn conn; struct nfs4_cb_conn conn;
...@@ -1255,8 +1317,7 @@ nfsd4_run_cb_work(struct work_struct *work) ...@@ -1255,8 +1317,7 @@ nfsd4_run_cb_work(struct work_struct *work)
clnt = clp->cl_cb_client; clnt = clp->cl_cb_client;
if (!clnt) { if (!clnt) {
/* Callback channel broken, or client killed; give up: */ /* Callback channel broken, or client killed; give up: */
if (cb->cb_ops && cb->cb_ops->release) nfsd41_destroy_cb(cb);
cb->cb_ops->release(cb);
return; return;
} }
...@@ -1265,6 +1326,7 @@ nfsd4_run_cb_work(struct work_struct *work) ...@@ -1265,6 +1326,7 @@ nfsd4_run_cb_work(struct work_struct *work)
*/ */
if (!cb->cb_ops && clp->cl_minorversion) { if (!cb->cb_ops && clp->cl_minorversion) {
clp->cl_cb_state = NFSD4_CB_UP; clp->cl_cb_state = NFSD4_CB_UP;
nfsd41_destroy_cb(cb);
return; return;
} }
...@@ -1290,5 +1352,9 @@ void nfsd4_init_cb(struct nfsd4_callback *cb, struct nfs4_client *clp, ...@@ -1290,5 +1352,9 @@ void nfsd4_init_cb(struct nfsd4_callback *cb, struct nfs4_client *clp,
void nfsd4_run_cb(struct nfsd4_callback *cb) void nfsd4_run_cb(struct nfsd4_callback *cb)
{ {
queue_work(callback_wq, &cb->cb_work); struct nfs4_client *clp = cb->cb_clp;
nfsd41_cb_inflight_begin(clp);
if (!nfsd4_queue_cb(cb))
nfsd41_cb_inflight_end(clp);
} }
...@@ -1077,7 +1077,8 @@ nfsd4_clone(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ...@@ -1077,7 +1077,8 @@ nfsd4_clone(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
goto out; goto out;
status = nfsd4_clone_file_range(src->nf_file, clone->cl_src_pos, status = nfsd4_clone_file_range(src->nf_file, clone->cl_src_pos,
dst->nf_file, clone->cl_dst_pos, clone->cl_count); dst->nf_file, clone->cl_dst_pos, clone->cl_count,
EX_ISSYNC(cstate->current_fh.fh_export));
nfsd_file_put(dst); nfsd_file_put(dst);
nfsd_file_put(src); nfsd_file_put(src);
...@@ -1297,7 +1298,8 @@ nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ...@@ -1297,7 +1298,8 @@ nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
out: out:
return status; return status;
out_err: out_err:
cleanup_async_copy(async_copy); if (async_copy)
cleanup_async_copy(async_copy);
goto out; goto out;
} }
......
...@@ -1578,6 +1578,7 @@ nfsd4_cld_tracking_init(struct net *net) ...@@ -1578,6 +1578,7 @@ nfsd4_cld_tracking_init(struct net *net)
struct nfsd_net *nn = net_generic(net, nfsd_net_id); struct nfsd_net *nn = net_generic(net, nfsd_net_id);
bool running; bool running;
int retries = 10; int retries = 10;
struct crypto_shash *tfm;
status = nfs4_cld_state_init(net); status = nfs4_cld_state_init(net);
if (status) if (status)
...@@ -1586,11 +1587,6 @@ nfsd4_cld_tracking_init(struct net *net) ...@@ -1586,11 +1587,6 @@ nfsd4_cld_tracking_init(struct net *net)
status = __nfsd4_init_cld_pipe(net); status = __nfsd4_init_cld_pipe(net);
if (status) if (status)
goto err_shutdown; goto err_shutdown;
nn->cld_net->cn_tfm = crypto_alloc_shash("sha256", 0, 0);
if (IS_ERR(nn->cld_net->cn_tfm)) {
status = PTR_ERR(nn->cld_net->cn_tfm);
goto err_remove;
}
/* /*
* rpc pipe upcalls take 30 seconds to time out, so we don't want to * rpc pipe upcalls take 30 seconds to time out, so we don't want to
...@@ -1607,6 +1603,12 @@ nfsd4_cld_tracking_init(struct net *net) ...@@ -1607,6 +1603,12 @@ nfsd4_cld_tracking_init(struct net *net)
status = -ETIMEDOUT; status = -ETIMEDOUT;
goto err_remove; goto err_remove;
} }
tfm = crypto_alloc_shash("sha256", 0, 0);
if (IS_ERR(tfm)) {
status = PTR_ERR(tfm);
goto err_remove;
}
nn->cld_net->cn_tfm = tfm;
status = nfsd4_cld_get_version(nn); status = nfsd4_cld_get_version(nn);
if (status == -EOPNOTSUPP) if (status == -EOPNOTSUPP)
...@@ -1850,19 +1852,14 @@ nfsd4_umh_cltrack_upcall(char *cmd, char *arg, char *env0, char *env1) ...@@ -1850,19 +1852,14 @@ nfsd4_umh_cltrack_upcall(char *cmd, char *arg, char *env0, char *env1)
static char * static char *
bin_to_hex_dup(const unsigned char *src, int srclen) bin_to_hex_dup(const unsigned char *src, int srclen)
{ {
int i; char *buf;
char *buf, *hex;
/* +1 for terminating NULL */ /* +1 for terminating NULL */
buf = kmalloc((srclen * 2) + 1, GFP_KERNEL); buf = kzalloc((srclen * 2) + 1, GFP_KERNEL);
if (!buf) if (!buf)
return buf; return buf;
hex = buf; bin2hex(buf, src, srclen);
for (i = 0; i < srclen; i++) {
sprintf(hex, "%2.2x", *src++);
hex += 2;
}
return buf; return buf;
} }
......
...@@ -2382,10 +2382,10 @@ static int nfs4_show_open(struct seq_file *s, struct nfs4_stid *st) ...@@ -2382,10 +2382,10 @@ static int nfs4_show_open(struct seq_file *s, struct nfs4_stid *st)
access = bmap_to_share_mode(ols->st_access_bmap); access = bmap_to_share_mode(ols->st_access_bmap);
deny = bmap_to_share_mode(ols->st_deny_bmap); deny = bmap_to_share_mode(ols->st_deny_bmap);
seq_printf(s, "access: \%s\%s, ", seq_printf(s, "access: %s%s, ",
access & NFS4_SHARE_ACCESS_READ ? "r" : "-", access & NFS4_SHARE_ACCESS_READ ? "r" : "-",
access & NFS4_SHARE_ACCESS_WRITE ? "w" : "-"); access & NFS4_SHARE_ACCESS_WRITE ? "w" : "-");
seq_printf(s, "deny: \%s\%s, ", seq_printf(s, "deny: %s%s, ",
deny & NFS4_SHARE_ACCESS_READ ? "r" : "-", deny & NFS4_SHARE_ACCESS_READ ? "r" : "-",
deny & NFS4_SHARE_ACCESS_WRITE ? "w" : "-"); deny & NFS4_SHARE_ACCESS_WRITE ? "w" : "-");
...@@ -3548,12 +3548,17 @@ static bool replay_matches_cache(struct svc_rqst *rqstp, ...@@ -3548,12 +3548,17 @@ static bool replay_matches_cache(struct svc_rqst *rqstp,
(bool)seq->cachethis) (bool)seq->cachethis)
return false; return false;
/* /*
* If there's an error than the reply can have fewer ops than * If there's an error then the reply can have fewer ops than
* the call. But if we cached a reply with *more* ops than the * the call.
* call you're sending us now, then this new call is clearly not
* really a replay of the old one:
*/ */
if (slot->sl_opcnt < argp->opcnt) if (slot->sl_opcnt < argp->opcnt && !slot->sl_status)
return false;
/*
* But if we cached a reply with *more* ops than the call you're
* sending us now, then this new call is clearly not really a
* replay of the old one:
*/
if (slot->sl_opcnt > argp->opcnt)
return false; return false;
/* This is the only check explicitly called by spec: */ /* This is the only check explicitly called by spec: */
if (!same_creds(&rqstp->rq_cred, &slot->sl_cred)) if (!same_creds(&rqstp->rq_cred, &slot->sl_cred))
......
...@@ -3452,7 +3452,6 @@ static __be32 nfsd4_encode_splice_read( ...@@ -3452,7 +3452,6 @@ static __be32 nfsd4_encode_splice_read(
struct xdr_stream *xdr = &resp->xdr; struct xdr_stream *xdr = &resp->xdr;
struct xdr_buf *buf = xdr->buf; struct xdr_buf *buf = xdr->buf;
u32 eof; u32 eof;
long len;
int space_left; int space_left;
__be32 nfserr; __be32 nfserr;
__be32 *p = xdr->p - 2; __be32 *p = xdr->p - 2;
...@@ -3461,7 +3460,6 @@ static __be32 nfsd4_encode_splice_read( ...@@ -3461,7 +3460,6 @@ static __be32 nfsd4_encode_splice_read(
if (xdr->end - xdr->p < 1) if (xdr->end - xdr->p < 1)
return nfserr_resource; return nfserr_resource;
len = maxcount;
nfserr = nfsd_splice_read(read->rd_rqstp, read->rd_fhp, nfserr = nfsd_splice_read(read->rd_rqstp, read->rd_fhp,
file, read->rd_offset, &maxcount, &eof); file, read->rd_offset, &maxcount, &eof);
read->rd_length = maxcount; read->rd_length = maxcount;
......
...@@ -280,7 +280,8 @@ void nfsd_lockd_shutdown(void); ...@@ -280,7 +280,8 @@ void nfsd_lockd_shutdown(void);
#define nfserr_union_notsupp cpu_to_be32(NFS4ERR_UNION_NOTSUPP) #define nfserr_union_notsupp cpu_to_be32(NFS4ERR_UNION_NOTSUPP)
#define nfserr_offload_denied cpu_to_be32(NFS4ERR_OFFLOAD_DENIED) #define nfserr_offload_denied cpu_to_be32(NFS4ERR_OFFLOAD_DENIED)
#define nfserr_wrong_lfs cpu_to_be32(NFS4ERR_WRONG_LFS) #define nfserr_wrong_lfs cpu_to_be32(NFS4ERR_WRONG_LFS)
#define nfserr_badlabel cpu_to_be32(NFS4ERR_BADLABEL) #define nfserr_badlabel cpu_to_be32(NFS4ERR_BADLABEL)
#define nfserr_file_open cpu_to_be32(NFS4ERR_FILE_OPEN)
/* error codes for internal use */ /* error codes for internal use */
/* if a request fails due to kmalloc failure, it gets dropped. /* if a request fails due to kmalloc failure, it gets dropped.
......
...@@ -95,12 +95,11 @@ static const struct svc_version *nfsd_acl_version[] = { ...@@ -95,12 +95,11 @@ static const struct svc_version *nfsd_acl_version[] = {
#define NFSD_ACL_MINVERS 2 #define NFSD_ACL_MINVERS 2
#define NFSD_ACL_NRVERS ARRAY_SIZE(nfsd_acl_version) #define NFSD_ACL_NRVERS ARRAY_SIZE(nfsd_acl_version)
static const struct svc_version *nfsd_acl_versions[NFSD_ACL_NRVERS];
static struct svc_program nfsd_acl_program = { static struct svc_program nfsd_acl_program = {
.pg_prog = NFS_ACL_PROGRAM, .pg_prog = NFS_ACL_PROGRAM,
.pg_nvers = NFSD_ACL_NRVERS, .pg_nvers = NFSD_ACL_NRVERS,
.pg_vers = nfsd_acl_versions, .pg_vers = nfsd_acl_version,
.pg_name = "nfsacl", .pg_name = "nfsacl",
.pg_class = "nfsd", .pg_class = "nfsd",
.pg_stats = &nfsd_acl_svcstats, .pg_stats = &nfsd_acl_svcstats,
......
...@@ -367,6 +367,7 @@ struct nfs4_client { ...@@ -367,6 +367,7 @@ struct nfs4_client {
struct net *net; struct net *net;
struct list_head async_copies; /* list of async copies */ struct list_head async_copies; /* list of async copies */
spinlock_t async_lock; /* lock for async copies */ spinlock_t async_lock; /* lock for async copies */
atomic_t cl_cb_inflight; /* Outstanding callbacks */
}; };
/* struct nfs4_client_reset /* struct nfs4_client_reset
......
...@@ -525,7 +525,7 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp, ...@@ -525,7 +525,7 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp,
#endif #endif
__be32 nfsd4_clone_file_range(struct file *src, u64 src_pos, struct file *dst, __be32 nfsd4_clone_file_range(struct file *src, u64 src_pos, struct file *dst,
u64 dst_pos, u64 count) u64 dst_pos, u64 count, bool sync)
{ {
loff_t cloned; loff_t cloned;
...@@ -534,6 +534,12 @@ __be32 nfsd4_clone_file_range(struct file *src, u64 src_pos, struct file *dst, ...@@ -534,6 +534,12 @@ __be32 nfsd4_clone_file_range(struct file *src, u64 src_pos, struct file *dst,
return nfserrno(cloned); return nfserrno(cloned);
if (count && cloned != count) if (count && cloned != count)
return nfserrno(-EINVAL); return nfserrno(-EINVAL);
if (sync) {
loff_t dst_end = count ? dst_pos + count - 1 : LLONG_MAX;
int status = vfs_fsync_range(dst, dst_pos, dst_end, 0);
if (status < 0)
return nfserrno(status);
}
return 0; return 0;
} }
...@@ -1809,7 +1815,17 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, ...@@ -1809,7 +1815,17 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
out_drop_write: out_drop_write:
fh_drop_write(fhp); fh_drop_write(fhp);
out_nfserr: out_nfserr:
err = nfserrno(host_err); if (host_err == -EBUSY) {
/* name is mounted-on. There is no perfect
* error status.
*/
if (nfsd_v4client(rqstp))
err = nfserr_file_open;
else
err = nfserr_acces;
} else {
err = nfserrno(host_err);
}
out: out:
return err; return err;
} }
......
...@@ -56,7 +56,7 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *, struct svc_fh *, ...@@ -56,7 +56,7 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *, struct svc_fh *,
__be32 nfsd4_vfs_fallocate(struct svc_rqst *, struct svc_fh *, __be32 nfsd4_vfs_fallocate(struct svc_rqst *, struct svc_fh *,
struct file *, loff_t, loff_t, int); struct file *, loff_t, loff_t, int);
__be32 nfsd4_clone_file_range(struct file *, u64, struct file *, __be32 nfsd4_clone_file_range(struct file *, u64, struct file *,
u64, u64); u64, u64, bool);
#endif /* CONFIG_NFSD_V4 */ #endif /* CONFIG_NFSD_V4 */
__be32 nfsd_create_locked(struct svc_rqst *, struct svc_fh *, __be32 nfsd_create_locked(struct svc_rqst *, struct svc_fh *,
char *name, int len, struct iattr *attrs, char *name, int len, struct iattr *attrs,
......
...@@ -10,8 +10,6 @@ ...@@ -10,8 +10,6 @@
#ifndef LINUX_LOCKD_DEBUG_H #ifndef LINUX_LOCKD_DEBUG_H
#define LINUX_LOCKD_DEBUG_H #define LINUX_LOCKD_DEBUG_H
#ifdef __KERNEL__
#include <linux/sunrpc/debug.h> #include <linux/sunrpc/debug.h>
/* /*
...@@ -25,8 +23,6 @@ ...@@ -25,8 +23,6 @@
# define ifdebug(flag) if (0) # define ifdebug(flag) if (0)
#endif #endif
#endif /* __KERNEL__ */
/* /*
* Debug flags * Debug flags
*/ */
......
...@@ -10,8 +10,6 @@ ...@@ -10,8 +10,6 @@
#ifndef LINUX_LOCKD_LOCKD_H #ifndef LINUX_LOCKD_LOCKD_H
#define LINUX_LOCKD_LOCKD_H #define LINUX_LOCKD_LOCKD_H
#ifdef __KERNEL__
#include <linux/in.h> #include <linux/in.h>
#include <linux/in6.h> #include <linux/in6.h>
#include <net/ipv6.h> #include <net/ipv6.h>
...@@ -373,6 +371,4 @@ static inline int nlm_compare_locks(const struct file_lock *fl1, ...@@ -373,6 +371,4 @@ static inline int nlm_compare_locks(const struct file_lock *fl1,
extern const struct lock_manager_operations nlmsvc_lock_operations; extern const struct lock_manager_operations nlmsvc_lock_operations;
#endif /* __KERNEL__ */
#endif /* LINUX_LOCKD_LOCKD_H */ #endif /* LINUX_LOCKD_LOCKD_H */
...@@ -10,8 +10,6 @@ ...@@ -10,8 +10,6 @@
#ifndef _LINUX_SUNRPC_AUTH_H #ifndef _LINUX_SUNRPC_AUTH_H
#define _LINUX_SUNRPC_AUTH_H #define _LINUX_SUNRPC_AUTH_H
#ifdef __KERNEL__
#include <linux/sunrpc/sched.h> #include <linux/sunrpc/sched.h>
#include <linux/sunrpc/msg_prot.h> #include <linux/sunrpc/msg_prot.h>
#include <linux/sunrpc/xdr.h> #include <linux/sunrpc/xdr.h>
...@@ -194,5 +192,4 @@ struct rpc_cred *get_rpccred(struct rpc_cred *cred) ...@@ -194,5 +192,4 @@ struct rpc_cred *get_rpccred(struct rpc_cred *cred)
return NULL; return NULL;
} }
#endif /* __KERNEL__ */
#endif /* _LINUX_SUNRPC_AUTH_H */ #endif /* _LINUX_SUNRPC_AUTH_H */
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
#ifndef _LINUX_SUNRPC_AUTH_GSS_H #ifndef _LINUX_SUNRPC_AUTH_GSS_H
#define _LINUX_SUNRPC_AUTH_GSS_H #define _LINUX_SUNRPC_AUTH_GSS_H
#ifdef __KERNEL__
#include <linux/refcount.h> #include <linux/refcount.h>
#include <linux/sunrpc/auth.h> #include <linux/sunrpc/auth.h>
#include <linux/sunrpc/svc.h> #include <linux/sunrpc/svc.h>
...@@ -90,6 +89,5 @@ struct gss_cred { ...@@ -90,6 +89,5 @@ struct gss_cred {
unsigned long gc_upcall_timestamp; unsigned long gc_upcall_timestamp;
}; };
#endif /* __KERNEL__ */
#endif /* _LINUX_SUNRPC_AUTH_GSS_H */ #endif /* _LINUX_SUNRPC_AUTH_GSS_H */
...@@ -109,8 +109,6 @@ struct rpc_procinfo { ...@@ -109,8 +109,6 @@ struct rpc_procinfo {
const char * p_name; /* name of procedure */ const char * p_name; /* name of procedure */
}; };
#ifdef __KERNEL__
struct rpc_create_args { struct rpc_create_args {
struct net *net; struct net *net;
int protocol; int protocol;
...@@ -238,5 +236,4 @@ static inline int rpc_reply_expected(struct rpc_task *task) ...@@ -238,5 +236,4 @@ static inline int rpc_reply_expected(struct rpc_task *task)
(task->tk_msg.rpc_proc->p_decode != NULL); (task->tk_msg.rpc_proc->p_decode != NULL);
} }
#endif /* __KERNEL__ */
#endif /* _LINUX_SUNRPC_CLNT_H */ #endif /* _LINUX_SUNRPC_CLNT_H */
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
#ifndef _LINUX_SUNRPC_GSS_API_H #ifndef _LINUX_SUNRPC_GSS_API_H
#define _LINUX_SUNRPC_GSS_API_H #define _LINUX_SUNRPC_GSS_API_H
#ifdef __KERNEL__
#include <linux/sunrpc/xdr.h> #include <linux/sunrpc/xdr.h>
#include <linux/sunrpc/msg_prot.h> #include <linux/sunrpc/msg_prot.h>
#include <linux/uio.h> #include <linux/uio.h>
...@@ -160,6 +159,5 @@ struct gss_api_mech * gss_mech_get(struct gss_api_mech *); ...@@ -160,6 +159,5 @@ struct gss_api_mech * gss_mech_get(struct gss_api_mech *);
* corresponding call to gss_mech_put. */ * corresponding call to gss_mech_put. */
void gss_mech_put(struct gss_api_mech *); void gss_mech_put(struct gss_api_mech *);
#endif /* __KERNEL__ */
#endif /* _LINUX_SUNRPC_GSS_API_H */ #endif /* _LINUX_SUNRPC_GSS_API_H */
...@@ -34,8 +34,6 @@ ...@@ -34,8 +34,6 @@
#ifndef _LINUX_SUNRPC_GSS_ERR_H #ifndef _LINUX_SUNRPC_GSS_ERR_H
#define _LINUX_SUNRPC_GSS_ERR_H #define _LINUX_SUNRPC_GSS_ERR_H
#ifdef __KERNEL__
typedef unsigned int OM_uint32; typedef unsigned int OM_uint32;
/* /*
...@@ -163,5 +161,4 @@ typedef unsigned int OM_uint32; ...@@ -163,5 +161,4 @@ typedef unsigned int OM_uint32;
/* XXXX This is a necessary evil until the spec is fixed */ /* XXXX This is a necessary evil until the spec is fixed */
#define GSS_S_CRED_UNAVAIL GSS_S_FAILURE #define GSS_S_CRED_UNAVAIL GSS_S_FAILURE
#endif /* __KERNEL__ */
#endif /* __LINUX_SUNRPC_GSS_ERR_H */ #endif /* __LINUX_SUNRPC_GSS_ERR_H */
...@@ -8,8 +8,6 @@ ...@@ -8,8 +8,6 @@
#ifndef _LINUX_SUNRPC_MSGPROT_H_ #ifndef _LINUX_SUNRPC_MSGPROT_H_
#define _LINUX_SUNRPC_MSGPROT_H_ #define _LINUX_SUNRPC_MSGPROT_H_
#ifdef __KERNEL__ /* user programs should get these from the rpc header files */
#define RPC_VERSION 2 #define RPC_VERSION 2
/* size of an XDR encoding unit in bytes, i.e. 32bit */ /* size of an XDR encoding unit in bytes, i.e. 32bit */
...@@ -217,5 +215,4 @@ typedef __be32 rpc_fraghdr; ...@@ -217,5 +215,4 @@ typedef __be32 rpc_fraghdr;
/* Assume INET6_ADDRSTRLEN will always be larger than INET_ADDRSTRLEN... */ /* Assume INET6_ADDRSTRLEN will always be larger than INET_ADDRSTRLEN... */
#define RPCBIND_MAXUADDRLEN RPCBIND_MAXUADDR6LEN #define RPCBIND_MAXUADDRLEN RPCBIND_MAXUADDR6LEN
#endif /* __KERNEL__ */
#endif /* _LINUX_SUNRPC_MSGPROT_H_ */ #endif /* _LINUX_SUNRPC_MSGPROT_H_ */
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
#ifndef _LINUX_SUNRPC_RPC_PIPE_FS_H #ifndef _LINUX_SUNRPC_RPC_PIPE_FS_H
#define _LINUX_SUNRPC_RPC_PIPE_FS_H #define _LINUX_SUNRPC_RPC_PIPE_FS_H
#ifdef __KERNEL__
#include <linux/workqueue.h> #include <linux/workqueue.h>
struct rpc_pipe_dir_head { struct rpc_pipe_dir_head {
...@@ -133,4 +131,3 @@ extern void unregister_rpc_pipefs(void); ...@@ -133,4 +131,3 @@ extern void unregister_rpc_pipefs(void);
extern bool gssd_running(struct net *net); extern bool gssd_running(struct net *net);
#endif #endif
#endif
...@@ -10,8 +10,6 @@ ...@@ -10,8 +10,6 @@
#ifndef _LINUX_SUNRPC_SVCAUTH_H_ #ifndef _LINUX_SUNRPC_SVCAUTH_H_
#define _LINUX_SUNRPC_SVCAUTH_H_ #define _LINUX_SUNRPC_SVCAUTH_H_
#ifdef __KERNEL__
#include <linux/string.h> #include <linux/string.h>
#include <linux/sunrpc/msg_prot.h> #include <linux/sunrpc/msg_prot.h>
#include <linux/sunrpc/cache.h> #include <linux/sunrpc/cache.h>
...@@ -185,6 +183,4 @@ static inline unsigned long hash_mem(char const *buf, int length, int bits) ...@@ -185,6 +183,4 @@ static inline unsigned long hash_mem(char const *buf, int length, int bits)
return full_name_hash(NULL, buf, length) >> (32 - bits); return full_name_hash(NULL, buf, length) >> (32 - bits);
} }
#endif /* __KERNEL__ */
#endif /* _LINUX_SUNRPC_SVCAUTH_H_ */ #endif /* _LINUX_SUNRPC_SVCAUTH_H_ */
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
#ifndef _LINUX_SUNRPC_SVCAUTH_GSS_H #ifndef _LINUX_SUNRPC_SVCAUTH_GSS_H
#define _LINUX_SUNRPC_SVCAUTH_GSS_H #define _LINUX_SUNRPC_SVCAUTH_GSS_H
#ifdef __KERNEL__
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/sunrpc/types.h> #include <linux/sunrpc/types.h>
#include <linux/sunrpc/xdr.h> #include <linux/sunrpc/xdr.h>
...@@ -24,5 +23,4 @@ void gss_svc_shutdown_net(struct net *net); ...@@ -24,5 +23,4 @@ void gss_svc_shutdown_net(struct net *net);
int svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name); int svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name);
u32 svcauth_gss_flavor(struct auth_domain *dom); u32 svcauth_gss_flavor(struct auth_domain *dom);
#endif /* __KERNEL__ */
#endif /* _LINUX_SUNRPC_SVCAUTH_GSS_H */ #endif /* _LINUX_SUNRPC_SVCAUTH_GSS_H */
...@@ -11,8 +11,6 @@ ...@@ -11,8 +11,6 @@
#ifndef _SUNRPC_XDR_H_ #ifndef _SUNRPC_XDR_H_
#define _SUNRPC_XDR_H_ #define _SUNRPC_XDR_H_
#ifdef __KERNEL__
#include <linux/uio.h> #include <linux/uio.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
...@@ -552,6 +550,5 @@ xdr_stream_decode_uint32_array(struct xdr_stream *xdr, ...@@ -552,6 +550,5 @@ xdr_stream_decode_uint32_array(struct xdr_stream *xdr,
*array = be32_to_cpup(p); *array = be32_to_cpup(p);
return retval; return retval;
} }
#endif /* __KERNEL__ */
#endif /* _SUNRPC_XDR_H_ */ #endif /* _SUNRPC_XDR_H_ */
...@@ -19,8 +19,6 @@ ...@@ -19,8 +19,6 @@
#include <linux/sunrpc/xdr.h> #include <linux/sunrpc/xdr.h>
#include <linux/sunrpc/msg_prot.h> #include <linux/sunrpc/msg_prot.h>
#ifdef __KERNEL__
#define RPC_MIN_SLOT_TABLE (2U) #define RPC_MIN_SLOT_TABLE (2U)
#define RPC_DEF_SLOT_TABLE (16U) #define RPC_DEF_SLOT_TABLE (16U)
#define RPC_MAX_SLOT_TABLE_LIMIT (65536U) #define RPC_MAX_SLOT_TABLE_LIMIT (65536U)
...@@ -506,6 +504,4 @@ static inline void xprt_inject_disconnect(struct rpc_xprt *xprt) ...@@ -506,6 +504,4 @@ static inline void xprt_inject_disconnect(struct rpc_xprt *xprt)
} }
#endif #endif
#endif /* __KERNEL__*/
#endif /* _LINUX_SUNRPC_XPRT_H */ #endif /* _LINUX_SUNRPC_XPRT_H */
...@@ -8,8 +8,6 @@ ...@@ -8,8 +8,6 @@
#ifndef _LINUX_SUNRPC_XPRTSOCK_H #ifndef _LINUX_SUNRPC_XPRTSOCK_H
#define _LINUX_SUNRPC_XPRTSOCK_H #define _LINUX_SUNRPC_XPRTSOCK_H
#ifdef __KERNEL__
int init_socket_xprt(void); int init_socket_xprt(void);
void cleanup_socket_xprt(void); void cleanup_socket_xprt(void);
...@@ -91,6 +89,4 @@ struct sock_xprt { ...@@ -91,6 +89,4 @@ struct sock_xprt {
#define XPRT_SOCK_WAKE_PENDING (6) #define XPRT_SOCK_WAKE_PENDING (6)
#define XPRT_SOCK_WAKE_DISCONNECT (7) #define XPRT_SOCK_WAKE_DISCONNECT (7)
#endif /* __KERNEL__ */
#endif /* _LINUX_SUNRPC_XPRTSOCK_H */ #endif /* _LINUX_SUNRPC_XPRTSOCK_H */
...@@ -126,6 +126,34 @@ DEFINE_GSSAPI_EVENT(verify_mic); ...@@ -126,6 +126,34 @@ DEFINE_GSSAPI_EVENT(verify_mic);
DEFINE_GSSAPI_EVENT(wrap); DEFINE_GSSAPI_EVENT(wrap);
DEFINE_GSSAPI_EVENT(unwrap); DEFINE_GSSAPI_EVENT(unwrap);
TRACE_EVENT(rpcgss_accept_upcall,
TP_PROTO(
__be32 xid,
u32 major_status,
u32 minor_status
),
TP_ARGS(xid, major_status, minor_status),
TP_STRUCT__entry(
__field(u32, xid)
__field(u32, minor_status)
__field(unsigned long, major_status)
),
TP_fast_assign(
__entry->xid = be32_to_cpu(xid);
__entry->minor_status = minor_status;
__entry->major_status = major_status;
),
TP_printk("xid=0x%08x major_status=%s (0x%08lx) minor_status=%u",
__entry->xid, __entry->major_status == 0 ? "GSS_S_COMPLETE" :
show_gss_status(__entry->major_status),
__entry->major_status, __entry->minor_status
)
);
/** /**
** GSS auth unwrap failures ** GSS auth unwrap failures
...@@ -355,6 +383,23 @@ TRACE_EVENT(rpcgss_createauth, ...@@ -355,6 +383,23 @@ TRACE_EVENT(rpcgss_createauth,
show_pseudoflavor(__entry->flavor), __entry->error) show_pseudoflavor(__entry->flavor), __entry->error)
); );
TRACE_EVENT(rpcgss_oid_to_mech,
TP_PROTO(
const char *oid
),
TP_ARGS(oid),
TP_STRUCT__entry(
__string(oid, oid)
),
TP_fast_assign(
__assign_str(oid, oid);
),
TP_printk("mech for oid %s was not found", __get_str(oid))
);
#endif /* _TRACE_RPCGSS_H */ #endif /* _TRACE_RPCGSS_H */
......
...@@ -1564,31 +1564,47 @@ DEFINE_ERROR_EVENT(chunk); ...@@ -1564,31 +1564,47 @@ DEFINE_ERROR_EVENT(chunk);
** Server-side RDMA API events ** Server-side RDMA API events
**/ **/
TRACE_EVENT(svcrdma_dma_map_page, DECLARE_EVENT_CLASS(svcrdma_dma_map_class,
TP_PROTO( TP_PROTO(
const struct svcxprt_rdma *rdma, const struct svcxprt_rdma *rdma,
const void *page u64 dma_addr,
u32 length
), ),
TP_ARGS(rdma, page), TP_ARGS(rdma, dma_addr, length),
TP_STRUCT__entry( TP_STRUCT__entry(
__field(const void *, page); __field(u64, dma_addr)
__field(u32, length)
__string(device, rdma->sc_cm_id->device->name) __string(device, rdma->sc_cm_id->device->name)
__string(addr, rdma->sc_xprt.xpt_remotebuf) __string(addr, rdma->sc_xprt.xpt_remotebuf)
), ),
TP_fast_assign( TP_fast_assign(
__entry->page = page; __entry->dma_addr = dma_addr;
__entry->length = length;
__assign_str(device, rdma->sc_cm_id->device->name); __assign_str(device, rdma->sc_cm_id->device->name);
__assign_str(addr, rdma->sc_xprt.xpt_remotebuf); __assign_str(addr, rdma->sc_xprt.xpt_remotebuf);
), ),
TP_printk("addr=%s device=%s page=%p", TP_printk("addr=%s device=%s dma_addr=%llu length=%u",
__get_str(addr), __get_str(device), __entry->page __get_str(addr), __get_str(device),
__entry->dma_addr, __entry->length
) )
); );
#define DEFINE_SVC_DMA_EVENT(name) \
DEFINE_EVENT(svcrdma_dma_map_class, svcrdma_##name, \
TP_PROTO( \
const struct svcxprt_rdma *rdma,\
u64 dma_addr, \
u32 length \
), \
TP_ARGS(rdma, dma_addr, length))
DEFINE_SVC_DMA_EVENT(dma_map_page);
DEFINE_SVC_DMA_EVENT(dma_unmap_page);
TRACE_EVENT(svcrdma_dma_map_rwctx, TRACE_EVENT(svcrdma_dma_map_rwctx,
TP_PROTO( TP_PROTO(
const struct svcxprt_rdma *rdma, const struct svcxprt_rdma *rdma,
......
...@@ -14,6 +14,26 @@ ...@@ -14,6 +14,26 @@
#include <linux/net.h> #include <linux/net.h>
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
TRACE_DEFINE_ENUM(RPC_AUTH_OK);
TRACE_DEFINE_ENUM(RPC_AUTH_BADCRED);
TRACE_DEFINE_ENUM(RPC_AUTH_REJECTEDCRED);
TRACE_DEFINE_ENUM(RPC_AUTH_BADVERF);
TRACE_DEFINE_ENUM(RPC_AUTH_REJECTEDVERF);
TRACE_DEFINE_ENUM(RPC_AUTH_TOOWEAK);
TRACE_DEFINE_ENUM(RPCSEC_GSS_CREDPROBLEM);
TRACE_DEFINE_ENUM(RPCSEC_GSS_CTXPROBLEM);
#define rpc_show_auth_stat(status) \
__print_symbolic(status, \
{ RPC_AUTH_OK, "AUTH_OK" }, \
{ RPC_AUTH_BADCRED, "BADCRED" }, \
{ RPC_AUTH_REJECTEDCRED, "REJECTEDCRED" }, \
{ RPC_AUTH_BADVERF, "BADVERF" }, \
{ RPC_AUTH_REJECTEDVERF, "REJECTEDVERF" }, \
{ RPC_AUTH_TOOWEAK, "TOOWEAK" }, \
{ RPCSEC_GSS_CREDPROBLEM, "GSS_CREDPROBLEM" }, \
{ RPCSEC_GSS_CTXPROBLEM, "GSS_CTXPROBLEM" }) \
DECLARE_EVENT_CLASS(rpc_task_status, DECLARE_EVENT_CLASS(rpc_task_status,
TP_PROTO(const struct rpc_task *task), TP_PROTO(const struct rpc_task *task),
...@@ -960,6 +980,41 @@ TRACE_EVENT(svc_recv, ...@@ -960,6 +980,41 @@ TRACE_EVENT(svc_recv,
show_rqstp_flags(__entry->flags)) show_rqstp_flags(__entry->flags))
); );
#define svc_show_status(status) \
__print_symbolic(status, \
{ SVC_GARBAGE, "SVC_GARBAGE" }, \
{ SVC_SYSERR, "SVC_SYSERR" }, \
{ SVC_VALID, "SVC_VALID" }, \
{ SVC_NEGATIVE, "SVC_NEGATIVE" }, \
{ SVC_OK, "SVC_OK" }, \
{ SVC_DROP, "SVC_DROP" }, \
{ SVC_CLOSE, "SVC_CLOSE" }, \
{ SVC_DENIED, "SVC_DENIED" }, \
{ SVC_PENDING, "SVC_PENDING" }, \
{ SVC_COMPLETE, "SVC_COMPLETE" })
TRACE_EVENT(svc_authenticate,
TP_PROTO(const struct svc_rqst *rqst, int auth_res, __be32 auth_stat),
TP_ARGS(rqst, auth_res, auth_stat),
TP_STRUCT__entry(
__field(u32, xid)
__field(unsigned long, svc_status)
__field(unsigned long, auth_stat)
),
TP_fast_assign(
__entry->xid = be32_to_cpu(rqst->rq_xid);
__entry->svc_status = auth_res;
__entry->auth_stat = be32_to_cpu(auth_stat);
),
TP_printk("xid=0x%08x auth_res=%s auth_stat=%s",
__entry->xid, svc_show_status(__entry->svc_status),
rpc_show_auth_stat(__entry->auth_stat))
);
TRACE_EVENT(svc_process, TRACE_EVENT(svc_process,
TP_PROTO(const struct svc_rqst *rqst, const char *name), TP_PROTO(const struct svc_rqst *rqst, const char *name),
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/sunrpc/sched.h> #include <linux/sunrpc/sched.h>
#include <linux/sunrpc/gss_api.h> #include <linux/sunrpc/gss_api.h>
#include <linux/sunrpc/clnt.h> #include <linux/sunrpc/clnt.h>
#include <trace/events/rpcgss.h>
#if IS_ENABLED(CONFIG_SUNRPC_DEBUG) #if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
# define RPCDBG_FACILITY RPCDBG_AUTH # define RPCDBG_FACILITY RPCDBG_AUTH
...@@ -158,7 +159,6 @@ struct gss_api_mech *gss_mech_get_by_OID(struct rpcsec_gss_oid *obj) ...@@ -158,7 +159,6 @@ struct gss_api_mech *gss_mech_get_by_OID(struct rpcsec_gss_oid *obj)
if (sprint_oid(obj->data, obj->len, buf, sizeof(buf)) < 0) if (sprint_oid(obj->data, obj->len, buf, sizeof(buf)) < 0)
return NULL; return NULL;
dprintk("RPC: %s(%s)\n", __func__, buf);
request_module("rpc-auth-gss-%s", buf); request_module("rpc-auth-gss-%s", buf);
rcu_read_lock(); rcu_read_lock();
...@@ -172,6 +172,8 @@ struct gss_api_mech *gss_mech_get_by_OID(struct rpcsec_gss_oid *obj) ...@@ -172,6 +172,8 @@ struct gss_api_mech *gss_mech_get_by_OID(struct rpcsec_gss_oid *obj)
} }
} }
rcu_read_unlock(); rcu_read_unlock();
if (!gm)
trace_rpcgss_oid_to_mech(buf);
return gm; return gm;
} }
......
...@@ -49,6 +49,9 @@ ...@@ -49,6 +49,9 @@
#include <linux/sunrpc/svcauth.h> #include <linux/sunrpc/svcauth.h>
#include <linux/sunrpc/svcauth_gss.h> #include <linux/sunrpc/svcauth_gss.h>
#include <linux/sunrpc/cache.h> #include <linux/sunrpc/cache.h>
#include <trace/events/rpcgss.h>
#include "gss_rpc_upcall.h" #include "gss_rpc_upcall.h"
...@@ -1075,24 +1078,32 @@ gss_read_verf(struct rpc_gss_wire_cred *gc, ...@@ -1075,24 +1078,32 @@ gss_read_verf(struct rpc_gss_wire_cred *gc,
return 0; return 0;
} }
/* Ok this is really heavily depending on a set of semantics in static void gss_free_in_token_pages(struct gssp_in_token *in_token)
* how rqstp is set up by svc_recv and pages laid down by the
* server when reading a request. We are basically guaranteed that
* the token lays all down linearly across a set of pages, starting
* at iov_base in rq_arg.head[0] which happens to be the first of a
* set of pages stored in rq_pages[].
* rq_arg.head[0].iov_base will provide us the page_base to pass
* to the upcall.
*/
static inline int
gss_read_proxy_verf(struct svc_rqst *rqstp,
struct rpc_gss_wire_cred *gc, __be32 *authp,
struct xdr_netobj *in_handle,
struct gssp_in_token *in_token)
{ {
struct kvec *argv = &rqstp->rq_arg.head[0];
u32 inlen; u32 inlen;
int res; int i;
i = 0;
inlen = in_token->page_len;
while (inlen) {
if (in_token->pages[i])
put_page(in_token->pages[i]);
inlen -= inlen > PAGE_SIZE ? PAGE_SIZE : inlen;
}
kfree(in_token->pages);
in_token->pages = NULL;
}
static int gss_read_proxy_verf(struct svc_rqst *rqstp,
struct rpc_gss_wire_cred *gc, __be32 *authp,
struct xdr_netobj *in_handle,
struct gssp_in_token *in_token)
{
struct kvec *argv = &rqstp->rq_arg.head[0];
unsigned int page_base, length;
int pages, i, res;
size_t inlen;
res = gss_read_common_verf(gc, argv, authp, in_handle); res = gss_read_common_verf(gc, argv, authp, in_handle);
if (res) if (res)
...@@ -1102,10 +1113,36 @@ gss_read_proxy_verf(struct svc_rqst *rqstp, ...@@ -1102,10 +1113,36 @@ gss_read_proxy_verf(struct svc_rqst *rqstp,
if (inlen > (argv->iov_len + rqstp->rq_arg.page_len)) if (inlen > (argv->iov_len + rqstp->rq_arg.page_len))
return SVC_DENIED; return SVC_DENIED;
in_token->pages = rqstp->rq_pages; pages = DIV_ROUND_UP(inlen, PAGE_SIZE);
in_token->page_base = (ulong)argv->iov_base & ~PAGE_MASK; in_token->pages = kcalloc(pages, sizeof(struct page *), GFP_KERNEL);
if (!in_token->pages)
return SVC_DENIED;
in_token->page_base = 0;
in_token->page_len = inlen; in_token->page_len = inlen;
for (i = 0; i < pages; i++) {
in_token->pages[i] = alloc_page(GFP_KERNEL);
if (!in_token->pages[i]) {
gss_free_in_token_pages(in_token);
return SVC_DENIED;
}
}
length = min_t(unsigned int, inlen, argv->iov_len);
memcpy(page_address(in_token->pages[0]), argv->iov_base, length);
inlen -= length;
i = 1;
page_base = rqstp->rq_arg.page_base;
while (inlen) {
length = min_t(unsigned int, inlen, PAGE_SIZE);
memcpy(page_address(in_token->pages[i]),
page_address(rqstp->rq_arg.pages[i]) + page_base,
length);
inlen -= length;
page_base = 0;
i++;
}
return 0; return 0;
} }
...@@ -1270,9 +1307,8 @@ static int svcauth_gss_proxy_init(struct svc_rqst *rqstp, ...@@ -1270,9 +1307,8 @@ static int svcauth_gss_proxy_init(struct svc_rqst *rqstp,
if (status) if (status)
goto out; goto out;
dprintk("RPC: svcauth_gss: gss major status = %d " trace_rpcgss_accept_upcall(rqstp->rq_xid, ud.major_status,
"minor status = %d\n", ud.minor_status);
ud.major_status, ud.minor_status);
switch (ud.major_status) { switch (ud.major_status) {
case GSS_S_CONTINUE_NEEDED: case GSS_S_CONTINUE_NEEDED:
...@@ -1280,8 +1316,11 @@ static int svcauth_gss_proxy_init(struct svc_rqst *rqstp, ...@@ -1280,8 +1316,11 @@ static int svcauth_gss_proxy_init(struct svc_rqst *rqstp,
break; break;
case GSS_S_COMPLETE: case GSS_S_COMPLETE:
status = gss_proxy_save_rsc(sn->rsc_cache, &ud, &handle); status = gss_proxy_save_rsc(sn->rsc_cache, &ud, &handle);
if (status) if (status) {
pr_info("%s: gss_proxy_save_rsc failed (%d)\n",
__func__, status);
goto out; goto out;
}
cli_handle.data = (u8 *)&handle; cli_handle.data = (u8 *)&handle;
cli_handle.len = sizeof(handle); cli_handle.len = sizeof(handle);
break; break;
...@@ -1292,15 +1331,20 @@ static int svcauth_gss_proxy_init(struct svc_rqst *rqstp, ...@@ -1292,15 +1331,20 @@ static int svcauth_gss_proxy_init(struct svc_rqst *rqstp,
/* Got an answer to the upcall; use it: */ /* Got an answer to the upcall; use it: */
if (gss_write_init_verf(sn->rsc_cache, rqstp, if (gss_write_init_verf(sn->rsc_cache, rqstp,
&cli_handle, &ud.major_status)) &cli_handle, &ud.major_status)) {
pr_info("%s: gss_write_init_verf failed\n", __func__);
goto out; goto out;
}
if (gss_write_resv(resv, PAGE_SIZE, if (gss_write_resv(resv, PAGE_SIZE,
&cli_handle, &ud.out_token, &cli_handle, &ud.out_token,
ud.major_status, ud.minor_status)) ud.major_status, ud.minor_status)) {
pr_info("%s: gss_write_resv failed\n", __func__);
goto out; goto out;
}
ret = SVC_COMPLETE; ret = SVC_COMPLETE;
out: out:
gss_free_in_token_pages(&ud.in_token);
gssp_free_upcall_data(&ud); gssp_free_upcall_data(&ud);
return ret; return ret;
} }
......
...@@ -53,9 +53,6 @@ static void cache_init(struct cache_head *h, struct cache_detail *detail) ...@@ -53,9 +53,6 @@ static void cache_init(struct cache_head *h, struct cache_detail *detail)
h->last_refresh = now; h->last_refresh = now;
} }
static inline int cache_is_valid(struct cache_head *h);
static void cache_fresh_locked(struct cache_head *head, time_t expiry,
struct cache_detail *detail);
static void cache_fresh_unlocked(struct cache_head *head, static void cache_fresh_unlocked(struct cache_head *head,
struct cache_detail *detail); struct cache_detail *detail);
...@@ -105,9 +102,6 @@ static struct cache_head *sunrpc_cache_add_entry(struct cache_detail *detail, ...@@ -105,9 +102,6 @@ static struct cache_head *sunrpc_cache_add_entry(struct cache_detail *detail,
if (cache_is_expired(detail, tmp)) { if (cache_is_expired(detail, tmp)) {
hlist_del_init_rcu(&tmp->cache_list); hlist_del_init_rcu(&tmp->cache_list);
detail->entries --; detail->entries --;
if (cache_is_valid(tmp) == -EAGAIN)
set_bit(CACHE_NEGATIVE, &tmp->flags);
cache_fresh_locked(tmp, 0, detail);
freeme = tmp; freeme = tmp;
break; break;
} }
......
...@@ -1337,6 +1337,8 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) ...@@ -1337,6 +1337,8 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
auth_stat = rpc_autherr_badcred; auth_stat = rpc_autherr_badcred;
auth_res = progp->pg_authenticate(rqstp); auth_res = progp->pg_authenticate(rqstp);
} }
if (auth_res != SVC_OK)
trace_svc_authenticate(rqstp, auth_res, auth_stat);
switch (auth_res) { switch (auth_res) {
case SVC_OK: case SVC_OK:
break; break;
......
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/hash.h> #include <linux/hash.h>
#include <trace/events/sunrpc.h>
#define RPCDBG_FACILITY RPCDBG_AUTH #define RPCDBG_FACILITY RPCDBG_AUTH
......
...@@ -195,6 +195,7 @@ rpcrdma_bc_send_request(struct svcxprt_rdma *rdma, struct rpc_rqst *rqst) ...@@ -195,6 +195,7 @@ rpcrdma_bc_send_request(struct svcxprt_rdma *rdma, struct rpc_rqst *rqst)
pr_info("%s: %*ph\n", __func__, 64, rqst->rq_buffer); pr_info("%s: %*ph\n", __func__, 64, rqst->rq_buffer);
#endif #endif
rqst->rq_xtime = ktime_get();
rc = svc_rdma_bc_sendto(rdma, rqst, ctxt); rc = svc_rdma_bc_sendto(rdma, rqst, ctxt);
if (rc) { if (rc) {
svc_rdma_send_ctxt_put(rdma, ctxt); svc_rdma_send_ctxt_put(rdma, ctxt);
......
...@@ -233,11 +233,15 @@ void svc_rdma_send_ctxt_put(struct svcxprt_rdma *rdma, ...@@ -233,11 +233,15 @@ void svc_rdma_send_ctxt_put(struct svcxprt_rdma *rdma,
/* The first SGE contains the transport header, which /* The first SGE contains the transport header, which
* remains mapped until @ctxt is destroyed. * remains mapped until @ctxt is destroyed.
*/ */
for (i = 1; i < ctxt->sc_send_wr.num_sge; i++) for (i = 1; i < ctxt->sc_send_wr.num_sge; i++) {
ib_dma_unmap_page(device, ib_dma_unmap_page(device,
ctxt->sc_sges[i].addr, ctxt->sc_sges[i].addr,
ctxt->sc_sges[i].length, ctxt->sc_sges[i].length,
DMA_TO_DEVICE); DMA_TO_DEVICE);
trace_svcrdma_dma_unmap_page(rdma,
ctxt->sc_sges[i].addr,
ctxt->sc_sges[i].length);
}
for (i = 0; i < ctxt->sc_page_count; ++i) for (i = 0; i < ctxt->sc_page_count; ++i)
put_page(ctxt->sc_pages[i]); put_page(ctxt->sc_pages[i]);
...@@ -490,6 +494,7 @@ static int svc_rdma_dma_map_page(struct svcxprt_rdma *rdma, ...@@ -490,6 +494,7 @@ static int svc_rdma_dma_map_page(struct svcxprt_rdma *rdma,
dma_addr_t dma_addr; dma_addr_t dma_addr;
dma_addr = ib_dma_map_page(dev, page, offset, len, DMA_TO_DEVICE); dma_addr = ib_dma_map_page(dev, page, offset, len, DMA_TO_DEVICE);
trace_svcrdma_dma_map_page(rdma, dma_addr, len);
if (ib_dma_mapping_error(dev, dma_addr)) if (ib_dma_mapping_error(dev, dma_addr))
goto out_maperr; goto out_maperr;
...@@ -499,7 +504,6 @@ static int svc_rdma_dma_map_page(struct svcxprt_rdma *rdma, ...@@ -499,7 +504,6 @@ static int svc_rdma_dma_map_page(struct svcxprt_rdma *rdma,
return 0; return 0;
out_maperr: out_maperr:
trace_svcrdma_dma_map_page(rdma, page);
return -EIO; return -EIO;
} }
......
...@@ -2659,6 +2659,8 @@ static int bc_sendto(struct rpc_rqst *req) ...@@ -2659,6 +2659,8 @@ static int bc_sendto(struct rpc_rqst *req)
.iov_len = sizeof(marker), .iov_len = sizeof(marker),
}; };
req->rq_xtime = ktime_get();
len = kernel_sendmsg(transport->sock, &msg, &iov, 1, iov.iov_len); len = kernel_sendmsg(transport->sock, &msg, &iov, 1, iov.iov_len);
if (len != iov.iov_len) if (len != iov.iov_len)
return -EAGAIN; return -EAGAIN;
...@@ -2684,7 +2686,6 @@ static int bc_send_request(struct rpc_rqst *req) ...@@ -2684,7 +2686,6 @@ static int bc_send_request(struct rpc_rqst *req)
struct svc_xprt *xprt; struct svc_xprt *xprt;
int len; int len;
dprintk("sending request with xid: %08x\n", ntohl(req->rq_xid));
/* /*
* Get the server socket associated with this callback xprt * Get the server socket associated with this callback xprt
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment