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;
|
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);
|
||||||
|
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include <linux/utsname.h>
|
#include <linux/utsname.h>
|
||||||
#include <linux/sched/mm.h>
|
#include <linux/sched/mm.h>
|
||||||
#include <linux/netfs.h>
|
#include <linux/netfs.h>
|
||||||
|
#include <linux/fcntl.h>
|
||||||
#include "cifs_fs_sb.h"
|
#include "cifs_fs_sb.h"
|
||||||
#include "cifsacl.h"
|
#include "cifsacl.h"
|
||||||
#include <crypto/internal/hash.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_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
|
||||||
@@ -2375,4 +2376,14 @@ static inline bool cifs_forced_shutdown(const struct cifs_sb_info *sbi)
|
|||||||
return cifs_sb_flags(sbi) & CIFS_MOUNT_SHUTDOWN;
|
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 */
|
#endif /* _CIFS_GLOB_H */
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
|
|||||||
const char *full_path;
|
const char *full_path;
|
||||||
void *page = alloc_dentry_path();
|
void *page = alloc_dentry_path();
|
||||||
struct inode *newinode = NULL;
|
struct inode *newinode = NULL;
|
||||||
unsigned int sbflags;
|
unsigned int sbflags = cifs_sb_flags(cifs_sb);
|
||||||
int disposition;
|
int disposition;
|
||||||
struct TCP_Server_Info *server = tcon->ses->server;
|
struct TCP_Server_Info *server = tcon->ses->server;
|
||||||
struct cifs_open_parms oparms;
|
struct cifs_open_parms oparms;
|
||||||
@@ -308,6 +308,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
create_options |= cifs_open_create_options(oflags, create_options);
|
||||||
/*
|
/*
|
||||||
* if we're not using unix extensions, see if we need to set
|
* if we're not using unix extensions, see if we need to set
|
||||||
* ATTR_READONLY on the create call
|
* 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
|
* If Open reported that we actually created a file then we now have to
|
||||||
* set the mode if possible.
|
* set the mode if possible.
|
||||||
*/
|
*/
|
||||||
sbflags = cifs_sb_flags(cifs_sb);
|
|
||||||
if ((tcon->unix_ext) && (*oplock & CIFS_CREATE_ACTION)) {
|
if ((tcon->unix_ext) && (*oplock & CIFS_CREATE_ACTION)) {
|
||||||
struct cifs_unix_set_info_args args = {
|
struct cifs_unix_set_info_args args = {
|
||||||
.mode = mode,
|
.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);
|
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;
|
||||||
@@ -584,15 +584,8 @@ static int cifs_nt_open(const char *full_path, struct inode *inode, struct cifs_
|
|||||||
*********************************************************************/
|
*********************************************************************/
|
||||||
|
|
||||||
disposition = cifs_get_disposition(f_flags);
|
disposition = cifs_get_disposition(f_flags);
|
||||||
|
|
||||||
/* BB pass O_SYNC flag through on file attributes .. BB */
|
/* BB pass O_SYNC flag through on file attributes .. BB */
|
||||||
|
create_options |= cifs_open_create_options(f_flags, create_options);
|
||||||
/* 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;
|
|
||||||
|
|
||||||
retry_open:
|
retry_open:
|
||||||
oparms = (struct cifs_open_parms) {
|
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,
|
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);
|
||||||
@@ -988,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) {
|
||||||
@@ -1068,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;
|
||||||
@@ -1314,13 +1304,8 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
|
|||||||
rdwr_for_fscache = 1;
|
rdwr_for_fscache = 1;
|
||||||
|
|
||||||
desired_access = cifs_convert_flags(cfile->f_flags, rdwr_for_fscache);
|
desired_access = cifs_convert_flags(cfile->f_flags, rdwr_for_fscache);
|
||||||
|
create_options |= cifs_open_create_options(cfile->f_flags,
|
||||||
/* O_SYNC also has bit for O_DSYNC so following check picks up either */
|
create_options);
|
||||||
if (cfile->f_flags & O_SYNC)
|
|
||||||
create_options |= CREATE_WRITE_THROUGH;
|
|
||||||
|
|
||||||
if (cfile->f_flags & O_DIRECT)
|
|
||||||
create_options |= CREATE_NO_BUFFER;
|
|
||||||
|
|
||||||
if (server->ops->get_lease_key)
|
if (server->ops->get_lease_key)
|
||||||
server->ops->get_lease_key(inode, &cfile->fid);
|
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);
|
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 */
|
||||||
@@ -2541,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 */
|
||||||
@@ -2559,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;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2603,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 */
|
||||||
@@ -2722,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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) {
|
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);
|
||||||
|
|||||||
@@ -1997,7 +1997,7 @@ int smb3_init_fs_context(struct fs_context *fc)
|
|||||||
ctx->backupuid_specified = false; /* no backup intent for a user */
|
ctx->backupuid_specified = false; /* no backup intent for a user */
|
||||||
ctx->backupgid_specified = false; /* no backup intent for a group */
|
ctx->backupgid_specified = false; /* no backup intent for a group */
|
||||||
|
|
||||||
ctx->retrans = 1;
|
ctx->retrans = 0;
|
||||||
ctx->reparse_type = CIFS_REPARSE_TYPE_DEFAULT;
|
ctx->reparse_type = CIFS_REPARSE_TYPE_DEFAULT;
|
||||||
ctx->symlink_type = CIFS_SYMLINK_TYPE_DEFAULT;
|
ctx->symlink_type = CIFS_SYMLINK_TYPE_DEFAULT;
|
||||||
ctx->nonativesocket = 0;
|
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)
|
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,
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,6 +109,9 @@ int __init smb2_init_maperror(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_SMB_KUNIT_TESTS)
|
#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. */
|
/* Previous prototype for eliminating the build warning. */
|
||||||
const struct status_to_posix_error *smb2_get_err_map_test(__u32 smb2_status);
|
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);
|
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;
|
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);
|
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
|
#endif
|
||||||
|
|||||||
@@ -628,6 +628,7 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
|
|||||||
struct smb_sockaddr_in6 *p6;
|
struct smb_sockaddr_in6 *p6;
|
||||||
struct cifs_server_iface *info = NULL, *iface = NULL, *niface = NULL;
|
struct cifs_server_iface *info = NULL, *iface = NULL, *niface = NULL;
|
||||||
struct cifs_server_iface tmp_iface;
|
struct cifs_server_iface tmp_iface;
|
||||||
|
__be16 port;
|
||||||
ssize_t bytes_left;
|
ssize_t bytes_left;
|
||||||
size_t next = 0;
|
size_t next = 0;
|
||||||
int nb_iface = 0;
|
int nb_iface = 0;
|
||||||
@@ -662,6 +663,15 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
|
|||||||
goto out;
|
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)) {
|
while (bytes_left >= (ssize_t)sizeof(*p)) {
|
||||||
memset(&tmp_iface, 0, sizeof(tmp_iface));
|
memset(&tmp_iface, 0, sizeof(tmp_iface));
|
||||||
/* default to 1Gbps when link speed is unset */
|
/* 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);
|
memcpy(&addr4->sin_addr, &p4->IPv4Address, 4);
|
||||||
|
|
||||||
/* [MS-SMB2] 2.2.32.5.1.1 Clients MUST ignore these */
|
/* [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__,
|
cifs_dbg(FYI, "%s: ipv4 %pI4\n", __func__,
|
||||||
&addr4->sin_addr);
|
&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 */
|
/* [MS-SMB2] 2.2.32.5.1.2 Clients MUST ignore these */
|
||||||
addr6->sin6_flowinfo = 0;
|
addr6->sin6_flowinfo = 0;
|
||||||
addr6->sin6_scope_id = 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__,
|
cifs_dbg(FYI, "%s: ipv6 %pI6\n", __func__,
|
||||||
&addr6->sin6_addr);
|
&addr6->sin6_addr);
|
||||||
@@ -3352,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);
|
||||||
|
|
||||||
@@ -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
|
* 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);
|
||||||
|
|||||||
@@ -5307,7 +5307,10 @@ replay_again:
|
|||||||
|
|
||||||
memset(&rqst, 0, sizeof(struct smb_rqst));
|
memset(&rqst, 0, sizeof(struct smb_rqst));
|
||||||
rqst.rq_iov = iov;
|
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) {
|
if (retries) {
|
||||||
/* Back-off before retry */
|
/* Back-off before retry */
|
||||||
|
|||||||
Reference in New Issue
Block a user