aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4state.c
diff options
context:
space:
mode:
authorAndy Adamson <andros@netapp.com>2009-07-23 19:02:16 -0400
committerJ. Bruce Fields <bfields@citi.umich.edu>2009-07-28 14:30:29 -0400
commit49557cc74c7bdf6a984be227ead9a84b3a26f053 (patch)
tree796abd9b62301d16f3307dacd0b21e47b79622b1 /fs/nfsd/nfs4state.c
parent88e588d56a2f0226a34386b94a03fda97d2b8e67 (diff)
nfsd41: Use separate DRC for setclientid
Instead of trying to share the generic 4.1 reply cache code for the CREATE_SESSION reply cache, it's simpler to handle CREATE_SESSION separately. The nfs41 single slot clientid DRC holds the results of create session processing. CREATE_SESSION can be preceeded by a SEQUENCE operation (an embedded CREATE_SESSION) and the create session single slot cache must be maintained. nfsd4_replay_cache_entry() and nfsd4_store_cache_entry() do not implement the replay of an embedded CREATE_SESSION. The clientid DRC slot does not need the inuse, cachethis or other fields that the multiple slot session cache uses. Replace the clientid DRC cache struct nfs4_slot cache with a new nfsd4_clid_slot cache. Save the xdr struct nfsd4_create_session into the cache at the end of processing, and on a replay, replace the struct for the replay request with the cached version all while under the state lock. nfsd4_proc_compound will handle both the solo and embedded CREATE_SESSION case via the normal use of encode_operation. Errors that do not change the create session cache: A create session NFS4ERR_STALE_CLIENTID error means that a client record (and associated create session slot) could not be found and therefore can't be changed. NFSERR_SEQ_MISORDERED errors do not change the slot cache. All other errors get cached. Remove the clientid DRC specific check in nfs4svc_encode_compoundres to put the session only if cstate.session is set which will now always be true. Signed-off-by: Andy Adamson <andros@netapp.com> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r--fs/nfsd/nfs4state.c64
1 files changed, 38 insertions, 26 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 99df8e7a687b..7729d092c8a5 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -653,8 +653,6 @@ static inline void
653free_client(struct nfs4_client *clp) 653free_client(struct nfs4_client *clp)
654{ 654{
655 shutdown_callback_client(clp); 655 shutdown_callback_client(clp);
656 nfsd4_release_respages(clp->cl_slot.sl_cache_entry.ce_respages,
657 clp->cl_slot.sl_cache_entry.ce_resused);
658 if (clp->cl_cred.cr_group_info) 656 if (clp->cl_cred.cr_group_info)
659 put_group_info(clp->cl_cred.cr_group_info); 657 put_group_info(clp->cl_cred.cr_group_info);
660 kfree(clp->cl_principal); 658 kfree(clp->cl_principal);
@@ -1293,12 +1291,11 @@ out_copy:
1293 exid->clientid.cl_boot = new->cl_clientid.cl_boot; 1291 exid->clientid.cl_boot = new->cl_clientid.cl_boot;
1294 exid->clientid.cl_id = new->cl_clientid.cl_id; 1292 exid->clientid.cl_id = new->cl_clientid.cl_id;
1295 1293
1296 new->cl_slot.sl_seqid = 0;
1297 exid->seqid = 1; 1294 exid->seqid = 1;
1298 nfsd4_set_ex_flags(new, exid); 1295 nfsd4_set_ex_flags(new, exid);
1299 1296
1300 dprintk("nfsd4_exchange_id seqid %d flags %x\n", 1297 dprintk("nfsd4_exchange_id seqid %d flags %x\n",
1301 new->cl_slot.sl_seqid, new->cl_exchange_flags); 1298 new->cl_cs_slot.sl_seqid, new->cl_exchange_flags);
1302 status = nfs_ok; 1299 status = nfs_ok;
1303 1300
1304out: 1301out:
@@ -1334,15 +1331,35 @@ check_slot_seqid(u32 seqid, u32 slot_seqid, int slot_inuse)
1334 return nfserr_seq_misordered; 1331 return nfserr_seq_misordered;
1335} 1332}
1336 1333
1334/*
1335 * Cache the create session result into the create session single DRC
1336 * slot cache by saving the xdr structure. sl_seqid has been set.
1337 * Do this for solo or embedded create session operations.
1338 */
1339static void
1340nfsd4_cache_create_session(struct nfsd4_create_session *cr_ses,
1341 struct nfsd4_clid_slot *slot, int nfserr)
1342{
1343 slot->sl_status = nfserr;
1344 memcpy(&slot->sl_cr_ses, cr_ses, sizeof(*cr_ses));
1345}
1346
1347static __be32
1348nfsd4_replay_create_session(struct nfsd4_create_session *cr_ses,
1349 struct nfsd4_clid_slot *slot)
1350{
1351 memcpy(cr_ses, &slot->sl_cr_ses, sizeof(*cr_ses));
1352 return slot->sl_status;
1353}
1354
1337__be32 1355__be32
1338nfsd4_create_session(struct svc_rqst *rqstp, 1356nfsd4_create_session(struct svc_rqst *rqstp,
1339 struct nfsd4_compound_state *cstate, 1357 struct nfsd4_compound_state *cstate,
1340 struct nfsd4_create_session *cr_ses) 1358 struct nfsd4_create_session *cr_ses)
1341{ 1359{
1342 u32 ip_addr = svc_addr_in(rqstp)->sin_addr.s_addr; 1360 u32 ip_addr = svc_addr_in(rqstp)->sin_addr.s_addr;
1343 struct nfsd4_compoundres *resp = rqstp->rq_resp;
1344 struct nfs4_client *conf, *unconf; 1361 struct nfs4_client *conf, *unconf;
1345 struct nfsd4_slot *slot = NULL; 1362 struct nfsd4_clid_slot *cs_slot = NULL;
1346 int status = 0; 1363 int status = 0;
1347 1364
1348 nfs4_lock_state(); 1365 nfs4_lock_state();
@@ -1350,25 +1367,22 @@ nfsd4_create_session(struct svc_rqst *rqstp,
1350 conf = find_confirmed_client(&cr_ses->clientid); 1367 conf = find_confirmed_client(&cr_ses->clientid);
1351 1368
1352 if (conf) { 1369 if (conf) {
1353 slot = &conf->cl_slot; 1370 cs_slot = &conf->cl_cs_slot;
1354 status = check_slot_seqid(cr_ses->seqid, slot->sl_seqid, 1371 status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0);
1355 slot->sl_inuse);
1356 if (status == nfserr_replay_cache) { 1372 if (status == nfserr_replay_cache) {
1357 dprintk("Got a create_session replay! seqid= %d\n", 1373 dprintk("Got a create_session replay! seqid= %d\n",
1358 slot->sl_seqid); 1374 cs_slot->sl_seqid);
1359 cstate->slot = slot;
1360 cstate->status = status;
1361 /* Return the cached reply status */ 1375 /* Return the cached reply status */
1362 status = nfsd4_replay_cache_entry(resp, NULL); 1376 status = nfsd4_replay_create_session(cr_ses, cs_slot);
1363 goto out; 1377 goto out;
1364 } else if (cr_ses->seqid != conf->cl_slot.sl_seqid + 1) { 1378 } else if (cr_ses->seqid != cs_slot->sl_seqid + 1) {
1365 status = nfserr_seq_misordered; 1379 status = nfserr_seq_misordered;
1366 dprintk("Sequence misordered!\n"); 1380 dprintk("Sequence misordered!\n");
1367 dprintk("Expected seqid= %d but got seqid= %d\n", 1381 dprintk("Expected seqid= %d but got seqid= %d\n",
1368 slot->sl_seqid, cr_ses->seqid); 1382 cs_slot->sl_seqid, cr_ses->seqid);
1369 goto out; 1383 goto out;
1370 } 1384 }
1371 conf->cl_slot.sl_seqid++; 1385 cs_slot->sl_seqid++;
1372 } else if (unconf) { 1386 } else if (unconf) {
1373 if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred) || 1387 if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred) ||
1374 (ip_addr != unconf->cl_addr)) { 1388 (ip_addr != unconf->cl_addr)) {
@@ -1376,16 +1390,15 @@ nfsd4_create_session(struct svc_rqst *rqstp,
1376 goto out; 1390 goto out;
1377 } 1391 }
1378 1392
1379 slot = &unconf->cl_slot; 1393 cs_slot = &unconf->cl_cs_slot;
1380 status = check_slot_seqid(cr_ses->seqid, slot->sl_seqid, 1394 status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0);
1381 slot->sl_inuse);
1382 if (status) { 1395 if (status) {
1383 /* an unconfirmed replay returns misordered */ 1396 /* an unconfirmed replay returns misordered */
1384 status = nfserr_seq_misordered; 1397 status = nfserr_seq_misordered;
1385 goto out; 1398 goto out_cache;
1386 } 1399 }
1387 1400
1388 slot->sl_seqid++; /* from 0 to 1 */ 1401 cs_slot->sl_seqid++; /* from 0 to 1 */
1389 move_to_confirmed(unconf); 1402 move_to_confirmed(unconf);
1390 1403
1391 /* 1404 /*
@@ -1406,12 +1419,11 @@ nfsd4_create_session(struct svc_rqst *rqstp,
1406 1419
1407 memcpy(cr_ses->sessionid.data, conf->cl_sessionid.data, 1420 memcpy(cr_ses->sessionid.data, conf->cl_sessionid.data,
1408 NFS4_MAX_SESSIONID_LEN); 1421 NFS4_MAX_SESSIONID_LEN);
1409 cr_ses->seqid = slot->sl_seqid; 1422 cr_ses->seqid = cs_slot->sl_seqid;
1410 1423
1411 slot->sl_inuse = true; 1424out_cache:
1412 cstate->slot = slot; 1425 /* cache solo and embedded create sessions under the state lock */
1413 /* Ensure a page is used for the cache */ 1426 nfsd4_cache_create_session(cr_ses, cs_slot, status);
1414 slot->sl_cache_entry.ce_cachethis = 1;
1415out: 1427out:
1416 nfs4_unlock_state(); 1428 nfs4_unlock_state();
1417 dprintk("%s returns %d\n", __func__, ntohl(status)); 1429 dprintk("%s returns %d\n", __func__, ntohl(status));