From: Namjae Jeon Date: Thu, 18 Jun 2026 12:31:53 +0000 (+0900) Subject: ksmbd: do not wait for RH lease break ack on overwrite X-Git-Tag: v7.2-rc1~23^2~38 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=752bbd323e779691998920035b6e9417d5a6a78c;p=thirdparty%2Fkernel%2Flinux.git ksmbd: do not wait for RH lease break ack on overwrite smb2.lease.breaking4 expects an overwrite against an RH lease to send RH->NONE lease break notification but complete the triggering create without waiting for the break ack. Keep the lease in break-in-progress state until the client eventually acknowledges the downgrade, but do not hold the overwrite request behind that ack. Signed-off-by: Namjae Jeon Signed-off-by: Steve French --- diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c index 608961c838c97..4d89fbb6c9c59 100644 --- a/fs/smb/server/oplock.c +++ b/fs/smb/server/oplock.c @@ -927,7 +927,7 @@ out: * * Return: 0 on success, otherwise error */ -static int smb2_lease_break_noti(struct oplock_info *opinfo) +static int smb2_lease_break_noti(struct oplock_info *opinfo, bool wait_ack) { struct ksmbd_conn *conn; struct ksmbd_work *work; @@ -964,7 +964,8 @@ static int smb2_lease_break_noti(struct oplock_info *opinfo) if (opinfo->op_state == OPLOCK_ACK_WAIT) { INIT_WORK(&work->work, __smb2_lease_break_noti); ksmbd_queue_work(work); - wait_for_break_ack(opinfo); + if (wait_ack) + wait_for_break_ack(opinfo); } else { __smb2_lease_break_noti(&work->work); if (opinfo->o_lease->new_state == SMB2_LEASE_NONE_LE) { @@ -1006,6 +1007,7 @@ static int oplock_break(struct oplock_info *brk_opinfo, int req_op_level, if (brk_opinfo->is_lease) { struct lease *lease = brk_opinfo->o_lease; bool open_trunc = brk_opinfo->open_trunc; + bool wait_ack; if (in_work && test_bit(0, &brk_opinfo->pending_break)) { setup_async_work(in_work, NULL, NULL); @@ -1058,14 +1060,19 @@ again: } else atomic_dec(&brk_opinfo->breaking_cnt); - err = smb2_lease_break_noti(brk_opinfo); + wait_ack = !(open_trunc && + lease->state == (SMB2_LEASE_READ_CACHING_LE | + SMB2_LEASE_HANDLE_CACHING_LE)); + err = smb2_lease_break_noti(brk_opinfo, wait_ack); ksmbd_debug(OPLOCK, "oplock granted = %d\n", brk_opinfo->level); if (brk_opinfo->op_state == OPLOCK_CLOSING) err = -ENOENT; - wait_lease_breaking(brk_opinfo); - if (!err && lease_break_needed(brk_opinfo, req_op_level, open_trunc)) + if (wait_ack) + wait_lease_breaking(brk_opinfo); + if (wait_ack && !err && + lease_break_needed(brk_opinfo, req_op_level, open_trunc)) goto again; wake_up_oplock_break(brk_opinfo);