]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - fs/nfs/nfs4proc.c
nfs41: resize slot table in reset
[mv-sheeva.git] / fs / nfs / nfs4proc.c
index 198d51d17c135e1b41564636511ff0119e0a7219..84b53d38f50be9ccd1d8c15f6bc669c0d6f4424b 100644 (file)
@@ -249,19 +249,15 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
                        if (state == NULL)
                                break;
                        nfs4_state_mark_reclaim_nograce(clp, state);
-               case -NFS4ERR_STALE_CLIENTID:
+                       goto do_state_recovery;
                case -NFS4ERR_STALE_STATEID:
-               case -NFS4ERR_EXPIRED:
-                       nfs4_schedule_state_recovery(clp);
-                       ret = nfs4_wait_clnt_recover(clp);
-                       if (ret == 0)
-                               exception->retry = 1;
-#if !defined(CONFIG_NFS_V4_1)
-                       break;
-#else /* !defined(CONFIG_NFS_V4_1) */
-                       if (!nfs4_has_session(server->nfs_client))
+                       if (state == NULL)
                                break;
-                       /* FALLTHROUGH */
+                       nfs4_state_mark_reclaim_reboot(clp, state);
+               case -NFS4ERR_STALE_CLIENTID:
+               case -NFS4ERR_EXPIRED:
+                       goto do_state_recovery;
+#if defined(CONFIG_NFS_V4_1)
                case -NFS4ERR_BADSESSION:
                case -NFS4ERR_BADSLOT:
                case -NFS4ERR_BAD_HIGH_SLOT:
@@ -274,7 +270,7 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
                        nfs4_schedule_state_recovery(clp);
                        exception->retry = 1;
                        break;
-#endif /* !defined(CONFIG_NFS_V4_1) */
+#endif /* defined(CONFIG_NFS_V4_1) */
                case -NFS4ERR_FILE_OPEN:
                        if (exception->timeout > HZ) {
                                /* We have retried a decent amount, time to
@@ -285,6 +281,7 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
                        }
                case -NFS4ERR_GRACE:
                case -NFS4ERR_DELAY:
+               case -EKEYEXPIRED:
                        ret = nfs4_delay(server->client, &exception->timeout);
                        if (ret != 0)
                                break;
@@ -293,6 +290,12 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
        }
        /* We failed to handle the error */
        return nfs4_map_errors(ret);
+do_state_recovery:
+       nfs4_schedule_state_recovery(clp);
+       ret = nfs4_wait_clnt_recover(clp);
+       if (ret == 0)
+               exception->retry = 1;
+       return ret;
 }
 
 
@@ -1161,7 +1164,7 @@ static int nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state
        int err;
        do {
                err = _nfs4_do_open_reclaim(ctx, state);
-               if (err != -NFS4ERR_DELAY)
+               if (err != -NFS4ERR_DELAY && err != -EKEYEXPIRED)
                        break;
                nfs4_handle_exception(server, err, &exception);
        } while (exception.retry);
@@ -1580,6 +1583,7 @@ static int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state
                        goto out;
                case -NFS4ERR_GRACE:
                case -NFS4ERR_DELAY:
+               case -EKEYEXPIRED:
                        nfs4_handle_exception(server, err, &exception);
                        err = 0;
                }
@@ -1658,6 +1662,8 @@ static int _nfs4_do_open(struct inode *dir, struct path *path, fmode_t fmode, in
        status = PTR_ERR(state);
        if (IS_ERR(state))
                goto err_opendata_put;
+       if ((opendata->o_res.rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) != 0)
+               set_bit(NFS_STATE_POSIX_LOCKS, &state->flags);
        nfs4_opendata_put(opendata);
        nfs4_put_state_owner(sp);
        *res = state;
@@ -3422,15 +3428,14 @@ _nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
                        if (state == NULL)
                                break;
                        nfs4_state_mark_reclaim_nograce(clp, state);
-               case -NFS4ERR_STALE_CLIENTID:
+                       goto do_state_recovery;
                case -NFS4ERR_STALE_STATEID:
+                       if (state == NULL)
+                               break;
+                       nfs4_state_mark_reclaim_reboot(clp, state);
+               case -NFS4ERR_STALE_CLIENTID:
                case -NFS4ERR_EXPIRED:
-                       rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL);
-                       nfs4_schedule_state_recovery(clp);
-                       if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0)
-                               rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task);
-                       task->tk_status = 0;
-                       return -EAGAIN;
+                       goto do_state_recovery;
 #if defined(CONFIG_NFS_V4_1)
                case -NFS4ERR_BADSESSION:
                case -NFS4ERR_BADSLOT:
