Skip to content

Commit

Permalink
Merge branch 'for-4.1' of git://linux-nfs.org/~bfields/linux
Browse files Browse the repository at this point in the history
Pull nfsd bugfixes from Bruce Fields:
 "Mainly pnfs fixes (and for problems with generic callback code made
  more obvious by pnfs)"

* 'for-4.1' of git://linux-nfs.org/~bfields/linux:
  nfsd: skip CB_NULL probes for 4.1 or later
  nfsd: fix callback restarts
  nfsd: split transport vs operation errors for callbacks
  svcrpc: fix potential GSSX_ACCEPT_SEC_CONTEXT decoding failures
  nfsd: fix pNFS return on close semantics
  nfsd: fix the check for confirmed openowner in nfs4_preprocess_stateid_op
  nfsd/blocklayout: pretend we can send deviceid notifications
  • Loading branch information
Linus Torvalds committed May 11, 2015
2 parents ef20816 + 4bd9e9b commit 4cfceaf
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 92 deletions.
11 changes: 11 additions & 0 deletions fs/nfsd/blocklayout.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,17 @@ nfsd4_block_proc_layoutcommit(struct inode *inode,
}

const struct nfsd4_layout_ops bl_layout_ops = {
/*
* Pretend that we send notification to the client. This is a blatant
* lie to force recent Linux clients to cache our device IDs.
* We rarely ever change the device ID, so the harm of leaking deviceids
* for a while isn't too bad. Unfortunately RFC5661 is a complete mess
* in this regard, but I filed errata 4119 for this a while ago, and
* hopefully the Linux client will eventually start caching deviceids
* without this again.
*/
.notify_types =
NOTIFY_DEVICEID4_DELETE | NOTIFY_DEVICEID4_CHANGE,
.proc_getdeviceinfo = nfsd4_block_proc_getdeviceinfo,
.encode_getdeviceinfo = nfsd4_block_encode_getdeviceinfo,
.proc_layoutget = nfsd4_block_proc_layoutget,
Expand Down
119 changes: 55 additions & 64 deletions fs/nfsd/nfs4callback.c
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ static int nfs_cb_stat_to_errno(int status)
}

static int decode_cb_op_status(struct xdr_stream *xdr, enum nfs_opnum4 expected,
enum nfsstat4 *status)
int *status)
{
__be32 *p;
u32 op;
Expand All @@ -235,7 +235,7 @@ static int decode_cb_op_status(struct xdr_stream *xdr, enum nfs_opnum4 expected,
op = be32_to_cpup(p++);
if (unlikely(op != expected))
goto out_unexpected;
*status = be32_to_cpup(p);
*status = nfs_cb_stat_to_errno(be32_to_cpup(p));
return 0;
out_overflow:
print_overflow_msg(__func__, xdr);
Expand Down Expand Up @@ -446,22 +446,16 @@ static int decode_cb_sequence4resok(struct xdr_stream *xdr,
static int decode_cb_sequence4res(struct xdr_stream *xdr,
struct nfsd4_callback *cb)
{
enum nfsstat4 nfserr;
int status;

if (cb->cb_minorversion == 0)
return 0;

status = decode_cb_op_status(xdr, OP_CB_SEQUENCE, &nfserr);
if (unlikely(status))
goto out;
if (unlikely(nfserr != NFS4_OK))
goto out_default;
status = decode_cb_sequence4resok(xdr, cb);
out:
return status;
out_default:
return nfs_cb_stat_to_errno(nfserr);
status = decode_cb_op_status(xdr, OP_CB_SEQUENCE, &cb->cb_status);
if (unlikely(status || cb->cb_status))
return status;

return decode_cb_sequence4resok(xdr, cb);
}

/*
Expand Down Expand Up @@ -524,26 +518,19 @@ static int nfs4_xdr_dec_cb_recall(struct rpc_rqst *rqstp,
struct nfsd4_callback *cb)
{
struct nfs4_cb_compound_hdr hdr;
enum nfsstat4 nfserr;
int status;

status = decode_cb_compound4res(xdr, &hdr);
if (unlikely(status))
goto out;
return status;

if (cb != NULL) {
status = decode_cb_sequence4res(xdr, cb);
if (unlikely(status))
goto out;
if (unlikely(status || cb->cb_status))
return status;
}

status = decode_cb_op_status(xdr, OP_CB_RECALL, &nfserr);
if (unlikely(status))
goto out;
if (unlikely(nfserr != NFS4_OK))
status = nfs_cb_stat_to_errno(nfserr);
out:
return status;
return decode_cb_op_status(xdr, OP_CB_RECALL, &cb->cb_status);
}

#ifdef CONFIG_NFSD_PNFS
Expand Down Expand Up @@ -621,24 +608,18 @@ static int nfs4_xdr_dec_cb_layout(struct rpc_rqst *rqstp,
struct nfsd4_callback *cb)
{
struct nfs4_cb_compound_hdr hdr;
enum nfsstat4 nfserr;
int status;

status = decode_cb_compound4res(xdr, &hdr);
if (unlikely(status))
goto out;
return status;

if (cb) {
status = decode_cb_sequence4res(xdr, cb);
if (unlikely(status))
goto out;
if (unlikely(status || cb->cb_status))
return status;
}
status = decode_cb_op_status(xdr, OP_CB_LAYOUTRECALL, &nfserr);
if (unlikely(status))
goto out;
if (unlikely(nfserr != NFS4_OK))
status = nfs_cb_stat_to_errno(nfserr);
out:
return status;
return decode_cb_op_status(xdr, OP_CB_LAYOUTRECALL, &cb->cb_status);
}
#endif /* CONFIG_NFSD_PNFS */

Expand Down Expand Up @@ -898,13 +879,6 @@ static void nfsd4_cb_prepare(struct rpc_task *task, void *calldata)
if (!nfsd41_cb_get_slot(clp, task))
return;
}
spin_lock(&clp->cl_lock);
if (list_empty(&cb->cb_per_client)) {
/* This is the first call, not a restart */
cb->cb_done = false;
list_add(&cb->cb_per_client, &clp->cl_callbacks);
}
spin_unlock(&clp->cl_lock);
rpc_call_start(task);
}

Expand All @@ -918,22 +892,33 @@ static void nfsd4_cb_done(struct rpc_task *task, void *calldata)

if (clp->cl_minorversion) {
/* No need for lock, access serialized in nfsd4_cb_prepare */
++clp->cl_cb_session->se_cb_seq_nr;
if (!task->tk_status)
++clp->cl_cb_session->se_cb_seq_nr;
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__,
clp->cl_cb_session->se_cb_seq_nr);
}

