[PATCH 12/15] smb: client: avoid batch oplocks for reentrant POSIX EAs
Ze Tan <[email protected]> Fri, 24 Jul 2026 18:40:06 +0800
| Newsgroups | org.kernel.vger.linux-cifs |
|---|---|
| Message-ID | <c8d554906ee1093a732435c6178394c0b519b502.1784888897.git.tanze@kylinos.cn> |
Native killpriv handling can reopen a path for EA queries or removal while a write handle is active. Without lease support, a batch oplock cannot identify the temporary EA open as the same caching owner and can deadlock while breaking against the blocked write path. Request no oplock for data-writing opens when POSIX extensions and xattrs are enabled but leasing is unavailable. Leave read opens, non-POSIX mounts, and servers with lease support unchanged. After applying the native EA patches, configure the server with oplocks enabled and SMB2 leases disabled. Use an SMB account that maps to root or an admin account on the server. Mount both the TEST and SCRATCH shares with SMB3 POSIX extensions and SID-encoded Unix IDs: $ TEST_USER=fsgqa $ TEST_UID=$(id -u "$TEST_USER") $ TEST_GID=$(id -g "$TEST_USER") $ MOUNT_OPTS="credentials=/path/to/credentials,vers=3.1.1" $ MOUNT_OPTS="$MOUNT_OPTS,posix,idsfromsid" $ MOUNT_OPTS="$MOUNT_OPTS,uid=$TEST_UID,gid=$TEST_GID" $ export TEST_FS_MOUNT_OPTS="-o $MOUNT_OPTS" $ export MOUNT_OPTIONS="-o $MOUNT_OPTS" Then run: $ su root $ XFSTESTS_DIR=/path/to/xfstests $ cd "$XFSTESTS_DIR" $ ./check generic/093 Signed-off-by: Ze Tan <[email protected]> --- fs/smb/client/smb2file.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c index f35b6488d810..b07ff4570f56 100644 --- a/fs/smb/client/smb2file.c +++ b/fs/smb/client/smb2file.c @@ -160,6 +160,13 @@ int smb2_parse_symlink_response(struct cifs_sb_info *cifs_sb, const struct kvec cifs_sb); } +static bool smb2_open_writes_data(const struct cifs_open_parms *oparms) +{ + return oparms->desired_access & + (FILE_WRITE_DATA | FILE_APPEND_DATA | + GENERIC_WRITE | GENERIC_ALL); +} + int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 *oplock, void *buf) { @@ -192,6 +199,17 @@ int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, retry_without_read_attributes = true; } smb2_oplock = SMB2_OPLOCK_LEVEL_BATCH; + /* + * A killpriv EA reopen without a lease can break this write's batch + * oplock and deadlock against itself. + */ + if (IS_ENABLED(CONFIG_CIFS_XATTR) && oparms->cifs_sb && + !(cifs_sb_flags(oparms->cifs_sb) & CIFS_MOUNT_NO_XATTR) && + oparms->tcon->posix_extensions && + !(oparms->tcon->ses->server->capabilities & + SMB2_GLOBAL_CAP_LEASING) && + smb2_open_writes_data(oparms)) + smb2_oplock = SMB2_OPLOCK_LEVEL_NONE; rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, data, NULL, &err_iov, &err_buftype); -- 2.43.0