<feed xmlns='http://www.w3.org/2005/Atom'>
<title>kernel/git/stable/linux.git/fs/smb/server/oplock.c, branch master</title>
<subtitle>Linux kernel stable tree</subtitle>
<id>https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/atom?h=master</id>
<link rel='self' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/atom?h=master'/>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/'/>
<updated>2026-07-01T02:29:46+00:00</updated>
<entry>
<title>ksmbd: snapshot previous oplock state before durable checks</title>
<updated>2026-07-01T02:29:46+00:00</updated>
<author>
<name>Namjae Jeon</name>
<email>linkinjeon@kernel.org</email>
</author>
<published>2026-06-28T00:30:00+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=5138c84dbb501363510f6f9c300797b240a119cb'/>
<id>urn:sha1:5138c84dbb501363510f6f9c300797b240a119cb</id>
<content type='text'>
smb_grant_oplock() checks the previous oplock holder's o_fp to decide
whether a durable handle should be invalidated when the oplock break
cannot be delivered. prev_opinfo is obtained with opinfo_get_list(),
which pins only the oplock_info. It does not pin the ksmbd_file stored
in opinfo-&gt;o_fp.

A concurrent last close can unlink the opinfo from ci-&gt;m_op_list under
ci-&gt;m_lock and then free the ksmbd_file. The oplock_info can still be
kept alive by the refcount taken by opinfo_get_list(), but o_fp may
already point at freed memory by the time smb_grant_oplock() reads
is_durable, conn, or tcon.

Snapshot the previous holder's durable state while ci-&gt;m_lock is held,
then use only the copied values after dropping the lock. This keeps the
o_fp lifetime tied to the inode lock without taking an extra ksmbd_file
reference. Taking such a reference is unsafe here because smb_grant_oplock()
does not necessarily have the previous holder's session work, and dropping
the temporary reference can otherwise become the final putter.

Fixes: 26fa88dc877c ("ksmbd: invalidate durable handles on oplock break")
Reported-by: Gil Portnoy &lt;dddhkts1@gmail.com&gt;
Signed-off-by: Namjae Jeon &lt;linkinjeon@kernel.org&gt;
Signed-off-by: Steve French &lt;stfrench@microsoft.com&gt;
</content>
</entry>
<entry>
<title>ksmbd: don't hold ci-&gt;m_lock while waiting for a lease break ack</title>
<updated>2026-07-01T02:29:46+00:00</updated>
<author>
<name>Namjae Jeon</name>
<email>linkinjeon@kernel.org</email>
</author>
<published>2026-06-28T05:40:22+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=27a9bc968d4ae809a3f5ca2f2b136856ee613cb4'/>
<id>urn:sha1:27a9bc968d4ae809a3f5ca2f2b136856ee613cb4</id>
<content type='text'>
When a cifs.ko client caches a read-handle (RH) lease via deferred close
and a conflicting open arrives, ksmbd breaks the lease and waits for the
acknowledgment in wait_for_break_ack() for up to OPLOCK_WAIT_TIME (35s).
__smb_break_all_levII_oplock() runs that wait while holding ci-&gt;m_lock
for read.

cifs.ko reacts to a handle-lease break by closing the deferred handle
rather than sending a lease break acknowledgment. That close path
(close_id_del_oplock() -&gt; opinfo_del()) takes ci-&gt;m_lock for write and
is exactly what would wake the waiter, but it blocks on the read lock
held by the waiting thread. The break is then resolved only by the 35s
timeout, so xfstests generic/001 takes ~78s with leases enabled versus
~4s with oplocks only.

Collect the target opinfos (each pinned with a reference) while holding
ci-&gt;m_lock, then break them after releasing it, matching how
smb_grant_oplock() already breaks a conflicting lease using only a
reference.  The reference keeps the opinfo (and its conn and lease)
alive across the unlocked window, and a close racing the break is
handled by the existing OPLOCK_CLOSING state check. Apply the same fix
to the parent lease break paths.

Signed-off-by: Namjae Jeon &lt;linkinjeon@kernel.org&gt;
Signed-off-by: Steve French &lt;stfrench@microsoft.com&gt;
</content>
</entry>
<entry>
<title>ksmbd: fix kernel-doc warnings in smb2_lease_break_noti()</title>
<updated>2026-06-23T22:52:42+00:00</updated>
<author>
<name>Namjae Jeon</name>
<email>linkinjeon@kernel.org</email>
</author>
<published>2026-06-23T20:59:13+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=da793cf6d60233f47ea5e7e9e39425d71dfcdb79'/>
<id>urn:sha1:da793cf6d60233f47ea5e7e9e39425d71dfcdb79</id>
<content type='text'>
kernel test robot report missing kernel-doc descriptions for the 'wait_ack'
and 'inc_epoch' parameters of smb2_lease_break_noti():

  Warning: fs/smb/server/oplock.c:937 function parameter 'wait_ack' not
   described in 'smb2_lease_break_noti'
  Warning: fs/smb/server/oplock.c:937 function parameter 'inc_epoch' not
   described in 'smb2_lease_break_noti'

Document both parameters to silence the warnings.

Reported-by: kernel test robot &lt;lkp@intel.com&gt;
Signed-off-by: Namjae Jeon &lt;linkinjeon@kernel.org&gt;
Signed-off-by: Steve French &lt;stfrench@microsoft.com&gt;
</content>
</entry>
<entry>
<title>ksmbd: fix inconsistent indenting warnings</title>
<updated>2026-06-23T22:52:42+00:00</updated>
<author>
<name>Namjae Jeon</name>
<email>linkinjeon@kernel.org</email>
</author>
<published>2026-06-23T08:21:29+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=f455ea21f23e2a82e4adf00d8ee65c268ad82036'/>
<id>urn:sha1:f455ea21f23e2a82e4adf00d8ee65c268ad82036</id>
<content type='text'>
Detected by Smatch.

   fs/smb/server/oplock.c:1446 smb_grant_oplock()
   warn: inconsistent indenting

Reported-by: Dan Carpenter &lt;error27@gmail.com&gt;
Signed-off-by: Namjae Jeon &lt;linkinjeon@kernel.org&gt;
Signed-off-by: Steve French &lt;stfrench@microsoft.com&gt;
</content>
</entry>
<entry>
<title>ksmbd: treat read-control opens as stat opens only for leases</title>
<updated>2026-06-23T01:15:06+00:00</updated>
<author>
<name>Namjae Jeon</name>
<email>linkinjeon@kernel.org</email>
</author>
<published>2026-06-21T10:57:55+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=be939e11c4724d1de3650e8bafd4c3583d9684b2'/>
<id>urn:sha1:be939e11c4724d1de3650e8bafd4c3583d9684b2</id>
<content type='text'>
A second open that requests only metadata-level access must not break
the existing caching state. ksmbd already skips the break for such opens
via fp-&gt;attrib_only (FILE_READ_ATTRIBUTES,
FILE_WRITE_ATTRIBUTES and FILE_SYNCHRONIZE).

An open requesting only READ_CONTROL (reading the security descriptor)
must be treated differently depending on the existing caching state.
smbtorture smb2.lease.statopen4 expects a read-control open NOT to break
a caching lease, while smb2.oplock.statopen1 expects the same open to
break a batch oplock. So READ_CONTROL is a stat open for leases but not
for oplocks.

Extend the stat-open break-skip in smb_grant_oplock() to also cover a
read-control-only open, but only when the existing holder is a lease.
The global fp-&gt;attrib_only flag (used for share-mode, rename and truncate
decisions) is left unchanged so oplock behaviour is preserved.

Signed-off-by: Namjae Jeon &lt;linkinjeon@kernel.org&gt;
Signed-off-by: Steve French &lt;stfrench@microsoft.com&gt;
</content>
</entry>
<entry>
<title>ksmbd: break conflicting-open leases only as far as needed</title>
<updated>2026-06-23T01:15:06+00:00</updated>
<author>
<name>Namjae Jeon</name>
<email>linkinjeon@kernel.org</email>
</author>
<published>2026-06-21T10:51:35+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=889d2e38943ad9ab253dfd7520e6d92867825e7d'/>
<id>urn:sha1:889d2e38943ad9ab253dfd7520e6d92867825e7d</id>
<content type='text'>
smb2.lease.oplock and smb2.lease.breaking1 hold a lease and then issue a
single conflicting open on the same file.  The held lease must break one
step to drop write caching (RWH-&gt;RH, RW-&gt;R) and then stop, so
lease_break_info.count is 1 and the lease keeps its read/handle caching.

ksmbd instead cascaded the break all the way down to none
(e.g. RWH-&gt;RH-&gt;R-&gt;none), so the break count was 2 or 3 and the reported
lease state ended at 0.  Commit "chain pending lease breaks before waking
waiters" forces break_level to SMB2_OPLOCK_LEVEL_NONE for any non-lease
open against a handle-caching lease, which drives oplock_break()'s retry
loop down to none even when only one open is contending.

Drop that break_level override so a conflicting open breaks a lease only
to its own compatible level (level II, i.e. RH/R).

A deeper break is still required when a truncating open is also waiting
behind the same lease break.  smb2.lease.breaking3 keeps a normal open
pending through RWH-&gt;RH and an overwrite open pending behind it, and
expects the lease to continue RH-&gt;R-&gt;none before either open completes.
The overwrite waiter sets open_trunc on the lease while it blocks on the
pending break, so extend the retry loop to chain another break while that
truncating waiter still needs the lease at none.  The per-break open_trunc
snapshot stays cleared, so the cascade steps down (RH-&gt;R-&gt;none) instead of
collapsing straight to none, and the normal open stays pending until the
lease is fully broken.

