mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-22 07:27:12 +08:00
Merge tag 'v7.0-rc3-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6
Pull smb client fixes from Steve French: - Fix reconnect when using non-default port - Fix default retransmission behavior - Fix open handle reuse in cifs_open - Fix export for smb2-mapperror-test - Fix potential corruption on write retry - Fix potentially uninitialized superblock flags - Fix missing O_DIRECT and O_SYNC flags on create * tag 'v7.0-rc3-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6: cifs: make default value of retrans as zero smb: client: fix open handle lookup in cifs_open() smb: client: fix iface port assignment in parse_server_interfaces smb/client: only export symbol for 'smb2maperror-test' module smb: client: fix in-place encryption corruption in SMB2_write() smb: client: fix sbflags initialization smb: client: fix atomic open with O_DIRECT & O_SYNC
This commit is contained in:
@@ -1489,7 +1489,7 @@ struct smb_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
|
||||
struct cifsFileInfo *open_file = NULL;
|
||||
|
||||
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)
|
||||
return get_cifs_acl_by_path(cifs_sb, path, pacllen, info);
|
||||
|
||||
|
||||
@@ -1269,7 +1269,7 @@ static int cifs_precopy_set_eof(struct inode *src_inode, struct cifsInodeInfo *s
|
||||
struct cifsFileInfo *writeable_srcfile;
|
||||
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 (src_tcon->ses->server->ops->set_file_size)
|
||||
rc = src_tcon->ses->server->ops->set_file_size(
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <linux/utsname.h>
|
||||
#include <linux/sched/mm.h>
|
||||
#include <linux/netfs.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include "cifs_fs_sb.h"
|
||||
#include "cifsacl.h"
|
||||
#include <crypto/internal/hash.h>
|
||||
@@ -1884,12 +1885,12 @@ static inline bool is_replayable_error(int error)
|
||||
}
|
||||
|
||||
|
||||
/* cifs_get_writable_file() flags */
|
||||
enum cifs_writable_file_flags {
|
||||
FIND_WR_ANY = 0U,
|
||||
FIND_WR_FSUID_ONLY = (1U << 0),
|
||||
FIND_WR_WITH_DELETE = (1U << 1),
|
||||
FIND_WR_NO_PENDING_DELETE = (1U << 2),
|
||||
enum cifs_find_flags {
|
||||
FIND_ANY = 0U,
|
||||
FIND_FSUID_ONLY = (1U << 0),
|
||||
FIND_WITH_DELETE = (1U << 1),
|
||||
FIND_NO_PENDING_DELETE = (1U << 2),
|
||||
FIND_OPEN_FLAGS = (1U << 3),
|
||||
};
|
||||
|
||||
#define MID_FREE 0
|
||||
@@ -2375,4 +2376,14 @@ static inline bool cifs_forced_shutdown(const struct cifs_sb_info *sbi)
|
||||
return cifs_sb_flags(sbi) & CIFS_MOUNT_SHUTDOWN;
|
||||
}
|
||||
|
||||
static inline int cifs_open_create_options(unsigned int oflags, int opts)
|
||||
{
|
||||
/* O_SYNC also has bit for O_DSYNC so following check picks up either */
|
||||
if (oflags & O_SYNC)
|
||||
opts |= CREATE_WRITE_THROUGH;
|
||||
if (oflags & O_DIRECT)
|
||||
opts |= CREATE_NO_BUFFER;
|
||||
return opts;
|
||||
}
|
||||
|
||||
#endif /* _CIFS_GLOB_H */
|
||||
|
||||
@@ -138,12 +138,14 @@ void cifs_write_subrequest_terminated(struct cifs_io_subrequest *wdata,
|
||||
ssize_t result);
|
||||
struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
|
||||
int flags);
|
||||
int cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, int flags,
|
||||
struct cifsFileInfo **ret_file);
|
||||
int __cifs_get_writable_file(struct cifsInodeInfo *cifs_inode,
|
||||
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,
|
||||
struct cifsFileInfo **ret_file);
|
||||
struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
|
||||
bool fsuid_only);
|
||||
struct cifsFileInfo *__find_readable_file(struct cifsInodeInfo *cifs_inode,
|
||||
unsigned int find_flags,
|
||||
unsigned int open_flags);
|
||||
int cifs_get_readable_path(struct cifs_tcon *tcon, const char *name,
|
||||
struct cifsFileInfo **ret_file);
|
||||
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 */
|
||||
|
||||
@@ -187,7 +187,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
|
||||
const char *full_path;
|
||||
void *page = alloc_dentry_path();
|
||||
struct inode *newinode = NULL;
|
||||
unsigned int sbflags;
|
||||
unsigned int sbflags = cifs_sb_flags(cifs_sb);
|
||||
int disposition;
|
||||
struct TCP_Server_Info *server = tcon->ses->server;
|
||||
struct cifs_open_parms oparms;
|
||||
@@ -308,6 +308,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
|
||||
goto out;
|
||||
}
|
||||
|
||||
create_options |= cifs_open_create_options(oflags, create_options);
|
||||
/*
|
||||
* if we're not using unix extensions, see if we need to set
|
||||
* ATTR_READONLY on the create call
|
||||
@@ -367,7 +368,6 @@ retry_open:
|
||||
* If Open reported that we actually created a file then we now have to
|
||||
* set the mode if possible.
|
||||
*/
|
||||
sbflags = cifs_sb_flags(cifs_sb);
|
||||
if ((tcon->unix_ext) && (*oplock & CIFS_CREATE_ACTION)) {
|
||||
struct cifs_unix_set_info_args args = {
|
||||
.mode = mode,
|
||||
|
||||
@@ -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);
|
||||
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) {
|
||||
cifs_dbg(VFS, "No writable handle in writepages ret=%d\n", ret);
|
||||
return;
|
||||
@@ -584,15 +584,8 @@ static int cifs_nt_open(const char *full_path, struct inode *inode, struct cifs_
|
||||
*********************************************************************/
|
||||
|
||||
disposition = cifs_get_disposition(f_flags);
|
||||
|
||||
/* BB pass O_SYNC flag through on file attributes .. BB */
|
||||
|
||||
/* O_SYNC also has bit for O_DSYNC so following check picks up either */
|
||||
if (f_flags & O_SYNC)
|
||||
create_options |= CREATE_WRITE_THROUGH;
|
||||
|
||||
if (f_flags & O_DIRECT)
|
||||
create_options |= CREATE_NO_BUFFER;
|
||||
create_options |= cifs_open_create_options(f_flags, create_options);
|
||||
|
||||
retry_open:
|
||||
oparms = (struct cifs_open_parms) {
|
||||
@@ -963,7 +956,7 @@ int cifs_file_flush(const unsigned int xid, struct inode *inode,
|
||||
return tcon->ses->server->ops->flush(xid, tcon,
|
||||
&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) {
|
||||
tcon = tlink_tcon(cfile->tlink);
|
||||
rc = tcon->ses->server->ops->flush(xid, tcon, &cfile->fid);
|
||||
@@ -988,7 +981,7 @@ static int cifs_do_truncate(const unsigned int xid, struct dentry *dentry)
|
||||
return -ERESTARTSYS;
|
||||
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);
|
||||
if (!rc) {
|
||||
if (cfile) {
|
||||
@@ -1068,32 +1061,29 @@ int cifs_open(struct inode *inode, struct file *file)
|
||||
|
||||
/* Get the cached handle as SMB2 close is deferred */
|
||||
if (OPEN_FMODE(file->f_flags) & FMODE_WRITE) {
|
||||
rc = cifs_get_writable_path(tcon, full_path,
|
||||
FIND_WR_FSUID_ONLY |
|
||||
FIND_WR_NO_PENDING_DELETE,
|
||||
&cfile);
|
||||
rc = __cifs_get_writable_file(CIFS_I(inode),
|
||||
FIND_FSUID_ONLY |
|
||||
FIND_NO_PENDING_DELETE |
|
||||
FIND_OPEN_FLAGS,
|
||||
file->f_flags, &cfile);
|
||||
} 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) {
|
||||
unsigned int oflags = file->f_flags & ~(O_CREAT|O_EXCL|O_TRUNC);
|
||||
unsigned int cflags = cfile->f_flags & ~(O_CREAT|O_EXCL|O_TRUNC);
|
||||
|
||||
if (cifs_convert_flags(oflags, 0) == cifs_convert_flags(cflags, 0) &&
|
||||
(oflags & (O_SYNC|O_DIRECT)) == (cflags & (O_SYNC|O_DIRECT))) {
|
||||
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));
|
||||
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;
|
||||
}
|
||||
/* 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)
|
||||
oplock = REQ_OPLOCK;
|
||||
@@ -1314,13 +1304,8 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
|
||||
rdwr_for_fscache = 1;
|
||||
|
||||
desired_access = cifs_convert_flags(cfile->f_flags, rdwr_for_fscache);
|
||||
|
||||
/* O_SYNC also has bit for O_DSYNC so following check picks up either */
|
||||
if (cfile->f_flags & O_SYNC)
|
||||
create_options |= CREATE_WRITE_THROUGH;
|
||||
|
||||
if (cfile->f_flags & O_DIRECT)
|
||||
create_options |= CREATE_NO_BUFFER;
|
||||
create_options |= cifs_open_create_options(cfile->f_flags,
|
||||
create_options);
|
||||
|
||||
if (server->ops->get_lease_key)
|
||||
server->ops->get_lease_key(inode, &cfile->fid);
|
||||
@@ -2524,10 +2509,33 @@ void cifs_write_subrequest_terminated(struct cifs_io_subrequest *wdata, ssize_t
|
||||
netfs_write_subrequest_terminated(&wdata->subreq, result);
|
||||
}
|
||||
|
||||
struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
|
||||
bool fsuid_only)
|
||||
static bool open_flags_match(struct cifsInodeInfo *cinode,
|
||||
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);
|
||||
bool fsuid_only = find_flags & FIND_FSUID_ONLY;
|
||||
struct cifsFileInfo *open_file = NULL;
|
||||
|
||||
/* only filter by fsuid on multiuser mounts */
|
||||
@@ -2541,6 +2549,13 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
|
||||
list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
|
||||
if (fsuid_only && !uid_eq(open_file->uid, current_fsuid()))
|
||||
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_file->invalidHandle)) {
|
||||
/* found a good file */
|
||||
@@ -2559,17 +2574,17 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
|
||||
}
|
||||
|
||||
/* Return -EBADF if no handle is found and general rc otherwise */
|
||||
int
|
||||
cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, int flags,
|
||||
struct cifsFileInfo **ret_file)
|
||||
int __cifs_get_writable_file(struct cifsInodeInfo *cifs_inode,
|
||||
unsigned int find_flags, unsigned int open_flags,
|
||||
struct cifsFileInfo **ret_file)
|
||||
{
|
||||
struct cifsFileInfo *open_file, *inv_file = NULL;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
bool any_available = false;
|
||||
int rc = -EBADF;
|
||||
unsigned int refind = 0;
|
||||
bool fsuid_only = flags & FIND_WR_FSUID_ONLY;
|
||||
bool with_delete = flags & FIND_WR_WITH_DELETE;
|
||||
bool fsuid_only = find_flags & FIND_FSUID_ONLY;
|
||||
bool with_delete = find_flags & FIND_WITH_DELETE;
|
||||
*ret_file = NULL;
|
||||
|
||||
/*
|
||||
@@ -2603,9 +2618,13 @@ refind_writable:
|
||||
continue;
|
||||
if (with_delete && !(open_file->fid.access & DELETE))
|
||||
continue;
|
||||
if ((flags & FIND_WR_NO_PENDING_DELETE) &&
|
||||
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_WRITE) {
|
||||
if (!open_file->invalidHandle) {
|
||||
/* found a good writable file */
|
||||
@@ -2722,17 +2741,7 @@ cifs_get_readable_path(struct cifs_tcon *tcon, const char *name,
|
||||
cinode = CIFS_I(d_inode(cfile->dentry));
|
||||
spin_unlock(&tcon->open_file_lock);
|
||||
free_dentry_path(page);
|
||||
*ret_file = find_readable_file(cinode, 0);
|
||||
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);
|
||||
}
|
||||
}
|
||||
*ret_file = find_readable_file(cinode, FIND_ANY);
|
||||
return *ret_file ? 0 : -ENOENT;
|
||||
}
|
||||
|
||||
@@ -2804,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) {
|
||||
smbfile = find_writable_file(CIFS_I(inode), FIND_WR_ANY);
|
||||
smbfile = find_writable_file(CIFS_I(inode), FIND_ANY);
|
||||
if (smbfile) {
|
||||
rc = server->ops->flush(xid, tcon, &smbfile->fid);
|
||||
cifsFileInfo_put(smbfile);
|
||||
|
||||
@@ -1997,7 +1997,7 @@ int smb3_init_fs_context(struct fs_context *fc)
|
||||
ctx->backupuid_specified = false; /* no backup intent for a user */
|
||||
ctx->backupgid_specified = false; /* no backup intent for a group */
|
||||
|
||||
ctx->retrans = 1;
|
||||
ctx->retrans = 0;
|
||||
ctx->reparse_type = CIFS_REPARSE_TYPE_DEFAULT;
|
||||
ctx->symlink_type = CIFS_SYMLINK_TYPE_DEFAULT;
|
||||
ctx->nonativesocket = 0;
|
||||
|
||||
@@ -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)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -3050,7 +3050,7 @@ int cifs_file_set_size(const unsigned int xid, struct dentry *dentry,
|
||||
size, false);
|
||||
cifs_dbg(FYI, "%s: set_file_size: rc = %d\n", __func__, rc);
|
||||
} else {
|
||||
open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY);
|
||||
open_file = find_writable_file(cifsInode, FIND_FSUID_ONLY);
|
||||
if (open_file) {
|
||||
tcon = tlink_tcon(open_file->tlink);
|
||||
server = tcon->ses->server;
|
||||
@@ -3219,7 +3219,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
|
||||
open_file->fid.netfid,
|
||||
open_file->pid);
|
||||
} else {
|
||||
open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY);
|
||||
open_file = find_writable_file(cifsInode, FIND_FSUID_ONLY);
|
||||
if (open_file) {
|
||||
pTcon = tlink_tcon(open_file->tlink);
|
||||
rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args,
|
||||
|
||||
@@ -960,7 +960,7 @@ smb_set_file_info(struct inode *inode, const char *full_path,
|
||||
struct cifs_tcon *tcon;
|
||||
|
||||
/* 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) {
|
||||
fid.netfid = open_file->fid.netfid;
|
||||
|
||||
@@ -1156,7 +1156,7 @@ smb2_mkdir_setinfo(struct inode *inode, const char *name,
|
||||
cifs_i = CIFS_I(inode);
|
||||
dosattrs = cifs_i->cifsAttrs | ATTR_READONLY;
|
||||
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,
|
||||
FILE_CREATE, CREATE_NOT_FILE, ACL_NO_MODE);
|
||||
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);
|
||||
|
||||
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,
|
||||
co, DELETE, SMB2_OP_RENAME, cfile, source_dentry);
|
||||
if (rc == -EINVAL) {
|
||||
cifs_dbg(FYI, "invalid lease key, resending request without lease");
|
||||
cifs_get_writable_path(tcon, from_name,
|
||||
FIND_WR_WITH_DELETE, &cfile);
|
||||
cifs_get_writable_path(tcon, from_name, FIND_WITH_DELETE, &cfile);
|
||||
rc = smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
|
||||
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_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,
|
||||
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);
|
||||
if (rc == -EINVAL) {
|
||||
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,
|
||||
full_path, &oparms, &in_iov,
|
||||
&(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)) {
|
||||
if (buf->Attributes == 0)
|
||||
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,
|
||||
@@ -1476,7 +1475,7 @@ struct inode *smb2_create_reparse_inode(struct cifs_open_info_data *data,
|
||||
|
||||
if (tcon->posix_extensions) {
|
||||
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,
|
||||
in_iov, cmds, 2, cfile, out_iov, out_buftype, NULL);
|
||||
if (!rc) {
|
||||
@@ -1485,7 +1484,7 @@ struct inode *smb2_create_reparse_inode(struct cifs_open_info_data *data,
|
||||
}
|
||||
} else {
|
||||
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,
|
||||
in_iov, cmds, 2, cfile, out_iov, out_buftype, NULL);
|
||||
if (!rc) {
|
||||
@@ -1636,13 +1635,12 @@ int smb2_rename_pending_delete(const char *full_path,
|
||||
iov[1].iov_base = 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,
|
||||
cmds, num_cmds, cfile, NULL, NULL, dentry);
|
||||
if (rc == -EINVAL) {
|
||||
cifs_dbg(FYI, "invalid lease key, resending request without lease\n");
|
||||
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,
|
||||
cmds, num_cmds, cfile, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
@@ -109,6 +109,9 @@ int __init smb2_init_maperror(void)
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_SMB_KUNIT_TESTS)
|
||||
#define EXPORT_SYMBOL_FOR_SMB_TEST(sym) \
|
||||
EXPORT_SYMBOL_FOR_MODULES(sym, "smb2maperror_test")
|
||||
|
||||
/* Previous prototype for eliminating the build warning. */
|
||||
const struct status_to_posix_error *smb2_get_err_map_test(__u32 smb2_status);
|
||||
|
||||
@@ -116,11 +119,11 @@ const struct status_to_posix_error *smb2_get_err_map_test(__u32 smb2_status)
|
||||
{
|
||||
return smb2_get_err_map(smb2_status);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(smb2_get_err_map_test);
|
||||
EXPORT_SYMBOL_FOR_SMB_TEST(smb2_get_err_map_test);
|
||||
|
||||
const struct status_to_posix_error *smb2_error_map_table_test = smb2_error_map_table;
|
||||
EXPORT_SYMBOL_GPL(smb2_error_map_table_test);
|
||||
EXPORT_SYMBOL_FOR_SMB_TEST(smb2_error_map_table_test);
|
||||
|
||||
unsigned int smb2_error_map_num = ARRAY_SIZE(smb2_error_map_table);
|
||||
EXPORT_SYMBOL_GPL(smb2_error_map_num);
|
||||
EXPORT_SYMBOL_FOR_SMB_TEST(smb2_error_map_num);
|
||||
#endif
|
||||
|
||||
@@ -628,6 +628,7 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
|
||||
struct smb_sockaddr_in6 *p6;
|
||||
struct cifs_server_iface *info = NULL, *iface = NULL, *niface = NULL;
|
||||
struct cifs_server_iface tmp_iface;
|
||||
__be16 port;
|
||||
ssize_t bytes_left;
|
||||
size_t next = 0;
|
||||
int nb_iface = 0;
|
||||
@@ -662,6 +663,15 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
|
||||
goto out;
|
||||
}
|
||||
|
||||
spin_lock(&ses->server->srv_lock);
|
||||
if (ses->server->dstaddr.ss_family == AF_INET)
|
||||
port = ((struct sockaddr_in *)&ses->server->dstaddr)->sin_port;
|
||||
else if (ses->server->dstaddr.ss_family == AF_INET6)
|
||||
port = ((struct sockaddr_in6 *)&ses->server->dstaddr)->sin6_port;
|
||||
else
|
||||
port = cpu_to_be16(CIFS_PORT);
|
||||
spin_unlock(&ses->server->srv_lock);
|
||||
|
||||
while (bytes_left >= (ssize_t)sizeof(*p)) {
|
||||
memset(&tmp_iface, 0, sizeof(tmp_iface));
|
||||
/* default to 1Gbps when link speed is unset */
|
||||
@@ -682,7 +692,7 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
|
||||
memcpy(&addr4->sin_addr, &p4->IPv4Address, 4);
|
||||
|
||||
/* [MS-SMB2] 2.2.32.5.1.1 Clients MUST ignore these */
|
||||
addr4->sin_port = cpu_to_be16(CIFS_PORT);
|
||||
addr4->sin_port = port;
|
||||
|
||||
cifs_dbg(FYI, "%s: ipv4 %pI4\n", __func__,
|
||||
&addr4->sin_addr);
|
||||
@@ -696,7 +706,7 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
|
||||
/* [MS-SMB2] 2.2.32.5.1.2 Clients MUST ignore these */
|
||||
addr6->sin6_flowinfo = 0;
|
||||
addr6->sin6_scope_id = 0;
|
||||
addr6->sin6_port = cpu_to_be16(CIFS_PORT);
|
||||
addr6->sin6_port = port;
|
||||
|
||||
cifs_dbg(FYI, "%s: ipv6 %pI6\n", __func__,
|
||||
&addr6->sin6_addr);
|
||||
@@ -3352,7 +3362,7 @@ get_smb2_acl(struct cifs_sb_info *cifs_sb,
|
||||
struct cifsFileInfo *open_file = NULL;
|
||||
|
||||
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))
|
||||
return get_smb2_acl_by_path(cifs_sb, path, pacllen, info);
|
||||
|
||||
@@ -3898,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
|
||||
* 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) {
|
||||
filemap_write_and_wait(inode->i_mapping);
|
||||
smb2_flush_file(xid, tcon, &wrcfile->fid);
|
||||
|
||||
@@ -5307,7 +5307,10 @@ replay_again:
|
||||
|
||||
memset(&rqst, 0, sizeof(struct smb_rqst));
|
||||
rqst.rq_iov = iov;
|
||||
rqst.rq_nvec = n_vec + 1;
|
||||
/* iov[0] is the SMB header; move payload to rq_iter for encryption safety */
|
||||
rqst.rq_nvec = 1;
|
||||
iov_iter_kvec(&rqst.rq_iter, ITER_SOURCE, &iov[1], n_vec,
|
||||
io_parms->length);
|
||||
|
||||
if (retries) {
|
||||
/* Back-off before retry */
|
||||
|
||||
Reference in New Issue
Block a user