diff options
author | Andy Adamson <andros@netapp.com> | 2009-04-01 09:22:31 -0400 |
---|---|---|
committer | Benny Halevy <bhalevy@panasas.com> | 2009-06-17 15:24:34 -0400 |
commit | fc931582c260e53ca5ca23bd70ccc9b2265cca9f (patch) | |
tree | e52ad324ae6bb236f66bfd3ea002a9362ec60727 /fs/nfs/nfs4proc.c | |
parent | 2050f0cc0703aab7cee798b3cb47037754f368bc (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.c | 172 |
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 | */ | ||
4290 | static 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); | ||
4323 | out: | ||
4324 | dprintk("<-- %s: return %d\n", __func__, ret); | ||
4325 | return ret; | ||
4326 | out_free: | ||
4327 | kfree(slot); | ||
4328 | goto out; | ||
4329 | } | ||
4330 | |||
4286 | /* Destroy the slot table */ | 4331 | /* Destroy the slot table */ |
4287 | static void nfs4_destroy_slot_table(struct nfs4_session *session) | 4332 | static 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 | */ | ||
4371 | static 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 | |||
4412 | static 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 | */ | ||
4449 | int 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 | } | ||
4484 | out: | ||
4485 | dprintk("<-- %s\n", __func__); | ||
4486 | return status; | ||
4487 | } | ||
4488 | |||
4317 | #endif /* CONFIG_NFS_V4_1 */ | 4489 | #endif /* CONFIG_NFS_V4_1 */ |
4318 | 4490 | ||
4319 | struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = { | 4491 | struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = { |