static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata) { struct nfs4_delegation *dp = calldata; struct nfs4_client *clp = dp->dl_client; nfsd4_cb_done(task, calldata); switch (task->tk_status) { case -EIO: /* Network partition? */ atomic_set(&clp->cl_cb_conn.cb_set, 0); warn_no_callback_path(clp, task->tk_status); case -EBADHANDLE: case -NFS4ERR_BAD_STATEID: /* Race: client probably got cb_recall * before open reply granting delegation */ break; default: /* success, or error we can't handle */ goto done; } if (dp->dl_retries--) { rpc_delay(task, 2*HZ); task->tk_status = 0; rpc_restart_call(task); return; } else { atomic_set(&clp->cl_cb_conn.cb_set, 0); warn_no_callback_path(clp, task->tk_status); } done: kfree(task->tk_msg.rpc_argp); }
static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata) { struct nfsd4_callback *cb = calldata; struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall); struct nfs4_client *clp = dp->dl_client; struct rpc_clnt *current_rpc_client = clp->cl_cb_client; nfsd4_cb_done(task, calldata); if (current_rpc_client == NULL) { /* We're shutting down; give up. */ /* XXX: err, or is it ok just to fall through * and rpc_restart_call? */ return; } switch (task->tk_status) { case 0: return; case -EBADHANDLE: case -NFS4ERR_BAD_STATEID: /* Race: client probably got cb_recall * before open reply granting delegation */ break; default: /* Network partition? */ atomic_set(&clp->cl_cb_set, 0); warn_no_callback_path(clp, task->tk_status); if (current_rpc_client != task->tk_client) { /* queue a callback on the new connection: */ atomic_inc(&dp->dl_count); nfsd4_cb_recall(dp); return; } } if (dp->dl_retries--) { rpc_delay(task, 2*HZ); task->tk_status = 0; rpc_restart_call_prepare(task); return; } else { atomic_set(&clp->cl_cb_set, 0); warn_no_callback_path(clp, task->tk_status); } }