mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 18:21:24 +02:00
ksmbd: compute lease break-in-progress flag on response
SMB2_LEASE_FLAG_BREAK_IN_PROGRESS is a transient create response flag, not persistent lease state. Do not store the flag in lease->flags when a same-key open is granted during a pending break. Instead, derive it from lease opens that are still waiting for a break ACK while building the lease create response, and keep lease->flags for persistent lease flags such as the parent lease key. This clears the flag naturally after the break ACK completes and fixes reopen responses that report BREAK_IN_PROGRESS after the lease is no longer breaking. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
171b5d72dd
commit
890825ed5c
|
|
@ -39,6 +39,23 @@ static bool lease_has_parent_key(struct lease *lease)
|
|||
return lease->flags & SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE;
|
||||
}
|
||||
|
||||
static bool lease_break_in_progress(struct lease *lease)
|
||||
{
|
||||
struct oplock_info *opinfo;
|
||||
bool ret = false;
|
||||
|
||||
spin_lock(&lease->lock);
|
||||
list_for_each_entry(opinfo, &lease->open_list, lease_entry) {
|
||||
if (opinfo->op_state == OPLOCK_ACK_WAIT) {
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock(&lease->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* alloc_opinfo() - allocate a new opinfo object for oplock info
|
||||
* @work: smb work
|
||||
|
|
@ -1292,15 +1309,12 @@ int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid,
|
|||
if (m_opinfo) {
|
||||
lease_put(opinfo->o_lease);
|
||||
lease_get(m_opinfo->o_lease);
|
||||
opinfo->o_lease = m_opinfo->o_lease;
|
||||
opinfo->level = m_opinfo->level;
|
||||
new_lease = false;
|
||||
if (atomic_read(&m_opinfo->breaking_cnt))
|
||||
opinfo->o_lease->flags |=
|
||||
SMB2_LEASE_FLAG_BREAK_IN_PROGRESS_LE;
|
||||
opinfo_put(m_opinfo);
|
||||
goto out;
|
||||
}
|
||||
opinfo->o_lease = m_opinfo->o_lease;
|
||||
opinfo->level = m_opinfo->level;
|
||||
new_lease = false;
|
||||
opinfo_put(m_opinfo);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
prev_opinfo = opinfo_get_list(ci);
|
||||
if (!prev_opinfo ||
|
||||
|
|
@ -1521,13 +1535,15 @@ void create_lease_buf(u8 *rbuf, struct lease *lease)
|
|||
{
|
||||
if (lease->version == 2) {
|
||||
struct create_lease_v2 *buf = (struct create_lease_v2 *)rbuf;
|
||||
__le32 flags = lease->flags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS_LE;
|
||||
__le32 flags = 0;
|
||||
|
||||
memset(buf, 0, sizeof(struct create_lease_v2));
|
||||
memcpy(buf->lcontext.LeaseKey, lease->lease_key,
|
||||
SMB2_LEASE_KEY_SIZE);
|
||||
if (lease_has_parent_key(lease))
|
||||
flags |= SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE;
|
||||
if (lease_break_in_progress(lease))
|
||||
flags |= SMB2_LEASE_FLAG_BREAK_IN_PROGRESS_LE;
|
||||
buf->lcontext.LeaseFlags = flags;
|
||||
buf->lcontext.Epoch = cpu_to_le16(lease->epoch);
|
||||
buf->lcontext.LeaseState = lease->state;
|
||||
|
|
@ -1549,8 +1565,9 @@ void create_lease_buf(u8 *rbuf, struct lease *lease)
|
|||
|
||||
memset(buf, 0, sizeof(struct create_lease));
|
||||
memcpy(buf->lcontext.LeaseKey, lease->lease_key, SMB2_LEASE_KEY_SIZE);
|
||||
buf->lcontext.LeaseFlags =
|
||||
lease->flags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS_LE;
|
||||
if (lease_break_in_progress(lease))
|
||||
buf->lcontext.LeaseFlags =
|
||||
SMB2_LEASE_FLAG_BREAK_IN_PROGRESS_LE;
|
||||
buf->lcontext.LeaseState = lease->state;
|
||||
buf->ccontext.DataOffset = cpu_to_le16(offsetof
|
||||
(struct create_lease, lcontext));
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user