aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
authorAndy Adamson <andros@netapp.com>2009-04-01 09:22:31 -0400
committerBenny Halevy <bhalevy@panasas.com>2009-06-17 15:24:34 -0400
commitfc931582c260e53ca5ca23bd70ccc9b2265cca9f (patch)
treee52ad324ae6bb236f66bfd3ea002a9362ec60727 /fs/nfs/nfs4proc.c
parent2050f0cc0703aab7cee798b3cb47037754f368bc (diff)
nfs41: create_session operation
Implement the create_session operation conforming to http://tools.ietf.org/html/draft-ietf-nfsv4-minorversion1-26 Set the real fore channel max operations to preserve server resources. Note: If the server returns < NFS4_MAX_OPS, the client will very soon get an NFS4ERR_TOO_MANY_OPS. A later patch will handle this. Set the max_rqst_sz and max_resp_sz to PAGE_SIZE - we preallocate the buffers. Set the back channel max_resp_sz_cached to zero to force the client to always set csa_cachethis to FALSE because the current implementation of the back channel DRC only supports caching the CB_SEQUENCE operation. The client back channel server supports one slot, and desires 2 operations per compound. Signed-off-by: Ricardo Labiaga <ricardo.labiaga@netapp.com> Signed-off-by: Andy Adamson<andros@umich.edu> Signed-off-by: Benny Halevy <bhalevy@panasas.com> [nfs41: remove extraneous rpc_clnt pointer] Use the struct nfs_client cl_rpcclient. Signed-off-by: Andy Adamson <andros@netapp.com> Signed-off-by: Benny Halevy <bhalevy@panasas.com> [nfs41: nfs4_init_channel_attrs, just use nfs41_create_session_args] Signed-off-by: Andy Adamson <andros@netapp.com> Signed-off-by: Benny Halevy <bhalevy@panasas.com> [nfs41: use rsize and wsize for session channel attributes] Signed-off-by: Andy Adamson <andros@netapp.com> Signed-off-by: Benny Halevy <bhalevy@panasas.com> [nfs41: set channel max operations] Signed-off-by: Andy Adamson <andros@netapp.com> Signed-off-by: Benny Halevy <bhalevy@panasas.com> [nfs41: set back channel attributes] Signed-off-by: Andy Adamson <andros@netapp.com> Signed-off-by: Benny Halevy <bhalevy@panasas.com> [nfs41: obliterate nfs4_adjust_channel_attrs] Signed-off-by: Andy Adamson <andros@netapp.com> Signed-off-by: Benny Halevy <bhalevy@panasas.com> [nfs41: have create_session work on nfs_client] Signed-off-by: Benny Halevy <bhalevy@panasas.com> [nfs41: move CONFIG_NFS_V4_1 endif] Signed-off-by: Andy Adamson <andros@netapp.com> Signed-off-by: Benny Halevy <bhalevy@panasas.com> [nfs41: pass *session in seq_args and seq_res] [moved nfs4_init_slot_table definition here] Signed-off-by: Benny Halevy <bhalevy@panasas.com> [nfs41: use kcalloc to allocate slot table] Signed-off-by: Benny Halevy <bhalevy@panasas.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> [nfs41: fix Xcode_create_session's xdr Xcoding pointer type] [nfs41: refactor decoding of channel attributes] Signed-off-by: Benny Halevy <bhalevy@panasas.com>
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c172
1 files changed, 172 insertions, 0 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index eafc99afd356..7d81d6e57533 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -54,6 +54,7 @@
54#include "delegation.h" 54#include "delegation.h"
55#include "internal.h" 55#include "internal.h"
56#include "iostat.h" 56#include "iostat.h"
57#include "callback.h"
57 58
58#define NFSDBG_FACILITY NFSDBG_PROC 59#define NFSDBG_FACILITY NFSDBG_PROC
59 60
@@ -4283,6 +4284,50 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo)
4283 return status; 4284 return status;
4284} 4285}
4285 4286
4287/*
4288 * Initialize slot table
4289 */
4290static int nfs4_init_slot_table(struct nfs4_session *session)
4291{
4292 struct nfs4_slot_table *tbl = &session->fc_slot_table;
4293 int i, max_slots = session->fc_attrs.max_reqs;
4294 struct nfs4_slot *slot;
4295 int ret = -ENOMEM;
4296
4297 BUG_ON(max_slots > NFS4_MAX_SLOT_TABLE);
4298
4299 dprintk("--> %s: max_reqs=%u\n", __func__,
4300 session->fc_attrs.max_reqs);
4301
4302 slot = kcalloc(max_slots, sizeof(struct nfs4_slot), GFP_KERNEL);
4303 if (!slot)
4304 goto out;
4305 for (i = 0; i < max_slots; ++i)
4306 slot[i].seq_nr = 1;
4307 ret = 0;
4308
4309 spin_lock(&tbl->slot_tbl_lock);
4310 if (tbl->slots != NULL) {
4311 spin_unlock(&tbl->slot_tbl_lock);
4312 dprintk("%s: slot table already initialized. tbl=%p slots=%p\n",
4313 __func__, tbl, tbl->slots);
4314 WARN_ON(1);
4315 goto out_free;
4316 }
4317 tbl->max_slots = max_slots;
4318 tbl->slots = slot;
4319 tbl->highest_used_slotid = -1; /* no slot is currently used */
4320 spin_unlock(&tbl->slot_tbl_lock);
4321 dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__,
4322 tbl, tbl->slots, tbl->max_slots);
4323out:
4324 dprintk("<-- %s: return %d\n", __func__, ret);
4325 return ret;
4326out_free:
4327 kfree(slot);
4328 goto out;
4329}
4330
4286/* Destroy the slot table */ 4331/* Destroy the slot table */
4287static void nfs4_destroy_slot_table(struct nfs4_session *session) 4332static void nfs4_destroy_slot_table(struct nfs4_session *session)
4288{ 4333{
@@ -4314,6 +4359,133 @@ void nfs4_destroy_session(struct nfs4_session *session)
4314 kfree(session); 4359 kfree(session);
4315} 4360}
4316 4361
4362/*
4363 * Initialize the values to be used by the client in CREATE_SESSION
4364 * If nfs4_init_session set the fore channel request and response sizes,
4365 * use them.
4366 *
4367 * Set the back channel max_resp_sz_cached to zero to force the client to
4368 * always set csa_cachethis to FALSE because the current implementation
4369 * of the back channel DRC only supports caching the CB_SEQUENCE operation.
4370 */
4371static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args)
4372{
4373 struct nfs4_session *session = args->client->cl_session;
4374 unsigned int mxrqst_sz = session->fc_attrs.max_rqst_sz,
4375 mxresp_sz = session->fc_attrs.max_resp_sz;
4376
4377 if (mxrqst_sz == 0)
4378 mxrqst_sz = NFS_MAX_FILE_IO_SIZE;
4379 if (mxresp_sz == 0)
4380 mxresp_sz = NFS_MAX_FILE_IO_SIZE;
4381 /* Fore channel attributes */
4382 args->fc_attrs.headerpadsz = 0;
4383 args->fc_attrs.max_rqst_sz = mxrqst_sz;
4384 args->fc_attrs.max_resp_sz = mxresp_sz;
4385 args->fc_attrs.max_resp_sz_cached = mxresp_sz;
4386 args->fc_attrs.max_ops = NFS4_MAX_OPS;
4387 args->fc_attrs.max_reqs = session->clp->cl_rpcclient->cl_xprt->max_reqs;
4388
4389 dprintk("%s: Fore Channel : max_rqst_sz=%u max_resp_sz=%u "
4390 "max_resp_sz_cached=%u max_ops=%u max_reqs=%u\n",
4391 __func__,
4392 args->fc_attrs.max_rqst_sz, args->fc_attrs.max_resp_sz,
4393 args->fc_attrs.max_resp_sz_cached, args->fc_attrs.max_ops,
4394 args->fc_attrs.max_reqs);
4395
4396 /* Back channel attributes */
4397 args->bc_attrs.headerpadsz = 0;
4398 args->bc_attrs.max_rqst_sz = PAGE_SIZE;
4399 args->bc_attrs.max_resp_sz = PAGE_SIZE;
4400 args->bc_attrs.max_resp_sz_cached = 0;
4401 args->bc_attrs.max_ops = NFS4_MAX_BACK_CHANNEL_OPS;
4402 args->bc_attrs.max_reqs = 1;
4403
4404 dprintk("%s: Back Channel : max_rqst_sz=%u max_resp_sz=%u "
4405 "max_resp_sz_cached=%u max_ops=%u max_reqs=%u\n",
4406 __func__,
4407 args->bc_attrs.max_rqst_sz, args->bc_attrs.max_resp_sz,
4408 args->bc_attrs.max_resp_sz_cached, args->bc_attrs.max_ops,
4409 args->bc_attrs.max_reqs);
4410}
4411
4412static int _nfs4_proc_create_session(struct nfs_client *clp)
4413{
4414 struct nfs4_session *session = clp->cl_session;
4415 struct nfs41_create_session_args args = {
4416 .client = clp,
4417 .cb_program = NFS4_CALLBACK,
4418 };
4419 struct nfs41_create_session_res res = {
4420 .client = clp,
4421 };
4422 struct rpc_message msg = {
4423 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE_SESSION],
4424 .rpc_argp = &args,
4425 .rpc_resp = &res,
4426 };
4427 int status;
4428
4429 nfs4_init_channel_attrs(&args);
4430 args.flags = (SESSION4_PERSIST);
4431
4432 status = rpc_call_sync(session->clp->cl_rpcclient, &msg, 0);
4433
4434 /* Set the negotiated values in the session's channel_attrs struct */
4435
4436 if (!status) {
4437 /* Increment the clientid slot sequence id */
4438 clp->cl_seqid++;
4439 }
4440
4441 return status;
4442}
4443
4444/*
4445 * Issues a CREATE_SESSION operation to the server.
4446 * It is the responsibility of the caller to verify the session is
4447 * expired before calling this routine.
4448 */
4449int nfs4_proc_create_session(struct nfs_client *clp)
4450{
4451 int status;
4452 unsigned *ptr;
4453 struct nfs_fsinfo fsinfo;
4454 struct nfs4_session *session = clp->cl_session;
4455
4456 dprintk("--> %s clp=%p session=%p\n", __func__, clp, session);
4457
4458 status = _nfs4_proc_create_session(clp);
4459 if (status)
4460 goto out;
4461
4462 /* Init the fore channel */
4463 status = nfs4_init_slot_table(session);
4464 dprintk("fore channel slot table initialization returned %d\n", status);
4465 if (status)
4466 goto out;
4467
4468 ptr = (unsigned *)&session->sess_id.data[0];
4469 dprintk("%s client>seqid %d sessionid %u:%u:%u:%u\n", __func__,
4470 clp->cl_seqid, ptr[0], ptr[1], ptr[2], ptr[3]);
4471
4472 /* Get the lease time */
4473 status = nfs4_proc_get_lease_time(clp, &fsinfo);
4474 if (status == 0) {
4475 /* Update lease time and schedule renewal */
4476 spin_lock(&clp->cl_lock);
4477 clp->cl_lease_time = fsinfo.lease_time * HZ;
4478 clp->cl_last_renewal = jiffies;
4479 clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
4480 spin_unlock(&clp->cl_lock);
4481
4482 nfs4_schedule_state_renewal(clp);
4483 }
4484out:
4485 dprintk("<-- %s\n", __func__);
4486 return status;
4487}
4488
4317#endif /* CONFIG_NFS_V4_1 */ 4489#endif /* CONFIG_NFS_V4_1 */
4318 4490
4319struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = { 4491struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = {