smb: client: fix open handle lookup in cifs_open()

When looking up open handles to be re-used in cifs_open(), calling
cifs_get_{writable,readable}_path() is wrong as it will look up for
the first matching open handle, and if @file->f_flags doesn't match,
it will ignore the remaining open handles in
cifsInodeInfo::openFileList that might potentially match
@file->f_flags.

For writable and readable handles, fix this by calling
__cifs_get_writable_file() and __find_readable_file(), respectively,
with FIND_OPEN_FLAGS set.

With the patch, the following program ends up with two opens instead
of three sent over the wire.

```
  #define _GNU_SOURCE
  #include <unistd.h>
  #include <string.h>
  #include <fcntl.h>

  int main(int argc, char *argv[])
  {
          int fd;

          fd = open("/mnt/1/foo", O_CREAT | O_WRONLY | O_TRUNC, 0664);
          close(fd);
          fd = open("/mnt/1/foo", O_DIRECT | O_WRONLY);
          close(fd);
          fd = open("/mnt/1/foo", O_WRONLY);
          close(fd);
          fd = open("/mnt/1/foo", O_DIRECT | O_WRONLY);
          close(fd);
          return 0;
  }
```

```
$ mount.cifs //srv/share /mnt/1 -o ...
$ gcc test.c && ./a.out
```

Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.org>
Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
Cc: David Howells <dhowells@redhat.com>
Cc: linux-cifs@vger.kernel.org
Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
Paulo Alcantara
2026-03-11 15:00:52 -03:00
committed by Steve French
parent d4c7210d2f
commit 40e75e42f4
9 changed files with 112 additions and 75 deletions

View File

@@ -1489,7 +1489,7 @@ struct smb_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
struct cifsFileInfo *open_file = NULL; struct cifsFileInfo *open_file = NULL;
if (inode) if (inode)
open_file = find_readable_file(CIFS_I(inode), true); open_file = find_readable_file(CIFS_I(inode), FIND_FSUID_ONLY);
if (!open_file) if (!open_file)
return get_cifs_acl_by_path(cifs_sb, path, pacllen, info); return get_cifs_acl_by_path(cifs_sb, path, pacllen, info);

View File

@@ -1269,7 +1269,7 @@ static int cifs_precopy_set_eof(struct inode *src_inode, struct cifsInodeInfo *s
struct cifsFileInfo *writeable_srcfile; struct cifsFileInfo *writeable_srcfile;
int rc = -EINVAL; int rc = -EINVAL;
writeable_srcfile = find_writable_file(src_cifsi, FIND_WR_FSUID_ONLY); writeable_srcfile = find_writable_file(src_cifsi, FIND_FSUID_ONLY);
if (writeable_srcfile) { if (writeable_srcfile) {
if (src_tcon->ses->server->ops->set_file_size) if (src_tcon->ses->server->ops->set_file_size)
rc = src_tcon->ses->server->ops->set_file_size( rc = src_tcon->ses->server->ops->set_file_size(

View File

@@ -1885,12 +1885,12 @@ static inline bool is_replayable_error(int error)
} }
/* cifs_get_writable_file() flags */ enum cifs_find_flags {
enum cifs_writable_file_flags { FIND_ANY = 0U,
FIND_WR_ANY = 0U, FIND_FSUID_ONLY = (1U << 0),
FIND_WR_FSUID_ONLY = (1U << 0), FIND_WITH_DELETE = (1U << 1),
FIND_WR_WITH_DELETE = (1U << 1), FIND_NO_PENDING_DELETE = (1U << 2),
FIND_WR_NO_PENDING_DELETE = (1U << 2), FIND_OPEN_FLAGS = (1U << 3),
}; };
#define MID_FREE 0 #define MID_FREE 0

View File

@@ -138,12 +138,14 @@ void cifs_write_subrequest_terminated(struct cifs_io_subrequest *wdata,
ssize_t result); ssize_t result);
struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode, struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
int flags); int flags);
int cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, int flags, int __cifs_get_writable_file(struct cifsInodeInfo *cifs_inode,
struct cifsFileInfo **ret_file); unsigned int find_flags, unsigned int open_flags,
struct cifsFileInfo **ret_file);
int cifs_get_writable_path(struct cifs_tcon *tcon, const char *name, int flags, int cifs_get_writable_path(struct cifs_tcon *tcon, const char *name, int flags,
struct cifsFileInfo **ret_file); struct cifsFileInfo **ret_file);
struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode, struct cifsFileInfo *__find_readable_file(struct cifsInodeInfo *cifs_inode,
bool fsuid_only); unsigned int find_flags,
unsigned int open_flags);
int cifs_get_readable_path(struct cifs_tcon *tcon, const char *name, int cifs_get_readable_path(struct cifs_tcon *tcon, const char *name,
struct cifsFileInfo **ret_file); struct cifsFileInfo **ret_file);
int cifs_get_hardlink_path(struct cifs_tcon *tcon, struct inode *inode, int cifs_get_hardlink_path(struct cifs_tcon *tcon, struct inode *inode,
@@ -596,4 +598,20 @@ static inline void cifs_sg_set_buf(struct sg_table *sgtable,
} }
} }
static inline int cifs_get_writable_file(struct cifsInodeInfo *cifs_inode,
unsigned int find_flags,
struct cifsFileInfo **ret_file)
{
find_flags &= ~FIND_OPEN_FLAGS;
return __cifs_get_writable_file(cifs_inode, find_flags, 0, ret_file);
}
static inline struct cifsFileInfo *
find_readable_file(struct cifsInodeInfo *cinode, unsigned int find_flags)
{
find_flags &= ~FIND_OPEN_FLAGS;
find_flags |= FIND_NO_PENDING_DELETE;
return __find_readable_file(cinode, find_flags, 0);
}
#endif /* _CIFSPROTO_H */ #endif /* _CIFSPROTO_H */

View File

@@ -255,7 +255,7 @@ static void cifs_begin_writeback(struct netfs_io_request *wreq)
struct cifs_io_request *req = container_of(wreq, struct cifs_io_request, rreq); struct cifs_io_request *req = container_of(wreq, struct cifs_io_request, rreq);
int ret; int ret;
ret = cifs_get_writable_file(CIFS_I(wreq->inode), FIND_WR_ANY, &req->cfile); ret = cifs_get_writable_file(CIFS_I(wreq->inode), FIND_ANY, &req->cfile);
if (ret) { if (ret) {
cifs_dbg(VFS, "No writable handle in writepages ret=%d\n", ret); cifs_dbg(VFS, "No writable handle in writepages ret=%d\n", ret);
return; return;
@@ -956,7 +956,7 @@ int cifs_file_flush(const unsigned int xid, struct inode *inode,
return tcon->ses->server->ops->flush(xid, tcon, return tcon->ses->server->ops->flush(xid, tcon,
&cfile->fid); &cfile->fid);
} }
rc = cifs_get_writable_file(CIFS_I(inode), FIND_WR_ANY, &cfile); rc = cifs_get_writable_file(CIFS_I(inode), FIND_ANY, &cfile);
if (!rc) { if (!rc) {
tcon = tlink_tcon(cfile->tlink); tcon = tlink_tcon(cfile->tlink);
rc = tcon->ses->server->ops->flush(xid, tcon, &cfile->fid); rc = tcon->ses->server->ops->flush(xid, tcon, &cfile->fid);
@@ -981,7 +981,7 @@ static int cifs_do_truncate(const unsigned int xid, struct dentry *dentry)
return -ERESTARTSYS; return -ERESTARTSYS;
mapping_set_error(inode->i_mapping, rc); mapping_set_error(inode->i_mapping, rc);
cfile = find_writable_file(cinode, FIND_WR_FSUID_ONLY); cfile = find_writable_file(cinode, FIND_FSUID_ONLY);
rc = cifs_file_flush(xid, inode, cfile); rc = cifs_file_flush(xid, inode, cfile);
if (!rc) { if (!rc) {
if (cfile) { if (cfile) {
@@ -1061,32 +1061,29 @@ int cifs_open(struct inode *inode, struct file *file)
/* Get the cached handle as SMB2 close is deferred */ /* Get the cached handle as SMB2 close is deferred */
if (OPEN_FMODE(file->f_flags) & FMODE_WRITE) { if (OPEN_FMODE(file->f_flags) & FMODE_WRITE) {
rc = cifs_get_writable_path(tcon, full_path, rc = __cifs_get_writable_file(CIFS_I(inode),
FIND_WR_FSUID_ONLY | FIND_FSUID_ONLY |
FIND_WR_NO_PENDING_DELETE, FIND_NO_PENDING_DELETE |
&cfile); FIND_OPEN_FLAGS,
file->f_flags, &cfile);
} else { } else {
rc = cifs_get_readable_path(tcon, full_path, &cfile); cfile = __find_readable_file(CIFS_I(inode),
FIND_NO_PENDING_DELETE |
FIND_OPEN_FLAGS,
file->f_flags);
rc = cfile ? 0 : -ENOENT;
} }
if (rc == 0) { if (rc == 0) {
unsigned int oflags = file->f_flags & ~(O_CREAT|O_EXCL|O_TRUNC); file->private_data = cfile;
unsigned int cflags = cfile->f_flags & ~(O_CREAT|O_EXCL|O_TRUNC); spin_lock(&CIFS_I(inode)->deferred_lock);
cifs_del_deferred_close(cfile);
if (cifs_convert_flags(oflags, 0) == cifs_convert_flags(cflags, 0) && spin_unlock(&CIFS_I(inode)->deferred_lock);
(oflags & (O_SYNC|O_DIRECT)) == (cflags & (O_SYNC|O_DIRECT))) { goto use_cache;
file->private_data = cfile;
spin_lock(&CIFS_I(inode)->deferred_lock);
cifs_del_deferred_close(cfile);
spin_unlock(&CIFS_I(inode)->deferred_lock);
goto use_cache;
}
_cifsFileInfo_put(cfile, true, false);
} else {
/* hard link on the defeered close file */
rc = cifs_get_hardlink_path(tcon, inode, file);
if (rc)
cifs_close_deferred_file(CIFS_I(inode));
} }
/* hard link on the deferred close file */
rc = cifs_get_hardlink_path(tcon, inode, file);
if (rc)
cifs_close_deferred_file(CIFS_I(inode));
if (server->oplocks) if (server->oplocks)
oplock = REQ_OPLOCK; oplock = REQ_OPLOCK;
@@ -2512,10 +2509,33 @@ void cifs_write_subrequest_terminated(struct cifs_io_subrequest *wdata, ssize_t
netfs_write_subrequest_terminated(&wdata->subreq, result); netfs_write_subrequest_terminated(&wdata->subreq, result);
} }
struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode, static bool open_flags_match(struct cifsInodeInfo *cinode,
bool fsuid_only) unsigned int oflags, unsigned int cflags)
{
struct inode *inode = &cinode->netfs.inode;
int crw = 0, orw = 0;
oflags &= ~(O_CREAT | O_EXCL | O_TRUNC);
cflags &= ~(O_CREAT | O_EXCL | O_TRUNC);
if (cifs_fscache_enabled(inode)) {
if (OPEN_FMODE(cflags) & FMODE_WRITE)
crw = 1;
if (OPEN_FMODE(oflags) & FMODE_WRITE)
orw = 1;
}
if (cifs_convert_flags(oflags, orw) != cifs_convert_flags(cflags, crw))
return false;
return (oflags & (O_SYNC | O_DIRECT)) == (cflags & (O_SYNC | O_DIRECT));
}
struct cifsFileInfo *__find_readable_file(struct cifsInodeInfo *cifs_inode,
unsigned int find_flags,
unsigned int open_flags)
{ {
struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode); struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode);
bool fsuid_only = find_flags & FIND_FSUID_ONLY;
struct cifsFileInfo *open_file = NULL; struct cifsFileInfo *open_file = NULL;
/* only filter by fsuid on multiuser mounts */ /* only filter by fsuid on multiuser mounts */
@@ -2529,6 +2549,13 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
if (fsuid_only && !uid_eq(open_file->uid, current_fsuid())) if (fsuid_only && !uid_eq(open_file->uid, current_fsuid()))
continue; continue;
if ((find_flags & FIND_NO_PENDING_DELETE) &&
open_file->status_file_deleted)
continue;
if ((find_flags & FIND_OPEN_FLAGS) &&
!open_flags_match(cifs_inode, open_flags,
open_file->f_flags))
continue;
if (OPEN_FMODE(open_file->f_flags) & FMODE_READ) { if (OPEN_FMODE(open_file->f_flags) & FMODE_READ) {
if ((!open_file->invalidHandle)) { if ((!open_file->invalidHandle)) {
/* found a good file */ /* found a good file */
@@ -2547,17 +2574,17 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
} }
/* Return -EBADF if no handle is found and general rc otherwise */ /* Return -EBADF if no handle is found and general rc otherwise */
int int __cifs_get_writable_file(struct cifsInodeInfo *cifs_inode,
cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, int flags, unsigned int find_flags, unsigned int open_flags,
struct cifsFileInfo **ret_file) struct cifsFileInfo **ret_file)
{ {
struct cifsFileInfo *open_file, *inv_file = NULL; struct cifsFileInfo *open_file, *inv_file = NULL;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
bool any_available = false; bool any_available = false;
int rc = -EBADF; int rc = -EBADF;
unsigned int refind = 0; unsigned int refind = 0;
bool fsuid_only = flags & FIND_WR_FSUID_ONLY; bool fsuid_only = find_flags & FIND_FSUID_ONLY;
bool with_delete = flags & FIND_WR_WITH_DELETE; bool with_delete = find_flags & FIND_WITH_DELETE;
*ret_file = NULL; *ret_file = NULL;
/* /*
@@ -2591,9 +2618,13 @@ refind_writable:
continue; continue;
if (with_delete && !(open_file->fid.access & DELETE)) if (with_delete && !(open_file->fid.access & DELETE))
continue; continue;
if ((flags & FIND_WR_NO_PENDING_DELETE) && if ((find_flags & FIND_NO_PENDING_DELETE) &&
open_file->status_file_deleted) open_file->status_file_deleted)
continue; continue;
if ((find_flags & FIND_OPEN_FLAGS) &&
!open_flags_match(cifs_inode, open_flags,
open_file->f_flags))
continue;
if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) { if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
if (!open_file->invalidHandle) { if (!open_file->invalidHandle) {
/* found a good writable file */ /* found a good writable file */
@@ -2710,17 +2741,7 @@ cifs_get_readable_path(struct cifs_tcon *tcon, const char *name,
cinode = CIFS_I(d_inode(cfile->dentry)); cinode = CIFS_I(d_inode(cfile->dentry));
spin_unlock(&tcon->open_file_lock); spin_unlock(&tcon->open_file_lock);
free_dentry_path(page); free_dentry_path(page);
*ret_file = find_readable_file(cinode, 0); *ret_file = find_readable_file(cinode, FIND_ANY);
if (*ret_file) {
spin_lock(&cinode->open_file_lock);
if ((*ret_file)->status_file_deleted) {
spin_unlock(&cinode->open_file_lock);
cifsFileInfo_put(*ret_file);
*ret_file = NULL;
} else {
spin_unlock(&cinode->open_file_lock);
}
}
return *ret_file ? 0 : -ENOENT; return *ret_file ? 0 : -ENOENT;
} }
@@ -2792,7 +2813,7 @@ int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
} }
if ((OPEN_FMODE(smbfile->f_flags) & FMODE_WRITE) == 0) { if ((OPEN_FMODE(smbfile->f_flags) & FMODE_WRITE) == 0) {
smbfile = find_writable_file(CIFS_I(inode), FIND_WR_ANY); smbfile = find_writable_file(CIFS_I(inode), FIND_ANY);
if (smbfile) { if (smbfile) {
rc = server->ops->flush(xid, tcon, &smbfile->fid); rc = server->ops->flush(xid, tcon, &smbfile->fid);
cifsFileInfo_put(smbfile); cifsFileInfo_put(smbfile);

View File

@@ -2997,7 +2997,7 @@ int cifs_fiemap(struct inode *inode, struct fiemap_extent_info *fei, u64 start,
} }
} }
cfile = find_readable_file(cifs_i, false); cfile = find_readable_file(cifs_i, FIND_ANY);
if (cfile == NULL) if (cfile == NULL)
return -EINVAL; return -EINVAL;
@@ -3050,7 +3050,7 @@ int cifs_file_set_size(const unsigned int xid, struct dentry *dentry,
size, false); size, false);
cifs_dbg(FYI, "%s: set_file_size: rc = %d\n", __func__, rc); cifs_dbg(FYI, "%s: set_file_size: rc = %d\n", __func__, rc);
} else { } else {
open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY); open_file = find_writable_file(cifsInode, FIND_FSUID_ONLY);
if (open_file) { if (open_file) {
tcon = tlink_tcon(open_file->tlink); tcon = tlink_tcon(open_file->tlink);
server = tcon->ses->server; server = tcon->ses->server;
@@ -3219,7 +3219,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
open_file->fid.netfid, open_file->fid.netfid,
open_file->pid); open_file->pid);
} else { } else {
open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY); open_file = find_writable_file(cifsInode, FIND_FSUID_ONLY);
if (open_file) { if (open_file) {
pTcon = tlink_tcon(open_file->tlink); pTcon = tlink_tcon(open_file->tlink);
rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args,

View File

@@ -960,7 +960,7 @@ smb_set_file_info(struct inode *inode, const char *full_path,
struct cifs_tcon *tcon; struct cifs_tcon *tcon;
/* if the file is already open for write, just use that fileid */ /* if the file is already open for write, just use that fileid */
open_file = find_writable_file(cinode, FIND_WR_FSUID_ONLY); open_file = find_writable_file(cinode, FIND_FSUID_ONLY);
if (open_file) { if (open_file) {
fid.netfid = open_file->fid.netfid; fid.netfid = open_file->fid.netfid;

View File

@@ -1156,7 +1156,7 @@ smb2_mkdir_setinfo(struct inode *inode, const char *name,
cifs_i = CIFS_I(inode); cifs_i = CIFS_I(inode);
dosattrs = cifs_i->cifsAttrs | ATTR_READONLY; dosattrs = cifs_i->cifsAttrs | ATTR_READONLY;
data.Attributes = cpu_to_le32(dosattrs); data.Attributes = cpu_to_le32(dosattrs);
cifs_get_writable_path(tcon, name, FIND_WR_ANY, &cfile); cifs_get_writable_path(tcon, name, FIND_ANY, &cfile);
oparms = CIFS_OPARMS(cifs_sb, tcon, name, FILE_WRITE_ATTRIBUTES, oparms = CIFS_OPARMS(cifs_sb, tcon, name, FILE_WRITE_ATTRIBUTES,
FILE_CREATE, CREATE_NOT_FILE, ACL_NO_MODE); FILE_CREATE, CREATE_NOT_FILE, ACL_NO_MODE);
tmprc = smb2_compound_op(xid, tcon, cifs_sb, name, tmprc = smb2_compound_op(xid, tcon, cifs_sb, name,
@@ -1336,14 +1336,13 @@ int smb2_rename_path(const unsigned int xid,
__u32 co = file_create_options(source_dentry); __u32 co = file_create_options(source_dentry);
drop_cached_dir_by_name(xid, tcon, from_name, cifs_sb); drop_cached_dir_by_name(xid, tcon, from_name, cifs_sb);
cifs_get_writable_path(tcon, from_name, FIND_WR_WITH_DELETE, &cfile); cifs_get_writable_path(tcon, from_name, FIND_WITH_DELETE, &cfile);
int rc = smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb, int rc = smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
co, DELETE, SMB2_OP_RENAME, cfile, source_dentry); co, DELETE, SMB2_OP_RENAME, cfile, source_dentry);
if (rc == -EINVAL) { if (rc == -EINVAL) {
cifs_dbg(FYI, "invalid lease key, resending request without lease"); cifs_dbg(FYI, "invalid lease key, resending request without lease");
cifs_get_writable_path(tcon, from_name, cifs_get_writable_path(tcon, from_name, FIND_WITH_DELETE, &cfile);
FIND_WR_WITH_DELETE, &cfile);
rc = smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb, rc = smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
co, DELETE, SMB2_OP_RENAME, cfile, NULL); co, DELETE, SMB2_OP_RENAME, cfile, NULL);
} }
@@ -1377,7 +1376,7 @@ smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon,
in_iov.iov_base = &eof; in_iov.iov_base = &eof;
in_iov.iov_len = sizeof(eof); in_iov.iov_len = sizeof(eof);
cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile); cifs_get_writable_path(tcon, full_path, FIND_ANY, &cfile);
oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_WRITE_DATA, oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_WRITE_DATA,
FILE_OPEN, 0, ACL_NO_MODE); FILE_OPEN, 0, ACL_NO_MODE);
@@ -1387,7 +1386,7 @@ smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon,
cfile, NULL, NULL, dentry); cfile, NULL, NULL, dentry);
if (rc == -EINVAL) { if (rc == -EINVAL) {
cifs_dbg(FYI, "invalid lease key, resending request without lease"); cifs_dbg(FYI, "invalid lease key, resending request without lease");
cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile); cifs_get_writable_path(tcon, full_path, FIND_ANY, &cfile);
rc = smb2_compound_op(xid, tcon, cifs_sb, rc = smb2_compound_op(xid, tcon, cifs_sb,
full_path, &oparms, &in_iov, full_path, &oparms, &in_iov,
&(int){SMB2_OP_SET_EOF}, 1, &(int){SMB2_OP_SET_EOF}, 1,
@@ -1417,7 +1416,7 @@ smb2_set_file_info(struct inode *inode, const char *full_path,
(buf->LastWriteTime == 0) && (buf->ChangeTime == 0)) { (buf->LastWriteTime == 0) && (buf->ChangeTime == 0)) {
if (buf->Attributes == 0) if (buf->Attributes == 0)
goto out; /* would be a no op, no sense sending this */ goto out; /* would be a no op, no sense sending this */
cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile); cifs_get_writable_path(tcon, full_path, FIND_ANY, &cfile);
} }
oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_WRITE_ATTRIBUTES, oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_WRITE_ATTRIBUTES,
@@ -1476,7 +1475,7 @@ struct inode *smb2_create_reparse_inode(struct cifs_open_info_data *data,
if (tcon->posix_extensions) { if (tcon->posix_extensions) {
cmds[1] = SMB2_OP_POSIX_QUERY_INFO; cmds[1] = SMB2_OP_POSIX_QUERY_INFO;
cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile); cifs_get_writable_path(tcon, full_path, FIND_ANY, &cfile);
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms,
in_iov, cmds, 2, cfile, out_iov, out_buftype, NULL); in_iov, cmds, 2, cfile, out_iov, out_buftype, NULL);
if (!rc) { if (!rc) {
@@ -1485,7 +1484,7 @@ struct inode *smb2_create_reparse_inode(struct cifs_open_info_data *data,
} }
} else { } else {
cmds[1] = SMB2_OP_QUERY_INFO; cmds[1] = SMB2_OP_QUERY_INFO;
cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile); cifs_get_writable_path(tcon, full_path, FIND_ANY, &cfile);
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms,
in_iov, cmds, 2, cfile, out_iov, out_buftype, NULL); in_iov, cmds, 2, cfile, out_iov, out_buftype, NULL);
if (!rc) { if (!rc) {
@@ -1636,13 +1635,12 @@ int smb2_rename_pending_delete(const char *full_path,
iov[1].iov_base = utf16_path; iov[1].iov_base = utf16_path;
iov[1].iov_len = sizeof(*utf16_path) * UniStrlen((wchar_t *)utf16_path); iov[1].iov_len = sizeof(*utf16_path) * UniStrlen((wchar_t *)utf16_path);
cifs_get_writable_path(tcon, full_path, FIND_WR_WITH_DELETE, &cfile); cifs_get_writable_path(tcon, full_path, FIND_WITH_DELETE, &cfile);
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, iov, rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, iov,
cmds, num_cmds, cfile, NULL, NULL, dentry); cmds, num_cmds, cfile, NULL, NULL, dentry);
if (rc == -EINVAL) { if (rc == -EINVAL) {
cifs_dbg(FYI, "invalid lease key, resending request without lease\n"); cifs_dbg(FYI, "invalid lease key, resending request without lease\n");
cifs_get_writable_path(tcon, full_path, cifs_get_writable_path(tcon, full_path, FIND_WITH_DELETE, &cfile);
FIND_WR_WITH_DELETE, &cfile);
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, iov, rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, iov,
cmds, num_cmds, cfile, NULL, NULL, NULL); cmds, num_cmds, cfile, NULL, NULL, NULL);
} }

View File

@@ -3362,7 +3362,7 @@ get_smb2_acl(struct cifs_sb_info *cifs_sb,
struct cifsFileInfo *open_file = NULL; struct cifsFileInfo *open_file = NULL;
if (inode && !(info & SACL_SECINFO)) if (inode && !(info & SACL_SECINFO))
open_file = find_readable_file(CIFS_I(inode), true); open_file = find_readable_file(CIFS_I(inode), FIND_FSUID_ONLY);
if (!open_file || (info & SACL_SECINFO)) if (!open_file || (info & SACL_SECINFO))
return get_smb2_acl_by_path(cifs_sb, path, pacllen, info); return get_smb2_acl_by_path(cifs_sb, path, pacllen, info);
@@ -3908,7 +3908,7 @@ static loff_t smb3_llseek(struct file *file, struct cifs_tcon *tcon, loff_t offs
* some servers (Windows2016) will not reflect recent writes in * some servers (Windows2016) will not reflect recent writes in
* QUERY_ALLOCATED_RANGES until SMB2_flush is called. * QUERY_ALLOCATED_RANGES until SMB2_flush is called.
*/ */
wrcfile = find_writable_file(cifsi, FIND_WR_ANY); wrcfile = find_writable_file(cifsi, FIND_ANY);
if (wrcfile) { if (wrcfile) {
filemap_write_and_wait(inode->i_mapping); filemap_write_and_wait(inode->i_mapping);
smb2_flush_file(xid, tcon, &wrcfile->fid); smb2_flush_file(xid, tcon, &wrcfile->fid);