NFS: move delegation lookup into can_open_delegated

Keep the delegation handling in a single place, and just return the
stateid in an optional argument.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
This commit is contained in:
Christoph Hellwig 2026-01-07 08:27:04 +01:00 committed by Anna Schumaker
parent 2d80e59f29
commit 3e39019e68

View File

@ -1609,26 +1609,37 @@ static int can_open_cached(struct nfs4_state *state, fmode_t mode,
return ret;
}
static int can_open_delegated(struct nfs_delegation *delegation, fmode_t fmode,
enum open_claim_type4 claim)
static bool can_open_delegated(const struct inode *inode, fmode_t fmode,
enum open_claim_type4 claim, nfs4_stateid *stateid)
{
if (delegation == NULL)
return 0;
if ((delegation->type & fmode) != fmode)
return 0;
struct nfs_delegation *delegation;
bool ret = false;
rcu_read_lock();
delegation = nfs4_get_valid_delegation(inode);
if (!delegation || (delegation->type & fmode) != fmode)
goto out_unlock;
switch (claim) {
case NFS4_OPEN_CLAIM_NULL:
case NFS4_OPEN_CLAIM_FH:
break;
case NFS4_OPEN_CLAIM_PREVIOUS:
if (!test_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags))
if (test_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags))
break;
fallthrough;
case NFS4_OPEN_CLAIM_NULL:
case NFS4_OPEN_CLAIM_FH:
nfs_mark_delegation_referenced(delegation);
/* Save the delegation stateid */
if (stateid)
nfs4_stateid_copy(stateid, &delegation->stateid);
ret = true;
break;
default:
return 0;
break;
}
nfs_mark_delegation_referenced(delegation);
return 1;
out_unlock:
rcu_read_unlock();
return ret;
}
static void update_open_stateflags(struct nfs4_state *state, fmode_t fmode)
@ -1981,7 +1992,6 @@ static void nfs4_return_incompatible_delegation(struct inode *inode, fmode_t fmo
static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata)
{
struct nfs4_state *state = opendata->state;
struct nfs_delegation *delegation;
int open_mode = opendata->o_arg.open_flags;
fmode_t fmode = opendata->o_arg.fmode;
enum open_claim_type4 claim = opendata->o_arg.claim;
@ -1996,15 +2006,10 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata)
goto out_return_state;
}
spin_unlock(&state->owner->so_lock);
rcu_read_lock();
delegation = nfs4_get_valid_delegation(state->inode);
if (!can_open_delegated(delegation, fmode, claim)) {
rcu_read_unlock();
if (!can_open_delegated(state->inode, fmode, claim, &stateid))
break;
}
/* Save the delegation */
nfs4_stateid_copy(&stateid, &delegation->stateid);
rcu_read_unlock();
nfs_release_seqid(opendata->o_arg.seqid);
if (!opendata->is_recover) {
ret = nfs_may_open(state->inode, state->owner->so_cred, open_mode);
@ -2556,16 +2561,14 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
* a delegation instead.
*/
if (data->state != NULL) {
struct nfs_delegation *delegation;
if (can_open_cached(data->state, data->o_arg.fmode,
data->o_arg.open_flags, claim))
goto out_no_action;
rcu_read_lock();
delegation = nfs4_get_valid_delegation(data->state->inode);
if (can_open_delegated(delegation, data->o_arg.fmode, claim))
goto unlock_no_action;
rcu_read_unlock();
if (can_open_delegated(data->state->inode, data->o_arg.fmode,
claim, NULL)) {
trace_nfs4_cached_open(data->state);
goto out_no_action;
}
}
/* Update client id. */
data->o_arg.clientid = clp->cl_clientid;
@ -2601,9 +2604,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
data->o_arg.createmode = NFS4_CREATE_GUARDED;
}
return;
unlock_no_action:
trace_nfs4_cached_open(data->state);
rcu_read_unlock();
out_no_action:
task->tk_action = NULL;
out_wait: