Hi, this is my proposed solution to the problem I outlined in NFSv4 state management issue - Linux disagrees with Netapp. I haven't tested it yet (no direct access to the Netapp), but I'll try to get some testing done. RFC for now. NeilBrown When opening a file, nfs _nfs4_do_open() will return any incompatible delegation, meaning if the delegation held for that file does not give all the permissions required, it is returned. This is because various places assume that the current delegation provides all necessary access. However when a delegation is received, it is not validated in the same way so it is possible to, for example, hold a read-only delegation while the file is open write-only. When that delegation is recalled, the NFS client will try to reclaim the write-only open, and that will fail. So when considering a new delegation, reject it if it is incompatible with any open. Signed-off-by: NeilBrown <neilb@xxxxxxx> URL: https://bugzilla.suse.com/show_bug.cgi?id=934203 diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index 029d688..92cecd3 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c @@ -377,6 +377,25 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct old_delegation, clp); if (freeme == NULL) goto out; + } else { + /* Don't accept an incompatible delegation */ + int incompatible = 0; + struct nfs_inode *nfsi = NFS_I(inode); + struct nfs4_state *state; + + spin_lock(&inode->i_lock); + list_for_each_entry(state, &nfsi->open_states, inode_states) { + if ((state->state & delegation->type) != state->state) { + incompatible = 1; + break; + } + } + spin_unlock(&inode->i_lock); + if (incompatible) { + freeme = delegation; + delegation = NULL; + goto out; + } } list_add_tail_rcu(&delegation->super_list, &server->delegations); rcu_assign_pointer(nfsi->delegation, delegation); -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in