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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'nfs-for-4.9-4' of git://git.linux-nfs.org/projects/anna/linux-nfs

Pull NFS client bugfixes from Anna Schumaker:
"Most of these fix regressions or races, but there is one patch for
stable that Arnd sent me

Stable bugfix:
- Hide array-bounds warning

Bugfixes:
- Keep a reference on lock states while checking
- Handle NFS4ERR_OLD_STATEID in nfs4_reclaim_open_state
- Don't call close if the open stateid has already been cleared
- Fix CLOSE rases with OPEN
- Fix a regression in DELEGRETURN"

* tag 'nfs-for-4.9-4' of git://git.linux-nfs.org/projects/anna/linux-nfs:
NFSv4.x: hide array-bounds warning
NFSv4.1: Keep a reference on lock states while checking
NFSv4.1: Handle NFS4ERR_OLD_STATEID in nfs4_reclaim_open_state
NFSv4: Don't call close if the open stateid has already been cleared
NFSv4: Fix CLOSE races with OPEN
NFSv4.1: Fix a regression in DELEGRETURN

+35 -13
+1 -1
fs/nfs/callback.c
··· 197 197 } 198 198 199 199 ret = -EPROTONOSUPPORT; 200 - if (minorversion == 0) 200 + if (!IS_ENABLED(CONFIG_NFS_V4_1) || minorversion == 0) 201 201 ret = nfs4_callback_up_net(serv, net); 202 202 else if (xprt->ops->bc_up) 203 203 ret = xprt->ops->bc_up(serv, net);
+7
fs/nfs/nfs4_fs.h
··· 542 542 return test_bit(NFS_STATE_RECOVERY_FAILED, &state->flags) == 0; 543 543 } 544 544 545 + static inline bool nfs4_state_match_open_stateid_other(const struct nfs4_state *state, 546 + const nfs4_stateid *stateid) 547 + { 548 + return test_bit(NFS_OPEN_STATE, &state->flags) && 549 + nfs4_stateid_match_other(&state->open_stateid, stateid); 550 + } 551 + 545 552 #else 546 553 547 554 #define nfs4_close_state(a, b) do { } while (0)
+26 -12
fs/nfs/nfs4proc.c
··· 1451 1451 } 1452 1452 1453 1453 static void nfs_clear_open_stateid_locked(struct nfs4_state *state, 1454 - nfs4_stateid *arg_stateid, 1455 1454 nfs4_stateid *stateid, fmode_t fmode) 1456 1455 { 1457 1456 clear_bit(NFS_O_RDWR_STATE, &state->flags); ··· 1468 1469 } 1469 1470 if (stateid == NULL) 1470 1471 return; 1471 - /* Handle races with OPEN */ 1472 - if (!nfs4_stateid_match_other(arg_stateid, &state->open_stateid) || 1473 - (nfs4_stateid_match_other(stateid, &state->open_stateid) && 1474 - !nfs4_stateid_is_newer(stateid, &state->open_stateid))) { 1472 + /* Handle OPEN+OPEN_DOWNGRADE races */ 1473 + if (nfs4_stateid_match_other(stateid, &state->open_stateid) && 1474 + !nfs4_stateid_is_newer(stateid, &state->open_stateid)) { 1475 1475 nfs_resync_open_stateid_locked(state); 1476 1476 return; 1477 1477 } ··· 1484 1486 nfs4_stateid *stateid, fmode_t fmode) 1485 1487 { 1486 1488 write_seqlock(&state->seqlock); 1487 - nfs_clear_open_stateid_locked(state, arg_stateid, stateid, fmode); 1489 + /* Ignore, if the CLOSE argment doesn't match the current stateid */ 1490 + if (nfs4_state_match_open_stateid_other(state, arg_stateid)) 1491 + nfs_clear_open_stateid_locked(state, stateid, fmode); 1488 1492 write_sequnlock(&state->seqlock); 1489 1493 if (test_bit(NFS_STATE_RECLAIM_NOGRACE, &state->flags)) 1490 1494 nfs4_schedule_state_manager(state->owner->so_server->nfs_client); ··· 2564 2564 static int nfs41_check_expired_locks(struct nfs4_state *state) 2565 2565 { 2566 2566 int status, ret = NFS_OK; 2567 - struct nfs4_lock_state *lsp; 2567 + struct nfs4_lock_state *lsp, *prev = NULL; 2568 2568 struct nfs_server *server = NFS_SERVER(state->inode); 2569 2569 2570 2570 if (!test_bit(LK_STATE_IN_USE, &state->flags)) 2571 2571 goto out; 2572 + 2573 + spin_lock(&state->state_lock); 2572 2574 list_for_each_entry(lsp, &state->lock_states, ls_locks) { 2573 2575 if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags)) { 2574 2576 struct rpc_cred *cred = lsp->ls_state->owner->so_cred; 2577 + 2578 + atomic_inc(&lsp->ls_count); 2579 + spin_unlock(&state->state_lock); 2580 + 2581 + nfs4_put_lock_state(prev); 2582 + prev = lsp; 2575 2583 2576 2584 status = nfs41_test_and_free_expired_stateid(server, 2577 2585 &lsp->ls_stateid, ··· 2593 2585 set_bit(NFS_LOCK_LOST, &lsp->ls_flags); 2594 2586 } else if (status != NFS_OK) { 2595 2587 ret = status; 2596 - break; 2588 + nfs4_put_lock_state(prev); 2589 + goto out; 2597 2590 } 2591 + spin_lock(&state->state_lock); 2598 2592 } 2599 - }; 2593 + } 2594 + spin_unlock(&state->state_lock); 2595 + nfs4_put_lock_state(prev); 2600 2596 out: 2601 2597 return ret; 2602 2598 } ··· 3134 3122 } else if (is_rdwr) 3135 3123 calldata->arg.fmode |= FMODE_READ|FMODE_WRITE; 3136 3124 3137 - if (!nfs4_valid_open_stateid(state)) 3125 + if (!nfs4_valid_open_stateid(state) || 3126 + test_bit(NFS_OPEN_STATE, &state->flags) == 0) 3138 3127 call_close = 0; 3139 3128 spin_unlock(&state->owner->so_lock); 3140 3129 ··· 5582 5569 switch (task->tk_status) { 5583 5570 case 0: 5584 5571 renew_lease(data->res.server, data->timestamp); 5572 + break; 5585 5573 case -NFS4ERR_ADMIN_REVOKED: 5586 5574 case -NFS4ERR_DELEG_REVOKED: 5587 5575 case -NFS4ERR_EXPIRED: ··· 5593 5579 case -NFS4ERR_OLD_STATEID: 5594 5580 case -NFS4ERR_STALE_STATEID: 5595 5581 task->tk_status = 0; 5596 - if (data->roc) 5597 - pnfs_roc_set_barrier(data->inode, data->roc_barrier); 5598 5582 break; 5599 5583 default: 5600 5584 if (nfs4_async_handle_error(task, data->res.server, ··· 5602 5590 } 5603 5591 } 5604 5592 data->rpc_status = task->tk_status; 5593 + if (data->roc && data->rpc_status == 0) 5594 + pnfs_roc_set_barrier(data->inode, data->roc_barrier); 5605 5595 } 5606 5596 5607 5597 static void nfs4_delegreturn_release(void *calldata)
+1
fs/nfs/nfs4state.c
··· 1547 1547 ssleep(1); 1548 1548 case -NFS4ERR_ADMIN_REVOKED: 1549 1549 case -NFS4ERR_STALE_STATEID: 1550 + case -NFS4ERR_OLD_STATEID: 1550 1551 case -NFS4ERR_BAD_STATEID: 1551 1552 case -NFS4ERR_RECLAIM_BAD: 1552 1553 case -NFS4ERR_RECLAIM_CONFLICT: