From: Namjae Jeon <linkinjeon@kernel.org>
To: linux-cifs@vger.kernel.org
Cc: smfrench@gmail.com, senozhatsky@chromium.org, tom@talpey.com,
atteh.mailbox@gmail.com, Namjae Jeon <linkinjeon@kernel.org>
Subject: [PATCH 23/29] ksmbd: break handle caching for share conflicts
Date: Sun, 21 Jun 2026 21:48:38 +0900 [thread overview]
Message-ID: <20260621124844.6235-23-linkinjeon@kernel.org> (raw)
In-Reply-To: <20260621124844.6235-1-linkinjeon@kernel.org>
smb2.lease.break_twice first opens a file with an RHW lease and then tries
a second open with restrictive sharing. That open must fail with a sharing
violation, but the existing lease should be broken from RHW to RW because
only handle caching conflicts with the requested sharing.
ksmbd used the normal write-cache break calculation for this path, so RHW
was broken to RH. The following successful open then did not generate the
expected second break from RW to R.
Pass share-conflict context into the lease break helper and, for lease
breaks caused by sharing, drop only SMB2_LEASE_HANDLE_CACHING from the
current lease state. Other break paths keep the existing write/truncate
break behavior.
A share-conflict break must also remain a single break. The triggering
open fails with a sharing violation and is never granted, so there is no
target oplock level to converge on. The lease break retry loop, however,
keeps breaking while the lease level is still above req_op_level, which
broke RHW all the way down to R in one open (lease_break_info.count became
2 instead of 1). Skip the again loop for share-conflict breaks so the
sharing open produces exactly one RHW->RW break and the later successful
open produces the separate RW->R break the test expects.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
---
fs/smb/server/oplock.c | 26 +++++++++++++++++++-------
1 file changed, 19 insertions(+), 7 deletions(-)
diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c
index ff9a72236b4d..b15c0fb0c0c7 100644
--- a/fs/smb/server/oplock.c
+++ b/fs/smb/server/oplock.c
@@ -1035,7 +1035,7 @@ static void wait_lease_breaking(struct oplock_info *opinfo)
}
static int oplock_break(struct oplock_info *brk_opinfo, int req_op_level,
- struct ksmbd_work *in_work)
+ struct ksmbd_work *in_work, bool share_break)
{
int err = 0;
bool sent_interim = false;
@@ -1073,6 +1073,10 @@ static int oplock_break(struct oplock_info *brk_opinfo, int req_op_level,
* none.
*/
lease->new_state = SMB2_LEASE_NONE_LE;
+ } else if (share_break &&
+ lease->state & SMB2_LEASE_HANDLE_CACHING_LE) {
+ lease->new_state =
+ lease->state & ~SMB2_LEASE_HANDLE_CACHING_LE;
} else {
if (lease->state & SMB2_LEASE_WRITE_CACHING_LE) {
if (lease->state & SMB2_LEASE_HANDLE_CACHING_LE)
@@ -1121,7 +1125,13 @@ static int oplock_break(struct oplock_info *brk_opinfo, int req_op_level,
if (wait_ack)
wait_lease_breaking(brk_opinfo);
- if (wait_ack && !err &&
+ /*
+ * A break caused by a share-mode conflict only drops the
+ * conflicting caching bit and the triggering open still fails
+ * with a sharing violation, so it must stay a single break.
+ * Do not cascade down to req_op_level through the again loop.
+ */
+ if (wait_ack && !err && !share_break &&
lease_break_needed(brk_opinfo, req_op_level, open_trunc))
goto again;
@@ -1281,7 +1291,7 @@ void smb_send_parent_lease_break_noti(struct ksmbd_file *fp,
continue;
}
- oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE, NULL);
+ oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE, NULL, false);
opinfo_put(opinfo);
}
}
@@ -1322,7 +1332,7 @@ void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp)
continue;
}
- oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE, NULL);
+ oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE, NULL, false);
opinfo_put(opinfo);
}
}
@@ -1441,7 +1451,8 @@ int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid,
prev_fid = prev_opinfo->fid;
}
- err = oplock_break(prev_opinfo, break_level, work);
+ err = oplock_break(prev_opinfo, break_level, work,
+ share_ret < 0 && prev_opinfo->is_lease);
if (prev_durable_detached || (prev_durable_open && err == -ENOENT))
ksmbd_invalidate_durable_fd(prev_fid);
opinfo_put(prev_opinfo);
@@ -1539,7 +1550,7 @@ static bool smb_break_all_write_oplock(struct ksmbd_work *work,
}
brk_opinfo->open_trunc = is_trunc;
- oplock_break(brk_opinfo, SMB2_OPLOCK_LEVEL_II, work);
+ oplock_break(brk_opinfo, SMB2_OPLOCK_LEVEL_II, work, false);
sent_break = true;
opinfo_put(brk_opinfo);
@@ -1609,7 +1620,8 @@ static void __smb_break_all_levII_oplock(struct ksmbd_work *work,
oplock_break(brk_op,
brk_op->is_lease && !is_trunc ?
SMB2_OPLOCK_LEVEL_II : SMB2_OPLOCK_LEVEL_NONE,
- send_interim && !sent_interim ? work : NULL);
+ send_interim && !sent_interim ? work : NULL,
+ false);
}
sent_interim = true;
next:
--
2.25.1
next prev parent reply other threads:[~2026-06-21 12:49 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-21 12:48 [PATCH 01/29] ksmbd: handle missing create contexts for lease opens Namjae Jeon
2026-06-21 12:48 ` [PATCH 02/29] ksmbd: supersede disconnected delete-on-close durable handle Namjae Jeon
2026-06-21 12:48 ` [PATCH 03/29] ksmbd: invalidate durable handles on oplock break Namjae Jeon
2026-06-21 12:48 ` [PATCH 04/29] ksmbd: fix durable reconnect context parsing Namjae Jeon
2026-06-21 12:48 ` [PATCH 05/29] ksmbd: handle durable v2 app instance id Namjae Jeon
2026-06-21 12:48 ` [PATCH 06/29] ksmbd: preserve open change time across rename Namjae Jeon
2026-06-21 12:48 ` [PATCH 07/29] ksmbd: check parent directory sharing conflicts on rename Namjae Jeon
2026-06-21 12:48 ` [PATCH 08/29] ksmbd: deny renaming directory with open children Namjae Jeon
2026-06-21 12:48 ` [PATCH 09/29] ksmbd: propagate failed command status in related compounds Namjae Jeon
2026-06-21 12:48 ` [PATCH 10/29] ksmbd: validate handle for create or get object id Namjae Jeon
2026-06-21 12:48 ` [PATCH 11/29] ksmbd: preserve compound responses for chained errors Namjae Jeon
2026-06-21 12:48 ` [PATCH 12/29] ksmbd: return success for deferred final close Namjae Jeon
2026-06-21 12:48 ` [PATCH 13/29] ksmbd: send pending interim for last compound I/O Namjae Jeon
2026-06-21 12:48 ` [PATCH 14/29] ksmbd: honor stream delete sharing for base file Namjae Jeon
2026-06-21 12:48 ` [PATCH 15/29] ksmbd: reject empty-attribute synchronize-only create Namjae Jeon
2026-06-21 12:48 ` [PATCH 16/29] ksmbd: tighten create file attribute validation Namjae Jeon
2026-06-21 12:48 ` [PATCH 17/29] ksmbd: return requested create allocation size Namjae Jeon
2026-06-22 23:01 ` Nathan Chancellor
2026-06-23 1:28 ` Namjae Jeon
2026-06-21 12:48 ` [PATCH 18/29] ksmbd: apply create security descriptor first Namjae Jeon
2026-06-21 12:48 ` [PATCH 19/29] ksmbd: downgrade oplock after break timeout Namjae Jeon
2026-06-21 12:48 ` [PATCH 20/29] ksmbd: avoid level II oplock break notification on unlink Namjae Jeon
2026-06-21 12:48 ` [PATCH 21/29] ksmbd: return oplock protocol error for level II ack Namjae Jeon
2026-06-21 12:48 ` [PATCH 22/29] ksmbd: normalize ungrantable lease states Namjae Jeon
2026-06-21 12:48 ` Namjae Jeon [this message]
2026-06-21 12:48 ` [PATCH 24/29] ksmbd: break conflicting-open leases only as far as needed Namjae Jeon
2026-06-21 12:48 ` [PATCH 25/29] ksmbd: validate :: stream type against directory create Namjae Jeon
2026-06-21 12:48 ` [PATCH 26/29] ksmbd: treat read-control opens as stat opens only for leases Namjae Jeon
2026-06-21 12:48 ` [PATCH 27/29] ksmbd: start file id allocation at 1 Namjae Jeon
2026-06-21 12:48 ` [PATCH 28/29] ksmbd: sleep interruptibly in the durable handle scavenger Namjae Jeon
2026-06-21 12:48 ` [PATCH 29/29] ksmbd: fix UBSAN array-index-out-of-bounds in decode_compress_ctxt() Namjae Jeon
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260621124844.6235-23-linkinjeon@kernel.org \
--to=linkinjeon@kernel.org \
--cc=atteh.mailbox@gmail.com \
--cc=linux-cifs@vger.kernel.org \
--cc=senozhatsky@chromium.org \
--cc=smfrench@gmail.com \
--cc=tom@talpey.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.