aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfsd/nfs4proc.c2
-rw-r--r--fs/nfsd/nfs4state.c64
-rw-r--r--fs/nfsd/nfs4xdr.c3
-rw-r--r--include/linux/nfsd/state.h21
-rw-r--r--include/linux/nfsd/xdr4.h12
5 files changed, 60 insertions, 42 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index d781658e8084..d606c6a427de 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -1120,7 +1120,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
1120 BUG_ON(op->status == nfs_ok); 1120 BUG_ON(op->status == nfs_ok);
1121 1121
1122encode_op: 1122encode_op:
1123 /* Only from SEQUENCE or CREATE_SESSION */ 1123 /* Only from SEQUENCE */
1124 if (resp->cstate.status == nfserr_replay_cache) { 1124 if (resp->cstate.status == nfserr_replay_cache) {
1125 dprintk("%s NFS4.1 replay from cache\n", __func__); 1125 dprintk("%s NFS4.1 replay from cache\n", __func__);
1126 if (nfsd4_not_cached(resp)) 1126 if (nfsd4_not_cached(resp))
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));
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 2dcc7feaa6ff..fdf632bf1cfe 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -3313,8 +3313,7 @@ nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compo
3313 dprintk("%s: SET SLOT STATE TO AVAILABLE\n", __func__); 3313 dprintk("%s: SET SLOT STATE TO AVAILABLE\n", __func__);
3314 resp->cstate.slot->sl_inuse = 0; 3314 resp->cstate.slot->sl_inuse = 0;
3315 } 3315 }
3316 if (resp->cstate.session) 3316 nfsd4_put_session(resp->cstate.session);
3317 nfsd4_put_session(resp->cstate.session);
3318 } 3317 }
3319 return 1; 3318 return 1;
3320} 3319}
diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
index a6c87d623891..58bb19784e12 100644
--- a/include/linux/nfsd/state.h
+++ b/include/linux/nfsd/state.h
@@ -127,6 +127,25 @@ struct nfsd4_channel_attrs {
127 u32 rdma_attrs; 127 u32 rdma_attrs;
128}; 128};
129 129
130struct nfsd4_create_session {
131 clientid_t clientid;
132 struct nfs4_sessionid sessionid;
133 u32 seqid;
134 u32 flags;
135 struct nfsd4_channel_attrs fore_channel;
136 struct nfsd4_channel_attrs back_channel;
137 u32 callback_prog;
138 u32 uid;
139 u32 gid;
140};
141
142/* The single slot clientid cache structure */
143struct nfsd4_clid_slot {
144 u32 sl_seqid;
145 __be32 sl_status;
146 struct nfsd4_create_session sl_cr_ses;
147};
148
130struct nfsd4_session { 149struct nfsd4_session {
131 struct kref se_ref; 150 struct kref se_ref;
132 struct list_head se_hash; /* hash by sessionid */ 151 struct list_head se_hash; /* hash by sessionid */
@@ -193,7 +212,7 @@ struct nfs4_client {
193 212
194 /* for nfs41 */ 213 /* for nfs41 */
195 struct list_head cl_sessions; 214 struct list_head cl_sessions;
196 struct nfsd4_slot cl_slot; /* create_session slot */ 215 struct nfsd4_clid_slot cl_cs_slot; /* create_session slot */
197 u32 cl_exchange_flags; 216 u32 cl_exchange_flags;
198 struct nfs4_sessionid cl_sessionid; 217 struct nfs4_sessionid cl_sessionid;
199}; 218};
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
index 2bacf7535069..5e4beb0deb80 100644
--- a/include/linux/nfsd/xdr4.h
+++ b/include/linux/nfsd/xdr4.h
@@ -366,18 +366,6 @@ struct nfsd4_exchange_id {
366 int spa_how; 366 int spa_how;
367}; 367};
368 368
369struct nfsd4_create_session {
370 clientid_t clientid;
371 struct nfs4_sessionid sessionid;
372 u32 seqid;
373 u32 flags;
374 struct nfsd4_channel_attrs fore_channel;
375 struct nfsd4_channel_attrs back_channel;
376 u32 callback_prog;
377 u32 uid;
378 u32 gid;
379};
380
381struct nfsd4_sequence { 369struct nfsd4_sequence {
382 struct nfs4_sessionid sessionid; /* request/response */ 370 struct nfs4_sessionid sessionid; /* request/response */
383 u32 seqid; /* request/response */ 371 u32 seqid; /* request/response */