if (clp->cl_cb_client != task->tk_client) {
/* We're shutting down or changing cl_cb_client; leave
* it to nfsd4_process_cb_update to restart the call if
* necessary. */
/*
* If the backchannel connection was shut down while this
* task was queued, we need to resubmit it after setting up
* a new backchannel connection.
*
* Note that if we lost our callback connection permanently
* the submission code will error out, so we don't need to
* handle that case here.
*/
if (task->tk_flags & RPC_TASK_KILLED) {
task->tk_status = 0;
cb->cb_need_restart = true;
return;
}

if (cb->cb_done)
return;
if (cb->cb_status) {
WARN_ON_ONCE(task->tk_status);
task->tk_status = cb->cb_status;
}

switch (cb->cb_ops->done(cb, task)) {
case 0:
Expand All @@ -949,21 +934,17 @@ static void nfsd4_cb_done(struct rpc_task *task, void *calldata)
default:
BUG();
}
cb->cb_done = true;
}

static void nfsd4_cb_release(void *calldata)
{
struct nfsd4_callback *cb = calldata;
struct nfs4_client *clp = cb->cb_clp;

if (cb->cb_done) {
spin_lock(&clp->cl_lock);
list_del(&cb->cb_per_client);
spin_unlock(&clp->cl_lock);

if (cb->cb_need_restart)
nfsd4_run_cb(cb);
else
cb->cb_ops->release(cb);
}

}

static const struct rpc_call_ops nfsd4_cb_ops = {
Expand Down Expand Up @@ -1058,9 +1039,6 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb)
nfsd4_mark_cb_down(clp, err);
return;
}
/* Yay, the callback channel's back! Restart any callbacks: */
list_for_each_entry(cb, &clp->cl_callbacks, cb_per_client)
queue_work(callback_wq, &cb->cb_work);
}

static void
Expand All @@ -1071,8 +1049,12 @@ nfsd4_run_cb_work(struct work_struct *work)
struct nfs4_client *clp = cb->cb_clp;
struct rpc_clnt *clnt;

if (cb->cb_ops && cb->cb_ops->prepare)
cb->cb_ops->prepare(cb);
if (cb->cb_need_restart) {
cb->cb_need_restart = false;
} else {
if (cb->cb_ops && cb->cb_ops->prepare)
cb->cb_ops->prepare(cb);
}

if (clp->cl_flags & NFSD4_CLIENT_CB_FLAG_MASK)
nfsd4_process_cb_update(cb);
Expand All @@ -1084,6 +1066,15 @@ nfsd4_run_cb_work(struct work_struct *work)
cb->cb_ops->release(cb);
return;
}

/*
* Don't send probe messages for 4.1 or later.
*/
if (!cb->cb_ops && clp->cl_minorversion) {
clp->cl_cb_state = NFSD4_CB_UP;
return;
}

cb->cb_msg.rpc_cred = clp->cl_cb_cred;
rpc_call_async(clnt, &cb->cb_msg, RPC_TASK_SOFT | RPC_TASK_SOFTCONN,
cb->cb_ops ? &nfsd4_cb_ops : &nfsd4_cb_probe_ops, cb);
Expand All @@ -1098,8 +1089,8 @@ void nfsd4_init_cb(struct nfsd4_callback *cb, struct nfs4_client *clp,
cb->cb_msg.rpc_resp = cb;
cb->cb_ops = ops;
INIT_WORK(&cb->cb_work, nfsd4_run_cb_work);
INIT_LIST_HEAD(&cb->cb_per_client);
cb->cb_done = true;
cb->cb_status = 0;
cb->cb_need_restart = false;
}

void nfsd4_run_cb(struct nfsd4_callback *cb)
Expand Down
Loading

0 comments on commit 4cfceaf

Please sign in to comment.