Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

NFSv4.1: Add a helper function to deal with expired stateids

In NFSv4.1 and newer, if the server decides to revoke some or all of
the protocol state, the client is required to iterate through all the
stateids that it holds and call TEST_STATEID to determine which stateids
still correspond to valid state, and then call FREE_STATEID on the
others.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Tested-by: Oleg Drokin <green@linuxhacker.ru>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>

authored by

Trond Myklebust and committed by
Anna Schumaker
4586f6e2 43912bbb

+24 -21
+24 -21
fs/nfs/nfs4proc.c
··· 2408 2408 } 2409 2409 2410 2410 #if defined(CONFIG_NFS_V4_1) 2411 + static int nfs41_test_and_free_expired_stateid(struct nfs_server *server, 2412 + nfs4_stateid *stateid, 2413 + struct rpc_cred *cred) 2414 + { 2415 + int status; 2416 + 2417 + status = nfs41_test_stateid(server, stateid, cred); 2418 + 2419 + switch (status) { 2420 + case -NFS4ERR_EXPIRED: 2421 + case -NFS4ERR_ADMIN_REVOKED: 2422 + case -NFS4ERR_DELEG_REVOKED: 2423 + /* Ack the revoked state to the server */ 2424 + nfs41_free_stateid(server, stateid, cred); 2425 + case -NFS4ERR_BAD_STATEID: 2426 + return status; 2427 + } 2428 + return NFS_OK; 2429 + } 2430 + 2411 2431 static void nfs41_check_delegation_stateid(struct nfs4_state *state) 2412 2432 { 2413 2433 struct nfs_server *server = NFS_SERVER(state->inode); ··· 2452 2432 nfs4_stateid_copy(&stateid, &delegation->stateid); 2453 2433 cred = get_rpccred(delegation->cred); 2454 2434 rcu_read_unlock(); 2455 - status = nfs41_test_stateid(server, &stateid, cred); 2435 + status = nfs41_test_and_free_expired_stateid(server, &stateid, cred); 2456 2436 trace_nfs4_test_delegation_stateid(state, NULL, status); 2457 - 2458 - if (status != NFS_OK) { 2459 - /* Free the stateid unless the server explicitly 2460 - * informs us the stateid is unrecognized. */ 2461 - if (status != -NFS4ERR_BAD_STATEID) 2462 - nfs41_free_stateid(server, &stateid, cred); 2437 + if (status != NFS_OK) 2463 2438 nfs_finish_clear_delegation_stateid(state); 2464 - } 2465 2439 2466 2440 put_rpccred(cred); 2467 2441 } ··· 2481 2467 (test_bit(NFS_O_RDWR_STATE, &state->flags) == 0)) 2482 2468 return -NFS4ERR_BAD_STATEID; 2483 2469 2484 - status = nfs41_test_stateid(server, stateid, cred); 2470 + status = nfs41_test_and_free_expired_stateid(server, stateid, cred); 2485 2471 trace_nfs4_test_open_stateid(state, NULL, status); 2486 2472 if (status != NFS_OK) { 2487 - /* Free the stateid unless the server explicitly 2488 - * informs us the stateid is unrecognized. */ 2489 - if (status != -NFS4ERR_BAD_STATEID) 2490 - nfs41_free_stateid(server, stateid, cred); 2491 - 2492 2473 clear_bit(NFS_O_RDONLY_STATE, &state->flags); 2493 2474 clear_bit(NFS_O_WRONLY_STATE, &state->flags); 2494 2475 clear_bit(NFS_O_RDWR_STATE, &state->flags); ··· 6099 6090 if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags)) { 6100 6091 struct rpc_cred *cred = lsp->ls_state->owner->so_cred; 6101 6092 6102 - status = nfs41_test_stateid(server, 6093 + status = nfs41_test_and_free_expired_stateid(server, 6103 6094 &lsp->ls_stateid, 6104 6095 cred); 6105 6096 trace_nfs4_test_lock_stateid(state, lsp, status); 6106 6097 if (status != NFS_OK) { 6107 - /* Free the stateid unless the server 6108 - * informs us the stateid is unrecognized. */ 6109 - if (status != -NFS4ERR_BAD_STATEID) 6110 - nfs41_free_stateid(server, 6111 - &lsp->ls_stateid, 6112 - cred); 6113 6098 clear_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags); 6114 6099 ret = status; 6115 6100 }