Skip to content

Commit d874ca0

Browse files
committed
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
2 parents b36eb6e + e3beefd commit d874ca0

13 files changed

Lines changed: 152 additions & 100 deletions

File tree

fs/smb/client/cifsacl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1489,7 +1489,7 @@ struct smb_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
14891489
struct cifsFileInfo *open_file = NULL;
14901490

14911491
if (inode)
1492-
open_file = find_readable_file(CIFS_I(inode), true);
1492+
open_file = find_readable_file(CIFS_I(inode), FIND_FSUID_ONLY);
14931493
if (!open_file)
14941494
return get_cifs_acl_by_path(cifs_sb, path, pacllen, info);
14951495

fs/smb/client/cifsfs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1269,7 +1269,7 @@ static int cifs_precopy_set_eof(struct inode *src_inode, struct cifsInodeInfo *s
12691269
struct cifsFileInfo *writeable_srcfile;
12701270
int rc = -EINVAL;
12711271

1272-
writeable_srcfile = find_writable_file(src_cifsi, FIND_WR_FSUID_ONLY);
1272+
writeable_srcfile = find_writable_file(src_cifsi, FIND_FSUID_ONLY);
12731273
if (writeable_srcfile) {
12741274
if (src_tcon->ses->server->ops->set_file_size)
12751275
rc = src_tcon->ses->server->ops->set_file_size(

fs/smb/client/cifsglob.h

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <linux/utsname.h>
2121
#include <linux/sched/mm.h>
2222
#include <linux/netfs.h>
23+
#include <linux/fcntl.h>
2324
#include "cifs_fs_sb.h"
2425
#include "cifsacl.h"
2526
#include <crypto/internal/hash.h>
@@ -1884,12 +1885,12 @@ static inline bool is_replayable_error(int error)
18841885
}
18851886

18861887

1887-
/* cifs_get_writable_file() flags */
1888-
enum cifs_writable_file_flags {
1889-
FIND_WR_ANY = 0U,
1890-
FIND_WR_FSUID_ONLY = (1U << 0),
1891-
FIND_WR_WITH_DELETE = (1U << 1),
1892-
FIND_WR_NO_PENDING_DELETE = (1U << 2),
1888+
enum cifs_find_flags {
1889+
FIND_ANY = 0U,
1890+
FIND_FSUID_ONLY = (1U << 0),
1891+
FIND_WITH_DELETE = (1U << 1),
1892+
FIND_NO_PENDING_DELETE = (1U << 2),
1893+
FIND_OPEN_FLAGS = (1U << 3),
18931894
};
18941895

18951896
#define MID_FREE 0
@@ -2375,4 +2376,14 @@ static inline bool cifs_forced_shutdown(const struct cifs_sb_info *sbi)
23752376
return cifs_sb_flags(sbi) & CIFS_MOUNT_SHUTDOWN;
23762377
}
23772378

2379+
static inline int cifs_open_create_options(unsigned int oflags, int opts)
2380+
{
2381+
/* O_SYNC also has bit for O_DSYNC so following check picks up either */
2382+
if (oflags & O_SYNC)
2383+
opts |= CREATE_WRITE_THROUGH;
2384+
if (oflags & O_DIRECT)
2385+
opts |= CREATE_NO_BUFFER;
2386+
return opts;
2387+
}
2388+
23782389
#endif /* _CIFS_GLOB_H */

fs/smb/client/cifsproto.h

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,12 +138,14 @@ void cifs_write_subrequest_terminated(struct cifs_io_subrequest *wdata,
138138
ssize_t result);
139139
struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
140140
int flags);
141-
int cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, int flags,
142-
struct cifsFileInfo **ret_file);
141+
int __cifs_get_writable_file(struct cifsInodeInfo *cifs_inode,
142+
unsigned int find_flags, unsigned int open_flags,
143+
struct cifsFileInfo **ret_file);
143144
int cifs_get_writable_path(struct cifs_tcon *tcon, const char *name, int flags,
144145
struct cifsFileInfo **ret_file);
145-
struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
146-
bool fsuid_only);
146+
struct cifsFileInfo *__find_readable_file(struct cifsInodeInfo *cifs_inode,
147+
unsigned int find_flags,
148+
unsigned int open_flags);
147149
int cifs_get_readable_path(struct cifs_tcon *tcon, const char *name,
148150
struct cifsFileInfo **ret_file);
149151
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,
596598
}
597599
}
598600

