]> rtime.felk.cvut.cz Git - linux-imx.git/blobdiff - fs/nfs/nfs4proc.c
NFSv4: Handle timeouts correctly when probing for lease validity
[linux-imx.git] / fs / nfs / nfs4proc.c
index 3e7d42fb775cbbc5597d2f499d2af80cd4c7cff0..264ddb16255fa0197eadbcd0c7a5ffdad72e8521 100644 (file)
@@ -1373,71 +1373,72 @@ static int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *sta
 
        ctx = nfs4_state_find_open_context(state);
        if (IS_ERR(ctx))
-               return PTR_ERR(ctx);
+               return -EAGAIN;
        ret = nfs4_do_open_reclaim(ctx, state);
        put_nfs_open_context(ctx);
        return ret;
 }
 
-static int _nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid)
+static int nfs4_handle_delegation_recall_error(struct nfs_server *server, struct nfs4_state *state, const nfs4_stateid *stateid, int err)
+{
+       switch (err) {
+               default:
+                       printk(KERN_ERR "NFS: %s: unhandled error "
+                                       "%d.\n", __func__, err);
+               case 0:
+               case -ENOENT:
+               case -ESTALE:
+                       break;
+               case -NFS4ERR_BADSESSION:
+               case -NFS4ERR_BADSLOT:
+               case -NFS4ERR_BAD_HIGH_SLOT:
+               case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
+               case -NFS4ERR_DEADSESSION:
+                       set_bit(NFS_DELEGATED_STATE, &state->flags);
+                       nfs4_schedule_session_recovery(server->nfs_client->cl_session, err);
+                       return -EAGAIN;
+               case -NFS4ERR_STALE_CLIENTID:
+               case -NFS4ERR_STALE_STATEID:
+                       set_bit(NFS_DELEGATED_STATE, &state->flags);
+               case -NFS4ERR_EXPIRED:
+                       /* Don't recall a delegation if it was lost */
+                       nfs4_schedule_lease_recovery(server->nfs_client);
+                       return -EAGAIN;
+               case -NFS4ERR_DELEG_REVOKED:
+               case -NFS4ERR_ADMIN_REVOKED:
+               case -NFS4ERR_BAD_STATEID:
+               case -NFS4ERR_OPENMODE:
+                       nfs_inode_find_state_and_recover(state->inode,
+                                       stateid);
+                       nfs4_schedule_stateid_recovery(server, state);
+                       return 0;
+               case -NFS4ERR_DELAY:
+               case -NFS4ERR_GRACE:
+                       set_bit(NFS_DELEGATED_STATE, &state->flags);
+                       ssleep(1);
+                       return -EAGAIN;
+               case -ENOMEM:
+               case -NFS4ERR_DENIED:
+                       /* kill_proc(fl->fl_pid, SIGLOST, 1); */
+                       return 0;
+       }
+       return err;
+}
+
+int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid)
 {
+       struct nfs_server *server = NFS_SERVER(state->inode);
        struct nfs4_opendata *opendata;
-       int ret;
+       int err;
 
        opendata = nfs4_open_recoverdata_alloc(ctx, state,
                        NFS4_OPEN_CLAIM_DELEG_CUR_FH);
        if (IS_ERR(opendata))
                return PTR_ERR(opendata);
        nfs4_stateid_copy(&opendata->o_arg.u.delegation, stateid);
-       ret = nfs4_open_recover(opendata, state);
+       err = nfs4_open_recover(opendata, state);
        nfs4_opendata_put(opendata);
-       return ret;
-}
-
-int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid)
-{
-       struct nfs4_exception exception = { };
-       struct nfs_server *server = NFS_SERVER(state->inode);
-       int err;
-       do {
-               err = _nfs4_open_delegation_recall(ctx, state, stateid);
-               switch (err) {
-                       case 0:
-                       case -ENOENT:
-                       case -ESTALE:
-                               goto out;
-                       case -NFS4ERR_BADSESSION:
-                       case -NFS4ERR_BADSLOT:
-                       case -NFS4ERR_BAD_HIGH_SLOT:
-                       case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
-                       case -NFS4ERR_DEADSESSION:
-                               set_bit(NFS_DELEGATED_STATE, &state->flags);
-                               nfs4_schedule_session_recovery(server->nfs_client->cl_session, err);
-                               err = -EAGAIN;
-                               goto out;
-                       case -NFS4ERR_STALE_CLIENTID:
-                       case -NFS4ERR_STALE_STATEID:
-                               set_bit(NFS_DELEGATED_STATE, &state->flags);
-                       case -NFS4ERR_EXPIRED:
-                               /* Don't recall a delegation if it was lost */
-                               nfs4_schedule_lease_recovery(server->nfs_client);
-                               err = -EAGAIN;
-                               goto out;
-                       case -NFS4ERR_DELEG_REVOKED:
-                       case -NFS4ERR_ADMIN_REVOKED:
-                       case -NFS4ERR_BAD_STATEID:
-                               nfs_inode_find_state_and_recover(state->inode,
-                                               stateid);
-                               nfs4_schedule_stateid_recovery(server, state);
-                       case -ENOMEM:
-                               err = 0;
-                               goto out;
-               }
-               set_bit(NFS_DELEGATED_STATE, &state->flags);
-               err = nfs4_handle_exception(server, err, &exception);
-       } while (exception.retry);
-out:
-       return err;
+       return nfs4_handle_delegation_recall_error(server, state, stateid, err);
 }
 
 static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata)