Signed-off-by: Namjae Jeon &lt;linkinjeon@kernel.org&gt;
Signed-off-by: Steve French &lt;stfrench@microsoft.com&gt;
</content>
</entry>
<entry>
<title>ksmbd: break handle caching for share conflicts</title>
<updated>2026-06-23T01:15:06+00:00</updated>
<author>
<name>Namjae Jeon</name>
<email>linkinjeon@kernel.org</email>
</author>
<published>2026-06-21T10:50:41+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=b35f8f898cd99d61ac9acbdc87ca3955922e956a'/>
<id>urn:sha1:b35f8f898cd99d61ac9acbdc87ca3955922e956a</id>
<content type='text'>
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-&gt;RW break and the later successful
open produces the separate RW-&gt;R break the test expects.

Signed-off-by: Namjae Jeon &lt;linkinjeon@kernel.org&gt;
Signed-off-by: Steve French &lt;stfrench@microsoft.com&gt;
</content>
</entry>
<entry>
<title>ksmbd: normalize ungrantable lease states</title>
<updated>2026-06-23T01:15:06+00:00</updated>
<author>
<name>Namjae Jeon</name>
<email>linkinjeon@kernel.org</email>
</author>
<published>2026-06-21T10:50:12+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=43f21349427dc964bfc7aa450e7e560f292698bb'/>
<id>urn:sha1:43f21349427dc964bfc7aa450e7e560f292698bb</id>
<content type='text'>
smb2.lease.request verifies which SMB2 lease state combinations are granted
by the server.  Requests for H-only, W-only, and HW leases are valid lease
state bitmasks, but they are not grantable combinations and should be
returned as lease state none.

ksmbd only checked that the requested bits were inside the SMB2 lease state
mask.  As a result it could grant H-only, W-only, or HW requests and return
non-zero lease states where the client expects no lease.

Keep the bitmask validation, but normalize ungrantable combinations to zero
before allocating or looking up the lease.  The grantable combinations
remain unchanged: R, RH, RW, and RHW.

Signed-off-by: Namjae Jeon &lt;linkinjeon@kernel.org&gt;
Signed-off-by: Steve French &lt;stfrench@microsoft.com&gt;
</content>
</entry>
<entry>
<title>ksmbd: avoid level II oplock break notification on unlink</title>
<updated>2026-06-23T01:15:05+00:00</updated>
<author>
<name>Namjae Jeon</name>
<email>linkinjeon@kernel.org</email>
</author>
<published>2026-06-21T10:49:05+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=ec476c2580050ea050c562eeeb508519fc69ea21'/>
<id>urn:sha1:ec476c2580050ea050c562eeeb508519fc69ea21</id>
<content type='text'>
smb2_util_unlink() opens the target with FILE_DELETE_ON_CLOSE and then
closes that handle.  Other clients can also mark a file for delete with
SMB2 SET_INFO FileDispositionInformation.

When these unlink paths break existing SMB2 level II oplocks, ksmbd sends
an unsolicited SMB2_OPLOCK_BREAK notification to none.  This races with the
synchronous CREATE or SET_INFO response expected by the client, and
smbtorture reports NT_STATUS_INVALID_NETWORK_RESPONSE while running
smb2.oplock.exclusive2.

SMB2 level II oplock breaks do not require an acknowledgment in the delete
path.  Keep lease handling unchanged, but drop plain SMB2 level II oplocks
locally for unlink requests without sending a break notification.  Normal
write/truncate paths still send the level II to none notification,
preserving the behavior covered by smb2.oplock.levelII500.

Signed-off-by: Namjae Jeon &lt;linkinjeon@kernel.org&gt;
Signed-off-by: Steve French &lt;stfrench@microsoft.com&gt;
</content>
</entry>
<entry>
<title>ksmbd: downgrade oplock after break timeout</title>
<updated>2026-06-23T01:15:05+00:00</updated>
<author>
<name>Namjae Jeon</name>
<email>linkinjeon@kernel.org</email>
</author>
<published>2026-06-21T10:48:27+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=7db0da9915fdfd40156d01f20faac08f040fcfa3'/>
<id>urn:sha1:7db0da9915fdfd40156d01f20faac08f040fcfa3</id>
<content type='text'>
smb2.oplock.batch22a opens a file with a batch oplock and then issues a
second open that waits for the oplock break timeout.  After the timeout the
second open should succeed, but the granted oplock level must be level II.

When the break times out, oplock_break() returns -ENOENT after invalidating
the previous opener.  smb_grant_oplock() went straight to set_lev with the
original requested oplock level, so the second open could be granted a new
batch oplock.  Downgrade the requested oplock to level II on the -ENOENT
break-timeout path before granting the oplock to the new open.

A break that completes because the previous owner closed its handle from
the oplock break handler must be distinguished from a real timeout.
smb2.oplock.batch7 closes the first handle during the break wait, and the
second open is then expected to be granted the originally requested batch
oplock.  Return -EAGAIN from the non-lease break path when the previous
opener closed during the break wait, recheck sharing in smb_grant_oplock(),
and grant the requested oplock if the close removed the conflict. Real
break timeouts still return -ENOENT and keep the downgrade to level II.

Signed-off-by: Namjae Jeon &lt;linkinjeon@kernel.org&gt;
Signed-off-by: Steve French &lt;stfrench@microsoft.com&gt;
</content>
</entry>
</feed>
