diff options
author | Andy Adamson <andros@netapp.com> | 2009-07-23 19:02:16 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@citi.umich.edu> | 2009-07-28 14:30:29 -0400 |
commit | 49557cc74c7bdf6a984be227ead9a84b3a26f053 (patch) | |
tree | 796abd9b62301d16f3307dacd0b21e47b79622b1 | |
parent | 88e588d56a2f0226a34386b94a03fda97d2b8e67 (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>
-rw-r--r-- | fs/nfsd/nfs4proc.c | 2 | ||||
-rw-r--r-- | fs/nfsd/nfs4state.c | 64 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 3 | ||||
-rw-r--r-- | include/linux/nfsd/state.h | 21 | ||||
-rw-r--r-- | include/linux/nfsd/xdr4.h | 12 |
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 | ||
1122 | encode_op: | 1122 | encode_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 | |||
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)); |
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 | ||
130 | struct 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 */ | ||
143 | struct nfsd4_clid_slot { | ||
144 | u32 sl_seqid; | ||
145 | __be32 sl_status; | ||
146 | struct nfsd4_create_session sl_cr_ses; | ||
147 | }; | ||
148 | |||
130 | struct nfsd4_session { | 149 | struct 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 | ||
369 | struct 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 | |||
381 | struct nfsd4_sequence { | 369 | struct 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 */ |