diff options
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r-- | fs/nfsd/nfs4state.c | 64 |
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 | |||
653 | free_client(struct nfs4_client *clp) | 653 | free_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 | ||
1304 | out: | 1301 | out: |
@@ -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 | */ | ||
1339 | static void | ||
1340 | nfsd4_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 | |||
1347 | static __be32 | ||
1348 | nfsd4_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 |
1338 | nfsd4_create_session(struct svc_rqst *rqstp, | 1356 | nfsd4_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; | 1424 | out_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; | ||
1415 | out: | 1427 | out: |
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)); |