@@ -1814,7 +1815,7 @@ static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *sta
 
        ctx = nfs4_state_find_open_context(state);
        if (IS_ERR(ctx))
-               return PTR_ERR(ctx);
+               return -EAGAIN;
        ret = nfs4_do_open_expired(ctx, state);
        put_nfs_open_context(ctx);
        return ret;
@@ -1936,10 +1937,8 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
        if (ret != 0)
                goto out;
 
-       if (read_seqcount_retry(&sp->so_reclaim_seqcount, seq)) {
+       if (read_seqcount_retry(&sp->so_reclaim_seqcount, seq))
                nfs4_schedule_stateid_recovery(server, state);
-               nfs4_wait_clnt_recover(server->nfs_client);
-       }
        *res = state;
 out:
        return ret;
@@ -3798,7 +3797,7 @@ static int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred,
                return -ENOMEM;
        data->client = clp;
        data->timestamp = jiffies;
-       return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_SOFT,
+       return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT,
                        &nfs4_renew_ops, data);
 }
 
@@ -3812,7 +3811,7 @@ static int nfs4_proc_renew(struct nfs_client *clp, struct rpc_cred *cred)
        unsigned long now = jiffies;
        int status;
 
-       status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
+       status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
        if (status < 0)
                return status;
        do_renew_lease(clp, now);
@@ -5137,58 +5136,16 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
        return status;
 }
 
-int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl)
+int nfs4_lock_delegation_recall(struct file_lock *fl, struct nfs4_state *state, const nfs4_stateid *stateid)
 {
        struct nfs_server *server = NFS_SERVER(state->inode);
-       struct nfs4_exception exception = { };
        int err;
 
        err = nfs4_set_lock_state(state, fl);
        if (err != 0)
-               goto out;
-       do {
-               err = _nfs4_do_setlk(state, F_SETLK, fl, NFS_LOCK_NEW);
-               switch (err) {
-                       default:
-                               printk(KERN_ERR "NFS: %s: unhandled error "
-                                       "%d.\n", __func__, err);
-                       case 0:
-                       case -ESTALE:
-                               goto out;
-                       case -NFS4ERR_STALE_CLIENTID:
-                       case -NFS4ERR_STALE_STATEID:
-                               set_bit(NFS_DELEGATED_STATE, &state->flags);
-                       case -NFS4ERR_EXPIRED:
-                               nfs4_schedule_lease_recovery(server->nfs_client);
-                               err = -EAGAIN;
-                               goto out;
-                       case -NFS4ERR_BADSESSION:
-                       case -NFS4ERR_BADSLOT:
-                       case -NFS4ERR_BAD_HIGH_SLOT:
-                       case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
-                       case -NFS4ERR_DEADSESSION:
-                               set_bit(NFS_DELEGATED_STATE, &state->flags);
-                               nfs4_schedule_session_recovery(server->nfs_client->cl_session, err);
-                               err = -EAGAIN;
-                               goto out;
-                       case -NFS4ERR_DELEG_REVOKED:
-                       case -NFS4ERR_ADMIN_REVOKED:
-                       case -NFS4ERR_BAD_STATEID:
-                       case -NFS4ERR_OPENMODE:
-                               nfs4_schedule_stateid_recovery(server, state);
-                               err = 0;
-                               goto out;
-                       case -ENOMEM:
-                       case -NFS4ERR_DENIED:
-                               /* kill_proc(fl->fl_pid, SIGLOST, 1); */
-                               err = 0;
-                               goto out;
-               }
-               set_bit(NFS_DELEGATED_STATE, &state->flags);
-               err = nfs4_handle_exception(server, err, &exception);
-       } while (exception.retry);
-out:
-       return err;
+               return err;
+       err = _nfs4_do_setlk(state, F_SETLK, fl, NFS_LOCK_NEW);
+       return nfs4_handle_delegation_recall_error(server, state, stateid, err);
 }
 
 struct nfs_release_lockowner_data {
@@ -6002,7 +5959,7 @@ static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp,
                .rpc_client = clp->cl_rpcclient,
                .rpc_message = &msg,
                .callback_ops = &nfs41_sequence_ops,
-               .flags = RPC_TASK_ASYNC | RPC_TASK_SOFT,
+               .flags = RPC_TASK_ASYNC | RPC_TASK_TIMEOUT,
        };
 
        if (!atomic_inc_not_zero(&clp->cl_count))