601+
static inline int cifs_get_writable_file(struct cifsInodeInfo *cifs_inode,
602+
unsigned int find_flags,
603+
struct cifsFileInfo **ret_file)
604+
{
605+
find_flags &= ~FIND_OPEN_FLAGS;
606+
return __cifs_get_writable_file(cifs_inode, find_flags, 0, ret_file);
607+
}
608+
609+
static inline struct cifsFileInfo *
610+
find_readable_file(struct cifsInodeInfo *cinode, unsigned int find_flags)
611+
{
612+
find_flags &= ~FIND_OPEN_FLAGS;
613+
find_flags |= FIND_NO_PENDING_DELETE;
614+
return __find_readable_file(cinode, find_flags, 0);
615+
}
616+
599617
#endif /* _CIFSPROTO_H */

fs/smb/client/dir.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
187187
const char *full_path;
188188
void *page = alloc_dentry_path();
189189
struct inode *newinode = NULL;
190-
unsigned int sbflags;
190+
unsigned int sbflags = cifs_sb_flags(cifs_sb);
191191
int disposition;
192192
struct TCP_Server_Info *server = tcon->ses->server;
193193
struct cifs_open_parms oparms;
@@ -308,6 +308,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
308308
goto out;
309309
}
310310

311+
create_options |= cifs_open_create_options(oflags, create_options);
311312
/*
312313
* if we're not using unix extensions, see if we need to set
313314
* ATTR_READONLY on the create call
@@ -367,7 +368,6 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
367368
* If Open reported that we actually created a file then we now have to
368369
* set the mode if possible.
369370
*/
370-
sbflags = cifs_sb_flags(cifs_sb);
371371
if ((tcon->unix_ext) && (*oplock & CIFS_CREATE_ACTION)) {
372372
struct cifs_unix_set_info_args args = {
373373
.mode = mode,

fs/smb/client/file.c

Lines changed: 70 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ static void cifs_begin_writeback(struct netfs_io_request *wreq)
255255
struct cifs_io_request *req = container_of(wreq, struct cifs_io_request, rreq);
256256
int ret;
257257

258-
ret = cifs_get_writable_file(CIFS_I(wreq->inode), FIND_WR_ANY, &req->cfile);
258+
ret = cifs_get_writable_file(CIFS_I(wreq->inode), FIND_ANY, &req->cfile);
259259
if (ret) {
260260
cifs_dbg(VFS, "No writable handle in writepages ret=%d\n", ret);
261261
return;
@@ -584,15 +584,8 @@ static int cifs_nt_open(const char *full_path, struct inode *inode, struct cifs_
584584
*********************************************************************/
585585

586586
disposition = cifs_get_disposition(f_flags);
587-
588587
/* BB pass O_SYNC flag through on file attributes .. BB */
589-
590-
/* O_SYNC also has bit for O_DSYNC so following check picks up either */
591-
if (f_flags & O_SYNC)
592-
create_options |= CREATE_WRITE_THROUGH;
593-
594-
if (f_flags & O_DIRECT)
595-
create_options |= CREATE_NO_BUFFER;
588+
create_options |= cifs_open_create_options(f_flags, create_options);
596589

597590
retry_open:
598591
oparms = (struct cifs_open_parms) {
@@ -963,7 +956,7 @@ int cifs_file_flush(const unsigned int xid, struct inode *inode,
963956
return tcon->ses->server->ops->flush(xid, tcon,
964957
&cfile->fid);
965958
}
966-
rc = cifs_get_writable_file(CIFS_I(inode), FIND_WR_ANY, &cfile);
959+
rc = cifs_get_writable_file(CIFS_I(inode), FIND_ANY, &cfile);
967960
if (!rc) {
968961
tcon = tlink_tcon(cfile->tlink);
969962
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)
988981
return -ERESTARTSYS;
989982
mapping_set_error(inode->i_mapping, rc);
990983

991-
cfile = find_writable_file(cinode, FIND_WR_FSUID_ONLY);
984+
cfile = find_writable_file(cinode, FIND_FSUID_ONLY);
992985
rc = cifs_file_flush(xid, inode, cfile);
993986
if (!rc) {
994987
if (cfile) {
@@ -1068,32 +1061,29 @@ int cifs_open(struct inode *inode, struct file *file)
10681061

10691062
/* Get the cached handle as SMB2 close is deferred */
10701063
if (OPEN_FMODE(file->f_flags) & FMODE_WRITE) {
1071-
rc = cifs_get_writable_path(tcon, full_path,
1072-
FIND_WR_FSUID_ONLY |
1073-
FIND_WR_NO_PENDING_DELETE,
1074-
&cfile);
1064+
rc = __cifs_get_writable_file(CIFS_I(inode),
1065+
FIND_FSUID_ONLY |
1066+
FIND_NO_PENDING_DELETE |
1067+
FIND_OPEN_FLAGS,
1068+
file->f_flags, &cfile);
10751069
} else {
1076-
rc = cifs_get_readable_path(tcon, full_path, &cfile);
1070+
cfile = __find_readable_file(CIFS_I(inode),
1071+
FIND_NO_PENDING_DELETE |
1072+
FIND_OPEN_FLAGS,
1073+
file->f_flags);
1074+
rc = cfile ? 0 : -ENOENT;
10771075
}
10781076
if (rc == 0) {
1079-
unsigned int oflags = file->f_flags & ~(O_CREAT|O_EXCL|O_TRUNC);
1080-
unsigned int cflags = cfile->f_flags & ~(O_CREAT|O_EXCL|O_TRUNC);
1081-
1082-
if (cifs_convert_flags(oflags, 0) == cifs_convert_flags(cflags, 0) &&
1083-
(oflags & (O_SYNC|O_DIRECT)) == (cflags & (O_SYNC|O_DIRECT))) {
1084-
file->private_data = cfile;
1085-
spin_lock(&CIFS_I(inode)->deferred_lock);
1086-
cifs_del_deferred_close(cfile);
1087-
spin_unlock(&CIFS_I(inode)->deferred_lock);
1088-
goto use_cache;
1089-
}
1090-
_cifsFileInfo_put(cfile, true, false);
1091-
} else {
1092-
/* hard link on the defeered close file */
1093-
rc = cifs_get_hardlink_path(tcon, inode, file);
1094-
if (rc)
1095-
cifs_close_deferred_file(CIFS_I(inode));
1096-
}
1077+
file->private_data = cfile;
1078+
spin_lock(&CIFS_I(inode)->deferred_lock);
1079+
cifs_del_deferred_close(cfile);
1080+
spin_unlock(&CIFS_I(inode)->deferred_lock);
1081+
goto use_cache;
1082+
}
1083+
/* hard link on the deferred close file */
1084+
rc = cifs_get_hardlink_path(tcon, inode, file);
1085+
if (rc)
1086+
cifs_close_deferred_file(CIFS_I(inode));
10971087

10981088
if (server->oplocks)
10991089
oplock = REQ_OPLOCK;
@@ -1314,13 +1304,8 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
13141304
rdwr_for_fscache = 1;
13151305

13161306
desired_access = cifs_convert_flags(cfile->f_flags, rdwr_for_fscache);
1317-
1318-
/* O_SYNC also has bit for O_DSYNC so following check picks up either */
1319-
if (cfile->f_flags & O_SYNC)
1320-
create_options |= CREATE_WRITE_THROUGH;
1321-
1322-
if (cfile->f_flags & O_DIRECT)
1323-
create_options |= CREATE_NO_BUFFER;
1307+
create_options |= cifs_open_create_options(cfile->f_flags,
1308+
create_options);
13241309

13251310
if (server->ops->get_lease_key)
13261311
server->ops->get_lease_key(inode, &cfile->fid);
@@ -2524,10 +2509,33 @@ void cifs_write_subrequest_terminated(struct cifs_io_subrequest *wdata, ssize_t
25242509
netfs_write_subrequest_terminated(&wdata->subreq, result);
25252510
}
25262511

2527-
struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
2528-
bool fsuid_only)
2512+
static bool open_flags_match(struct cifsInodeInfo *cinode,
2513+
unsigned int oflags, unsigned int cflags)
2514+
{
2515+
struct inode *inode = &cinode->netfs.inode;
2516+
int crw = 0, orw = 0;
2517+
2518+
oflags &= ~(O_CREAT | O_EXCL | O_TRUNC);
2519+
cflags &= ~(O_CREAT | O_EXCL | O_TRUNC);
2520+
2521+
if (cifs_fscache_enabled(inode)) {
2522+
if (OPEN_FMODE(cflags) & FMODE_WRITE)
2523+
crw = 1;
2524+
if (OPEN_FMODE(oflags) & FMODE_WRITE)
2525+
orw = 1;
2526+
}
2527+
if (cifs_convert_flags(oflags, orw) != cifs_convert_flags(cflags, crw))
2528+
return false;
2529+
2530+
return (oflags & (O_SYNC | O_DIRECT)) == (cflags & (O_SYNC | O_DIRECT));
2531+
}
2532+
2533+
struct cifsFileInfo *__find_readable_file(struct cifsInodeInfo *cifs_inode,
2534+
unsigned int find_flags,
2535+
unsigned int open_flags)
25292536
{
25302537
struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode);
2538+
bool fsuid_only = find_flags & FIND_FSUID_ONLY;
25312539
struct cifsFileInfo *open_file = NULL;
25322540

25332541
/* only filter by fsuid on multiuser mounts */
@@ -2541,6 +2549,13 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
25412549
list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
25422550
if (fsuid_only && !uid_eq(open_file->uid, current_fsuid()))
25432551
continue;
2552+
if ((find_flags & FIND_NO_PENDING_DELETE) &&
2553+
open_file->status_file_deleted)
2554+
continue;
2555+
if ((find_flags & FIND_OPEN_FLAGS) &&
2556+
!open_flags_match(cifs_inode, open_flags,
2557+
open_file->f_flags))
2558+
continue;
25442559
if (OPEN_FMODE(open_file->f_flags) & FMODE_READ) {
25452560
if ((!open_file->invalidHandle)) {
25462561
/* found a good file */
@@ -2559,17 +2574,17 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
25592574
}
25602575

25612576
/* Return -EBADF if no handle is found and general rc otherwise */
2562-
int
2563-
cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, int flags,
2564-
struct cifsFileInfo **ret_file)
2577+
int __cifs_get_writable_file(struct cifsInodeInfo *cifs_inode,
2578+
unsigned int find_flags, unsigned int open_flags,
2579+
struct cifsFileInfo **ret_file)
25652580
{
25662581
struct cifsFileInfo *open_file, *inv_file = NULL;
25672582
struct cifs_sb_info *cifs_sb;
25682583
bool any_available = false;
25692584
int rc = -EBADF;
25702585
unsigned int refind = 0;
2571-
bool fsuid_only = flags & FIND_WR_FSUID_ONLY;
2572-
bool with_delete = flags & FIND_WR_WITH_DELETE;
2586+
bool fsuid_only = find_flags & FIND_FSUID_ONLY;
2587+
bool with_delete = find_flags & FIND_WITH_DELETE;
25732588
*ret_file = NULL;
25742589

25752590
/*
@@ -2603,9 +2618,13 @@ cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, int flags,
26032618
continue;
26042619
if (with_delete && !(open_file->fid.access & DELETE))
26052620
continue;
2606-
if ((flags & FIND_WR_NO_PENDING_DELETE) &&
2621+
if ((find_flags & FIND_NO_PENDING_DELETE) &&
26072622
open_file->status_file_deleted)
26082623
continue;
2624+
if ((find_flags & FIND_OPEN_FLAGS) &&
2625+
!open_flags_match(cifs_inode, open_flags,
2626+
open_file->f_flags))
2627+
continue;
26092628
if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
26102629
if (!open_file->invalidHandle) {
26112630
/* found a good writable file */
@@ -2722,17 +2741,7 @@ cifs_get_readable_path(struct cifs_tcon *tcon, const char *name,
27222741
cinode = CIFS_I(d_inode(cfile->dentry));
27232742
spin_unlock(&tcon->open_file_lock);
27242743
free_dentry_path(page);
2725-
*ret_file = find_readable_file(cinode, 0);
2726-
if (*ret_file) {
2727-
spin_lock(&cinode->open_file_lock);
2728-
if ((*ret_file)->status_file_deleted) {
2729-
spin_unlock(&cinode->open_file_lock);
2730-
cifsFileInfo_put(*ret_file);
2731-
*ret_file = NULL;
2732-
} else {
2733-
spin_unlock(&cinode->open_file_lock);
2734-
}
2735-
}
2744+
*ret_file = find_readable_file(cinode, FIND_ANY);
27362745
return *ret_file ? 0 : -ENOENT;
27372746
}
27382747

@@ -2804,7 +2813,7 @@ int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
28042813
}
28052814

28062815
if ((OPEN_FMODE(smbfile->f_flags) & FMODE_WRITE) == 0) {
2807-
smbfile = find_writable_file(CIFS_I(inode), FIND_WR_ANY);
2816+
smbfile = find_writable_file(CIFS_I(inode), FIND_ANY);
28082817
if (smbfile) {
28092818
rc = server->ops->flush(xid, tcon, &smbfile->fid);
28102819
cifsFileInfo_put(smbfile);

fs/smb/client/fs_context.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1997,7 +1997,7 @@ int smb3_init_fs_context(struct fs_context *fc)
19971997
ctx->backupuid_specified = false; /* no backup intent for a user */
19981998
ctx->backupgid_specified = false; /* no backup intent for a group */
19991999

2000-
ctx->retrans = 1;
2000+
ctx->retrans = 0;
20012001
ctx->reparse_type = CIFS_REPARSE_TYPE_DEFAULT;
20022002
ctx->symlink_type = CIFS_SYMLINK_TYPE_DEFAULT;
20032003
ctx->nonativesocket = 0;

fs/smb/client/inode.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2997,7 +2997,7 @@ int cifs_fiemap(struct inode *inode, struct fiemap_extent_info *fei, u64 start,
29972997
}
29982998
}
29992999

3000-
cfile = find_readable_file(cifs_i, false);
3000+
cfile = find_readable_file(cifs_i, FIND_ANY);
30013001
if (cfile == NULL)
30023002
return -EINVAL;
30033003

@@ -3050,7 +3050,7 @@ int cifs_file_set_size(const unsigned int xid, struct dentry *dentry,
30503050
size, false);
30513051
cifs_dbg(FYI, "%s: set_file_size: rc = %d\n", __func__, rc);
30523052
} else {
3053-
open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY);
3053+
open_file = find_writable_file(cifsInode, FIND_FSUID_ONLY);
30543054
if (open_file) {
30553055
tcon = tlink_tcon(open_file->tlink);
30563056
server = tcon->ses->server;
@@ -3219,7 +3219,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
32193219
open_file->fid.netfid,
32203220
open_file->pid);
32213221
} else {
3222-
open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY);
3222+
open_file = find_writable_file(cifsInode, FIND_FSUID_ONLY);
32233223
if (open_file) {
32243224
pTcon = tlink_tcon(open_file->tlink);
32253225
rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args,

fs/smb/client/smb1ops.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -960,7 +960,7 @@ smb_set_file_info(struct inode *inode, const char *full_path,
960960
struct cifs_tcon *tcon;
961961

962962
/* if the file is already open for write, just use that fileid */
963-
open_file = find_writable_file(cinode, FIND_WR_FSUID_ONLY);
963+
open_file = find_writable_file(cinode, FIND_FSUID_ONLY);
964964

965965
if (open_file) {
966966
fid.netfid = open_file->fid.netfid;

0 commit comments

Comments
 (0)