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 | |
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>
-rw-r--r-- | fs/nfs/nfs4proc.c | 172 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 185 | ||||
-rw-r--r-- | include/linux/nfs4.h | 10 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 12 |
4 files changed, 379 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 = { |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 85ee1d17a461..7a243a2cf0be 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -246,6 +246,8 @@ static int nfs4_stat_to_errno(int); | |||
246 | (0) | 246 | (0) |
247 | 247 | ||
248 | #if defined(CONFIG_NFS_V4_1) | 248 | #if defined(CONFIG_NFS_V4_1) |
249 | #define NFS4_MAX_MACHINE_NAME_LEN (64) | ||
250 | |||
249 | #define encode_exchange_id_maxsz (op_encode_hdr_maxsz + \ | 251 | #define encode_exchange_id_maxsz (op_encode_hdr_maxsz + \ |
250 | encode_verifier_maxsz + \ | 252 | encode_verifier_maxsz + \ |
251 | 1 /* co_ownerid.len */ + \ | 253 | 1 /* co_ownerid.len */ + \ |
@@ -267,6 +269,31 @@ static int nfs4_stat_to_errno(int); | |||
267 | XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \ | 269 | XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \ |
268 | 1 /* eir_server_impl_id array length */ + \ | 270 | 1 /* eir_server_impl_id array length */ + \ |
269 | 0 /* ignored eir_server_impl_id contents */) | 271 | 0 /* ignored eir_server_impl_id contents */) |
272 | #define encode_channel_attrs_maxsz (6 + 1 /* ca_rdma_ird.len (0) */) | ||
273 | #define decode_channel_attrs_maxsz (6 + \ | ||
274 | 1 /* ca_rdma_ird.len */ + \ | ||
275 | 1 /* ca_rdma_ird */) | ||
276 | #define encode_create_session_maxsz (op_encode_hdr_maxsz + \ | ||
277 | 2 /* csa_clientid */ + \ | ||
278 | 1 /* csa_sequence */ + \ | ||
279 | 1 /* csa_flags */ + \ | ||
280 | encode_channel_attrs_maxsz + \ | ||
281 | encode_channel_attrs_maxsz + \ | ||
282 | 1 /* csa_cb_program */ + \ | ||
283 | 1 /* csa_sec_parms.len (1) */ + \ | ||
284 | 1 /* cb_secflavor (AUTH_SYS) */ + \ | ||
285 | 1 /* stamp */ + \ | ||
286 | 1 /* machinename.len */ + \ | ||
287 | XDR_QUADLEN(NFS4_MAX_MACHINE_NAME_LEN) + \ | ||
288 | 1 /* uid */ + \ | ||
289 | 1 /* gid */ + \ | ||
290 | 1 /* gids.len (0) */) | ||
291 | #define decode_create_session_maxsz (op_decode_hdr_maxsz + \ | ||
292 | XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \ | ||
293 | 1 /* csr_sequence */ + \ | ||
294 | 1 /* csr_flags */ + \ | ||
295 | decode_channel_attrs_maxsz + \ | ||
296 | decode_channel_attrs_maxsz) | ||
270 | #define encode_sequence_maxsz 0 /* stub */ | 297 | #define encode_sequence_maxsz 0 /* stub */ |
271 | #define decode_sequence_maxsz 0 /* stub */ | 298 | #define decode_sequence_maxsz 0 /* stub */ |
272 | #else /* CONFIG_NFS_V4_1 */ | 299 | #else /* CONFIG_NFS_V4_1 */ |
@@ -622,6 +649,12 @@ static int nfs4_stat_to_errno(int); | |||
622 | #define NFS4_dec_exchange_id_sz \ | 649 | #define NFS4_dec_exchange_id_sz \ |
623 | (compound_decode_hdr_maxsz + \ | 650 | (compound_decode_hdr_maxsz + \ |
624 | decode_exchange_id_maxsz) | 651 | decode_exchange_id_maxsz) |
652 | #define NFS4_enc_create_session_sz \ | ||
653 | (compound_encode_hdr_maxsz + \ | ||
654 | encode_create_session_maxsz) | ||
655 | #define NFS4_dec_create_session_sz \ | ||
656 | (compound_decode_hdr_maxsz + \ | ||
657 | decode_create_session_maxsz) | ||
625 | #define NFS4_enc_get_lease_time_sz (compound_encode_hdr_maxsz + \ | 658 | #define NFS4_enc_get_lease_time_sz (compound_encode_hdr_maxsz + \ |
626 | encode_sequence_maxsz + \ | 659 | encode_sequence_maxsz + \ |
627 | encode_putrootfh_maxsz + \ | 660 | encode_putrootfh_maxsz + \ |
@@ -712,6 +745,7 @@ static void encode_compound_hdr(struct xdr_stream *xdr, | |||
712 | 745 | ||
713 | static void encode_nops(struct compound_hdr *hdr) | 746 | static void encode_nops(struct compound_hdr *hdr) |
714 | { | 747 | { |
748 | BUG_ON(hdr->nops > NFS4_MAX_OPS); | ||
715 | *hdr->nops_p = htonl(hdr->nops); | 749 | *hdr->nops_p = htonl(hdr->nops); |
716 | } | 750 | } |
717 | 751 | ||
@@ -1513,6 +1547,68 @@ static void encode_exchange_id(struct xdr_stream *xdr, | |||
1513 | hdr->nops++; | 1547 | hdr->nops++; |
1514 | hdr->replen += decode_exchange_id_maxsz; | 1548 | hdr->replen += decode_exchange_id_maxsz; |
1515 | } | 1549 | } |
1550 | |||
1551 | static void encode_create_session(struct xdr_stream *xdr, | ||
1552 | struct nfs41_create_session_args *args, | ||
1553 | struct compound_hdr *hdr) | ||
1554 | { | ||
1555 | __be32 *p; | ||
1556 | char machine_name[NFS4_MAX_MACHINE_NAME_LEN]; | ||
1557 | uint32_t len; | ||
1558 | struct nfs_client *clp = args->client; | ||
1559 | |||
1560 | RESERVE_SPACE(4); | ||
1561 | WRITE32(OP_CREATE_SESSION); | ||
1562 | |||
1563 | RESERVE_SPACE(8); | ||
1564 | WRITE64(clp->cl_ex_clid); | ||
1565 | |||
1566 | RESERVE_SPACE(8); | ||
1567 | WRITE32(clp->cl_seqid); /*Sequence id */ | ||
1568 | WRITE32(args->flags); /*flags */ | ||
1569 | |||
1570 | RESERVE_SPACE(2*28); /* 2 channel_attrs */ | ||
1571 | /* Fore Channel */ | ||
1572 | WRITE32(args->fc_attrs.headerpadsz); /* header padding size */ | ||
1573 | WRITE32(args->fc_attrs.max_rqst_sz); /* max req size */ | ||
1574 | WRITE32(args->fc_attrs.max_resp_sz); /* max resp size */ | ||
1575 | WRITE32(args->fc_attrs.max_resp_sz_cached); /* Max resp sz cached */ | ||
1576 | WRITE32(args->fc_attrs.max_ops); /* max operations */ | ||
1577 | WRITE32(args->fc_attrs.max_reqs); /* max requests */ | ||
1578 | WRITE32(0); /* rdmachannel_attrs */ | ||
1579 | |||
1580 | /* Back Channel */ | ||
1581 | WRITE32(args->fc_attrs.headerpadsz); /* header padding size */ | ||
1582 | WRITE32(args->bc_attrs.max_rqst_sz); /* max req size */ | ||
1583 | WRITE32(args->bc_attrs.max_resp_sz); /* max resp size */ | ||
1584 | WRITE32(args->bc_attrs.max_resp_sz_cached); /* Max resp sz cached */ | ||
1585 | WRITE32(args->bc_attrs.max_ops); /* max operations */ | ||
1586 | WRITE32(args->bc_attrs.max_reqs); /* max requests */ | ||
1587 | WRITE32(0); /* rdmachannel_attrs */ | ||
1588 | |||
1589 | RESERVE_SPACE(4); | ||
1590 | WRITE32(args->cb_program); /* cb_program */ | ||
1591 | |||
1592 | RESERVE_SPACE(4); /* # of security flavors */ | ||
1593 | WRITE32(1); | ||
1594 | |||
1595 | RESERVE_SPACE(4); | ||
1596 | WRITE32(RPC_AUTH_UNIX); /* auth_sys */ | ||
1597 | |||
1598 | /* authsys_parms rfc1831 */ | ||
1599 | RESERVE_SPACE(4); | ||
1600 | WRITE32((u32)clp->cl_boot_time.tv_nsec); /* stamp */ | ||
1601 | len = scnprintf(machine_name, sizeof(machine_name), "%s", | ||
1602 | clp->cl_ipaddr); | ||
1603 | RESERVE_SPACE(16 + len); | ||
1604 | WRITE32(len); | ||
1605 | WRITEMEM(machine_name, len); | ||
1606 | WRITE32(0); /* UID */ | ||
1607 | WRITE32(0); /* GID */ | ||
1608 | WRITE32(0); /* No more gids */ | ||
1609 | hdr->nops++; | ||
1610 | hdr->replen += decode_create_session_maxsz; | ||
1611 | } | ||
1516 | #endif /* CONFIG_NFS_V4_1 */ | 1612 | #endif /* CONFIG_NFS_V4_1 */ |
1517 | 1613 | ||
1518 | static void encode_sequence(struct xdr_stream *xdr, | 1614 | static void encode_sequence(struct xdr_stream *xdr, |
@@ -2241,6 +2337,24 @@ static int nfs4_xdr_enc_exchange_id(struct rpc_rqst *req, uint32_t *p, | |||
2241 | } | 2337 | } |
2242 | 2338 | ||
2243 | /* | 2339 | /* |
2340 | * a CREATE_SESSION request | ||
2341 | */ | ||
2342 | static int nfs4_xdr_enc_create_session(struct rpc_rqst *req, uint32_t *p, | ||
2343 | struct nfs41_create_session_args *args) | ||
2344 | { | ||
2345 | struct xdr_stream xdr; | ||
2346 | struct compound_hdr hdr = { | ||
2347 | .minorversion = args->client->cl_minorversion, | ||
2348 | }; | ||
2349 | |||
2350 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | ||
2351 | encode_compound_hdr(&xdr, req, &hdr); | ||
2352 | encode_create_session(&xdr, args, &hdr); | ||
2353 | encode_nops(&hdr); | ||
2354 | return 0; | ||
2355 | } | ||
2356 | |||
2357 | /* | ||
2244 | * a GET_LEASE_TIME request | 2358 | * a GET_LEASE_TIME request |
2245 | */ | 2359 | */ |
2246 | static int nfs4_xdr_enc_get_lease_time(struct rpc_rqst *req, uint32_t *p, | 2360 | static int nfs4_xdr_enc_get_lease_time(struct rpc_rqst *req, uint32_t *p, |
@@ -4021,6 +4135,59 @@ static int decode_exchange_id(struct xdr_stream *xdr, | |||
4021 | 4135 | ||
4022 | return 0; | 4136 | return 0; |
4023 | } | 4137 | } |
4138 | |||
4139 | static int decode_chan_attrs(struct xdr_stream *xdr, | ||
4140 | struct nfs4_channel_attrs *attrs) | ||
4141 | { | ||
4142 | __be32 *p; | ||
4143 | u32 nr_attrs; | ||
4144 | |||
4145 | READ_BUF(28); | ||
4146 | READ32(attrs->headerpadsz); | ||
4147 | READ32(attrs->max_rqst_sz); | ||
4148 | READ32(attrs->max_resp_sz); | ||
4149 | READ32(attrs->max_resp_sz_cached); | ||
4150 | READ32(attrs->max_ops); | ||
4151 | READ32(attrs->max_reqs); | ||
4152 | READ32(nr_attrs); | ||
4153 | if (unlikely(nr_attrs > 1)) { | ||
4154 | printk(KERN_WARNING "%s: Invalid rdma channel attrs count %u\n", | ||
4155 | __func__, nr_attrs); | ||
4156 | return -EINVAL; | ||
4157 | } | ||
4158 | if (nr_attrs == 1) | ||
4159 | READ_BUF(4); /* skip rdma_attrs */ | ||
4160 | return 0; | ||
4161 | } | ||
4162 | |||
4163 | static int decode_create_session(struct xdr_stream *xdr, | ||
4164 | struct nfs41_create_session_res *res) | ||
4165 | { | ||
4166 | __be32 *p; | ||
4167 | int status; | ||
4168 | struct nfs_client *clp = res->client; | ||
4169 | struct nfs4_session *session = clp->cl_session; | ||
4170 | |||
4171 | status = decode_op_hdr(xdr, OP_CREATE_SESSION); | ||
4172 | |||
4173 | if (status) | ||
4174 | return status; | ||
4175 | |||
4176 | /* sessionid */ | ||
4177 | READ_BUF(NFS4_MAX_SESSIONID_LEN); | ||
4178 | COPYMEM(&session->sess_id, NFS4_MAX_SESSIONID_LEN); | ||
4179 | |||
4180 | /* seqid, flags */ | ||
4181 | READ_BUF(8); | ||
4182 | READ32(clp->cl_seqid); | ||
4183 | READ32(session->flags); | ||
4184 | |||
4185 | /* Channel attributes */ | ||
4186 | status = decode_chan_attrs(xdr, &session->fc_attrs); | ||
4187 | if (!status) | ||
4188 | status = decode_chan_attrs(xdr, &session->bc_attrs); | ||
4189 | return status; | ||
4190 | } | ||
4024 | #endif /* CONFIG_NFS_V4_1 */ | 4191 | #endif /* CONFIG_NFS_V4_1 */ |
4025 | 4192 | ||
4026 | static int decode_sequence(struct xdr_stream *xdr, | 4193 | static int decode_sequence(struct xdr_stream *xdr, |
@@ -4939,6 +5106,23 @@ static int nfs4_xdr_dec_exchange_id(struct rpc_rqst *rqstp, uint32_t *p, | |||
4939 | } | 5106 | } |
4940 | 5107 | ||
4941 | /* | 5108 | /* |
5109 | * a CREATE_SESSION request | ||
5110 | */ | ||
5111 | static int nfs4_xdr_dec_create_session(struct rpc_rqst *rqstp, uint32_t *p, | ||
5112 | struct nfs41_create_session_res *res) | ||
5113 | { | ||
5114 | struct xdr_stream xdr; | ||
5115 | struct compound_hdr hdr; | ||
5116 | int status; | ||
5117 | |||
5118 | xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); | ||
5119 | status = decode_compound_hdr(&xdr, &hdr); | ||
5120 | if (!status) | ||
5121 | status = decode_create_session(&xdr, res); | ||
5122 | return status; | ||
5123 | } | ||
5124 | |||
5125 | /* | ||
4942 | * a GET_LEASE_TIME request | 5126 | * a GET_LEASE_TIME request |
4943 | */ | 5127 | */ |
4944 | static int nfs4_xdr_dec_get_lease_time(struct rpc_rqst *rqstp, uint32_t *p, | 5128 | static int nfs4_xdr_dec_get_lease_time(struct rpc_rqst *rqstp, uint32_t *p, |
@@ -5131,6 +5315,7 @@ struct rpc_procinfo nfs4_procedures[] = { | |||
5131 | PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations), | 5315 | PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations), |
5132 | #if defined(CONFIG_NFS_V4_1) | 5316 | #if defined(CONFIG_NFS_V4_1) |
5133 | PROC(EXCHANGE_ID, enc_exchange_id, dec_exchange_id), | 5317 | PROC(EXCHANGE_ID, enc_exchange_id, dec_exchange_id), |
5318 | PROC(CREATE_SESSION, enc_create_session, dec_create_session), | ||
5134 | PROC(GET_LEASE_TIME, enc_get_lease_time, dec_get_lease_time), | 5319 | PROC(GET_LEASE_TIME, enc_get_lease_time, dec_get_lease_time), |
5135 | #endif /* CONFIG_NFS_V4_1 */ | 5320 | #endif /* CONFIG_NFS_V4_1 */ |
5136 | }; | 5321 | }; |
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h index ad65709ed8d3..bd2eba530667 100644 --- a/include/linux/nfs4.h +++ b/include/linux/nfs4.h | |||
@@ -131,6 +131,16 @@ | |||
131 | 131 | ||
132 | #define NFS4_MAX_UINT64 (~(u64)0) | 132 | #define NFS4_MAX_UINT64 (~(u64)0) |
133 | 133 | ||
134 | /* An NFS4 sessions server must support at least NFS4_MAX_OPS operations. | ||
135 | * If a compound requires more operations, adjust NFS4_MAX_OPS accordingly. | ||
136 | */ | ||
137 | #define NFS4_MAX_OPS 8 | ||
138 | |||
139 | /* Our NFS4 client back channel server only wants the cb_sequene and the | ||
140 | * actual operation per compound | ||
141 | */ | ||
142 | #define NFS4_MAX_BACK_CHANNEL_OPS 2 | ||
143 | |||
134 | enum nfs4_acl_whotype { | 144 | enum nfs4_acl_whotype { |
135 | NFS4_ACL_WHO_NAMED = 0, | 145 | NFS4_ACL_WHO_NAMED = 0, |
136 | NFS4_ACL_WHO_OWNER, | 146 | NFS4_ACL_WHO_OWNER, |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index ca643aa87d46..62f63fb0c4c8 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -926,6 +926,18 @@ struct nfs41_exchange_id_res { | |||
926 | struct nfs_client *client; | 926 | struct nfs_client *client; |
927 | u32 flags; | 927 | u32 flags; |
928 | }; | 928 | }; |
929 | |||
930 | struct nfs41_create_session_args { | ||
931 | struct nfs_client *client; | ||
932 | uint32_t flags; | ||
933 | uint32_t cb_program; | ||
934 | struct nfs4_channel_attrs fc_attrs; /* Fore Channel */ | ||
935 | struct nfs4_channel_attrs bc_attrs; /* Back Channel */ | ||
936 | }; | ||
937 | |||
938 | struct nfs41_create_session_res { | ||
939 | struct nfs_client *client; | ||
940 | }; | ||
929 | #endif /* CONFIG_NFS_V4_1 */ | 941 | #endif /* CONFIG_NFS_V4_1 */ |
930 | 942 | ||
931 | struct nfs_page; | 943 | struct nfs_page; |