@@ -3449,6 +3454,7 @@ _nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
                        if (server)
                                nfs_inc_server_stats(server, NFSIOS_DELAY);
                case -NFS4ERR_GRACE:
+               case -EKEYEXPIRED:
                        rpc_delay(task, NFS4_POLL_RETRY_MAX);
                        task->tk_status = 0;
                        return -EAGAIN;
@@ -3458,6 +3464,13 @@ _nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
        }
        task->tk_status = nfs4_map_errors(task->tk_status);
        return 0;
+do_state_recovery:
+       rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL);
+       nfs4_schedule_state_recovery(clp);
+       if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0)
+               rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task);
+       task->tk_status = 0;
+       return -EAGAIN;
 }
 
 static int
@@ -3554,6 +3567,7 @@ int nfs4_proc_setclientid_confirm(struct nfs_client *clp, struct rpc_cred *cred)
                        case -NFS4ERR_RESOURCE:
                                /* The IBM lawyers misread another document! */
                        case -NFS4ERR_DELAY:
+                       case -EKEYEXPIRED:
                                err = nfs4_delay(clp->cl_rpcclient, &timeout);
                }
        } while (err == 0);
@@ -4088,6 +4102,28 @@ static const struct rpc_call_ops nfs4_recover_lock_ops = {
        .rpc_release = nfs4_lock_release,
 };
 
+static void nfs4_handle_setlk_error(struct nfs_server *server, struct nfs4_lock_state *lsp, int new_lock_owner, int error)
+{
+       struct nfs_client *clp = server->nfs_client;
+       struct nfs4_state *state = lsp->ls_state;
+
+       switch (error) {
+       case -NFS4ERR_ADMIN_REVOKED:
+       case -NFS4ERR_BAD_STATEID:
+       case -NFS4ERR_EXPIRED:
+               if (new_lock_owner != 0 ||
+                  (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0)
+                       nfs4_state_mark_reclaim_nograce(clp, state);
+               lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED;
+               break;
+       case -NFS4ERR_STALE_STATEID:
+               if (new_lock_owner != 0 ||
+                   (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0)
+                       nfs4_state_mark_reclaim_reboot(clp, state);
+               lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED;
+       };
+}
+
 static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *fl, int recovery_type)
 {
        struct nfs4_lockdata *data;
@@ -4126,6 +4162,9 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f
        ret = nfs4_wait_for_completion_rpc_task(task);
        if (ret == 0) {
                ret = data->rpc_status;
+               if (ret)
+                       nfs4_handle_setlk_error(data->server, data->lsp,
+                                       data->arg.new_lock_owner, ret);
        } else
                data->cancelled = 1;
        rpc_put_task(task);
@@ -4144,7 +4183,7 @@ static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request
                if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0)
                        return 0;
                err = _nfs4_do_setlk(state, F_SETLK, request, NFS_LOCK_RECLAIM);
-               if (err != -NFS4ERR_DELAY)
+               if (err != -NFS4ERR_DELAY && err != -EKEYEXPIRED)
                        break;
                nfs4_handle_exception(server, err, &exception);
        } while (exception.retry);
@@ -4169,6 +4208,7 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request
                        goto out;
                case -NFS4ERR_GRACE:
                case -NFS4ERR_DELAY:
+               case -EKEYEXPIRED:
                        nfs4_handle_exception(server, err, &exception);
                        err = 0;
                }
@@ -4181,8 +4221,11 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock
 {
        struct nfs_inode *nfsi = NFS_I(state->inode);
        unsigned char fl_flags = request->fl_flags;
-       int status;
+       int status = -ENOLCK;
 
+       if ((fl_flags & FL_POSIX) &&
+                       !test_bit(NFS_STATE_POSIX_LOCKS, &state->flags))
+               goto out;
        /* Is this a delegated open? */
        status = nfs4_set_lock_state(state, request);
        if (status != 0)
@@ -4317,6 +4360,7 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl)
                                err = 0;
                                goto out;
                        case -NFS4ERR_DELAY:
+                       case -EKEYEXPIRED:
                                break;
                }
                err = nfs4_handle_exception(server, err, &exception);
@@ -4516,6 +4560,7 @@ static void nfs4_get_lease_time_done(struct rpc_task *task, void *calldata)
        switch (task->tk_status) {
        case -NFS4ERR_DELAY:
        case -NFS4ERR_GRACE:
+       case -EKEYEXPIRED:
                dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status);
                rpc_delay(task, NFS4_POLL_RETRY_MIN);
                task->tk_status = 0;
@@ -4573,26 +4618,32 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo)
 /*
  * Reset a slot table
  */
-static int nfs4_reset_slot_table(struct nfs4_slot_table *tbl, int max_slots,
-               int old_max_slots, int ivalue)
+static int nfs4_reset_slot_table(struct nfs4_slot_table *tbl, u32 max_reqs,
+                                int ivalue)
 {
+       struct nfs4_slot *new = NULL;
        int i;
        int ret = 0;
 
-       dprintk("--> %s: max_reqs=%u, tbl %p\n", __func__, max_slots, tbl);
+       dprintk("--> %s: max_reqs=%u, tbl->max_slots %d\n", __func__,
+               max_reqs, tbl->max_slots);
 
-       /*
-        * Until we have dynamic slot table adjustment, insist
-        * upon the same slot table size
-        */
-       if (max_slots != old_max_slots) {
-               dprintk("%s reset slot table does't match old\n",
-                       __func__);
-               ret = -EINVAL; /*XXX NFS4ERR_REQ_TOO_BIG ? */
-               goto out;
+       /* Does the newly negotiated max_reqs match the existing slot table? */
+       if (max_reqs != tbl->max_slots) {
+               ret = -ENOMEM;
+               new = kmalloc(max_reqs * sizeof(struct nfs4_slot),
+                             GFP_KERNEL);
+               if (!new)
+                       goto out;
+               ret = 0;
+               kfree(tbl->slots);
        }
        spin_lock(&tbl->slot_tbl_lock);
-       for (i = 0; i < max_slots; ++i)
+       if (new) {
+               tbl->slots = new;
+               tbl->max_slots = max_reqs;
+       }
+       for (i = 0; i < tbl->max_slots; ++i)
                tbl->slots[i].seq_nr = ivalue;
        spin_unlock(&tbl->slot_tbl_lock);
        dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__,
@@ -4610,16 +4661,12 @@ static int nfs4_reset_slot_tables(struct nfs4_session *session)
        int status;
 
        status = nfs4_reset_slot_table(&session->fc_slot_table,
-                       session->fc_attrs.max_reqs,
-                       session->fc_slot_table.max_slots,
-                       1);
+                       session->fc_attrs.max_reqs, 1);
        if (status)
                return status;
 
        status = nfs4_reset_slot_table(&session->bc_slot_table,
-                       session->bc_attrs.max_reqs,
-                       session->bc_slot_table.max_slots,
-                       0);
+                       session->bc_attrs.max_reqs, 0);
        return status;
 }
 
@@ -4760,16 +4807,14 @@ static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args)
        args->fc_attrs.headerpadsz = 0;
        args->fc_attrs.max_rqst_sz = mxrqst_sz;
        args->fc_attrs.max_resp_sz = mxresp_sz;
-       args->fc_attrs.max_resp_sz_cached = mxresp_sz;
        args->fc_attrs.max_ops = NFS4_MAX_OPS;
        args->fc_attrs.max_reqs = session->clp->cl_rpcclient->cl_xprt->max_reqs;
 
        dprintk("%s: Fore Channel : max_rqst_sz=%u max_resp_sz=%u "
-               "max_resp_sz_cached=%u max_ops=%u max_reqs=%u\n",
+               "max_ops=%u max_reqs=%u\n",
                __func__,
                args->fc_attrs.max_rqst_sz, args->fc_attrs.max_resp_sz,
-               args->fc_attrs.max_resp_sz_cached, args->fc_attrs.max_ops,
-               args->fc_attrs.max_reqs);
+               args->fc_attrs.max_ops, args->fc_attrs.max_reqs);
 
        /* Back channel attributes */
        args->bc_attrs.headerpadsz = 0;