diff options
| -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; |
