diff options
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/nfs4state.c | 99 |
1 files changed, 35 insertions, 64 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index dc792b6b4513..b92dc9e08973 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -1429,90 +1429,61 @@ static struct lock_manager_operations nfsd_lease_mng_ops = { | |||
1429 | }; | 1429 | }; |
1430 | 1430 | ||
1431 | 1431 | ||
1432 | /* | ||
1433 | * nfsd4_process_open1() | ||
1434 | * lookup stateowner. | ||
1435 | * found: | ||
1436 | * check confirmed | ||
1437 | * confirmed: | ||
1438 | * check seqid | ||
1439 | * not confirmed: | ||
1440 | * delete owner | ||
1441 | * create new owner | ||
1442 | * notfound: | ||
1443 | * verify clientid | ||
1444 | * create new owner | ||
1445 | * | ||
1446 | * called with nfs4_lock_state() held. | ||
1447 | */ | ||
1448 | int | 1432 | int |
1449 | nfsd4_process_open1(struct nfsd4_open *open) | 1433 | nfsd4_process_open1(struct nfsd4_open *open) |
1450 | { | 1434 | { |
1451 | int status; | ||
1452 | clientid_t *clientid = &open->op_clientid; | 1435 | clientid_t *clientid = &open->op_clientid; |
1453 | struct nfs4_client *clp = NULL; | 1436 | struct nfs4_client *clp = NULL; |
1454 | unsigned int strhashval; | 1437 | unsigned int strhashval; |
1455 | struct nfs4_stateowner *sop = NULL; | 1438 | struct nfs4_stateowner *sop = NULL; |
1456 | 1439 | ||
1457 | status = nfserr_inval; | ||
1458 | if (!check_name(open->op_owner)) | 1440 | if (!check_name(open->op_owner)) |
1459 | goto out; | 1441 | return nfserr_inval; |
1460 | 1442 | ||
1461 | if (STALE_CLIENTID(&open->op_clientid)) | 1443 | if (STALE_CLIENTID(&open->op_clientid)) |
1462 | return nfserr_stale_clientid; | 1444 | return nfserr_stale_clientid; |
1463 | 1445 | ||
1464 | strhashval = ownerstr_hashval(clientid->cl_id, open->op_owner); | 1446 | strhashval = ownerstr_hashval(clientid->cl_id, open->op_owner); |
1465 | sop = find_openstateowner_str(strhashval, open); | 1447 | sop = find_openstateowner_str(strhashval, open); |
1466 | if (sop) { | 1448 | open->op_stateowner = sop; |
1467 | open->op_stateowner = sop; | 1449 | if (!sop) { |
1468 | if (!sop->so_confirmed) { | 1450 | /* Make sure the client's lease hasn't expired. */ |
1469 | /* Replace any unconfirmed stateowner without | ||
1470 | * even checking for replays */ | ||
1471 | clp = sop->so_client; | ||
1472 | release_stateowner(sop); | ||
1473 | } else if (open->op_seqid == sop->so_seqid) { | ||
1474 | /* normal case */ | ||
1475 | goto renew; | ||
1476 | } else if (open->op_seqid == sop->so_seqid - 1) { | ||
1477 | /* replay */ | ||
1478 | if (sop->so_replay.rp_buflen) | ||
1479 | return NFSERR_REPLAY_ME; | ||
1480 | else { | ||
1481 | /* The original OPEN failed so spectacularly | ||
1482 | * that we don't even have replay data saved! | ||
1483 | * Therefore, we have no choice but to continue | ||
1484 | * processing this OPEN; presumably, we'll | ||
1485 | * fail again for the same reason. | ||
1486 | */ | ||
1487 | dprintk("nfsd4_process_open1:" | ||
1488 | " replay with no replay cache\n"); | ||
1489 | goto renew; | ||
1490 | } | ||
1491 | } else { | ||
1492 | status = nfserr_bad_seqid; | ||
1493 | goto out; | ||
1494 | } | ||
1495 | } else { | ||
1496 | /* nfs4_stateowner not found. | ||
1497 | * Verify clientid and instantiate new nfs4_stateowner. | ||
1498 | * If verify fails this is presumably the result of the | ||
1499 | * client's lease expiring. | ||
1500 | */ | ||
1501 | status = nfserr_expired; | ||
1502 | clp = find_confirmed_client(clientid); | 1451 | clp = find_confirmed_client(clientid); |
1503 | if (clp == NULL) | 1452 | if (clp == NULL) |
1504 | goto out; | 1453 | return nfserr_expired; |
1454 | goto renew; | ||
1505 | } | 1455 | } |
1506 | status = nfserr_resource; | 1456 | if (!sop->so_confirmed) { |
1507 | sop = alloc_init_open_stateowner(strhashval, clp, open); | 1457 | /* Replace unconfirmed owners without checking for replay. */ |
1508 | if (sop == NULL) | 1458 | clp = sop->so_client; |
1509 | goto out; | 1459 | release_stateowner(sop); |
1510 | open->op_stateowner = sop; | 1460 | open->op_stateowner = NULL; |
1461 | goto renew; | ||
1462 | } | ||
1463 | if (open->op_seqid == sop->so_seqid - 1) { | ||
1464 | if (sop->so_replay.rp_buflen) | ||
1465 | return NFSERR_REPLAY_ME; | ||
1466 | /* The original OPEN failed so spectacularly | ||
1467 | * that we don't even have replay data saved! | ||
1468 | * Therefore, we have no choice but to continue | ||
1469 | * processing this OPEN; presumably, we'll | ||
1470 | * fail again for the same reason. | ||
1471 | */ | ||
1472 | dprintk("nfsd4_process_open1: replay with no replay cache\n"); | ||
1473 | goto renew; | ||
1474 | } | ||
1475 | if (open->op_seqid != sop->so_seqid) | ||
1476 | return nfserr_bad_seqid; | ||
1511 | renew: | 1477 | renew: |
1512 | status = nfs_ok; | 1478 | if (open->op_stateowner == NULL) { |
1479 | sop = alloc_init_open_stateowner(strhashval, clp, open); | ||
1480 | if (sop == NULL) | ||
1481 | return nfserr_resource; | ||
1482 | open->op_stateowner = sop; | ||
1483 | } | ||
1484 | list_del_init(&sop->so_close_lru); | ||
1513 | renew_client(sop->so_client); | 1485 | renew_client(sop->so_client); |
1514 | out: | 1486 | return nfs_ok; |
1515 | return status; | ||
1516 | } | 1487 | } |
1517 | 1488 | ||
1518 | static inline int | 1489 | static inline int |