Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
etercifs
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
etersoft
etercifs
Commits
7e23c0f8
Commit
7e23c0f8
authored
Jan 30, 2018
by
Vitaly Lipatov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
update 3.16 up to 3.16.53
parent
833e6356
Hide whitespace changes
Inline
Side-by-side
Showing
33 changed files
with
902 additions
and
346 deletions
+902
-346
Makefile
sources/3.16/Makefile
+7
-7
cifs_debug.c
sources/3.16/cifs_debug.c
+1
-0
cifs_fs_sb.h
sources/3.16/cifs_fs_sb.h
+4
-0
cifs_spnego.c
sources/3.16/cifs_spnego.c
+67
-0
cifsacl.c
sources/3.16/cifsacl.c
+0
-2
cifsencrypt.c
sources/3.16/cifsencrypt.c
+10
-6
cifsfs.c
sources/3.16/cifsfs.c
+29
-15
cifsglob.h
sources/3.16/cifsglob.h
+30
-24
cifspdu.h
sources/3.16/cifspdu.h
+0
-8
cifsproto.h
sources/3.16/cifsproto.h
+6
-1
cifssmb.c
sources/3.16/cifssmb.c
+10
-10
connect.c
sources/3.16/connect.c
+129
-19
dir.c
sources/3.16/dir.c
+53
-17
file.c
sources/3.16/file.c
+51
-39
inode.c
sources/3.16/inode.c
+26
-13
link.c
sources/3.16/link.c
+0
-2
misc.c
sources/3.16/misc.c
+9
-8
netmisc.c
sources/3.16/netmisc.c
+4
-4
ntlmssp.h
sources/3.16/ntlmssp.h
+1
-1
readdir.c
sources/3.16/readdir.c
+4
-4
sess.c
sources/3.16/sess.c
+118
-92
smb1ops.c
sources/3.16/smb1ops.c
+17
-5
smb2file.c
sources/3.16/smb2file.c
+1
-1
smb2glob.h
sources/3.16/smb2glob.h
+11
-0
smb2inode.c
sources/3.16/smb2inode.c
+12
-3
smb2maperror.c
sources/3.16/smb2maperror.c
+1
-1
smb2misc.c
sources/3.16/smb2misc.c
+55
-10
smb2ops.c
sources/3.16/smb2ops.c
+37
-11
smb2pdu.c
sources/3.16/smb2pdu.c
+142
-34
smb2pdu.h
sources/3.16/smb2pdu.h
+3
-3
smb2proto.h
sources/3.16/smb2proto.h
+10
-0
smb2transport.c
sources/3.16/smb2transport.c
+52
-6
transport.c
sources/3.16/transport.c
+2
-0
No files found.
sources/3.16/Makefile
View file @
7e23c0f8
#
#
# Makefile for Linux CIFS VFS client
# Makefile for Linux CIFS VFS client
#
#
obj-$(CONFIG_CIFS)
+=
eter
cifs.o
obj-$(CONFIG_CIFS)
+=
cifs.o
eter
cifs-y
:=
cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o
\
cifs-y
:=
cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o
\
link.o misc.o netmisc.o smbencrypt.o transport.o asn1.o
\
link.o misc.o netmisc.o smbencrypt.o transport.o asn1.o
\
cifs_unicode.o nterr.o xattr.o cifsencrypt.o
\
cifs_unicode.o nterr.o xattr.o cifsencrypt.o
\
readdir.o ioctl.o sess.o export.o smb1ops.o winucase.o
readdir.o ioctl.o sess.o export.o smb1ops.o winucase.o
eter
cifs-$(CONFIG_CIFS_ACL)
+=
cifsacl.o
cifs-$(CONFIG_CIFS_ACL)
+=
cifsacl.o
eter
cifs-$(CONFIG_CIFS_UPCALL)
+=
cifs_spnego.o
cifs-$(CONFIG_CIFS_UPCALL)
+=
cifs_spnego.o
eter
cifs-$(CONFIG_CIFS_DFS_UPCALL)
+=
dns_resolve.o
cifs_dfs_ref.o
cifs-$(CONFIG_CIFS_DFS_UPCALL)
+=
dns_resolve.o
cifs_dfs_ref.o
eter
cifs-$(CONFIG_CIFS_FSCACHE)
+=
fscache.o
cache.o
cifs-$(CONFIG_CIFS_FSCACHE)
+=
fscache.o
cache.o
eter
cifs-$(CONFIG_CIFS_SMB2)
+=
smb2ops.o
smb2maperror.o
smb2transport.o
\
cifs-$(CONFIG_CIFS_SMB2)
+=
smb2ops.o
smb2maperror.o
smb2transport.o
\
smb2misc.o
smb2pdu.o
smb2inode.o
smb2file.o
smb2misc.o
smb2pdu.o
smb2inode.o
smb2file.o
sources/3.16/cifs_debug.c
View file @
7e23c0f8
...
@@ -170,6 +170,7 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
...
@@ -170,6 +170,7 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
list_for_each
(
tmp1
,
&
cifs_tcp_ses_list
)
{
list_for_each
(
tmp1
,
&
cifs_tcp_ses_list
)
{
server
=
list_entry
(
tmp1
,
struct
TCP_Server_Info
,
server
=
list_entry
(
tmp1
,
struct
TCP_Server_Info
,
tcp_ses_list
);
tcp_ses_list
);
seq_printf
(
m
,
"
\n
Number of credits: %d"
,
server
->
credits
);
i
++
;
i
++
;
list_for_each
(
tmp2
,
&
server
->
smb_ses_list
)
{
list_for_each
(
tmp2
,
&
server
->
smb_ses_list
)
{
ses
=
list_entry
(
tmp2
,
struct
cifs_ses
,
ses
=
list_entry
(
tmp2
,
struct
cifs_ses
,
...
...
sources/3.16/cifs_fs_sb.h
View file @
7e23c0f8
...
@@ -45,6 +45,9 @@
...
@@ -45,6 +45,9 @@
#define CIFS_MOUNT_POSIXACL 0x100000
/* mirror of MS_POSIXACL in mnt_cifs_flags */
#define CIFS_MOUNT_POSIXACL 0x100000
/* mirror of MS_POSIXACL in mnt_cifs_flags */
#define CIFS_MOUNT_CIFS_BACKUPUID 0x200000
/* backup intent bit for a user */
#define CIFS_MOUNT_CIFS_BACKUPUID 0x200000
/* backup intent bit for a user */
#define CIFS_MOUNT_CIFS_BACKUPGID 0x400000
/* backup intent bit for a group */
#define CIFS_MOUNT_CIFS_BACKUPGID 0x400000
/* backup intent bit for a group */
#define CIFS_MOUNT_USE_PREFIX_PATH 0x1000000
/* make subpath with unaccessible
* root mountable
*/
struct
cifs_sb_info
{
struct
cifs_sb_info
{
struct
rb_root
tlink_tree
;
struct
rb_root
tlink_tree
;
...
@@ -66,5 +69,6 @@ struct cifs_sb_info {
...
@@ -66,5 +69,6 @@ struct cifs_sb_info {
struct
backing_dev_info
bdi
;
struct
backing_dev_info
bdi
;
struct
delayed_work
prune_tlinks
;
struct
delayed_work
prune_tlinks
;
struct
rcu_head
rcu
;
struct
rcu_head
rcu
;
char
*
prepath
;
};
};
#endif
/* _CIFS_FS_SB_H */
#endif
/* _CIFS_FS_SB_H */
sources/3.16/cifs_spnego.c
View file @
7e23c0f8
...
@@ -24,10 +24,13 @@
...
@@ -24,10 +24,13 @@
#include <linux/string.h>
#include <linux/string.h>
#include <keys/user-type.h>
#include <keys/user-type.h>
#include <linux/key-type.h>
#include <linux/key-type.h>
#include <linux/keyctl.h>
#include <linux/inet.h>
#include <linux/inet.h>
#include "cifsglob.h"
#include "cifsglob.h"
#include "cifs_spnego.h"
#include "cifs_spnego.h"
#include "cifs_debug.h"
#include "cifs_debug.h"
#include "cifsproto.h"
static
const
struct
cred
*
spnego_cred
;
/* create a new cifs key */
/* create a new cifs key */
static
int
static
int
...
@@ -103,6 +106,7 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo)
...
@@ -103,6 +106,7 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo)
size_t
desc_len
;
size_t
desc_len
;
struct
key
*
spnego_key
;
struct
key
*
spnego_key
;
const
char
*
hostname
=
server
->
hostname
;
const
char
*
hostname
=
server
->
hostname
;
const
struct
cred
*
saved_cred
;
/* length of fields (with semicolons): ver=0xyz ip4=ipaddress
/* length of fields (with semicolons): ver=0xyz ip4=ipaddress
host=hostname sec=mechanism uid=0xFF user=username */
host=hostname sec=mechanism uid=0xFF user=username */
...
@@ -164,7 +168,9 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo)
...
@@ -164,7 +168,9 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo)
sprintf
(
dp
,
";pid=0x%x"
,
current
->
pid
);
sprintf
(
dp
,
";pid=0x%x"
,
current
->
pid
);
cifs_dbg
(
FYI
,
"key description = %s
\n
"
,
description
);
cifs_dbg
(
FYI
,
"key description = %s
\n
"
,
description
);
saved_cred
=
override_creds
(
spnego_cred
);
spnego_key
=
request_key
(
&
cifs_spnego_key_type
,
description
,
""
);
spnego_key
=
request_key
(
&
cifs_spnego_key_type
,
description
,
""
);
revert_creds
(
saved_cred
);
#ifdef CONFIG_CIFS_DEBUG2
#ifdef CONFIG_CIFS_DEBUG2
if
(
cifsFYI
&&
!
IS_ERR
(
spnego_key
))
{
if
(
cifsFYI
&&
!
IS_ERR
(
spnego_key
))
{
...
@@ -178,3 +184,64 @@ out:
...
@@ -178,3 +184,64 @@ out:
kfree
(
description
);
kfree
(
description
);
return
spnego_key
;
return
spnego_key
;
}
}
int
init_cifs_spnego
(
void
)
{
struct
cred
*
cred
;
struct
key
*
keyring
;
int
ret
;
cifs_dbg
(
FYI
,
"Registering the %s key type
\n
"
,
cifs_spnego_key_type
.
name
);
/*
* Create an override credential set with special thread keyring for
* spnego upcalls.
*/
cred
=
prepare_kernel_cred
(
NULL
);
if
(
!
cred
)
return
-
ENOMEM
;
keyring
=
keyring_alloc
(
".cifs_spnego"
,
GLOBAL_ROOT_UID
,
GLOBAL_ROOT_GID
,
cred
,
(
KEY_POS_ALL
&
~
KEY_POS_SETATTR
)
|
KEY_USR_VIEW
|
KEY_USR_READ
,
KEY_ALLOC_NOT_IN_QUOTA
,
NULL
);
if
(
IS_ERR
(
keyring
))
{
ret
=
PTR_ERR
(
keyring
);
goto
failed_put_cred
;
}
ret
=
register_key_type
(
&
cifs_spnego_key_type
);
if
(
ret
<
0
)
goto
failed_put_key
;
/*
* instruct request_key() to use this special keyring as a cache for
* the results it looks up
*/
set_bit
(
KEY_FLAG_ROOT_CAN_CLEAR
,
&
keyring
->
flags
);
cred
->
thread_keyring
=
keyring
;
cred
->
jit_keyring
=
KEY_REQKEY_DEFL_THREAD_KEYRING
;
spnego_cred
=
cred
;
cifs_dbg
(
FYI
,
"cifs spnego keyring: %d
\n
"
,
key_serial
(
keyring
));
return
0
;
failed_put_key:
key_put
(
keyring
);
failed_put_cred:
put_cred
(
cred
);
return
ret
;
}
void
exit_cifs_spnego
(
void
)
{
key_revoke
(
spnego_cred
->
thread_keyring
);
unregister_key_type
(
&
cifs_spnego_key_type
);
put_cred
(
spnego_cred
);
cifs_dbg
(
FYI
,
"Unregistered %s key type
\n
"
,
cifs_spnego_key_type
.
name
);
}
sources/3.16/cifsacl.c
View file @
7e23c0f8
...
@@ -913,7 +913,6 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
...
@@ -913,7 +913,6 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
oparms
.
tcon
=
tcon
;
oparms
.
tcon
=
tcon
;
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
desired_access
=
READ_CONTROL
;
oparms
.
desired_access
=
READ_CONTROL
;
oparms
.
share_access
=
FILE_SHARE_ALL
;
oparms
.
create_options
=
create_options
;
oparms
.
create_options
=
create_options
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
path
=
path
;
oparms
.
path
=
path
;
...
@@ -983,7 +982,6 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
...
@@ -983,7 +982,6 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
oparms
.
tcon
=
tcon
;
oparms
.
tcon
=
tcon
;
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
desired_access
=
access_flags
;
oparms
.
desired_access
=
access_flags
;
oparms
.
share_access
=
FILE_SHARE_ALL
;
oparms
.
create_options
=
create_options
;
oparms
.
create_options
=
create_options
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
path
=
path
;
oparms
.
path
=
path
;
...
...
sources/3.16/cifsencrypt.c
View file @
7e23c0f8
...
@@ -727,24 +727,26 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
...
@@ -727,24 +727,26 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
memcpy
(
ses
->
auth_key
.
response
+
baselen
,
tiblob
,
tilen
);
memcpy
(
ses
->
auth_key
.
response
+
baselen
,
tiblob
,
tilen
);
mutex_lock
(
&
ses
->
server
->
srv_mutex
);
rc
=
crypto_hmacmd5_alloc
(
ses
->
server
);
rc
=
crypto_hmacmd5_alloc
(
ses
->
server
);
if
(
rc
)
{
if
(
rc
)
{
cifs_dbg
(
VFS
,
"could not crypto alloc hmacmd5 rc %d
\n
"
,
rc
);
cifs_dbg
(
VFS
,
"could not crypto alloc hmacmd5 rc %d
\n
"
,
rc
);
goto
setup_ntlmv2_rsp_ret
;
goto
unlock
;
}
}
/* calculate ntlmv2_hash */
/* calculate ntlmv2_hash */
rc
=
calc_ntlmv2_hash
(
ses
,
ntlmv2_hash
,
nls_cp
);
rc
=
calc_ntlmv2_hash
(
ses
,
ntlmv2_hash
,
nls_cp
);
if
(
rc
)
{
if
(
rc
)
{
cifs_dbg
(
VFS
,
"could not get v2 hash rc %d
\n
"
,
rc
);
cifs_dbg
(
VFS
,
"could not get v2 hash rc %d
\n
"
,
rc
);
goto
setup_ntlmv2_rsp_ret
;
goto
unlock
;
}
}
/* calculate first part of the client response (CR1) */
/* calculate first part of the client response (CR1) */
rc
=
CalcNTLMv2_response
(
ses
,
ntlmv2_hash
);
rc
=
CalcNTLMv2_response
(
ses
,
ntlmv2_hash
);
if
(
rc
)
{
if
(
rc
)
{
cifs_dbg
(
VFS
,
"Could not calculate CR1 rc: %d
\n
"
,
rc
);
cifs_dbg
(
VFS
,
"Could not calculate CR1 rc: %d
\n
"
,
rc
);
goto
setup_ntlmv2_rsp_ret
;
goto
unlock
;
}
}
/* now calculate the session key for NTLMv2 */
/* now calculate the session key for NTLMv2 */
...
@@ -753,13 +755,13 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
...
@@ -753,13 +755,13 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
if
(
rc
)
{
if
(
rc
)
{
cifs_dbg
(
VFS
,
"%s: Could not set NTLMV2 Hash as a key
\n
"
,
cifs_dbg
(
VFS
,
"%s: Could not set NTLMV2 Hash as a key
\n
"
,
__func__
);
__func__
);
goto
setup_ntlmv2_rsp_ret
;
goto
unlock
;
}
}
rc
=
crypto_shash_init
(
&
ses
->
server
->
secmech
.
sdeschmacmd5
->
shash
);
rc
=
crypto_shash_init
(
&
ses
->
server
->
secmech
.
sdeschmacmd5
->
shash
);
if
(
rc
)
{
if
(
rc
)
{
cifs_dbg
(
VFS
,
"%s: Could not init hmacmd5
\n
"
,
__func__
);
cifs_dbg
(
VFS
,
"%s: Could not init hmacmd5
\n
"
,
__func__
);
goto
setup_ntlmv2_rsp_ret
;
goto
unlock
;
}
}
rc
=
crypto_shash_update
(
&
ses
->
server
->
secmech
.
sdeschmacmd5
->
shash
,
rc
=
crypto_shash_update
(
&
ses
->
server
->
secmech
.
sdeschmacmd5
->
shash
,
...
@@ -767,7 +769,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
...
@@ -767,7 +769,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
CIFS_HMAC_MD5_HASH_SIZE
);
CIFS_HMAC_MD5_HASH_SIZE
);
if
(
rc
)
{
if
(
rc
)
{
cifs_dbg
(
VFS
,
"%s: Could not update with response
\n
"
,
__func__
);
cifs_dbg
(
VFS
,
"%s: Could not update with response
\n
"
,
__func__
);
goto
setup_ntlmv2_rsp_ret
;
goto
unlock
;
}
}
rc
=
crypto_shash_final
(
&
ses
->
server
->
secmech
.
sdeschmacmd5
->
shash
,
rc
=
crypto_shash_final
(
&
ses
->
server
->
secmech
.
sdeschmacmd5
->
shash
,
...
@@ -775,6 +777,8 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
...
@@ -775,6 +777,8 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
if
(
rc
)
if
(
rc
)
cifs_dbg
(
VFS
,
"%s: Could not generate md5 hash
\n
"
,
__func__
);
cifs_dbg
(
VFS
,
"%s: Could not generate md5 hash
\n
"
,
__func__
);
unlock:
mutex_unlock
(
&
ses
->
server
->
srv_mutex
);
setup_ntlmv2_rsp_ret:
setup_ntlmv2_rsp_ret:
kfree
(
tiblob
);
kfree
(
tiblob
);
...
...
sources/3.16/cifsfs.c
View file @
7e23c0f8
...
@@ -86,6 +86,7 @@ extern mempool_t *cifs_req_poolp;
...
@@ -86,6 +86,7 @@ extern mempool_t *cifs_req_poolp;
extern
mempool_t
*
cifs_mid_poolp
;
extern
mempool_t
*
cifs_mid_poolp
;
struct
workqueue_struct
*
cifsiod_wq
;
struct
workqueue_struct
*
cifsiod_wq
;
struct
workqueue_struct
*
cifsoplockd_wq
;
/*
/*
* Bumps refcount for cifs super block.
* Bumps refcount for cifs super block.
...
@@ -256,7 +257,7 @@ cifs_alloc_inode(struct super_block *sb)
...
@@ -256,7 +257,7 @@ cifs_alloc_inode(struct super_block *sb)
cifs_inode
->
createtime
=
0
;
cifs_inode
->
createtime
=
0
;
cifs_inode
->
epoch
=
0
;
cifs_inode
->
epoch
=
0
;
#ifdef CONFIG_CIFS_SMB2
#ifdef CONFIG_CIFS_SMB2
ge
t_random_bytes
(
cifs_inode
->
lease_key
,
SMB2_LEASE_KEY_SIZE
);
ge
nerate_random_uuid
(
cifs_inode
->
lease_key
);
#endif
#endif
/*
/*
* Can not set i_flags here - they get immediately overwritten to zero
* Can not set i_flags here - they get immediately overwritten to zero
...
@@ -471,9 +472,6 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
...
@@ -471,9 +472,6 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
seq_puts
(
s
,
",mfsymlinks"
);
seq_puts
(
s
,
",mfsymlinks"
);
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_FSCACHE
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_FSCACHE
)
seq_puts
(
s
,
",fsc"
);
seq_puts
(
s
,
",fsc"
);
if
((
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_STRICT_IO
)
&&
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NOPOSIXBRL
))
seq_puts
(
s
,
",wine"
);
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NOSSYNC
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NOSSYNC
)
seq_puts
(
s
,
",nostrictsync"
);
seq_puts
(
s
,
",nostrictsync"
);
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NO_PERM
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NO_PERM
)
...
@@ -586,6 +584,9 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
...
@@ -586,6 +584,9 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
char
*
s
,
*
p
;
char
*
s
,
*
p
;
char
sep
;
char
sep
;
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_USE_PREFIX_PATH
)
return
dget
(
sb
->
s_root
);
full_path
=
cifs_build_path_to_root
(
vol
,
cifs_sb
,
full_path
=
cifs_build_path_to_root
(
vol
,
cifs_sb
,
cifs_sb_master_tcon
(
cifs_sb
));
cifs_sb_master_tcon
(
cifs_sb
));
if
(
full_path
==
NULL
)
if
(
full_path
==
NULL
)
...
@@ -665,10 +666,14 @@ cifs_do_mount(struct file_system_type *fs_type,
...
@@ -665,10 +666,14 @@ cifs_do_mount(struct file_system_type *fs_type,
cifs_sb
->
mountdata
=
kstrndup
(
data
,
PAGE_SIZE
,
GFP_KERNEL
);
cifs_sb
->
mountdata
=
kstrndup
(
data
,
PAGE_SIZE
,
GFP_KERNEL
);
if
(
cifs_sb
->
mountdata
==
NULL
)
{
if
(
cifs_sb
->
mountdata
==
NULL
)
{
root
=
ERR_PTR
(
-
ENOMEM
);
root
=
ERR_PTR
(
-
ENOMEM
);
goto
out_
cifs_sb
;
goto
out_
free
;
}
}
cifs_setup_cifs_sb
(
volume_info
,
cifs_sb
);
rc
=
cifs_setup_cifs_sb
(
volume_info
,
cifs_sb
);
if
(
rc
)
{
root
=
ERR_PTR
(
rc
);
goto
out_free
;
}
rc
=
cifs_mount
(
cifs_sb
,
volume_info
);
rc
=
cifs_mount
(
cifs_sb
,
volume_info
);
if
(
rc
)
{
if
(
rc
)
{
...
@@ -676,7 +681,7 @@ cifs_do_mount(struct file_system_type *fs_type,
...
@@ -676,7 +681,7 @@ cifs_do_mount(struct file_system_type *fs_type,
cifs_dbg
(
VFS
,
"cifs_mount failed w/return code = %d
\n
"
,
cifs_dbg
(
VFS
,
"cifs_mount failed w/return code = %d
\n
"
,
rc
);
rc
);
root
=
ERR_PTR
(
rc
);
root
=
ERR_PTR
(
rc
);
goto
out_
mountdata
;
goto
out_
free
;
}
}
mnt_data
.
vol
=
volume_info
;
mnt_data
.
vol
=
volume_info
;
...
@@ -719,9 +724,9 @@ out:
...
@@ -719,9 +724,9 @@ out:
cifs_cleanup_volume_info
(
volume_info
);
cifs_cleanup_volume_info
(
volume_info
);
return
root
;
return
root
;
out_mountdata:
out_free:
kfree
(
cifs_sb
->
prepath
);
kfree
(
cifs_sb
->
mountdata
);
kfree
(
cifs_sb
->
mountdata
);
out_cifs_sb:
kfree
(
cifs_sb
);
kfree
(
cifs_sb
);
out_nls:
out_nls:
unload_nls
(
volume_info
->
local_nls
);
unload_nls
(
volume_info
->
local_nls
);
...
@@ -1196,7 +1201,6 @@ init_cifs(void)
...
@@ -1196,7 +1201,6 @@ init_cifs(void)
GlobalTotalActiveXid
=
0
;
GlobalTotalActiveXid
=
0
;
GlobalMaxActiveXid
=
0
;
GlobalMaxActiveXid
=
0
;
spin_lock_init
(
&
cifs_tcp_ses_lock
);
spin_lock_init
(
&
cifs_tcp_ses_lock
);
spin_lock_init
(
&
cifs_file_list_lock
);
spin_lock_init
(
&
GlobalMid_Lock
);
spin_lock_init
(
&
GlobalMid_Lock
);
if
(
cifs_max_pending
<
2
)
{
if
(
cifs_max_pending
<
2
)
{
...
@@ -1214,9 +1218,16 @@ init_cifs(void)
...
@@ -1214,9 +1218,16 @@ init_cifs(void)
goto
out_clean_proc
;
goto
out_clean_proc
;
}
}
cifsoplockd_wq
=
alloc_workqueue
(
"cifsoplockd"
,
WQ_FREEZABLE
|
WQ_MEM_RECLAIM
,
0
);
if
(
!
cifsoplockd_wq
)
{
rc
=
-
ENOMEM
;
goto
out_destroy_cifsiod_wq
;
}
rc
=
cifs_fscache_register
();
rc
=
cifs_fscache_register
();
if
(
rc
)
if
(
rc
)
goto
out_destroy_wq
;
goto
out_destroy_
cifsoplockd_
wq
;
rc
=
cifs_init_inodecache
();
rc
=
cifs_init_inodecache
();
if
(
rc
)
if
(
rc
)
...
@@ -1231,7 +1242,7 @@ init_cifs(void)
...
@@ -1231,7 +1242,7 @@ init_cifs(void)
goto
out_destroy_mids
;
goto
out_destroy_mids
;
#ifdef CONFIG_CIFS_UPCALL
#ifdef CONFIG_CIFS_UPCALL
rc
=
register_key_type
(
&
cifs_spnego_key_type
);
rc
=
init_cifs_spnego
(
);
if
(
rc
)
if
(
rc
)
goto
out_destroy_request_bufs
;
goto
out_destroy_request_bufs
;
#endif
/* CONFIG_CIFS_UPCALL */
#endif
/* CONFIG_CIFS_UPCALL */
...
@@ -1254,7 +1265,7 @@ out_init_cifs_idmap:
...
@@ -1254,7 +1265,7 @@ out_init_cifs_idmap:
out_register_key_type:
out_register_key_type:
#endif
#endif
#ifdef CONFIG_CIFS_UPCALL
#ifdef CONFIG_CIFS_UPCALL
unregister_key_type
(
&
cifs_spnego_key_type
);
exit_cifs_spnego
(
);
out_destroy_request_bufs:
out_destroy_request_bufs:
#endif
#endif
cifs_destroy_request_bufs
();
cifs_destroy_request_bufs
();
...
@@ -1264,7 +1275,9 @@ out_destroy_inodecache:
...
@@ -1264,7 +1275,9 @@ out_destroy_inodecache:
cifs_destroy_inodecache
();
cifs_destroy_inodecache
();
out_unreg_fscache:
out_unreg_fscache:
cifs_fscache_unregister
();
cifs_fscache_unregister
();
out_destroy_wq:
out_destroy_cifsoplockd_wq:
destroy_workqueue
(
cifsoplockd_wq
);
out_destroy_cifsiod_wq:
destroy_workqueue
(
cifsiod_wq
);
destroy_workqueue
(
cifsiod_wq
);
out_clean_proc:
out_clean_proc:
cifs_proc_clean
();
cifs_proc_clean
();
...
@@ -1281,12 +1294,13 @@ exit_cifs(void)
...
@@ -1281,12 +1294,13 @@ exit_cifs(void)
exit_cifs_idmap
();
exit_cifs_idmap
();
#endif
#endif
#ifdef CONFIG_CIFS_UPCALL
#ifdef CONFIG_CIFS_UPCALL
unregister_key_type
(
&
cifs_spnego_key_type
);
exit_cifs_spnego
(
);
#endif
#endif
cifs_destroy_request_bufs
();
cifs_destroy_request_bufs
();
cifs_destroy_mids
();
cifs_destroy_mids
();
cifs_destroy_inodecache
();
cifs_destroy_inodecache
();
cifs_fscache_unregister
();
cifs_fscache_unregister
();
destroy_workqueue
(
cifsoplockd_wq
);
destroy_workqueue
(
cifsiod_wq
);
destroy_workqueue
(
cifsiod_wq
);
cifs_proc_clean
();
cifs_proc_clean
();
}
}
...
...
sources/3.16/cifsglob.h
View file @
7e23c0f8
...
@@ -223,6 +223,7 @@ struct smb_version_operations {
...
@@ -223,6 +223,7 @@ struct smb_version_operations {
/* verify the message */
/* verify the message */
int
(
*
check_message
)(
char
*
,
unsigned
int
);
int
(
*
check_message
)(
char
*
,
unsigned
int
);
bool
(
*
is_oplock_break
)(
char
*
,
struct
TCP_Server_Info
*
);
bool
(
*
is_oplock_break
)(
char
*
,
struct
TCP_Server_Info
*
);
int
(
*
handle_cancelled_mid
)(
char
*
,
struct
TCP_Server_Info
*
);
void
(
*
downgrade_oplock
)(
struct
TCP_Server_Info
*
,
void
(
*
downgrade_oplock
)(
struct
TCP_Server_Info
*
,
struct
cifsInodeInfo
*
,
bool
);
struct
cifsInodeInfo
*
,
bool
);
/* process transaction2 response */
/* process transaction2 response */
...
@@ -606,6 +607,8 @@ struct TCP_Server_Info {
...
@@ -606,6 +607,8 @@ struct TCP_Server_Info {
#ifdef CONFIG_CIFS_SMB2
#ifdef CONFIG_CIFS_SMB2
unsigned
int
max_read
;
unsigned
int
max_read
;
unsigned
int
max_write
;
unsigned
int
max_write
;
struct
delayed_work
reconnect
;
/* reconnect workqueue job */
struct
mutex
reconnect_mutex
;
/* prevent simultaneous reconnects */
#endif
/* CONFIG_CIFS_SMB2 */
#endif
/* CONFIG_CIFS_SMB2 */
};
};
...
@@ -795,7 +798,9 @@ cap_unix(struct cifs_ses *ses)
...
@@ -795,7 +798,9 @@ cap_unix(struct cifs_ses *ses)
struct
cifs_tcon
{
struct
cifs_tcon
{
struct
list_head
tcon_list
;
struct
list_head
tcon_list
;
int
tc_count
;
int
tc_count
;
struct
list_head
rlist
;
/* reconnect list */
struct
list_head
openFileList
;
struct
list_head
openFileList
;
spinlock_t
open_file_lock
;
/* protects list above */
struct
cifs_ses
*
ses
;
/* pointer to session associated with */
struct
cifs_ses
*
ses
;
/* pointer to session associated with */
char
treeName
[
MAX_TREE_SIZE
+
1
];
/* UNC name of resource in ASCII */
char
treeName
[
MAX_TREE_SIZE
+
1
];
/* UNC name of resource in ASCII */
char
*
nativeFileSystem
;
char
*
nativeFileSystem
;
...
@@ -852,7 +857,7 @@ struct cifs_tcon {
...
@@ -852,7 +857,7 @@ struct cifs_tcon {
#endif
/* CONFIG_CIFS_STATS2 */
#endif
/* CONFIG_CIFS_STATS2 */
__u64
bytes_read
;
__u64
bytes_read
;
__u64
bytes_written
;
__u64
bytes_written
;
spinlock_t
stat_lock
;
spinlock_t
stat_lock
;
/* protects the two fields above */
#endif
/* CONFIG_CIFS_STATS */
#endif
/* CONFIG_CIFS_STATS */
FILE_SYSTEM_DEVICE_INFO
fsDevInfo
;
FILE_SYSTEM_DEVICE_INFO
fsDevInfo
;
FILE_SYSTEM_ATTRIBUTE_INFO
fsAttrInfo
;
/* ok if fs name truncated */
FILE_SYSTEM_ATTRIBUTE_INFO
fsAttrInfo
;
/* ok if fs name truncated */
...
@@ -868,7 +873,6 @@ struct cifs_tcon {
...
@@ -868,7 +873,6 @@ struct cifs_tcon {
bool
need_reconnect
:
1
;
/* connection reset, tid now invalid */
bool
need_reconnect
:
1
;
/* connection reset, tid now invalid */
#ifdef CONFIG_CIFS_SMB2
#ifdef CONFIG_CIFS_SMB2
bool
print
:
1
;
/* set if connection to printer share */
bool
print
:
1
;
/* set if connection to printer share */
bool
bad_network_name
:
1
;
/* set if ret status STATUS_BAD_NETWORK_NAME */
__le32
capabilities
;
__le32
capabilities
;
__u32
share_flags
;
__u32
share_flags
;
__u32
maximal_access
;
__u32
maximal_access
;
...
@@ -974,7 +978,6 @@ struct cifs_open_parms {
...
@@ -974,7 +978,6 @@ struct cifs_open_parms {
struct
cifs_sb_info
*
cifs_sb
;
struct
cifs_sb_info
*
cifs_sb
;
int
disposition
;
int
disposition
;
int
desired_access
;
int
desired_access
;
int
share_access
;
int
create_options
;
int
create_options
;
const
char
*
path
;
const
char
*
path
;
struct
cifs_fid
*
fid
;
struct
cifs_fid
*
fid
;
...
@@ -1000,8 +1003,10 @@ struct cifs_fid_locks {
...
@@ -1000,8 +1003,10 @@ struct cifs_fid_locks {
};
};
struct
cifsFileInfo
{
struct
cifsFileInfo
{
/* following two lists are protected by tcon->open_file_lock */
struct
list_head
tlist
;
/* pointer to next fid owned by tcon */
struct
list_head
tlist
;
/* pointer to next fid owned by tcon */
struct
list_head
flist
;
/* next fid (file instance) for this inode */
struct
list_head
flist
;
/* next fid (file instance) for this inode */
/* lock list below protected by cifsi->lock_sem */
struct
cifs_fid_locks
*
llist
;
/* brlocks held by this fid */
struct
cifs_fid_locks
*
llist
;
/* brlocks held by this fid */
kuid_t
uid
;
/* allows finding which FileInfo structure */
kuid_t
uid
;
/* allows finding which FileInfo structure */
__u32
pid
;
/* process id who opened file */
__u32
pid
;
/* process id who opened file */
...
@@ -1009,23 +1014,17 @@ struct cifsFileInfo {
...
@@ -1009,23 +1014,17 @@ struct cifsFileInfo {
/* BB add lock scope info here if needed */
;
/* BB add lock scope info here if needed */
;
/* lock scope id (0 if none) */
/* lock scope id (0 if none) */
struct
dentry
*
dentry
;
struct
dentry
*
dentry
;
unsigned
int
f_flags
;
struct
tcon_link
*
tlink
;
struct
tcon_link
*
tlink
;
unsigned
int
f_flags
;
bool
invalidHandle
:
1
;
/* file closed via session abend */
bool
invalidHandle
:
1
;
/* file closed via session abend */
bool
oplock_break_cancelled
:
1
;
bool
oplock_break_cancelled
:
1
;
int
count
;
/* refcount protected by cifs_file_list_lock */
int
count
;
spinlock_t
file_info_lock
;
/* protects four flag/count fields above */
struct
mutex
fh_mutex
;
/* prevents reopen race after dead ses*/
struct
mutex
fh_mutex
;
/* prevents reopen race after dead ses*/
struct
cifs_search_info
srch_inf
;
struct
cifs_search_info
srch_inf
;
struct
work_struct
oplock_break
;
/* work for oplock breaks */
struct
work_struct
oplock_break
;
/* work for oplock breaks */
};
};
#define SHARE_FLAGS_SHIFT 28
static
inline
int
cifs_get_share_flags
(
unsigned
int
flags
)
{
return
(
~
(
flags
>>
SHARE_FLAGS_SHIFT
))
&
7
;
}
struct
cifs_io_parms
{
struct
cifs_io_parms
{
__u16
netfid
;
__u16
netfid
;
#ifdef CONFIG_CIFS_SMB2
#ifdef CONFIG_CIFS_SMB2
...
@@ -1084,7 +1083,7 @@ struct cifs_writedata {
...
@@ -1084,7 +1083,7 @@ struct cifs_writedata {
/*
/*
* Take a reference on the file private data. Must be called with
* Take a reference on the file private data. Must be called with
* c
ifs_file_list
_lock held.
* c
file->file_info
_lock held.
*/
*/
static
inline
void
static
inline
void
cifsFileInfo_get_locked
(
struct
cifsFileInfo
*
cifs_file
)
cifsFileInfo_get_locked
(
struct
cifsFileInfo
*
cifs_file
)
...
@@ -1247,12 +1246,19 @@ struct mid_q_entry {
...
@@ -1247,12 +1246,19 @@ struct mid_q_entry {
void
*
callback_data
;
/* general purpose pointer for callback */
void
*
callback_data
;
/* general purpose pointer for callback */
void
*
resp_buf
;
/* pointer to received SMB header */
void
*
resp_buf
;
/* pointer to received SMB header */
int
mid_state
;
/* wish this were enum but can not pass to wait_event */
int
mid_state
;
/* wish this were enum but can not pass to wait_event */
unsigned
int
mid_flags
;
__le16
command
;
/* smb command code */
__le16
command
;
/* smb command code */
bool
large_buf
:
1
;
/* if valid response, is pointer to large buf */
bool
large_buf
:
1
;
/* if valid response, is pointer to large buf */
bool
multiRsp
:
1
;
/* multiple trans2 responses for one request */
bool
multiRsp
:
1
;
/* multiple trans2 responses for one request */
bool
multiEnd
:
1
;
/* both received */
bool
multiEnd
:
1
;
/* both received */
};
};
struct
close_cancelled_open
{
struct
cifs_fid
fid
;
struct
cifs_tcon
*
tcon
;
struct
work_struct
work
;
};
/* Make code in transport.c a little cleaner by moving
/* Make code in transport.c a little cleaner by moving
update of optional stats into function below */
update of optional stats into function below */
#ifdef CONFIG_CIFS_STATS2
#ifdef CONFIG_CIFS_STATS2
...
@@ -1384,6 +1390,9 @@ static inline void free_dfs_info_array(struct dfs_info3_param *param,
...
@@ -1384,6 +1390,9 @@ static inline void free_dfs_info_array(struct dfs_info3_param *param,
#define MID_RESPONSE_MALFORMED 0x10
#define MID_RESPONSE_MALFORMED 0x10
#define MID_SHUTDOWN 0x20
#define MID_SHUTDOWN 0x20
/* Flags */
#define MID_WAIT_CANCELLED 1
/* Cancelled while waiting for response */
/* Types of response buffer returned from SendReceive2 */
/* Types of response buffer returned from SendReceive2 */
#define CIFS_NO_BUFFER 0
/* Response buffer not returned */
#define CIFS_NO_BUFFER 0
/* Response buffer not returned */
#define CIFS_SMALL_BUFFER 1
#define CIFS_SMALL_BUFFER 1
...
@@ -1471,8 +1480,10 @@ require use of the stronger protocol */
...
@@ -1471,8 +1480,10 @@ require use of the stronger protocol */
* GlobalMid_Lock protects:
* GlobalMid_Lock protects:
* list operations on pending_mid_q and oplockQ
* list operations on pending_mid_q and oplockQ
* updates to XID counters, multiplex id and SMB sequence numbers
* updates to XID counters, multiplex id and SMB sequence numbers
* cifs_file_list_lock protects:
* tcp_ses_lock protects:
* list operations on tcp and SMB session lists and tCon lists
* list operations on tcp and SMB session lists
* tcon->open_file_lock protects the list of open files hanging off the tcon
* cfile->file_info_lock protects counters and fields in cifs file struct
* f_owner.lock protects certain per file struct operations
* f_owner.lock protects certain per file struct operations
* mapping->page_lock protects certain per page operations
* mapping->page_lock protects certain per page operations
*
*
...
@@ -1504,18 +1515,12 @@ GLOBAL_EXTERN struct list_head cifs_tcp_ses_list;
...
@@ -1504,18 +1515,12 @@ GLOBAL_EXTERN struct list_head cifs_tcp_ses_list;
* tcp session, and the list of tcon's per smb session. It also protects
* tcp session, and the list of tcon's per smb session. It also protects
* the reference counters for the server, smb session, and tcon. Finally,
* the reference counters for the server, smb session, and tcon. Finally,
* changes to the tcon->tidStatus should be done while holding this lock.
* changes to the tcon->tidStatus should be done while holding this lock.
* generally the locks should be taken in order tcp_ses_lock before
* tcon->open_file_lock and that before file->file_info_lock since the
* structure order is cifs_socket-->cifs_ses-->cifs_tcon-->cifs_file
*/
*/
GLOBAL_EXTERN
spinlock_t
cifs_tcp_ses_lock
;
GLOBAL_EXTERN
spinlock_t
cifs_tcp_ses_lock
;
/*
* This lock protects the cifs_file->llist and cifs_file->flist
* list operations, and updates to some flags (cifs_file->invalidHandle)
* It will be moved to either use the tcon->stat_lock or equivalent later.
* If cifs_tcp_ses_lock and the lock below are both needed to be held, then
* the cifs_tcp_ses_lock must be grabbed first and released last.
*/
GLOBAL_EXTERN
spinlock_t
cifs_file_list_lock
;
#ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL
/* unused temporarily */
#ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL
/* unused temporarily */
/* Outstanding dir notify requests */
/* Outstanding dir notify requests */
GLOBAL_EXTERN
struct
list_head
GlobalDnotifyReqList
;
GLOBAL_EXTERN
struct
list_head
GlobalDnotifyReqList
;
...
@@ -1576,6 +1581,7 @@ void cifs_oplock_break(struct work_struct *work);
...
@@ -1576,6 +1581,7 @@ void cifs_oplock_break(struct work_struct *work);
extern
const
struct
slow_work_ops
cifs_oplock_break_ops
;
extern
const
struct
slow_work_ops
cifs_oplock_break_ops
;
extern
struct
workqueue_struct
*
cifsiod_wq
;
extern
struct
workqueue_struct
*
cifsiod_wq
;
extern
struct
workqueue_struct
*
cifsoplockd_wq
;
extern
mempool_t
*
cifs_mid_poolp
;
extern
mempool_t
*
cifs_mid_poolp
;
...
...
sources/3.16/cifspdu.h
View file @
7e23c0f8
...
@@ -22,14 +22,6 @@
...
@@ -22,14 +22,6 @@
#ifndef _CIFSPDU_H
#ifndef _CIFSPDU_H
#define _CIFSPDU_H
#define _CIFSPDU_H
#ifndef CONFIG_CIFS_XATTR
#define CONFIG_CIFS_XATTR
#endif
#ifndef CONFIG_CIFS_POSIX
#define CONFIG_CIFS_POSIX
#endif
#include <net/sock.h>
#include <net/sock.h>
#include <asm/unaligned.h>
#include <asm/unaligned.h>
#include "smbfsctl.h"
#include "smbfsctl.h"
...
...
sources/3.16/cifsproto.h
View file @
7e23c0f8
...
@@ -59,6 +59,8 @@ do { \
...
@@ -59,6 +59,8 @@ do { \
} while (0)
} while (0)
extern
int
init_cifs_idmap
(
void
);
extern
int
init_cifs_idmap
(
void
);
extern
void
exit_cifs_idmap
(
void
);
extern
void
exit_cifs_idmap
(
void
);
extern
int
init_cifs_spnego
(
void
);
extern
void
exit_cifs_spnego
(
void
);
extern
char
*
build_path_from_dentry
(
struct
dentry
*
);
extern
char
*
build_path_from_dentry
(
struct
dentry
*
);
extern
char
*
cifs_build_path_to_root
(
struct
smb_vol
*
vol
,
extern
char
*
cifs_build_path_to_root
(
struct
smb_vol
*
vol
,
struct
cifs_sb_info
*
cifs_sb
,
struct
cifs_sb_info
*
cifs_sb
,
...
@@ -181,7 +183,7 @@ extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
...
@@ -181,7 +183,7 @@ extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
extern
int
cifs_readv_from_socket
(
struct
TCP_Server_Info
*
server
,
extern
int
cifs_readv_from_socket
(
struct
TCP_Server_Info
*
server
,
struct
kvec
*
iov_orig
,
unsigned
int
nr_segs
,
struct
kvec
*
iov_orig
,
unsigned
int
nr_segs
,
unsigned
int
to_read
);
unsigned
int
to_read
);
extern
void
cifs_setup_cifs_sb
(
struct
smb_vol
*
pvolume_info
,
extern
int
cifs_setup_cifs_sb
(
struct
smb_vol
*
pvolume_info
,
struct
cifs_sb_info
*
cifs_sb
);
struct
cifs_sb_info
*
cifs_sb
);
extern
int
cifs_match_super
(
struct
super_block
*
,
void
*
);
extern
int
cifs_match_super
(
struct
super_block
*
,
void
*
);
extern
void
cifs_cleanup_volume_info
(
struct
smb_vol
*
pvolume_info
);
extern
void
cifs_cleanup_volume_info
(
struct
smb_vol
*
pvolume_info
);
...
@@ -201,6 +203,9 @@ extern void cifs_add_pending_open_locked(struct cifs_fid *fid,
...
@@ -201,6 +203,9 @@ extern void cifs_add_pending_open_locked(struct cifs_fid *fid,
struct
tcon_link
*
tlink
,
struct
tcon_link
*
tlink
,
struct
cifs_pending_open
*
open
);
struct
cifs_pending_open
*
open
);
extern
void
cifs_del_pending_open
(
struct
cifs_pending_open
*
open
);
extern
void
cifs_del_pending_open
(
struct
cifs_pending_open
*
open
);
extern
void
cifs_put_tcp_session
(
struct
TCP_Server_Info
*
server
,
int
from_reconnect
);
extern
void
cifs_put_tcon
(
struct
cifs_tcon
*
tcon
);
#if IS_ENABLED(CONFIG_CIFS_DFS_UPCALL)
#if IS_ENABLED(CONFIG_CIFS_DFS_UPCALL)
extern
void
cifs_dfs_release_automount_timer
(
void
);
extern
void
cifs_dfs_release_automount_timer
(
void
);
...
...
sources/3.16/cifssmb.c
View file @
7e23c0f8
...
@@ -98,13 +98,13 @@ cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
...
@@ -98,13 +98,13 @@ cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
struct
list_head
*
tmp1
;
struct
list_head
*
tmp1
;
/* list all files open on tree connection and mark them invalid */
/* list all files open on tree connection and mark them invalid */
spin_lock
(
&
cifs_file_list
_lock
);
spin_lock
(
&
tcon
->
open_file
_lock
);
list_for_each_safe
(
tmp
,
tmp1
,
&
tcon
->
openFileList
)
{
list_for_each_safe
(
tmp
,
tmp1
,
&
tcon
->
openFileList
)
{
open_file
=
list_entry
(
tmp
,
struct
cifsFileInfo
,
tlist
);
open_file
=
list_entry
(
tmp
,
struct
cifsFileInfo
,
tlist
);
open_file
->
invalidHandle
=
true
;
open_file
->
invalidHandle
=
true
;
open_file
->
oplock_break_cancelled
=
true
;
open_file
->
oplock_break_cancelled
=
true
;
}
}
spin_unlock
(
&
cifs_file_list
_lock
);
spin_unlock
(
&
tcon
->
open_file
_lock
);
/*
/*
* BB Add call to invalidate_inodes(sb) for all superblocks mounted
* BB Add call to invalidate_inodes(sb) for all superblocks mounted
* to this tcon.
* to this tcon.
...
@@ -720,6 +720,9 @@ CIFSSMBEcho(struct TCP_Server_Info *server)
...
@@ -720,6 +720,9 @@ CIFSSMBEcho(struct TCP_Server_Info *server)
if
(
rc
)
if
(
rc
)
return
rc
;
return
rc
;
if
(
server
->
capabilities
&
CAP_UNICODE
)
smb
->
hdr
.
Flags2
|=
SMBFLG2_UNICODE
;
/* set up echo request */
/* set up echo request */
smb
->
hdr
.
Tid
=
0xffff
;
smb
->
hdr
.
Tid
=
0xffff
;
smb
->
hdr
.
WordCount
=
1
;
smb
->
hdr
.
WordCount
=
1
;
...
@@ -1121,7 +1124,6 @@ psx_create_err:
...
@@ -1121,7 +1124,6 @@ psx_create_err:
return
rc
;
return
rc
;
}
}
#ifdef ETERSOFT_USE_SMB_LEGACY_OPEN
static
__u16
convert_disposition
(
int
disposition
)
static
__u16
convert_disposition
(
int
disposition
)
{
{
__u16
ofun
=
0
;
__u16
ofun
=
0
;
...
@@ -1165,7 +1167,6 @@ access_flags_to_smbopen_mode(const int access_flags)
...
@@ -1165,7 +1167,6 @@ access_flags_to_smbopen_mode(const int access_flags)
/* just go for read/write */
/* just go for read/write */
return
SMBOPEN_READWRITE
;
return
SMBOPEN_READWRITE
;
}
}
#endif
int
int
SMBLegacyOpen
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
SMBLegacyOpen
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
...
@@ -1174,10 +1175,6 @@ SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -1174,10 +1175,6 @@ SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
int
*
pOplock
,
FILE_ALL_INFO
*
pfile_info
,
int
*
pOplock
,
FILE_ALL_INFO
*
pfile_info
,
const
struct
nls_table
*
nls_codepage
,
int
remap
)
const
struct
nls_table
*
nls_codepage
,
int
remap
)
{
{
#ifndef ETERSOFT_USE_SMB_LEGACY_OPEN
printk
(
"Etersoft: Do not use SMBLegacyOpen!
\n
"
);
return
-
EACCES
;
#else
int
rc
=
-
EACCES
;
int
rc
=
-
EACCES
;
OPENX_REQ
*
pSMB
=
NULL
;
OPENX_REQ
*
pSMB
=
NULL
;
OPENX_RSP
*
pSMBr
=
NULL
;
OPENX_RSP
*
pSMBr
=
NULL
;
...
@@ -1276,7 +1273,6 @@ OldOpenRetry:
...
@@ -1276,7 +1273,6 @@ OldOpenRetry:
if
(
rc
==
-
EAGAIN
)
if
(
rc
==
-
EAGAIN
)
goto
OldOpenRetry
;
goto
OldOpenRetry
;
return
rc
;
return
rc
;
#endif
}
}
int
int
...
@@ -1354,7 +1350,7 @@ openRetry:
...
@@ -1354,7 +1350,7 @@ openRetry:
if
(
create_options
&
CREATE_OPTION_READONLY
)
if
(
create_options
&
CREATE_OPTION_READONLY
)
req
->
FileAttributes
|=
cpu_to_le32
(
ATTR_READONLY
);
req
->
FileAttributes
|=
cpu_to_le32
(
ATTR_READONLY
);
req
->
ShareAccess
=
cpu_to_le32
(
oparms
->
share_access
);
req
->
ShareAccess
=
cpu_to_le32
(
FILE_SHARE_ALL
);
req
->
CreateDisposition
=
cpu_to_le32
(
disposition
);
req
->
CreateDisposition
=
cpu_to_le32
(
disposition
);
req
->
CreateOptions
=
cpu_to_le32
(
create_options
&
CREATE_OPTIONS_MASK
);
req
->
CreateOptions
=
cpu_to_le32
(
create_options
&
CREATE_OPTIONS_MASK
);
...
@@ -1434,6 +1430,8 @@ cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
...
@@ -1434,6 +1430,8 @@ cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
length
=
discard_remaining_data
(
server
);
length
=
discard_remaining_data
(
server
);
dequeue_mid
(
mid
,
rdata
->
result
);
dequeue_mid
(
mid
,
rdata
->
result
);
mid
->
resp_buf
=
server
->
smallbuf
;
server
->
smallbuf
=
NULL
;
return
length
;
return
length
;
}
}
...
@@ -1549,6 +1547,8 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
...
@@ -1549,6 +1547,8 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
return
cifs_readv_discard
(
server
,
mid
);
return
cifs_readv_discard
(
server
,
mid
);
dequeue_mid
(
mid
,
false
);
dequeue_mid
(
mid
,
false
);
mid
->
resp_buf
=
server
->
smallbuf
;
server
->
smallbuf
=
NULL
;
return
length
;
return
length
;
}
}
...
...
sources/3.16/connect.c
View file @
7e23c0f8
...
@@ -52,6 +52,9 @@
...
@@ -52,6 +52,9 @@
#include "nterr.h"
#include "nterr.h"
#include "rfc1002pdu.h"
#include "rfc1002pdu.h"
#include "fscache.h"
#include "fscache.h"
#ifdef CONFIG_CIFS_SMB2
#include "smb2proto.h"
#endif
#define CIFS_PORT 445
#define CIFS_PORT 445
#define RFC1001_PORT 139
#define RFC1001_PORT 139
...
@@ -81,7 +84,7 @@ enum {
...
@@ -81,7 +84,7 @@ enum {
Opt_nointr
,
Opt_intr
,
Opt_nointr
,
Opt_intr
,
Opt_nostrictsync
,
Opt_strictsync
,
Opt_nostrictsync
,
Opt_strictsync
,
Opt_serverino
,
Opt_noserverino
,
Opt_serverino
,
Opt_noserverino
,
Opt_rwpidforward
,
Opt_
wine
,
Opt_
cifsacl
,
Opt_nocifsacl
,
Opt_rwpidforward
,
Opt_cifsacl
,
Opt_nocifsacl
,
Opt_acl
,
Opt_noacl
,
Opt_locallease
,
Opt_acl
,
Opt_noacl
,
Opt_locallease
,
Opt_sign
,
Opt_seal
,
Opt_noac
,
Opt_sign
,
Opt_seal
,
Opt_noac
,
Opt_fsc
,
Opt_mfsymlinks
,
Opt_fsc
,
Opt_mfsymlinks
,
...
@@ -153,7 +156,6 @@ static const match_table_t cifs_mount_option_tokens = {
...
@@ -153,7 +156,6 @@ static const match_table_t cifs_mount_option_tokens = {
{
Opt_serverino
,
"serverino"
},
{
Opt_serverino
,
"serverino"
},
{
Opt_noserverino
,
"noserverino"
},
{
Opt_noserverino
,
"noserverino"
},
{
Opt_rwpidforward
,
"rwpidforward"
},
{
Opt_rwpidforward
,
"rwpidforward"
},
{
Opt_wine
,
"wine"
},
{
Opt_cifsacl
,
"cifsacl"
},
{
Opt_cifsacl
,
"cifsacl"
},
{
Opt_nocifsacl
,
"nocifsacl"
},
{
Opt_nocifsacl
,
"nocifsacl"
},
{
Opt_acl
,
"acl"
},
{
Opt_acl
,
"acl"
},
...
@@ -411,7 +413,9 @@ cifs_echo_request(struct work_struct *work)
...
@@ -411,7 +413,9 @@ cifs_echo_request(struct work_struct *work)
* server->ops->need_neg() == true. Also, no need to ping if
* server->ops->need_neg() == true. Also, no need to ping if
* we got a response recently.
* we got a response recently.
*/
*/
if
(
!
server
->
ops
->
need_neg
||
server
->
ops
->
need_neg
(
server
)
||
if
(
server
->
tcpStatus
==
CifsNeedReconnect
||
server
->
tcpStatus
==
CifsExiting
||
server
->
tcpStatus
==
CifsNew
||
(
server
->
ops
->
can_echo
&&
!
server
->
ops
->
can_echo
(
server
))
||
(
server
->
ops
->
can_echo
&&
!
server
->
ops
->
can_echo
(
server
))
||
time_before
(
jiffies
,
server
->
lstrp
+
SMB_ECHO_INTERVAL
-
HZ
))
time_before
(
jiffies
,
server
->
lstrp
+
SMB_ECHO_INTERVAL
-
HZ
))
goto
requeue_echo
;
goto
requeue_echo
;
...
@@ -907,10 +911,19 @@ cifs_demultiplex_thread(void *p)
...
@@ -907,10 +911,19 @@ cifs_demultiplex_thread(void *p)
server
->
lstrp
=
jiffies
;
server
->
lstrp
=
jiffies
;
if
(
mid_entry
!=
NULL
)
{
if
(
mid_entry
!=
NULL
)
{
if
((
mid_entry
->
mid_flags
&
MID_WAIT_CANCELLED
)
&&
mid_entry
->
mid_state
==
MID_RESPONSE_RECEIVED
&&
server
->
ops
->
handle_cancelled_mid
)
server
->
ops
->
handle_cancelled_mid
(
mid_entry
->
resp_buf
,
server
);
if
(
!
mid_entry
->
multiRsp
||
mid_entry
->
multiEnd
)
if
(
!
mid_entry
->
multiRsp
||
mid_entry
->
multiEnd
)
mid_entry
->
callback
(
mid_entry
);
mid_entry
->
callback
(
mid_entry
);
}
else
if
(
!
server
->
ops
->
is_oplock_break
||
}
else
if
(
server
->
ops
->
is_oplock_break
&&
!
server
->
ops
->
is_oplock_break
(
buf
,
server
))
{
server
->
ops
->
is_oplock_break
(
buf
,
server
))
{
cifs_dbg
(
FYI
,
"Received oplock break
\n
"
);
}
else
{
cifs_dbg
(
VFS
,
"No task to wake, unknown frame received! NumMids %d
\n
"
,
cifs_dbg
(
VFS
,
"No task to wake, unknown frame received! NumMids %d
\n
"
,
atomic_read
(
&
midCount
));
atomic_read
(
&
midCount
));
cifs_dump_mem
(
"Received Data is: "
,
buf
,
cifs_dump_mem
(
"Received Data is: "
,
buf
,
...
@@ -1421,10 +1434,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
...
@@ -1421,10 +1434,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
case
Opt_rwpidforward
:
case
Opt_rwpidforward
:
vol
->
rwpidforward
=
1
;
vol
->
rwpidforward
=
1
;
break
;
break
;
case
Opt_wine
:
vol
->
strict_io
=
1
;
vol
->
mand_lock
=
1
;
break
;
case
Opt_cifsacl
:
case
Opt_cifsacl
:
vol
->
cifs_acl
=
1
;
vol
->
cifs_acl
=
1
;
break
;
break
;
...
@@ -2063,8 +2072,8 @@ cifs_find_tcp_session(struct smb_vol *vol)
...
@@ -2063,8 +2072,8 @@ cifs_find_tcp_session(struct smb_vol *vol)
return
NULL
;
return
NULL
;
}
}
static
void
void
cifs_put_tcp_session
(
struct
TCP_Server_Info
*
server
)
cifs_put_tcp_session
(
struct
TCP_Server_Info
*
server
,
int
from_reconnect
)
{
{
struct
task_struct
*
task
;
struct
task_struct
*
task
;
...
@@ -2081,6 +2090,19 @@ cifs_put_tcp_session(struct TCP_Server_Info *server)
...
@@ -2081,6 +2090,19 @@ cifs_put_tcp_session(struct TCP_Server_Info *server)
cancel_delayed_work_sync
(
&
server
->
echo
);
cancel_delayed_work_sync
(
&
server
->
echo
);
#ifdef CONFIG_CIFS_SMB2
if
(
from_reconnect
)
/*
* Avoid deadlock here: reconnect work calls
* cifs_put_tcp_session() at its end. Need to be sure
* that reconnect work does nothing with server pointer after
* that step.
*/
cancel_delayed_work
(
&
server
->
reconnect
);
else
cancel_delayed_work_sync
(
&
server
->
reconnect
);
#endif
spin_lock
(
&
GlobalMid_Lock
);
spin_lock
(
&
GlobalMid_Lock
);
server
->
tcpStatus
=
CifsExiting
;
server
->
tcpStatus
=
CifsExiting
;
spin_unlock
(
&
GlobalMid_Lock
);
spin_unlock
(
&
GlobalMid_Lock
);
...
@@ -2145,12 +2167,16 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
...
@@ -2145,12 +2167,16 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
INIT_LIST_HEAD
(
&
tcp_ses
->
tcp_ses_list
);
INIT_LIST_HEAD
(
&
tcp_ses
->
tcp_ses_list
);
INIT_LIST_HEAD
(
&
tcp_ses
->
smb_ses_list
);
INIT_LIST_HEAD
(
&
tcp_ses
->
smb_ses_list
);
INIT_DELAYED_WORK
(
&
tcp_ses
->
echo
,
cifs_echo_request
);
INIT_DELAYED_WORK
(
&
tcp_ses
->
echo
,
cifs_echo_request
);
#ifdef CONFIG_CIFS_SMB2
INIT_DELAYED_WORK
(
&
tcp_ses
->
reconnect
,
smb2_reconnect_server
);
mutex_init
(
&
tcp_ses
->
reconnect_mutex
);
#endif
memcpy
(
&
tcp_ses
->
srcaddr
,
&
volume_info
->
srcaddr
,
memcpy
(
&
tcp_ses
->
srcaddr
,
&
volume_info
->
srcaddr
,
sizeof
(
tcp_ses
->
srcaddr
));
sizeof
(
tcp_ses
->
srcaddr
));
memcpy
(
&
tcp_ses
->
dstaddr
,
&
volume_info
->
dstaddr
,
memcpy
(
&
tcp_ses
->
dstaddr
,
&
volume_info
->
dstaddr
,
sizeof
(
tcp_ses
->
dstaddr
));
sizeof
(
tcp_ses
->
dstaddr
));
#ifdef CONFIG_CIFS_SMB2
#ifdef CONFIG_CIFS_SMB2
ge
t_random_bytes
(
tcp_ses
->
client_guid
,
SMB2_CLIENT_GUID_SIZE
);
ge
nerate_random_uuid
(
tcp_ses
->
client_guid
);
#endif
#endif
/*
/*
* at this point we are the only ones with the pointer
* at this point we are the only ones with the pointer
...
@@ -2297,7 +2323,7 @@ cifs_put_smb_ses(struct cifs_ses *ses)
...
@@ -2297,7 +2323,7 @@ cifs_put_smb_ses(struct cifs_ses *ses)
spin_unlock
(
&
cifs_tcp_ses_lock
);
spin_unlock
(
&
cifs_tcp_ses_lock
);
sesInfoFree
(
ses
);
sesInfoFree
(
ses
);
cifs_put_tcp_session
(
server
);
cifs_put_tcp_session
(
server
,
0
);
}
}
#ifdef CONFIG_KEYS
#ifdef CONFIG_KEYS
...
@@ -2470,7 +2496,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
...
@@ -2470,7 +2496,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
mutex_unlock
(
&
ses
->
session_mutex
);
mutex_unlock
(
&
ses
->
session_mutex
);
/* existing SMB ses has a server reference already */
/* existing SMB ses has a server reference already */
cifs_put_tcp_session
(
server
);
cifs_put_tcp_session
(
server
,
0
);
free_xid
(
xid
);
free_xid
(
xid
);
return
ses
;
return
ses
;
}
}
...
@@ -2560,7 +2586,7 @@ cifs_find_tcon(struct cifs_ses *ses, const char *unc)
...
@@ -2560,7 +2586,7 @@ cifs_find_tcon(struct cifs_ses *ses, const char *unc)
return
NULL
;
return
NULL
;
}
}
static
void
void
cifs_put_tcon
(
struct
cifs_tcon
*
tcon
)
cifs_put_tcon
(
struct
cifs_tcon
*
tcon
)
{
{
unsigned
int
xid
;
unsigned
int
xid
;
...
@@ -2725,6 +2751,22 @@ compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
...
@@ -2725,6 +2751,22 @@ compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
return
1
;
return
1
;
}
}
static
int
match_prepath
(
struct
super_block
*
sb
,
struct
cifs_mnt_data
*
mnt_data
)
{
struct
cifs_sb_info
*
old
=
CIFS_SB
(
sb
);
struct
cifs_sb_info
*
new
=
mnt_data
->
cifs_sb
;
bool
old_set
=
old
->
mnt_cifs_flags
&
CIFS_MOUNT_USE_PREFIX_PATH
;
bool
new_set
=
new
->
mnt_cifs_flags
&
CIFS_MOUNT_USE_PREFIX_PATH
;
if
(
old_set
&&
new_set
&&
!
strcmp
(
new
->
prepath
,
old
->
prepath
))
return
1
;
else
if
(
!
old_set
&&
!
new_set
)
return
1
;
return
0
;
}
int
int
cifs_match_super
(
struct
super_block
*
sb
,
void
*
data
)
cifs_match_super
(
struct
super_block
*
sb
,
void
*
data
)
{
{
...
@@ -2752,7 +2794,8 @@ cifs_match_super(struct super_block *sb, void *data)
...
@@ -2752,7 +2794,8 @@ cifs_match_super(struct super_block *sb, void *data)
if
(
!
match_server
(
tcp_srv
,
volume_info
)
||
if
(
!
match_server
(
tcp_srv
,
volume_info
)
||
!
match_session
(
ses
,
volume_info
)
||
!
match_session
(
ses
,
volume_info
)
||
!
match_tcon
(
tcon
,
volume_info
->
UNC
))
{
!
match_tcon
(
tcon
,
volume_info
->
UNC
)
||
!
match_prepath
(
sb
,
mnt_data
))
{
rc
=
0
;
rc
=
0
;
goto
out
;
goto
out
;
}
}
...
@@ -3168,7 +3211,7 @@ void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
...
@@ -3168,7 +3211,7 @@ void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
}
}
}
}
void
cifs_setup_cifs_sb
(
struct
smb_vol
*
pvolume_info
,
int
cifs_setup_cifs_sb
(
struct
smb_vol
*
pvolume_info
,
struct
cifs_sb_info
*
cifs_sb
)
struct
cifs_sb_info
*
cifs_sb
)
{
{
INIT_DELAYED_WORK
(
&
cifs_sb
->
prune_tlinks
,
cifs_prune_tlinks
);
INIT_DELAYED_WORK
(
&
cifs_sb
->
prune_tlinks
,
cifs_prune_tlinks
);
...
@@ -3250,6 +3293,14 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
...
@@ -3250,6 +3293,14 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
if
((
pvolume_info
->
cifs_acl
)
&&
(
pvolume_info
->
dynperm
))
if
((
pvolume_info
->
cifs_acl
)
&&
(
pvolume_info
->
dynperm
))
cifs_dbg
(
VFS
,
"mount option dynperm ignored if cifsacl mount option supported
\n
"
);
cifs_dbg
(
VFS
,
"mount option dynperm ignored if cifsacl mount option supported
\n
"
);
if
(
pvolume_info
->
prepath
)
{
cifs_sb
->
prepath
=
kstrdup
(
pvolume_info
->
prepath
,
GFP_KERNEL
);
if
(
cifs_sb
->
prepath
==
NULL
)
return
-
ENOMEM
;
}
return
0
;
}
}
static
void
static
void
...
@@ -3420,6 +3471,44 @@ cifs_get_volume_info(char *mount_data, const char *devname)
...
@@ -3420,6 +3471,44 @@ cifs_get_volume_info(char *mount_data, const char *devname)
return
volume_info
;
return
volume_info
;
}
}
static
int
cifs_are_all_path_components_accessible
(
struct
TCP_Server_Info
*
server
,
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
struct
cifs_sb_info
*
cifs_sb
,
char
*
full_path
)
{
int
rc
;
char
*
s
;
char
sep
,
tmp
;
sep
=
CIFS_DIR_SEP
(
cifs_sb
);
s
=
full_path
;
rc
=
server
->
ops
->
is_path_accessible
(
xid
,
tcon
,
cifs_sb
,
""
);
while
(
rc
==
0
)
{
/* skip separators */
while
(
*
s
==
sep
)
s
++
;
if
(
!*
s
)
break
;
/* next separator */
while
(
*
s
&&
*
s
!=
sep
)
s
++
;
/*
* temporarily null-terminate the path at the end of
* the current component
*/
tmp
=
*
s
;
*
s
=
0
;
rc
=
server
->
ops
->
is_path_accessible
(
xid
,
tcon
,
cifs_sb
,
full_path
);
*
s
=
tmp
;
}
return
rc
;
}
int
int
cifs_mount
(
struct
cifs_sb_info
*
cifs_sb
,
struct
smb_vol
*
volume_info
)
cifs_mount
(
struct
cifs_sb_info
*
cifs_sb
,
struct
smb_vol
*
volume_info
)
{
{
...
@@ -3546,6 +3635,18 @@ remote_path_check:
...
@@ -3546,6 +3635,18 @@ remote_path_check:
kfree
(
full_path
);
kfree
(
full_path
);
goto
mount_fail_check
;
goto
mount_fail_check
;
}
}
if
(
rc
!=
-
EREMOTE
)
{
rc
=
cifs_are_all_path_components_accessible
(
server
,
xid
,
tcon
,
cifs_sb
,
full_path
);
if
(
rc
!=
0
)
{
cifs_dbg
(
VFS
,
"cannot query dirs between root and final path, "
"enabling CIFS_MOUNT_USE_PREFIX_PATH
\n
"
);
cifs_sb
->
mnt_cifs_flags
|=
CIFS_MOUNT_USE_PREFIX_PATH
;
rc
=
0
;
}
}
kfree
(
full_path
);
kfree
(
full_path
);
}
}
...
@@ -3609,7 +3710,7 @@ mount_fail_check:
...
@@ -3609,7 +3710,7 @@ mount_fail_check:
else
if
(
ses
)
else
if
(
ses
)
cifs_put_smb_ses
(
ses
);
cifs_put_smb_ses
(
ses
);
else
else
cifs_put_tcp_session
(
server
);
cifs_put_tcp_session
(
server
,
0
);
bdi_destroy
(
&
cifs_sb
->
bdi
);
bdi_destroy
(
&
cifs_sb
->
bdi
);
}
}
...
@@ -3809,6 +3910,7 @@ cifs_umount(struct cifs_sb_info *cifs_sb)
...
@@ -3809,6 +3910,7 @@ cifs_umount(struct cifs_sb_info *cifs_sb)
bdi_destroy
(
&
cifs_sb
->
bdi
);
bdi_destroy
(
&
cifs_sb
->
bdi
);
kfree
(
cifs_sb
->
mountdata
);
kfree
(
cifs_sb
->
mountdata
);
kfree
(
cifs_sb
->
prepath
);
call_rcu
(
&
cifs_sb
->
rcu
,
delayed_free
);
call_rcu
(
&
cifs_sb
->
rcu
,
delayed_free
);
}
}
...
@@ -3854,6 +3956,14 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
...
@@ -3854,6 +3956,14 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
cifs_dbg
(
FYI
,
"Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d
\n
"
,
cifs_dbg
(
FYI
,
"Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d
\n
"
,
server
->
sec_mode
,
server
->
capabilities
,
server
->
timeAdj
);
server
->
sec_mode
,
server
->
capabilities
,
server
->
timeAdj
);
if
(
ses
->
auth_key
.
response
)
{
cifs_dbg
(
VFS
,
"Free previous auth_key.response = %p
\n
"
,
ses
->
auth_key
.
response
);
kfree
(
ses
->
auth_key
.
response
);
ses
->
auth_key
.
response
=
NULL
;
ses
->
auth_key
.
len
=
0
;
}
if
(
server
->
ops
->
sess_setup
)
if
(
server
->
ops
->
sess_setup
)
rc
=
server
->
ops
->
sess_setup
(
xid
,
ses
,
nls_info
);
rc
=
server
->
ops
->
sess_setup
(
xid
,
ses
,
nls_info
);
...
@@ -3913,7 +4023,7 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
...
@@ -3913,7 +4023,7 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
ses
=
cifs_get_smb_ses
(
master_tcon
->
ses
->
server
,
vol_info
);
ses
=
cifs_get_smb_ses
(
master_tcon
->
ses
->
server
,
vol_info
);
if
(
IS_ERR
(
ses
))
{
if
(
IS_ERR
(
ses
))
{
tcon
=
(
struct
cifs_tcon
*
)
ses
;
tcon
=
(
struct
cifs_tcon
*
)
ses
;
cifs_put_tcp_session
(
master_tcon
->
ses
->
server
);
cifs_put_tcp_session
(
master_tcon
->
ses
->
server
,
0
);
goto
out
;
goto
out
;
}
}
...
...
sources/3.16/dir.c
View file @
7e23c0f8
...
@@ -84,6 +84,7 @@ build_path_from_dentry(struct dentry *direntry)
...
@@ -84,6 +84,7 @@ build_path_from_dentry(struct dentry *direntry)
struct
dentry
*
temp
;
struct
dentry
*
temp
;
int
namelen
;
int
namelen
;
int
dfsplen
;
int
dfsplen
;
int
pplen
=
0
;
char
*
full_path
;
char
*
full_path
;
char
dirsep
;
char
dirsep
;
struct
cifs_sb_info
*
cifs_sb
=
CIFS_SB
(
direntry
->
d_sb
);
struct
cifs_sb_info
*
cifs_sb
=
CIFS_SB
(
direntry
->
d_sb
);
...
@@ -95,8 +96,12 @@ build_path_from_dentry(struct dentry *direntry)
...
@@ -95,8 +96,12 @@ build_path_from_dentry(struct dentry *direntry)
dfsplen
=
strnlen
(
tcon
->
treeName
,
MAX_TREE_SIZE
+
1
);
dfsplen
=
strnlen
(
tcon
->
treeName
,
MAX_TREE_SIZE
+
1
);
else
else
dfsplen
=
0
;
dfsplen
=
0
;
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_USE_PREFIX_PATH
)
pplen
=
cifs_sb
->
prepath
?
strlen
(
cifs_sb
->
prepath
)
+
1
:
0
;
cifs_bp_rename_retry:
cifs_bp_rename_retry:
namelen
=
dfsplen
;
namelen
=
dfsplen
+
pplen
;
seq
=
read_seqbegin
(
&
rename_lock
);
seq
=
read_seqbegin
(
&
rename_lock
);
rcu_read_lock
();
rcu_read_lock
();
for
(
temp
=
direntry
;
!
IS_ROOT
(
temp
);)
{
for
(
temp
=
direntry
;
!
IS_ROOT
(
temp
);)
{
...
@@ -137,7 +142,7 @@ cifs_bp_rename_retry:
...
@@ -137,7 +142,7 @@ cifs_bp_rename_retry:
}
}
}
}
rcu_read_unlock
();
rcu_read_unlock
();
if
(
namelen
!=
dfsplen
||
read_seqretry
(
&
rename_lock
,
seq
))
{
if
(
namelen
!=
dfsplen
+
pplen
||
read_seqretry
(
&
rename_lock
,
seq
))
{
cifs_dbg
(
FYI
,
"did not end path lookup where expected. namelen=%ddfsplen=%d
\n
"
,
cifs_dbg
(
FYI
,
"did not end path lookup where expected. namelen=%ddfsplen=%d
\n
"
,
namelen
,
dfsplen
);
namelen
,
dfsplen
);
/* presumably this is only possible if racing with a rename
/* presumably this is only possible if racing with a rename
...
@@ -153,6 +158,17 @@ cifs_bp_rename_retry:
...
@@ -153,6 +158,17 @@ cifs_bp_rename_retry:
those safely to '/' if any are found in the middle of the prepath */
those safely to '/' if any are found in the middle of the prepath */
/* BB test paths to Windows with '/' in the midst of prepath */
/* BB test paths to Windows with '/' in the midst of prepath */
if
(
pplen
)
{
int
i
;
cifs_dbg
(
FYI
,
"using cifs_sb prepath <%s>
\n
"
,
cifs_sb
->
prepath
);
memcpy
(
full_path
+
dfsplen
+
1
,
cifs_sb
->
prepath
,
pplen
-
1
);
full_path
[
dfsplen
]
=
'\\'
;
for
(
i
=
0
;
i
<
pplen
-
1
;
i
++
)
if
(
full_path
[
dfsplen
+
1
+
i
]
==
'/'
)
full_path
[
dfsplen
+
1
+
i
]
=
CIFS_DIR_SEP
(
cifs_sb
);
}
if
(
dfsplen
)
{
if
(
dfsplen
)
{
strncpy
(
full_path
,
tcon
->
treeName
,
dfsplen
);
strncpy
(
full_path
,
tcon
->
treeName
,
dfsplen
);
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_POSIX_PATHS
)
{
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_POSIX_PATHS
)
{
...
@@ -167,15 +183,21 @@ cifs_bp_rename_retry:
...
@@ -167,15 +183,21 @@ cifs_bp_rename_retry:
}
}
/*
/*
* Don't allow path components longer than the server max.
* Don't allow the separator character in a path component.
* Don't allow the separator character in a path component.
* The VFS will not allow "/", but "\" is allowed by posix.
* The VFS will not allow "/", but "\" is allowed by posix.
*/
*/
static
int
static
int
check_name
(
struct
dentry
*
direntry
)
check_name
(
struct
dentry
*
direntry
,
struct
cifs_tcon
*
tcon
)
{
{
struct
cifs_sb_info
*
cifs_sb
=
CIFS_SB
(
direntry
->
d_sb
);
struct
cifs_sb_info
*
cifs_sb
=
CIFS_SB
(
direntry
->
d_sb
);
int
i
;
int
i
;
if
(
unlikely
(
tcon
->
fsAttrInfo
.
MaxPathNameComponentLength
&&
direntry
->
d_name
.
len
>
le32_to_cpu
(
tcon
->
fsAttrInfo
.
MaxPathNameComponentLength
)))
return
-
ENAMETOOLONG
;
if
(
!
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_POSIX_PATHS
))
{
if
(
!
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_POSIX_PATHS
))
{
for
(
i
=
0
;
i
<
direntry
->
d_name
.
len
;
i
++
)
{
for
(
i
=
0
;
i
<
direntry
->
d_name
.
len
;
i
++
)
{
if
(
direntry
->
d_name
.
name
[
i
]
==
'\\'
)
{
if
(
direntry
->
d_name
.
name
[
i
]
==
'\\'
)
{
...
@@ -204,7 +226,6 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
...
@@ -204,7 +226,6 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
FILE_ALL_INFO
*
buf
=
NULL
;
FILE_ALL_INFO
*
buf
=
NULL
;
struct
inode
*
newinode
=
NULL
;
struct
inode
*
newinode
=
NULL
;
int
disposition
;
int
disposition
;
int
share_access
;
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
;
...
@@ -219,7 +240,6 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
...
@@ -219,7 +240,6 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
}
}
if
(
tcon
->
unix_ext
&&
cap_unix
(
tcon
->
ses
)
&&
!
tcon
->
broken_posix_open
&&
if
(
tcon
->
unix_ext
&&
cap_unix
(
tcon
->
ses
)
&&
!
tcon
->
broken_posix_open
&&
((
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NOPOSIXBRL
)
==
0
)
&&
(
CIFS_UNIX_POSIX_PATH_OPS_CAP
&
(
CIFS_UNIX_POSIX_PATH_OPS_CAP
&
le64_to_cpu
(
tcon
->
fsUnixInfo
.
Capability
)))
{
le64_to_cpu
(
tcon
->
fsUnixInfo
.
Capability
)))
{
rc
=
cifs_posix_open
(
full_path
,
&
newinode
,
inode
->
i_sb
,
mode
,
rc
=
cifs_posix_open
(
full_path
,
&
newinode
,
inode
->
i_sb
,
mode
,
...
@@ -231,6 +251,13 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
...
@@ -231,6 +251,13 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
goto
cifs_create_get_file_info
;
goto
cifs_create_get_file_info
;
}
}
if
(
S_ISDIR
(
newinode
->
i_mode
))
{
CIFSSMBClose
(
xid
,
tcon
,
fid
->
netfid
);
iput
(
newinode
);
rc
=
-
EISDIR
;
goto
out
;
}
if
(
!
S_ISREG
(
newinode
->
i_mode
))
{
if
(
!
S_ISREG
(
newinode
->
i_mode
))
{
/*
/*
* The server may allow us to open things like
* The server may allow us to open things like
...
@@ -297,8 +324,6 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
...
@@ -297,8 +324,6 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
else
else
cifs_dbg
(
FYI
,
"Create flag not set in create function
\n
"
);
cifs_dbg
(
FYI
,
"Create flag not set in create function
\n
"
);
share_access
=
cifs_get_share_flags
(
oflags
);
/*
/*
* BB add processing to set equivalent of mode - e.g. via CreateX with
* BB add processing to set equivalent of mode - e.g. via CreateX with
* ACLs
* ACLs
...
@@ -328,7 +353,6 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
...
@@ -328,7 +353,6 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
oparms
.
tcon
=
tcon
;
oparms
.
tcon
=
tcon
;
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
desired_access
=
desired_access
;
oparms
.
desired_access
=
desired_access
;
oparms
.
share_access
=
share_access
;
oparms
.
create_options
=
create_options
;
oparms
.
create_options
=
create_options
;
oparms
.
disposition
=
disposition
;
oparms
.
disposition
=
disposition
;
oparms
.
path
=
full_path
;
oparms
.
path
=
full_path
;
...
@@ -404,10 +428,14 @@ cifs_create_set_dentry:
...
@@ -404,10 +428,14 @@ cifs_create_set_dentry:
if
(
rc
!=
0
)
{
if
(
rc
!=
0
)
{
cifs_dbg
(
FYI
,
"Create worked, get_inode_info failed rc = %d
\n
"
,
cifs_dbg
(
FYI
,
"Create worked, get_inode_info failed rc = %d
\n
"
,
rc
);
rc
);
if
(
server
->
ops
->
close
)
goto
out_err
;
server
->
ops
->
close
(
xid
,
tcon
,
fid
);
goto
out
;
}
}
if
(
S_ISDIR
(
newinode
->
i_mode
))
{
rc
=
-
EISDIR
;
goto
out_err
;
}
d_drop
(
direntry
);
d_drop
(
direntry
);
d_add
(
direntry
,
newinode
);
d_add
(
direntry
,
newinode
);
...
@@ -415,6 +443,13 @@ out:
...
@@ -415,6 +443,13 @@ out:
kfree
(
buf
);
kfree
(
buf
);
kfree
(
full_path
);
kfree
(
full_path
);
return
rc
;
return
rc
;
out_err:
if
(
server
->
ops
->
close
)
server
->
ops
->
close
(
xid
,
tcon
,
fid
);
if
(
newinode
)
iput
(
newinode
);
goto
out
;
}
}
int
int
...
@@ -460,10 +495,6 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
...
@@ -460,10 +495,6 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
return
finish_no_open
(
file
,
res
);
return
finish_no_open
(
file
,
res
);
}
}
rc
=
check_name
(
direntry
);
if
(
rc
)
return
rc
;
xid
=
get_xid
();
xid
=
get_xid
();
cifs_dbg
(
FYI
,
"parent inode = 0x%p name is: %s and dentry = 0x%p
\n
"
,
cifs_dbg
(
FYI
,
"parent inode = 0x%p name is: %s and dentry = 0x%p
\n
"
,
...
@@ -476,6 +507,11 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
...
@@ -476,6 +507,11 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
}
}
tcon
=
tlink_tcon
(
tlink
);
tcon
=
tlink_tcon
(
tlink
);
rc
=
check_name
(
direntry
,
tcon
);
if
(
rc
)
goto
out
;
server
=
tcon
->
ses
->
server
;
server
=
tcon
->
ses
->
server
;
if
(
server
->
ops
->
new_lease_key
)
if
(
server
->
ops
->
new_lease_key
)
...
@@ -632,6 +668,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
...
@@ -632,6 +668,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
if
(
!
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_UNX_EMUL
))
if
(
!
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_UNX_EMUL
))
goto
mknod_out
;
goto
mknod_out
;
cifs_dbg
(
FYI
,
"sfu compat create special file
\n
"
);
cifs_dbg
(
FYI
,
"sfu compat create special file
\n
"
);
buf
=
kmalloc
(
sizeof
(
FILE_ALL_INFO
),
GFP_KERNEL
);
buf
=
kmalloc
(
sizeof
(
FILE_ALL_INFO
),
GFP_KERNEL
);
...
@@ -648,7 +685,6 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
...
@@ -648,7 +685,6 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
oparms
.
tcon
=
tcon
;
oparms
.
tcon
=
tcon
;
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
desired_access
=
GENERIC_WRITE
;
oparms
.
desired_access
=
GENERIC_WRITE
;
oparms
.
share_access
=
FILE_SHARE_ALL
;
oparms
.
create_options
=
create_options
;
oparms
.
create_options
=
create_options
;
oparms
.
disposition
=
FILE_CREATE
;
oparms
.
disposition
=
FILE_CREATE
;
oparms
.
path
=
full_path
;
oparms
.
path
=
full_path
;
...
@@ -723,7 +759,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
...
@@ -723,7 +759,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
}
}
pTcon
=
tlink_tcon
(
tlink
);
pTcon
=
tlink_tcon
(
tlink
);
rc
=
check_name
(
direntry
);
rc
=
check_name
(
direntry
,
pTcon
);
if
(
rc
)
if
(
rc
)
goto
lookup_out
;
goto
lookup_out
;
...
...
sources/3.16/file.c
View file @
7e23c0f8
...
@@ -179,7 +179,6 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
...
@@ -179,7 +179,6 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
{
{
int
rc
;
int
rc
;
int
desired_access
;
int
desired_access
;
int
share_access
;
int
disposition
;
int
disposition
;
int
create_options
=
CREATE_NOT_DIR
;
int
create_options
=
CREATE_NOT_DIR
;
FILE_ALL_INFO
*
buf
;
FILE_ALL_INFO
*
buf
;
...
@@ -216,7 +215,6 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
...
@@ -216,7 +215,6 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
*********************************************************************/
*********************************************************************/
disposition
=
cifs_get_disposition
(
f_flags
);
disposition
=
cifs_get_disposition
(
f_flags
);
share_access
=
cifs_get_share_flags
(
f_flags
);
/* BB pass O_SYNC flag through on file attributes .. BB */
/* BB pass O_SYNC flag through on file attributes .. BB */
...
@@ -227,10 +225,16 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
...
@@ -227,10 +225,16 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
if
(
backup_cred
(
cifs_sb
))
if
(
backup_cred
(
cifs_sb
))
create_options
|=
CREATE_OPEN_BACKUP_INTENT
;
create_options
|=
CREATE_OPEN_BACKUP_INTENT
;
/* 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
;
oparms
.
tcon
=
tcon
;
oparms
.
tcon
=
tcon
;
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
desired_access
=
desired_access
;
oparms
.
desired_access
=
desired_access
;
oparms
.
share_access
=
share_access
;
oparms
.
create_options
=
create_options
;
oparms
.
create_options
=
create_options
;
oparms
.
disposition
=
disposition
;
oparms
.
disposition
=
disposition
;
oparms
.
path
=
full_path
;
oparms
.
path
=
full_path
;
...
@@ -309,6 +313,7 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
...
@@ -309,6 +313,7 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
cfile
->
tlink
=
cifs_get_tlink
(
tlink
);
cfile
->
tlink
=
cifs_get_tlink
(
tlink
);
INIT_WORK
(
&
cfile
->
oplock_break
,
cifs_oplock_break
);
INIT_WORK
(
&
cfile
->
oplock_break
,
cifs_oplock_break
);
mutex_init
(
&
cfile
->
fh_mutex
);
mutex_init
(
&
cfile
->
fh_mutex
);
spin_lock_init
(
&
cfile
->
file_info_lock
);
cifs_sb_active
(
inode
->
i_sb
);
cifs_sb_active
(
inode
->
i_sb
);
...
@@ -321,7 +326,7 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
...
@@ -321,7 +326,7 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
oplock
=
0
;
oplock
=
0
;
}
}
spin_lock
(
&
cifs_file_list
_lock
);
spin_lock
(
&
tcon
->
open_file
_lock
);
if
(
fid
->
pending_open
->
oplock
!=
CIFS_OPLOCK_NO_CHANGE
&&
oplock
)
if
(
fid
->
pending_open
->
oplock
!=
CIFS_OPLOCK_NO_CHANGE
&&
oplock
)
oplock
=
fid
->
pending_open
->
oplock
;
oplock
=
fid
->
pending_open
->
oplock
;
list_del
(
&
fid
->
pending_open
->
olist
);
list_del
(
&
fid
->
pending_open
->
olist
);
...
@@ -330,12 +335,13 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
...
@@ -330,12 +335,13 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
server
->
ops
->
set_fid
(
cfile
,
fid
,
oplock
);
server
->
ops
->
set_fid
(
cfile
,
fid
,
oplock
);
list_add
(
&
cfile
->
tlist
,
&
tcon
->
openFileList
);
list_add
(
&
cfile
->
tlist
,
&
tcon
->
openFileList
);
/* if readable file instance put first in list*/
/* if readable file instance put first in list*/
if
(
file
->
f_mode
&
FMODE_READ
)
if
(
file
->
f_mode
&
FMODE_READ
)
list_add
(
&
cfile
->
flist
,
&
cinode
->
openFileList
);
list_add
(
&
cfile
->
flist
,
&
cinode
->
openFileList
);
else
else
list_add_tail
(
&
cfile
->
flist
,
&
cinode
->
openFileList
);
list_add_tail
(
&
cfile
->
flist
,
&
cinode
->
openFileList
);
spin_unlock
(
&
cifs_file_list
_lock
);
spin_unlock
(
&
tcon
->
open_file
_lock
);
if
(
fid
->
purge_cache
)
if
(
fid
->
purge_cache
)
cifs_zap_mapping
(
inode
);
cifs_zap_mapping
(
inode
);
...
@@ -347,16 +353,16 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
...
@@ -347,16 +353,16 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
struct
cifsFileInfo
*
struct
cifsFileInfo
*
cifsFileInfo_get
(
struct
cifsFileInfo
*
cifs_file
)
cifsFileInfo_get
(
struct
cifsFileInfo
*
cifs_file
)
{
{
spin_lock
(
&
cifs_file
_list
_lock
);
spin_lock
(
&
cifs_file
->
file_info
_lock
);
cifsFileInfo_get_locked
(
cifs_file
);
cifsFileInfo_get_locked
(
cifs_file
);
spin_unlock
(
&
cifs_file
_list
_lock
);
spin_unlock
(
&
cifs_file
->
file_info
_lock
);
return
cifs_file
;
return
cifs_file
;
}
}
/*
/*
* Release a reference on the file private data. This may involve closing
* Release a reference on the file private data. This may involve closing
* the filehandle out on the server. Must be called without holding
* the filehandle out on the server. Must be called without holding
*
cifs_file_list
_lock.
*
tcon->open_file_lock and cifs_file->file_info
_lock.
*/
*/
void
cifsFileInfo_put
(
struct
cifsFileInfo
*
cifs_file
)
void
cifsFileInfo_put
(
struct
cifsFileInfo
*
cifs_file
)
{
{
...
@@ -371,11 +377,15 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
...
@@ -371,11 +377,15 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
struct
cifs_pending_open
open
;
struct
cifs_pending_open
open
;
bool
oplock_break_cancelled
;
bool
oplock_break_cancelled
;
spin_lock
(
&
cifs_file_list_lock
);
spin_lock
(
&
tcon
->
open_file_lock
);
spin_lock
(
&
cifs_file
->
file_info_lock
);
if
(
--
cifs_file
->
count
>
0
)
{
if
(
--
cifs_file
->
count
>
0
)
{
spin_unlock
(
&
cifs_file_list_lock
);
spin_unlock
(
&
cifs_file
->
file_info_lock
);
spin_unlock
(
&
tcon
->
open_file_lock
);
return
;
return
;
}
}
spin_unlock
(
&
cifs_file
->
file_info_lock
);
if
(
server
->
ops
->
get_lease_key
)
if
(
server
->
ops
->
get_lease_key
)
server
->
ops
->
get_lease_key
(
inode
,
&
fid
);
server
->
ops
->
get_lease_key
(
inode
,
&
fid
);
...
@@ -399,7 +409,8 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
...
@@ -399,7 +409,8 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
set_bit
(
CIFS_INO_INVALID_MAPPING
,
&
cifsi
->
flags
);
set_bit
(
CIFS_INO_INVALID_MAPPING
,
&
cifsi
->
flags
);
cifs_set_oplock_level
(
cifsi
,
0
);
cifs_set_oplock_level
(
cifsi
,
0
);
}
}
spin_unlock
(
&
cifs_file_list_lock
);
spin_unlock
(
&
tcon
->
open_file_lock
);
oplock_break_cancelled
=
cancel_work_sync
(
&
cifs_file
->
oplock_break
);
oplock_break_cancelled
=
cancel_work_sync
(
&
cifs_file
->
oplock_break
);
...
@@ -479,9 +490,8 @@ int cifs_open(struct inode *inode, struct file *file)
...
@@ -479,9 +490,8 @@ int cifs_open(struct inode *inode, struct file *file)
else
else
oplock
=
0
;
oplock
=
0
;
if
(
!
tcon
->
broken_posix_open
&&
tcon
->
unix_ext
&&
cap_unix
(
tcon
->
ses
)
if
(
!
tcon
->
broken_posix_open
&&
tcon
->
unix_ext
&&
&&
((
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NOPOSIXBRL
)
==
0
)
&&
cap_unix
(
tcon
->
ses
)
&&
(
CIFS_UNIX_POSIX_PATH_OPS_CAP
&
(
CIFS_UNIX_POSIX_PATH_OPS_CAP
&
le64_to_cpu
(
tcon
->
fsUnixInfo
.
Capability
)))
{
le64_to_cpu
(
tcon
->
fsUnixInfo
.
Capability
)))
{
/* can not refresh inode info since size could be stale */
/* can not refresh inode info since size could be stale */
rc
=
cifs_posix_open
(
full_path
,
&
inode
,
inode
->
i_sb
,
rc
=
cifs_posix_open
(
full_path
,
&
inode
,
inode
->
i_sb
,
...
@@ -603,7 +613,6 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
...
@@ -603,7 +613,6 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
struct
inode
*
inode
;
struct
inode
*
inode
;
char
*
full_path
=
NULL
;
char
*
full_path
=
NULL
;
int
desired_access
;
int
desired_access
;
int
share_access
;
int
disposition
=
FILE_OPEN
;
int
disposition
=
FILE_OPEN
;
int
create_options
=
CREATE_NOT_DIR
;
int
create_options
=
CREATE_NOT_DIR
;
struct
cifs_open_parms
oparms
;
struct
cifs_open_parms
oparms
;
...
@@ -645,7 +654,6 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
...
@@ -645,7 +654,6 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
oplock
=
0
;
oplock
=
0
;
if
(
tcon
->
unix_ext
&&
cap_unix
(
tcon
->
ses
)
&&
if
(
tcon
->
unix_ext
&&
cap_unix
(
tcon
->
ses
)
&&
((
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NOPOSIXBRL
)
==
0
)
&&
(
CIFS_UNIX_POSIX_PATH_OPS_CAP
&
(
CIFS_UNIX_POSIX_PATH_OPS_CAP
&
le64_to_cpu
(
tcon
->
fsUnixInfo
.
Capability
)))
{
le64_to_cpu
(
tcon
->
fsUnixInfo
.
Capability
)))
{
/*
/*
...
@@ -670,7 +678,6 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
...
@@ -670,7 +678,6 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
}
}
desired_access
=
cifs_convert_flags
(
cfile
->
f_flags
);
desired_access
=
cifs_convert_flags
(
cfile
->
f_flags
);
share_access
=
cifs_get_share_flags
(
cfile
->
f_flags
);
if
(
backup_cred
(
cifs_sb
))
if
(
backup_cred
(
cifs_sb
))
create_options
|=
CREATE_OPEN_BACKUP_INTENT
;
create_options
|=
CREATE_OPEN_BACKUP_INTENT
;
...
@@ -681,7 +688,6 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
...
@@ -681,7 +688,6 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
oparms
.
tcon
=
tcon
;
oparms
.
tcon
=
tcon
;
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
desired_access
=
desired_access
;
oparms
.
desired_access
=
desired_access
;
oparms
.
share_access
=
share_access
;
oparms
.
create_options
=
create_options
;
oparms
.
create_options
=
create_options
;
oparms
.
disposition
=
disposition
;
oparms
.
disposition
=
disposition
;
oparms
.
path
=
full_path
;
oparms
.
path
=
full_path
;
...
@@ -773,10 +779,10 @@ int cifs_closedir(struct inode *inode, struct file *file)
...
@@ -773,10 +779,10 @@ int cifs_closedir(struct inode *inode, struct file *file)
server
=
tcon
->
ses
->
server
;
server
=
tcon
->
ses
->
server
;
cifs_dbg
(
FYI
,
"Freeing private data in close dir
\n
"
);
cifs_dbg
(
FYI
,
"Freeing private data in close dir
\n
"
);
spin_lock
(
&
c
ifs_file_list
_lock
);
spin_lock
(
&
c
file
->
file_info
_lock
);
if
(
server
->
ops
->
dir_needs_close
(
cfile
))
{
if
(
server
->
ops
->
dir_needs_close
(
cfile
))
{
cfile
->
invalidHandle
=
true
;
cfile
->
invalidHandle
=
true
;
spin_unlock
(
&
c
ifs_file_list
_lock
);
spin_unlock
(
&
c
file
->
file_info
_lock
);
if
(
server
->
ops
->
close_dir
)
if
(
server
->
ops
->
close_dir
)
rc
=
server
->
ops
->
close_dir
(
xid
,
tcon
,
&
cfile
->
fid
);
rc
=
server
->
ops
->
close_dir
(
xid
,
tcon
,
&
cfile
->
fid
);
else
else
...
@@ -785,7 +791,7 @@ int cifs_closedir(struct inode *inode, struct file *file)
...
@@ -785,7 +791,7 @@ int cifs_closedir(struct inode *inode, struct file *file)
/* not much we can do if it fails anyway, ignore rc */
/* not much we can do if it fails anyway, ignore rc */
rc
=
0
;
rc
=
0
;
}
else
}
else
spin_unlock
(
&
c
ifs_file_list
_lock
);
spin_unlock
(
&
c
file
->
file_info
_lock
);
buf
=
cfile
->
srch_inf
.
ntwrk_buf_start
;
buf
=
cfile
->
srch_inf
.
ntwrk_buf_start
;
if
(
buf
)
{
if
(
buf
)
{
...
@@ -1727,12 +1733,13 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
...
@@ -1727,12 +1733,13 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
{
{
struct
cifsFileInfo
*
open_file
=
NULL
;
struct
cifsFileInfo
*
open_file
=
NULL
;
struct
cifs_sb_info
*
cifs_sb
=
CIFS_SB
(
cifs_inode
->
vfs_inode
.
i_sb
);
struct
cifs_sb_info
*
cifs_sb
=
CIFS_SB
(
cifs_inode
->
vfs_inode
.
i_sb
);
struct
cifs_tcon
*
tcon
=
cifs_sb_master_tcon
(
cifs_sb
);
/* only filter by fsuid on multiuser mounts */
/* only filter by fsuid on multiuser mounts */
if
(
!
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MULTIUSER
))
if
(
!
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MULTIUSER
))
fsuid_only
=
false
;
fsuid_only
=
false
;
spin_lock
(
&
cifs_file_list
_lock
);
spin_lock
(
&
tcon
->
open_file
_lock
);
/* we could simply get the first_list_entry since write-only entries
/* we could simply get the first_list_entry since write-only entries
are always at the end of the list but since the first entry might
are always at the end of the list but since the first entry might
have a close pending, we go through the whole list */
have a close pending, we go through the whole list */
...
@@ -1743,8 +1750,8 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
...
@@ -1743,8 +1750,8 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
if
(
!
open_file
->
invalidHandle
)
{
if
(
!
open_file
->
invalidHandle
)
{
/* found a good file */
/* found a good file */
/* lock it so it will not be closed on us */
/* lock it so it will not be closed on us */
cifsFileInfo_get
_locked
(
open_file
);
cifsFileInfo_get
(
open_file
);
spin_unlock
(
&
cifs_file_list
_lock
);
spin_unlock
(
&
tcon
->
open_file
_lock
);
return
open_file
;
return
open_file
;
}
/* else might as well continue, and look for
}
/* else might as well continue, and look for
another, or simply have the caller reopen it
another, or simply have the caller reopen it
...
@@ -1752,7 +1759,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
...
@@ -1752,7 +1759,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
}
else
/* write only file */
}
else
/* write only file */
break
;
/* write only files are last so must be done */
break
;
/* write only files are last so must be done */
}
}
spin_unlock
(
&
cifs_file_list
_lock
);
spin_unlock
(
&
tcon
->
open_file
_lock
);
return
NULL
;
return
NULL
;
}
}
...
@@ -1761,6 +1768,7 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
...
@@ -1761,6 +1768,7 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
{
{
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
;
struct
cifs_tcon
*
tcon
;
bool
any_available
=
false
;
bool
any_available
=
false
;
int
rc
;
int
rc
;
unsigned
int
refind
=
0
;
unsigned
int
refind
=
0
;
...
@@ -1776,15 +1784,16 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
...
@@ -1776,15 +1784,16 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
}
}
cifs_sb
=
CIFS_SB
(
cifs_inode
->
vfs_inode
.
i_sb
);
cifs_sb
=
CIFS_SB
(
cifs_inode
->
vfs_inode
.
i_sb
);
tcon
=
cifs_sb_master_tcon
(
cifs_sb
);
/* only filter by fsuid on multiuser mounts */
/* only filter by fsuid on multiuser mounts */
if
(
!
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MULTIUSER
))
if
(
!
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MULTIUSER
))
fsuid_only
=
false
;
fsuid_only
=
false
;
spin_lock
(
&
cifs_file_list
_lock
);
spin_lock
(
&
tcon
->
open_file
_lock
);
refind_writable:
refind_writable:
if
(
refind
>
MAX_REOPEN_ATT
)
{
if
(
refind
>
MAX_REOPEN_ATT
)
{
spin_unlock
(
&
cifs_file_list
_lock
);
spin_unlock
(
&
tcon
->
open_file
_lock
);
return
NULL
;
return
NULL
;
}
}
list_for_each_entry
(
open_file
,
&
cifs_inode
->
openFileList
,
flist
)
{
list_for_each_entry
(
open_file
,
&
cifs_inode
->
openFileList
,
flist
)
{
...
@@ -1795,8 +1804,8 @@ refind_writable:
...
@@ -1795,8 +1804,8 @@ refind_writable:
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 */
cifsFileInfo_get
_locked
(
open_file
);
cifsFileInfo_get
(
open_file
);
spin_unlock
(
&
cifs_file_list
_lock
);
spin_unlock
(
&
tcon
->
open_file
_lock
);
return
open_file
;
return
open_file
;
}
else
{
}
else
{
if
(
!
inv_file
)
if
(
!
inv_file
)
...
@@ -1812,24 +1821,24 @@ refind_writable:
...
@@ -1812,24 +1821,24 @@ refind_writable:
if
(
inv_file
)
{
if
(
inv_file
)
{
any_available
=
false
;
any_available
=
false
;
cifsFileInfo_get
_locked
(
inv_file
);
cifsFileInfo_get
(
inv_file
);
}
}
spin_unlock
(
&
cifs_file_list
_lock
);
spin_unlock
(
&
tcon
->
open_file
_lock
);
if
(
inv_file
)
{
if
(
inv_file
)
{
rc
=
cifs_reopen_file
(
inv_file
,
false
);
rc
=
cifs_reopen_file
(
inv_file
,
false
);
if
(
!
rc
)
if
(
!
rc
)
return
inv_file
;
return
inv_file
;
else
{
else
{
spin_lock
(
&
cifs_file_list
_lock
);
spin_lock
(
&
tcon
->
open_file
_lock
);
list_move_tail
(
&
inv_file
->
flist
,
list_move_tail
(
&
inv_file
->
flist
,
&
cifs_inode
->
openFileList
);
&
cifs_inode
->
openFileList
);
spin_unlock
(
&
cifs_file_list
_lock
);
spin_unlock
(
&
tcon
->
open_file
_lock
);
cifsFileInfo_put
(
inv_file
);
cifsFileInfo_put
(
inv_file
);
spin_lock
(
&
cifs_file_list_lock
);
++
refind
;
++
refind
;
inv_file
=
NULL
;
inv_file
=
NULL
;
spin_lock
(
&
tcon
->
open_file_lock
);
goto
refind_writable
;
goto
refind_writable
;
}
}
}
}
...
@@ -2591,18 +2600,19 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *from)
...
@@ -2591,18 +2600,19 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *from)
ssize_t
rc
=
-
EACCES
;
ssize_t
rc
=
-
EACCES
;
loff_t
lock_pos
=
iocb
->
ki_pos
;
loff_t
lock_pos
=
iocb
->
ki_pos
;
mutex_lock
(
&
inode
->
i_mutex
);
/*
/*
* We need to hold the sem to be sure nobody modifies lock list
* We need to hold the sem to be sure nobody modifies lock list
* with a brlock that prevents writing.
* with a brlock that prevents writing.
*/
*/
down_read
(
&
cinode
->
lock_sem
);
down_read
(
&
cinode
->
lock_sem
);
mutex_lock
(
&
inode
->
i_mutex
);
if
(
file
->
f_flags
&
O_APPEND
)
if
(
file
->
f_flags
&
O_APPEND
)
lock_pos
=
i_size_read
(
inode
);
lock_pos
=
i_size_read
(
inode
);
if
(
!
cifs_find_lock_conflict
(
cfile
,
lock_pos
,
iov_iter_count
(
from
),
if
(
!
cifs_find_lock_conflict
(
cfile
,
lock_pos
,
iov_iter_count
(
from
),
server
->
vals
->
exclusive_lock_type
,
NULL
,
server
->
vals
->
exclusive_lock_type
,
NULL
,
CIFS_WRITE_OP
))
{
CIFS_WRITE_OP
))
{
rc
=
__generic_file_write_iter
(
iocb
,
from
);
rc
=
__generic_file_write_iter
(
iocb
,
from
);
up_read
(
&
cinode
->
lock_sem
);
mutex_unlock
(
&
inode
->
i_mutex
);
mutex_unlock
(
&
inode
->
i_mutex
);
if
(
rc
>
0
)
{
if
(
rc
>
0
)
{
...
@@ -2613,9 +2623,9 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *from)
...
@@ -2613,9 +2623,9 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *from)
rc
=
err
;
rc
=
err
;
}
}
}
else
{
}
else
{
up_read
(
&
cinode
->
lock_sem
);
mutex_unlock
(
&
inode
->
i_mutex
);
mutex_unlock
(
&
inode
->
i_mutex
);
}
}
up_read
(
&
cinode
->
lock_sem
);
return
rc
;
return
rc
;
}
}
...
@@ -3474,15 +3484,17 @@ static int cifs_readpage(struct file *file, struct page *page)
...
@@ -3474,15 +3484,17 @@ static int cifs_readpage(struct file *file, struct page *page)
static
int
is_inode_writable
(
struct
cifsInodeInfo
*
cifs_inode
)
static
int
is_inode_writable
(
struct
cifsInodeInfo
*
cifs_inode
)
{
{
struct
cifsFileInfo
*
open_file
;
struct
cifsFileInfo
*
open_file
;
struct
cifs_tcon
*
tcon
=
cifs_sb_master_tcon
(
CIFS_SB
(
cifs_inode
->
vfs_inode
.
i_sb
));
spin_lock
(
&
cifs_file_list
_lock
);
spin_lock
(
&
tcon
->
open_file
_lock
);
list_for_each_entry
(
open_file
,
&
cifs_inode
->
openFileList
,
flist
)
{
list_for_each_entry
(
open_file
,
&
cifs_inode
->
openFileList
,
flist
)
{
if
(
OPEN_FMODE
(
open_file
->
f_flags
)
&
FMODE_WRITE
)
{
if
(
OPEN_FMODE
(
open_file
->
f_flags
)
&
FMODE_WRITE
)
{
spin_unlock
(
&
cifs_file_list
_lock
);
spin_unlock
(
&
tcon
->
open_file
_lock
);
return
1
;
return
1
;
}
}
}
}
spin_unlock
(
&
cifs_file_list
_lock
);
spin_unlock
(
&
tcon
->
open_file
_lock
);
return
0
;
return
0
;
}
}
...
...
sources/3.16/inode.c
View file @
7e23c0f8
...
@@ -445,7 +445,6 @@ cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
...
@@ -445,7 +445,6 @@ cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
oparms
.
tcon
=
tcon
;
oparms
.
tcon
=
tcon
;
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
desired_access
=
GENERIC_READ
;
oparms
.
desired_access
=
GENERIC_READ
;
oparms
.
share_access
=
FILE_SHARE_ALL
;
oparms
.
create_options
=
CREATE_NOT_DIR
;
oparms
.
create_options
=
CREATE_NOT_DIR
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
path
=
path
;
oparms
.
path
=
path
;
...
@@ -951,12 +950,29 @@ struct inode *cifs_root_iget(struct super_block *sb)
...
@@ -951,12 +950,29 @@ struct inode *cifs_root_iget(struct super_block *sb)
struct
inode
*
inode
=
NULL
;
struct
inode
*
inode
=
NULL
;
long
rc
;
long
rc
;
struct
cifs_tcon
*
tcon
=
cifs_sb_master_tcon
(
cifs_sb
);
struct
cifs_tcon
*
tcon
=
cifs_sb_master_tcon
(
cifs_sb
);
char
*
path
=
NULL
;
int
len
;
if
((
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_USE_PREFIX_PATH
)
&&
cifs_sb
->
prepath
)
{
len
=
strlen
(
cifs_sb
->
prepath
);
path
=
kzalloc
(
len
+
2
/* leading sep + null */
,
GFP_KERNEL
);
if
(
path
==
NULL
)
return
ERR_PTR
(
-
ENOMEM
);
path
[
0
]
=
'/'
;
memcpy
(
path
+
1
,
cifs_sb
->
prepath
,
len
);
}
else
{
path
=
kstrdup
(
""
,
GFP_KERNEL
);
if
(
path
==
NULL
)
return
ERR_PTR
(
-
ENOMEM
);
}
xid
=
get_xid
();
xid
=
get_xid
();
convert_delimiter
(
path
,
CIFS_DIR_SEP
(
cifs_sb
));
if
(
tcon
->
unix_ext
)
if
(
tcon
->
unix_ext
)
rc
=
cifs_get_inode_info_unix
(
&
inode
,
""
,
sb
,
xid
);
rc
=
cifs_get_inode_info_unix
(
&
inode
,
path
,
sb
,
xid
);
else
else
rc
=
cifs_get_inode_info
(
&
inode
,
""
,
NULL
,
sb
,
xid
,
NULL
);
rc
=
cifs_get_inode_info
(
&
inode
,
path
,
NULL
,
sb
,
xid
,
NULL
);
if
(
!
inode
)
{
if
(
!
inode
)
{
inode
=
ERR_PTR
(
rc
);
inode
=
ERR_PTR
(
rc
);
...
@@ -984,6 +1000,7 @@ struct inode *cifs_root_iget(struct super_block *sb)
...
@@ -984,6 +1000,7 @@ struct inode *cifs_root_iget(struct super_block *sb)
}
}
out:
out:
kfree
(
path
);
/* can not call macro free_xid here since in a void func
/* can not call macro free_xid here since in a void func
* TODO: This is no longer true
* TODO: This is no longer true
*/
*/
...
@@ -1078,7 +1095,6 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
...
@@ -1078,7 +1095,6 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
oparms
.
tcon
=
tcon
;
oparms
.
tcon
=
tcon
;
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
desired_access
=
DELETE
|
FILE_WRITE_ATTRIBUTES
;
oparms
.
desired_access
=
DELETE
|
FILE_WRITE_ATTRIBUTES
;
oparms
.
share_access
=
FILE_SHARE_ALL
;
oparms
.
create_options
=
CREATE_NOT_DIR
;
oparms
.
create_options
=
CREATE_NOT_DIR
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
path
=
full_path
;
oparms
.
path
=
full_path
;
...
@@ -1122,7 +1138,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
...
@@ -1122,7 +1138,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
cifs_sb
->
mnt_cifs_flags
&
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MAP_SPECIAL_CHR
);
CIFS_MOUNT_MAP_SPECIAL_CHR
);
if
(
rc
!=
0
)
{
if
(
rc
!=
0
)
{
rc
=
-
E
TXTB
SY
;
rc
=
-
E
BU
SY
;
goto
undo_setattr
;
goto
undo_setattr
;
}
}
...
@@ -1141,7 +1157,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
...
@@ -1141,7 +1157,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
if
(
rc
==
-
ENOENT
)
if
(
rc
==
-
ENOENT
)
rc
=
0
;
rc
=
0
;
else
if
(
rc
!=
0
)
{
else
if
(
rc
!=
0
)
{
rc
=
-
E
TXTB
SY
;
rc
=
-
E
BU
SY
;
goto
undo_rename
;
goto
undo_rename
;
}
}
set_bit
(
CIFS_INO_DELETE_PENDING
,
&
cifsInode
->
flags
);
set_bit
(
CIFS_INO_DELETE_PENDING
,
&
cifsInode
->
flags
);
...
@@ -1248,15 +1264,13 @@ psx_del_no_retry:
...
@@ -1248,15 +1264,13 @@ psx_del_no_retry:
cifs_drop_nlink
(
inode
);
cifs_drop_nlink
(
inode
);
}
else
if
(
rc
==
-
ENOENT
)
{
}
else
if
(
rc
==
-
ENOENT
)
{
d_drop
(
dentry
);
d_drop
(
dentry
);
}
else
if
(
rc
==
-
E
TXTB
SY
)
{
}
else
if
(
rc
==
-
E
BU
SY
)
{
if
(
server
->
ops
->
rename_pending_delete
)
{
if
(
server
->
ops
->
rename_pending_delete
)
{
rc
=
server
->
ops
->
rename_pending_delete
(
full_path
,
rc
=
server
->
ops
->
rename_pending_delete
(
full_path
,
dentry
,
xid
);
dentry
,
xid
);
if
(
rc
==
0
)
if
(
rc
==
0
)
cifs_drop_nlink
(
inode
);
cifs_drop_nlink
(
inode
);
}
}
if
(
rc
==
-
ETXTBSY
)
rc
=
-
EBUSY
;
}
else
if
((
rc
==
-
EACCES
)
&&
(
dosattr
==
0
)
&&
inode
)
{
}
else
if
((
rc
==
-
EACCES
)
&&
(
dosattr
==
0
)
&&
inode
)
{
attrs
=
kzalloc
(
sizeof
(
*
attrs
),
GFP_KERNEL
);
attrs
=
kzalloc
(
sizeof
(
*
attrs
),
GFP_KERNEL
);
if
(
attrs
==
NULL
)
{
if
(
attrs
==
NULL
)
{
...
@@ -1600,7 +1614,7 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
...
@@ -1600,7 +1614,7 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
* source. Note that cross directory moves do not work with
* source. Note that cross directory moves do not work with
* rename by filehandle to various Windows servers.
* rename by filehandle to various Windows servers.
*/
*/
if
(
rc
==
0
||
rc
!=
-
E
TXTB
SY
)
if
(
rc
==
0
||
rc
!=
-
E
BU
SY
)
goto
do_rename_exit
;
goto
do_rename_exit
;
/* open-file renames don't work across directories */
/* open-file renames don't work across directories */
...
@@ -1611,7 +1625,6 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
...
@@ -1611,7 +1625,6 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
cifs_sb
=
cifs_sb
;
/* open the file to be renamed -- we need DELETE perms */
/* open the file to be renamed -- we need DELETE perms */
oparms
.
desired_access
=
DELETE
;
oparms
.
desired_access
=
DELETE
;
oparms
.
share_access
=
FILE_SHARE_ALL
;
oparms
.
create_options
=
CREATE_NOT_DIR
;
oparms
.
create_options
=
CREATE_NOT_DIR
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
path
=
from_path
;
oparms
.
path
=
from_path
;
...
@@ -2079,7 +2092,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
...
@@ -2079,7 +2092,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NO_PERM
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NO_PERM
)
attrs
->
ia_valid
|=
ATTR_FORCE
;
attrs
->
ia_valid
|=
ATTR_FORCE
;
rc
=
inode_change_ok
(
inode
,
attrs
);
rc
=
setattr_prepare
(
direntry
,
attrs
);
if
(
rc
<
0
)
if
(
rc
<
0
)
goto
out
;
goto
out
;
...
@@ -2220,7 +2233,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
...
@@ -2220,7 +2233,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NO_PERM
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NO_PERM
)
attrs
->
ia_valid
|=
ATTR_FORCE
;
attrs
->
ia_valid
|=
ATTR_FORCE
;
rc
=
inode_change_ok
(
inode
,
attrs
);
rc
=
setattr_prepare
(
direntry
,
attrs
);
if
(
rc
<
0
)
{
if
(
rc
<
0
)
{
free_xid
(
xid
);
free_xid
(
xid
);
return
rc
;
return
rc
;
...
...
sources/3.16/link.c
View file @
7e23c0f8
...
@@ -333,7 +333,6 @@ cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
...
@@ -333,7 +333,6 @@ cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
oparms
.
tcon
=
tcon
;
oparms
.
tcon
=
tcon
;
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
desired_access
=
GENERIC_READ
;
oparms
.
desired_access
=
GENERIC_READ
;
oparms
.
share_access
=
FILE_SHARE_ALL
;
oparms
.
create_options
=
CREATE_NOT_DIR
;
oparms
.
create_options
=
CREATE_NOT_DIR
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
path
=
path
;
oparms
.
path
=
path
;
...
@@ -378,7 +377,6 @@ cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
...
@@ -378,7 +377,6 @@ cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
oparms
.
tcon
=
tcon
;
oparms
.
tcon
=
tcon
;
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
desired_access
=
GENERIC_WRITE
;
oparms
.
desired_access
=
GENERIC_WRITE
;
oparms
.
share_access
=
FILE_SHARE_ALL
;
oparms
.
create_options
=
create_options
;
oparms
.
create_options
=
create_options
;
oparms
.
disposition
=
FILE_CREATE
;
oparms
.
disposition
=
FILE_CREATE
;
oparms
.
path
=
path
;
oparms
.
path
=
path
;
...
...
sources/3.16/misc.c
View file @
7e23c0f8
...
@@ -120,6 +120,7 @@ tconInfoAlloc(void)
...
@@ -120,6 +120,7 @@ tconInfoAlloc(void)
++
ret_buf
->
tc_count
;
++
ret_buf
->
tc_count
;
INIT_LIST_HEAD
(
&
ret_buf
->
openFileList
);
INIT_LIST_HEAD
(
&
ret_buf
->
openFileList
);
INIT_LIST_HEAD
(
&
ret_buf
->
tcon_list
);
INIT_LIST_HEAD
(
&
ret_buf
->
tcon_list
);
spin_lock_init
(
&
ret_buf
->
open_file_lock
);
#ifdef CONFIG_CIFS_STATS
#ifdef CONFIG_CIFS_STATS
spin_lock_init
(
&
ret_buf
->
stat_lock
);
spin_lock_init
(
&
ret_buf
->
stat_lock
);
#endif
#endif
...
@@ -456,7 +457,7 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
...
@@ -456,7 +457,7 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
continue
;
continue
;
cifs_stats_inc
(
&
tcon
->
stats
.
cifs_stats
.
num_oplock_brks
);
cifs_stats_inc
(
&
tcon
->
stats
.
cifs_stats
.
num_oplock_brks
);
spin_lock
(
&
cifs_file_list
_lock
);
spin_lock
(
&
tcon
->
open_file
_lock
);
list_for_each
(
tmp2
,
&
tcon
->
openFileList
)
{
list_for_each
(
tmp2
,
&
tcon
->
openFileList
)
{
netfile
=
list_entry
(
tmp2
,
struct
cifsFileInfo
,
netfile
=
list_entry
(
tmp2
,
struct
cifsFileInfo
,
tlist
);
tlist
);
...
@@ -482,15 +483,15 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
...
@@ -482,15 +483,15 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2
,
CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2
,
&
pCifsInode
->
flags
);
&
pCifsInode
->
flags
);
queue_work
(
cifs
io
d_wq
,
queue_work
(
cifs
oplock
d_wq
,
&
netfile
->
oplock_break
);
&
netfile
->
oplock_break
);
netfile
->
oplock_break_cancelled
=
false
;
netfile
->
oplock_break_cancelled
=
false
;
spin_unlock
(
&
cifs_file_list
_lock
);
spin_unlock
(
&
tcon
->
open_file
_lock
);
spin_unlock
(
&
cifs_tcp_ses_lock
);
spin_unlock
(
&
cifs_tcp_ses_lock
);
return
true
;
return
true
;
}
}
spin_unlock
(
&
cifs_file_list
_lock
);
spin_unlock
(
&
tcon
->
open_file
_lock
);
spin_unlock
(
&
cifs_tcp_ses_lock
);
spin_unlock
(
&
cifs_tcp_ses_lock
);
cifs_dbg
(
FYI
,
"No matching file for oplock break
\n
"
);
cifs_dbg
(
FYI
,
"No matching file for oplock break
\n
"
);
return
true
;
return
true
;
...
@@ -639,9 +640,9 @@ backup_cred(struct cifs_sb_info *cifs_sb)
...
@@ -639,9 +640,9 @@ backup_cred(struct cifs_sb_info *cifs_sb)
void
void
cifs_del_pending_open
(
struct
cifs_pending_open
*
open
)
cifs_del_pending_open
(
struct
cifs_pending_open
*
open
)
{
{
spin_lock
(
&
cifs_file_list
_lock
);
spin_lock
(
&
tlink_tcon
(
open
->
tlink
)
->
open_file
_lock
);
list_del
(
&
open
->
olist
);
list_del
(
&
open
->
olist
);
spin_unlock
(
&
cifs_file_list
_lock
);
spin_unlock
(
&
tlink_tcon
(
open
->
tlink
)
->
open_file
_lock
);
}
}
void
void
...
@@ -661,7 +662,7 @@ void
...
@@ -661,7 +662,7 @@ void
cifs_add_pending_open
(
struct
cifs_fid
*
fid
,
struct
tcon_link
*
tlink
,
cifs_add_pending_open
(
struct
cifs_fid
*
fid
,
struct
tcon_link
*
tlink
,
struct
cifs_pending_open
*
open
)
struct
cifs_pending_open
*
open
)
{
{
spin_lock
(
&
cifs_file_list
_lock
);
spin_lock
(
&
tlink_tcon
(
tlink
)
->
open_file
_lock
);
cifs_add_pending_open_locked
(
fid
,
tlink
,
open
);
cifs_add_pending_open_locked
(
fid
,
tlink
,
open
);
spin_unlock
(
&
cifs_file_list
_lock
);
spin_unlock
(
&
tlink_tcon
(
open
->
tlink
)
->
open_file
_lock
);
}
}
sources/3.16/netmisc.c
View file @
7e23c0f8
...
@@ -62,7 +62,7 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = {
...
@@ -62,7 +62,7 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = {
{
ERRdiffdevice
,
-
EXDEV
},
{
ERRdiffdevice
,
-
EXDEV
},
{
ERRnofiles
,
-
ENOENT
},
{
ERRnofiles
,
-
ENOENT
},
{
ERRwriteprot
,
-
EROFS
},
{
ERRwriteprot
,
-
EROFS
},
{
ERRbadshare
,
-
E
TXTB
SY
},
{
ERRbadshare
,
-
E
BU
SY
},
{
ERRlock
,
-
EACCES
},
{
ERRlock
,
-
EACCES
},
{
ERRunsup
,
-
EINVAL
},
{
ERRunsup
,
-
EINVAL
},
{
ERRnosuchshare
,
-
ENXIO
},
{
ERRnosuchshare
,
-
ENXIO
},
...
@@ -966,10 +966,10 @@ struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, int offset)
...
@@ -966,10 +966,10 @@ struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, int offset)
cifs_dbg
(
VFS
,
"illegal hours %d
\n
"
,
st
->
Hours
);
cifs_dbg
(
VFS
,
"illegal hours %d
\n
"
,
st
->
Hours
);
days
=
sd
->
Day
;
days
=
sd
->
Day
;
month
=
sd
->
Month
;
month
=
sd
->
Month
;
if
(
(
days
>
31
)
||
(
month
>
12
)
)
{
if
(
days
<
1
||
days
>
31
||
month
<
1
||
month
>
12
)
{
cifs_dbg
(
VFS
,
"illegal date, month %d day: %d
\n
"
,
month
,
days
);
cifs_dbg
(
VFS
,
"illegal date, month %d day: %d
\n
"
,
month
,
days
);
if
(
month
>
12
)
days
=
clamp
(
days
,
1
,
31
);
month
=
12
;
month
=
clamp
(
month
,
1
,
12
)
;
}
}
month
-=
1
;
month
-=
1
;
days
+=
total_days_of_prev_months
[
month
];
days
+=
total_days_of_prev_months
[
month
];
...
...
sources/3.16/ntlmssp.h
View file @
7e23c0f8
...
@@ -133,6 +133,6 @@ typedef struct _AUTHENTICATE_MESSAGE {
...
@@ -133,6 +133,6 @@ typedef struct _AUTHENTICATE_MESSAGE {
int
decode_ntlmssp_challenge
(
char
*
bcc_ptr
,
int
blob_len
,
struct
cifs_ses
*
ses
);
int
decode_ntlmssp_challenge
(
char
*
bcc_ptr
,
int
blob_len
,
struct
cifs_ses
*
ses
);
void
build_ntlmssp_negotiate_blob
(
unsigned
char
*
pbuffer
,
struct
cifs_ses
*
ses
);
void
build_ntlmssp_negotiate_blob
(
unsigned
char
*
pbuffer
,
struct
cifs_ses
*
ses
);
int
build_ntlmssp_auth_blob
(
unsigned
char
*
pbuffer
,
u16
*
buflen
,
int
build_ntlmssp_auth_blob
(
unsigned
char
*
*
pbuffer
,
u16
*
buflen
,
struct
cifs_ses
*
ses
,
struct
cifs_ses
*
ses
,
const
struct
nls_table
*
nls_cp
);
const
struct
nls_table
*
nls_cp
);
sources/3.16/readdir.c
View file @
7e23c0f8
...
@@ -241,7 +241,7 @@ int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb,
...
@@ -241,7 +241,7 @@ int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb,
char *tmpbuffer;
char *tmpbuffer;
rc = CIFSSMBOpen(xid, ptcon, full_path, FILE_OPEN, GENERIC_READ,
rc = CIFSSMBOpen(xid, ptcon, full_path, FILE_OPEN, GENERIC_READ,
FILE_SHARE_ALL,
OPEN_REPARSE_POINT, &fid, &oplock, NULL,
OPEN_REPARSE_POINT, &fid, &oplock, NULL,
cifs_sb->local_nls,
cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
if (!rc) {
if (!rc) {
...
@@ -592,14 +592,14 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos,
...
@@ -592,14 +592,14 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos,
is_dir_changed
(
file
))
||
(
index_to_find
<
first_entry_in_buffer
))
{
is_dir_changed
(
file
))
||
(
index_to_find
<
first_entry_in_buffer
))
{
/* close and restart search */
/* close and restart search */
cifs_dbg
(
FYI
,
"search backing up - close and restart search
\n
"
);
cifs_dbg
(
FYI
,
"search backing up - close and restart search
\n
"
);
spin_lock
(
&
c
ifs_file_list
_lock
);
spin_lock
(
&
c
file
->
file_info
_lock
);
if
(
server
->
ops
->
dir_needs_close
(
cfile
))
{
if
(
server
->
ops
->
dir_needs_close
(
cfile
))
{
cfile
->
invalidHandle
=
true
;
cfile
->
invalidHandle
=
true
;
spin_unlock
(
&
c
ifs_file_list
_lock
);
spin_unlock
(
&
c
file
->
file_info
_lock
);
if
(
server
->
ops
->
close_dir
)
if
(
server
->
ops
->
close_dir
)
server
->
ops
->
close_dir
(
xid
,
tcon
,
&
cfile
->
fid
);
server
->
ops
->
close_dir
(
xid
,
tcon
,
&
cfile
->
fid
);
}
else
}
else
spin_unlock
(
&
c
ifs_file_list
_lock
);
spin_unlock
(
&
c
file
->
file_info
_lock
);
if
(
cfile
->
srch_inf
.
ntwrk_buf_start
)
{
if
(
cfile
->
srch_inf
.
ntwrk_buf_start
)
{
cifs_dbg
(
FYI
,
"freeing SMB ff cache buf on search rewind
\n
"
);
cifs_dbg
(
FYI
,
"freeing SMB ff cache buf on search rewind
\n
"
);
if
(
cfile
->
srch_inf
.
smallBuf
)
if
(
cfile
->
srch_inf
.
smallBuf
)
...
...
sources/3.16/sess.c
View file @
7e23c0f8
...
@@ -363,19 +363,43 @@ void build_ntlmssp_negotiate_blob(unsigned char *pbuffer,
...
@@ -363,19 +363,43 @@ void build_ntlmssp_negotiate_blob(unsigned char *pbuffer,
sec_blob
->
DomainName
.
MaximumLength
=
0
;
sec_blob
->
DomainName
.
MaximumLength
=
0
;
}
}
/* We do not malloc the blob, it is passed in pbuffer, because its
static
int
size_of_ntlmssp_blob
(
struct
cifs_ses
*
ses
)
maximum possible size is fixed and small, making this approach cleaner.
{
This function returns the length of the data in the blob */
int
sz
=
sizeof
(
AUTHENTICATE_MESSAGE
)
+
ses
->
auth_key
.
len
int
build_ntlmssp_auth_blob
(
unsigned
char
*
pbuffer
,
-
CIFS_SESS_KEY_SIZE
+
CIFS_CPHTXT_SIZE
+
2
;
if
(
ses
->
domainName
)
sz
+=
2
*
strnlen
(
ses
->
domainName
,
CIFS_MAX_DOMAINNAME_LEN
);
else
sz
+=
2
;
if
(
ses
->
user_name
)
sz
+=
2
*
strnlen
(
ses
->
user_name
,
CIFS_MAX_USERNAME_LEN
);
else
sz
+=
2
;
return
sz
;
}
int
build_ntlmssp_auth_blob
(
unsigned
char
**
pbuffer
,
u16
*
buflen
,
u16
*
buflen
,
struct
cifs_ses
*
ses
,
struct
cifs_ses
*
ses
,
const
struct
nls_table
*
nls_cp
)
const
struct
nls_table
*
nls_cp
)
{
{
int
rc
;
int
rc
;
AUTHENTICATE_MESSAGE
*
sec_blob
=
(
AUTHENTICATE_MESSAGE
*
)
pbuffer
;
AUTHENTICATE_MESSAGE
*
sec_blob
;
__u32
flags
;
__u32
flags
;
unsigned
char
*
tmp
;
unsigned
char
*
tmp
;
rc
=
setup_ntlmv2_rsp
(
ses
,
nls_cp
);
if
(
rc
)
{
cifs_dbg
(
VFS
,
"Error %d during NTLMSSP authentication
\n
"
,
rc
);
*
buflen
=
0
;
goto
setup_ntlmv2_ret
;
}
*
pbuffer
=
kmalloc
(
size_of_ntlmssp_blob
(
ses
),
GFP_KERNEL
);
sec_blob
=
(
AUTHENTICATE_MESSAGE
*
)
*
pbuffer
;
memcpy
(
sec_blob
->
Signature
,
NTLMSSP_SIGNATURE
,
8
);
memcpy
(
sec_blob
->
Signature
,
NTLMSSP_SIGNATURE
,
8
);
sec_blob
->
MessageType
=
NtLmAuthenticate
;
sec_blob
->
MessageType
=
NtLmAuthenticate
;
...
@@ -390,7 +414,7 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
...
@@ -390,7 +414,7 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
flags
|=
NTLMSSP_NEGOTIATE_KEY_XCH
;
flags
|=
NTLMSSP_NEGOTIATE_KEY_XCH
;
}
}
tmp
=
pbuffer
+
sizeof
(
AUTHENTICATE_MESSAGE
);
tmp
=
*
pbuffer
+
sizeof
(
AUTHENTICATE_MESSAGE
);
sec_blob
->
NegotiateFlags
=
cpu_to_le32
(
flags
);
sec_blob
->
NegotiateFlags
=
cpu_to_le32
(
flags
);
sec_blob
->
LmChallengeResponse
.
BufferOffset
=
sec_blob
->
LmChallengeResponse
.
BufferOffset
=
...
@@ -398,39 +422,43 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
...
@@ -398,39 +422,43 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
sec_blob
->
LmChallengeResponse
.
Length
=
0
;
sec_blob
->
LmChallengeResponse
.
Length
=
0
;
sec_blob
->
LmChallengeResponse
.
MaximumLength
=
0
;
sec_blob
->
LmChallengeResponse
.
MaximumLength
=
0
;
sec_blob
->
NtChallengeResponse
.
BufferOffset
=
cpu_to_le32
(
tmp
-
pbuffer
);
sec_blob
->
NtChallengeResponse
.
BufferOffset
=
rc
=
setup_ntlmv2_rsp
(
ses
,
nls_cp
);
cpu_to_le32
(
tmp
-
*
pbuffer
);
if
(
rc
)
{
if
(
ses
->
user_name
!=
NULL
)
{
cifs_dbg
(
VFS
,
"Error %d during NTLMSSP authentication
\n
"
,
rc
);
memcpy
(
tmp
,
ses
->
auth_key
.
response
+
CIFS_SESS_KEY_SIZE
,
goto
setup_ntlmv2_ret
;
ses
->
auth_key
.
len
-
CIFS_SESS_KEY_SIZE
);
}
tmp
+=
ses
->
auth_key
.
len
-
CIFS_SESS_KEY_SIZE
;
memcpy
(
tmp
,
ses
->
auth_key
.
response
+
CIFS_SESS_KEY_SIZE
,
ses
->
auth_key
.
len
-
CIFS_SESS_KEY_SIZE
);
tmp
+=
ses
->
auth_key
.
len
-
CIFS_SESS_KEY_SIZE
;
sec_blob
->
NtChallengeResponse
.
Length
=
sec_blob
->
NtChallengeResponse
.
Length
=
cpu_to_le16
(
ses
->
auth_key
.
len
-
CIFS_SESS_KEY_SIZE
);
cpu_to_le16
(
ses
->
auth_key
.
len
-
CIFS_SESS_KEY_SIZE
);
sec_blob
->
NtChallengeResponse
.
MaximumLength
=
sec_blob
->
NtChallengeResponse
.
MaximumLength
=
cpu_to_le16
(
ses
->
auth_key
.
len
-
CIFS_SESS_KEY_SIZE
);
cpu_to_le16
(
ses
->
auth_key
.
len
-
CIFS_SESS_KEY_SIZE
);
}
else
{
/*
* don't send an NT Response for anonymous access
*/
sec_blob
->
NtChallengeResponse
.
Length
=
0
;
sec_blob
->
NtChallengeResponse
.
MaximumLength
=
0
;
}
if
(
ses
->
domainName
==
NULL
)
{
if
(
ses
->
domainName
==
NULL
)
{
sec_blob
->
DomainName
.
BufferOffset
=
cpu_to_le32
(
tmp
-
pbuffer
);
sec_blob
->
DomainName
.
BufferOffset
=
cpu_to_le32
(
tmp
-
*
pbuffer
);
sec_blob
->
DomainName
.
Length
=
0
;
sec_blob
->
DomainName
.
Length
=
0
;
sec_blob
->
DomainName
.
MaximumLength
=
0
;
sec_blob
->
DomainName
.
MaximumLength
=
0
;
tmp
+=
2
;
tmp
+=
2
;
}
else
{
}
else
{
int
len
;
int
len
;
len
=
cifs_strtoUTF16
((
__le16
*
)
tmp
,
ses
->
domainName
,
len
=
cifs_strtoUTF16
((
__le16
*
)
tmp
,
ses
->
domainName
,
CIFS_MAX_
USER
NAME_LEN
,
nls_cp
);
CIFS_MAX_
DOMAIN
NAME_LEN
,
nls_cp
);
len
*=
2
;
/* unicode is 2 bytes each */
len
*=
2
;
/* unicode is 2 bytes each */
sec_blob
->
DomainName
.
BufferOffset
=
cpu_to_le32
(
tmp
-
pbuffer
);
sec_blob
->
DomainName
.
BufferOffset
=
cpu_to_le32
(
tmp
-
*
pbuffer
);
sec_blob
->
DomainName
.
Length
=
cpu_to_le16
(
len
);
sec_blob
->
DomainName
.
Length
=
cpu_to_le16
(
len
);
sec_blob
->
DomainName
.
MaximumLength
=
cpu_to_le16
(
len
);
sec_blob
->
DomainName
.
MaximumLength
=
cpu_to_le16
(
len
);
tmp
+=
len
;
tmp
+=
len
;
}
}
if
(
ses
->
user_name
==
NULL
)
{
if
(
ses
->
user_name
==
NULL
)
{
sec_blob
->
UserName
.
BufferOffset
=
cpu_to_le32
(
tmp
-
pbuffer
);
sec_blob
->
UserName
.
BufferOffset
=
cpu_to_le32
(
tmp
-
*
pbuffer
);
sec_blob
->
UserName
.
Length
=
0
;
sec_blob
->
UserName
.
Length
=
0
;
sec_blob
->
UserName
.
MaximumLength
=
0
;
sec_blob
->
UserName
.
MaximumLength
=
0
;
tmp
+=
2
;
tmp
+=
2
;
...
@@ -439,13 +467,13 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
...
@@ -439,13 +467,13 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
len
=
cifs_strtoUTF16
((
__le16
*
)
tmp
,
ses
->
user_name
,
len
=
cifs_strtoUTF16
((
__le16
*
)
tmp
,
ses
->
user_name
,
CIFS_MAX_USERNAME_LEN
,
nls_cp
);
CIFS_MAX_USERNAME_LEN
,
nls_cp
);
len
*=
2
;
/* unicode is 2 bytes each */
len
*=
2
;
/* unicode is 2 bytes each */
sec_blob
->
UserName
.
BufferOffset
=
cpu_to_le32
(
tmp
-
pbuffer
);
sec_blob
->
UserName
.
BufferOffset
=
cpu_to_le32
(
tmp
-
*
pbuffer
);
sec_blob
->
UserName
.
Length
=
cpu_to_le16
(
len
);
sec_blob
->
UserName
.
Length
=
cpu_to_le16
(
len
);
sec_blob
->
UserName
.
MaximumLength
=
cpu_to_le16
(
len
);
sec_blob
->
UserName
.
MaximumLength
=
cpu_to_le16
(
len
);
tmp
+=
len
;
tmp
+=
len
;
}
}
sec_blob
->
WorkstationName
.
BufferOffset
=
cpu_to_le32
(
tmp
-
pbuffer
);
sec_blob
->
WorkstationName
.
BufferOffset
=
cpu_to_le32
(
tmp
-
*
pbuffer
);
sec_blob
->
WorkstationName
.
Length
=
0
;
sec_blob
->
WorkstationName
.
Length
=
0
;
sec_blob
->
WorkstationName
.
MaximumLength
=
0
;
sec_blob
->
WorkstationName
.
MaximumLength
=
0
;
tmp
+=
2
;
tmp
+=
2
;
...
@@ -454,19 +482,19 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
...
@@ -454,19 +482,19 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
(
ses
->
ntlmssp
->
server_flags
&
NTLMSSP_NEGOTIATE_EXTENDED_SEC
))
(
ses
->
ntlmssp
->
server_flags
&
NTLMSSP_NEGOTIATE_EXTENDED_SEC
))
&&
!
calc_seckey
(
ses
))
{
&&
!
calc_seckey
(
ses
))
{
memcpy
(
tmp
,
ses
->
ntlmssp
->
ciphertext
,
CIFS_CPHTXT_SIZE
);
memcpy
(
tmp
,
ses
->
ntlmssp
->
ciphertext
,
CIFS_CPHTXT_SIZE
);
sec_blob
->
SessionKey
.
BufferOffset
=
cpu_to_le32
(
tmp
-
pbuffer
);
sec_blob
->
SessionKey
.
BufferOffset
=
cpu_to_le32
(
tmp
-
*
pbuffer
);
sec_blob
->
SessionKey
.
Length
=
cpu_to_le16
(
CIFS_CPHTXT_SIZE
);
sec_blob
->
SessionKey
.
Length
=
cpu_to_le16
(
CIFS_CPHTXT_SIZE
);
sec_blob
->
SessionKey
.
MaximumLength
=
sec_blob
->
SessionKey
.
MaximumLength
=
cpu_to_le16
(
CIFS_CPHTXT_SIZE
);
cpu_to_le16
(
CIFS_CPHTXT_SIZE
);
tmp
+=
CIFS_CPHTXT_SIZE
;
tmp
+=
CIFS_CPHTXT_SIZE
;
}
else
{
}
else
{
sec_blob
->
SessionKey
.
BufferOffset
=
cpu_to_le32
(
tmp
-
pbuffer
);
sec_blob
->
SessionKey
.
BufferOffset
=
cpu_to_le32
(
tmp
-
*
pbuffer
);
sec_blob
->
SessionKey
.
Length
=
0
;
sec_blob
->
SessionKey
.
Length
=
0
;
sec_blob
->
SessionKey
.
MaximumLength
=
0
;
sec_blob
->
SessionKey
.
MaximumLength
=
0
;
}
}
*
buflen
=
tmp
-
*
pbuffer
;
setup_ntlmv2_ret:
setup_ntlmv2_ret:
*
buflen
=
tmp
-
pbuffer
;
return
rc
;
return
rc
;
}
}
...
@@ -539,7 +567,7 @@ CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses,
...
@@ -539,7 +567,7 @@ CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses,
struct
key
*
spnego_key
=
NULL
;
struct
key
*
spnego_key
=
NULL
;
__le32
phase
=
NtLmNegotiate
;
/* NTLMSSP, if needed, is multistage */
__le32
phase
=
NtLmNegotiate
;
/* NTLMSSP, if needed, is multistage */
u16
blob_len
;
u16
blob_len
;
char
*
ntlmsspblob
=
NULL
;
unsigned
char
*
ntlmsspblob
=
NULL
;
if
(
ses
==
NULL
)
{
if
(
ses
==
NULL
)
{
WARN
(
1
,
"%s: ses == NULL!"
,
__func__
);
WARN
(
1
,
"%s: ses == NULL!"
,
__func__
);
...
@@ -624,22 +652,24 @@ ssetup_ntlmssp_authenticate:
...
@@ -624,22 +652,24 @@ ssetup_ntlmssp_authenticate:
pSMB
->
req
.
hdr
.
Flags2
&=
~
SMBFLG2_UNICODE
;
pSMB
->
req
.
hdr
.
Flags2
&=
~
SMBFLG2_UNICODE
;
/* no capabilities flags in old lanman negotiation */
if
(
ses
->
user_name
!=
NULL
)
{
/* no capabilities flags in old lanman negotiation */
pSMB
->
old_req
.
PasswordLength
=
cpu_to_le16
(
CIFS_AUTH_RESP_SIZE
);
pSMB
->
old_req
.
PasswordLength
=
cpu_to_le16
(
CIFS_AUTH_RESP_SIZE
);
/* Calculate hash with password and copy into bcc_ptr.
/* Calculate hash with password and copy into bcc_ptr.
* Encryption Key (stored as in cryptkey) gets used if the
* Encryption Key (stored as in cryptkey) gets used if the
* security mode bit in Negottiate Protocol response states
* security mode bit in Negottiate Protocol response states
* to use challenge/response method (i.e. Password bit is 1).
* to use challenge/response method (i.e. Password bit is 1).
*/
*/
rc
=
calc_lanman_hash
(
ses
->
password
,
ses
->
server
->
cryptkey
,
rc
=
calc_lanman_hash
(
ses
->
password
,
ses
->
server
->
cryptkey
,
ses
->
server
->
sec_mode
&
SECMODE_PW_ENCRYPT
?
ses
->
server
->
sec_mode
&
SECMODE_PW_ENCRYPT
?
true
:
false
,
lnm_session_key
);
true
:
false
,
lnm_session_key
);
memcpy
(
bcc_ptr
,
(
char
*
)
lnm_session_key
,
CIFS_AUTH_RESP_SIZE
);
memcpy
(
bcc_ptr
,
(
char
*
)
lnm_session_key
,
CIFS_AUTH_RESP_SIZE
);
bcc_ptr
+=
CIFS_AUTH_RESP_SIZE
;
bcc_ptr
+=
CIFS_AUTH_RESP_SIZE
;
}
else
{
pSMB
->
old_req
.
PasswordLength
=
0
;
}
/* can not sign if LANMAN negotiated so no need
/* can not sign if LANMAN negotiated so no need
to calculate signing key? but what if server
to calculate signing key? but what if server
...
@@ -652,26 +682,31 @@ ssetup_ntlmssp_authenticate:
...
@@ -652,26 +682,31 @@ ssetup_ntlmssp_authenticate:
#endif
#endif
}
else
if
(
type
==
NTLM
)
{
}
else
if
(
type
==
NTLM
)
{
pSMB
->
req_no_secext
.
Capabilities
=
cpu_to_le32
(
capabilities
);
pSMB
->
req_no_secext
.
Capabilities
=
cpu_to_le32
(
capabilities
);
pSMB
->
req_no_secext
.
CaseInsensitivePasswordLength
=
if
(
ses
->
user_name
!=
NULL
)
{
cpu_to_le16
(
CIFS_AUTH_RESP_SIZE
);
pSMB
->
req_no_secext
.
CaseInsensitivePasswordLength
=
pSMB
->
req_no_secext
.
CaseSensitivePasswordLength
=
cpu_to_le16
(
CIFS_AUTH_RESP_SIZE
);
cpu_to_le16
(
CIFS_AUTH_RESP_SIZE
);
pSMB
->
req_no_secext
.
CaseSensitivePasswordLength
=
cpu_to_le16
(
CIFS_AUTH_RESP_SIZE
);
/* calculate ntlm response and session key */
rc
=
setup_ntlm_response
(
ses
,
nls_cp
);
/* calculate ntlm response and session key */
if
(
rc
)
{
rc
=
setup_ntlm_response
(
ses
,
nls_cp
);
cifs_dbg
(
VFS
,
"Error %d during NTLM authentication
\n
"
,
if
(
rc
)
{
rc
);
cifs_dbg
(
VFS
,
"Error %d during NTLM authentication
\n
"
,
goto
ssetup_exit
;
rc
);
}
goto
ssetup_exit
;
}
/* copy ntlm response */
/* copy ntlm response */
memcpy
(
bcc_ptr
,
ses
->
auth_key
.
response
+
CIFS_SESS_KEY_SIZE
,
memcpy
(
bcc_ptr
,
ses
->
auth_key
.
response
+
CIFS_SESS_KEY_SIZE
,
CIFS_AUTH_RESP_SIZE
);
CIFS_AUTH_RESP_SIZE
);
bcc_ptr
+=
CIFS_AUTH_RESP_SIZE
;
bcc_ptr
+=
CIFS_AUTH_RESP_SIZE
;
memcpy
(
bcc_ptr
,
ses
->
auth_key
.
response
+
CIFS_SESS_KEY_SIZE
,
memcpy
(
bcc_ptr
,
ses
->
auth_key
.
response
+
CIFS_SESS_KEY_SIZE
,
CIFS_AUTH_RESP_SIZE
);
CIFS_AUTH_RESP_SIZE
);
bcc_ptr
+=
CIFS_AUTH_RESP_SIZE
;
bcc_ptr
+=
CIFS_AUTH_RESP_SIZE
;
}
else
{
pSMB
->
req_no_secext
.
CaseInsensitivePasswordLength
=
0
;
pSMB
->
req_no_secext
.
CaseSensitivePasswordLength
=
0
;
}
if
(
ses
->
capabilities
&
CAP_UNICODE
)
{
if
(
ses
->
capabilities
&
CAP_UNICODE
)
{
/* unicode strings must be word aligned */
/* unicode strings must be word aligned */
...
@@ -688,22 +723,26 @@ ssetup_ntlmssp_authenticate:
...
@@ -688,22 +723,26 @@ ssetup_ntlmssp_authenticate:
/* LM2 password would be here if we supported it */
/* LM2 password would be here if we supported it */
pSMB
->
req_no_secext
.
CaseInsensitivePasswordLength
=
0
;
pSMB
->
req_no_secext
.
CaseInsensitivePasswordLength
=
0
;
/* calculate nlmv2 response and session key */
if
(
ses
->
user_name
!=
NULL
)
{
rc
=
setup_ntlmv2_rsp
(
ses
,
nls_cp
);
/* calculate nlmv2 response and session key */
if
(
rc
)
{
rc
=
setup_ntlmv2_rsp
(
ses
,
nls_cp
);
cifs_dbg
(
VFS
,
"Error %d during NTLMv2 authentication
\n
"
,
if
(
rc
)
{
rc
);
cifs_dbg
(
VFS
,
"Error %d during NTLMv2 authentication
\n
"
,
rc
);
goto
ssetup_exit
;
goto
ssetup_exit
;
}
}
memcpy
(
bcc_ptr
,
ses
->
auth_key
.
response
+
CIFS_SESS_KEY_SIZE
,
ses
->
auth_key
.
len
-
CIFS_SESS_KEY_SIZE
);
bcc_ptr
+=
ses
->
auth_key
.
len
-
CIFS_SESS_KEY_SIZE
;
/* set case sensitive password length after tilen may get
memcpy
(
bcc_ptr
,
ses
->
auth_key
.
response
+
CIFS_SESS_KEY_SIZE
,
* assigned, tilen is 0 otherwise.
ses
->
auth_key
.
len
-
CIFS_SESS_KEY_SIZE
);
*/
bcc_ptr
+=
ses
->
auth_key
.
len
-
CIFS_SESS_KEY_SIZE
;
pSMB
->
req_no_secext
.
CaseSensitivePasswordLength
=
cpu_to_le16
(
ses
->
auth_key
.
len
-
CIFS_SESS_KEY_SIZE
);
/* set case sensitive password length after tilen may get
* assigned, tilen is 0 otherwise.
*/
pSMB
->
req_no_secext
.
CaseSensitivePasswordLength
=
cpu_to_le16
(
ses
->
auth_key
.
len
-
CIFS_SESS_KEY_SIZE
);
}
else
{
pSMB
->
req_no_secext
.
CaseSensitivePasswordLength
=
0
;
}
if
(
ses
->
capabilities
&
CAP_UNICODE
)
{
if
(
ses
->
capabilities
&
CAP_UNICODE
)
{
if
(
iov
[
0
].
iov_len
%
2
)
{
if
(
iov
[
0
].
iov_len
%
2
)
{
...
@@ -790,20 +829,7 @@ ssetup_ntlmssp_authenticate:
...
@@ -790,20 +829,7 @@ ssetup_ntlmssp_authenticate:
cpu_to_le16
(
sizeof
(
NEGOTIATE_MESSAGE
));
cpu_to_le16
(
sizeof
(
NEGOTIATE_MESSAGE
));
break
;
break
;
case
NtLmAuthenticate
:
case
NtLmAuthenticate
:
/*
rc
=
build_ntlmssp_auth_blob
(
&
ntlmsspblob
,
* 5 is an empirical value, large enough to hold
* authenticate message plus max 10 of av paris,
* domain, user, workstation names, flags, etc.
*/
ntlmsspblob
=
kzalloc
(
5
*
sizeof
(
struct
_AUTHENTICATE_MESSAGE
),
GFP_KERNEL
);
if
(
!
ntlmsspblob
)
{
rc
=
-
ENOMEM
;
goto
ssetup_exit
;
}
rc
=
build_ntlmssp_auth_blob
(
ntlmsspblob
,
&
blob_len
,
ses
,
nls_cp
);
&
blob_len
,
ses
,
nls_cp
);
if
(
rc
)
if
(
rc
)
goto
ssetup_exit
;
goto
ssetup_exit
;
...
...
sources/3.16/smb1ops.c
View file @
7e23c0f8
...
@@ -576,7 +576,6 @@ cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -576,7 +576,6 @@ cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
oparms
.
tcon
=
tcon
;
oparms
.
tcon
=
tcon
;
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
desired_access
=
FILE_READ_ATTRIBUTES
;
oparms
.
desired_access
=
FILE_READ_ATTRIBUTES
;
oparms
.
share_access
=
FILE_SHARE_ALL
;
oparms
.
create_options
=
0
;
oparms
.
create_options
=
0
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
path
=
full_path
;
oparms
.
path
=
full_path
;
...
@@ -813,7 +812,6 @@ smb_set_file_info(struct inode *inode, const char *full_path,
...
@@ -813,7 +812,6 @@ smb_set_file_info(struct inode *inode, const char *full_path,
oparms
.
tcon
=
tcon
;
oparms
.
tcon
=
tcon
;
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
desired_access
=
SYNCHRONIZE
|
FILE_WRITE_ATTRIBUTES
;
oparms
.
desired_access
=
SYNCHRONIZE
|
FILE_WRITE_ATTRIBUTES
;
oparms
.
share_access
=
FILE_SHARE_ALL
;
oparms
.
create_options
=
CREATE_NOT_DIR
;
oparms
.
create_options
=
CREATE_NOT_DIR
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
path
=
full_path
;
oparms
.
path
=
full_path
;
...
@@ -858,8 +856,13 @@ cifs_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -858,8 +856,13 @@ cifs_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
struct
cifs_fid
*
fid
,
__u16
search_flags
,
struct
cifs_fid
*
fid
,
__u16
search_flags
,
struct
cifs_search_info
*
srch_inf
)
struct
cifs_search_info
*
srch_inf
)
{
{
return
CIFSFindFirst
(
xid
,
tcon
,
path
,
cifs_sb
,
int
rc
;
&
fid
->
netfid
,
search_flags
,
srch_inf
,
true
);
rc
=
CIFSFindFirst
(
xid
,
tcon
,
path
,
cifs_sb
,
&
fid
->
netfid
,
search_flags
,
srch_inf
,
true
);
if
(
rc
)
cifs_dbg
(
FYI
,
"find first failed=%d
\n
"
,
rc
);
return
rc
;
}
}
static
int
static
int
...
@@ -981,7 +984,6 @@ cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -981,7 +984,6 @@ cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
oparms
.
tcon
=
tcon
;
oparms
.
tcon
=
tcon
;
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
desired_access
=
FILE_READ_ATTRIBUTES
;
oparms
.
desired_access
=
FILE_READ_ATTRIBUTES
;
oparms
.
share_access
=
FILE_SHARE_ALL
;
oparms
.
create_options
=
OPEN_REPARSE_POINT
;
oparms
.
create_options
=
OPEN_REPARSE_POINT
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
path
=
full_path
;
oparms
.
path
=
full_path
;
...
@@ -1018,6 +1020,15 @@ cifs_dir_needs_close(struct cifsFileInfo *cfile)
...
@@ -1018,6 +1020,15 @@ cifs_dir_needs_close(struct cifsFileInfo *cfile)
return
!
cfile
->
srch_inf
.
endOfSearch
&&
!
cfile
->
invalidHandle
;
return
!
cfile
->
srch_inf
.
endOfSearch
&&
!
cfile
->
invalidHandle
;
}
}
static
bool
cifs_can_echo
(
struct
TCP_Server_Info
*
server
)
{
if
(
server
->
tcpStatus
==
CifsGood
)
return
true
;
return
false
;
}
struct
smb_version_operations
smb1_operations
=
{
struct
smb_version_operations
smb1_operations
=
{
.
send_cancel
=
send_nt_cancel
,
.
send_cancel
=
send_nt_cancel
,
.
compare_fids
=
cifs_compare_fids
,
.
compare_fids
=
cifs_compare_fids
,
...
@@ -1051,6 +1062,7 @@ struct smb_version_operations smb1_operations = {
...
@@ -1051,6 +1062,7 @@ struct smb_version_operations smb1_operations = {
.
get_dfs_refer
=
CIFSGetDFSRefer
,
.
get_dfs_refer
=
CIFSGetDFSRefer
,
.
qfs_tcon
=
cifs_qfs_tcon
,
.
qfs_tcon
=
cifs_qfs_tcon
,
.
is_path_accessible
=
cifs_is_path_accessible
,
.
is_path_accessible
=
cifs_is_path_accessible
,
.
can_echo
=
cifs_can_echo
,
.
query_path_info
=
cifs_query_path_info
,
.
query_path_info
=
cifs_query_path_info
,
.
query_file_info
=
cifs_query_file_info
,
.
query_file_info
=
cifs_query_file_info
,
.
get_srv_inum
=
cifs_get_srv_inum
,
.
get_srv_inum
=
cifs_get_srv_inum
,
...
...
sources/3.16/smb2file.c
View file @
7e23c0f8
...
@@ -241,7 +241,7 @@ smb2_push_mandatory_locks(struct cifsFileInfo *cfile)
...
@@ -241,7 +241,7 @@ smb2_push_mandatory_locks(struct cifsFileInfo *cfile)
* and check it for zero before using.
* and check it for zero before using.
*/
*/
max_buf
=
tlink_tcon
(
cfile
->
tlink
)
->
ses
->
server
->
maxBuf
;
max_buf
=
tlink_tcon
(
cfile
->
tlink
)
->
ses
->
server
->
maxBuf
;
if
(
!
max_buf
)
{
if
(
max_buf
<
sizeof
(
struct
smb2_lock_element
)
)
{
free_xid
(
xid
);
free_xid
(
xid
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
...
...
sources/3.16/smb2glob.h
View file @
7e23c0f8
...
@@ -44,6 +44,7 @@
...
@@ -44,6 +44,7 @@
#define SMB2_OP_DELETE 7
#define SMB2_OP_DELETE 7
#define SMB2_OP_HARDLINK 8
#define SMB2_OP_HARDLINK 8
#define SMB2_OP_SET_EOF 9
#define SMB2_OP_SET_EOF 9
#define SMB2_OP_RMDIR 10
/* Used when constructing chained read requests. */
/* Used when constructing chained read requests. */
#define CHAINED_REQUEST 1
#define CHAINED_REQUEST 1
...
@@ -60,4 +61,14 @@
...
@@ -60,4 +61,14 @@
/* Maximum buffer size value we can send with 1 credit */
/* Maximum buffer size value we can send with 1 credit */
#define SMB2_MAX_BUFFER_SIZE 65536
#define SMB2_MAX_BUFFER_SIZE 65536
/*
* Maximum number of credits to keep available.
* This value is chosen somewhat arbitrarily. The Windows client
* defaults to 128 credits, the Windows server allows clients up to
* 512 credits, and the NetApp server does not limit clients at all.
* Choose a high enough value such that the client shouldn't limit
* performance.
*/
#define SMB2_MAX_CREDITS_AVAILABLE 32000
#endif
/* _SMB2_GLOB_H */
#endif
/* _SMB2_GLOB_H */
sources/3.16/smb2inode.c
View file @
7e23c0f8
...
@@ -55,7 +55,6 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -55,7 +55,6 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon,
oparms
.
tcon
=
tcon
;
oparms
.
tcon
=
tcon
;
oparms
.
desired_access
=
desired_access
;
oparms
.
desired_access
=
desired_access
;
oparms
.
share_access
=
FILE_SHARE_ALL
;
oparms
.
disposition
=
create_disposition
;
oparms
.
disposition
=
create_disposition
;
oparms
.
create_options
=
create_options
;
oparms
.
create_options
=
create_options
;
oparms
.
fid
=
&
fid
;
oparms
.
fid
=
&
fid
;
...
@@ -81,6 +80,10 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -81,6 +80,10 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon,
* SMB2_open() call.
* SMB2_open() call.
*/
*/
break
;
break
;
case
SMB2_OP_RMDIR
:
tmprc
=
SMB2_rmdir
(
xid
,
tcon
,
fid
.
persistent_fid
,
fid
.
volatile_fid
);
break
;
case
SMB2_OP_RENAME
:
case
SMB2_OP_RENAME
:
tmprc
=
SMB2_rename
(
xid
,
tcon
,
fid
.
persistent_fid
,
tmprc
=
SMB2_rename
(
xid
,
tcon
,
fid
.
persistent_fid
,
fid
.
volatile_fid
,
(
__le16
*
)
data
);
fid
.
volatile_fid
,
(
__le16
*
)
data
);
...
@@ -192,8 +195,8 @@ smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
...
@@ -192,8 +195,8 @@ smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
struct
cifs_sb_info
*
cifs_sb
)
struct
cifs_sb_info
*
cifs_sb
)
{
{
return
smb2_open_op_close
(
xid
,
tcon
,
cifs_sb
,
name
,
DELETE
,
FILE_OPEN
,
return
smb2_open_op_close
(
xid
,
tcon
,
cifs_sb
,
name
,
DELETE
,
FILE_OPEN
,
CREATE_NOT_FILE
|
CREATE_DELETE_ON_CLOSE
,
CREATE_NOT_FILE
,
NULL
,
SMB2_OP_
DELETE
);
NULL
,
SMB2_OP_
RMDIR
);
}
}
int
int
...
@@ -263,9 +266,15 @@ smb2_set_file_info(struct inode *inode, const char *full_path,
...
@@ -263,9 +266,15 @@ smb2_set_file_info(struct inode *inode, const char *full_path,
struct
tcon_link
*
tlink
;
struct
tcon_link
*
tlink
;
int
rc
;
int
rc
;
if
((
buf
->
CreationTime
==
0
)
&&
(
buf
->
LastAccessTime
==
0
)
&&
(
buf
->
LastWriteTime
==
0
)
&&
(
buf
->
ChangeTime
)
&&
(
buf
->
Attributes
==
0
))
return
0
;
/* would be a no op, no sense sending this */
tlink
=
cifs_sb_tlink
(
cifs_sb
);
tlink
=
cifs_sb_tlink
(
cifs_sb
);
if
(
IS_ERR
(
tlink
))
if
(
IS_ERR
(
tlink
))
return
PTR_ERR
(
tlink
);
return
PTR_ERR
(
tlink
);
rc
=
smb2_open_op_close
(
xid
,
tlink_tcon
(
tlink
),
cifs_sb
,
full_path
,
rc
=
smb2_open_op_close
(
xid
,
tlink_tcon
(
tlink
),
cifs_sb
,
full_path
,
FILE_WRITE_ATTRIBUTES
,
FILE_OPEN
,
0
,
buf
,
FILE_WRITE_ATTRIBUTES
,
FILE_OPEN
,
0
,
buf
,
SMB2_OP_SET_INFO
);
SMB2_OP_SET_INFO
);
...
...
sources/3.16/smb2maperror.c
View file @
7e23c0f8
...
@@ -358,7 +358,7 @@ static const struct status_to_posix_error smb2_error_map_table[] = {
...
@@ -358,7 +358,7 @@ static const struct status_to_posix_error smb2_error_map_table[] = {
{
STATUS_PORT_CONNECTION_REFUSED
,
-
ECONNREFUSED
,
{
STATUS_PORT_CONNECTION_REFUSED
,
-
ECONNREFUSED
,
"STATUS_PORT_CONNECTION_REFUSED"
},
"STATUS_PORT_CONNECTION_REFUSED"
},
{
STATUS_INVALID_PORT_HANDLE
,
-
EIO
,
"STATUS_INVALID_PORT_HANDLE"
},
{
STATUS_INVALID_PORT_HANDLE
,
-
EIO
,
"STATUS_INVALID_PORT_HANDLE"
},
{
STATUS_SHARING_VIOLATION
,
-
E
TXTB
SY
,
"STATUS_SHARING_VIOLATION"
},
{
STATUS_SHARING_VIOLATION
,
-
E
BU
SY
,
"STATUS_SHARING_VIOLATION"
},
{
STATUS_QUOTA_EXCEEDED
,
-
EDQUOT
,
"STATUS_QUOTA_EXCEEDED"
},
{
STATUS_QUOTA_EXCEEDED
,
-
EDQUOT
,
"STATUS_QUOTA_EXCEEDED"
},
{
STATUS_INVALID_PAGE_PROTECTION
,
-
EIO
,
{
STATUS_INVALID_PAGE_PROTECTION
,
-
EIO
,
"STATUS_INVALID_PAGE_PROTECTION"
},
"STATUS_INVALID_PAGE_PROTECTION"
},
...
...
sources/3.16/smb2misc.c
View file @
7e23c0f8
...
@@ -447,7 +447,7 @@ smb2_tcon_has_lease(struct cifs_tcon *tcon, struct smb2_lease_break *rsp,
...
@@ -447,7 +447,7 @@ smb2_tcon_has_lease(struct cifs_tcon *tcon, struct smb2_lease_break *rsp,
else
else
cfile
->
oplock_break_cancelled
=
true
;
cfile
->
oplock_break_cancelled
=
true
;
queue_work
(
cifs
io
d_wq
,
&
cfile
->
oplock_break
);
queue_work
(
cifs
oplock
d_wq
,
&
cfile
->
oplock_break
);
kfree
(
lw
);
kfree
(
lw
);
return
true
;
return
true
;
}
}
...
@@ -502,19 +502,19 @@ smb2_is_valid_lease_break(char *buffer)
...
@@ -502,19 +502,19 @@ smb2_is_valid_lease_break(char *buffer)
list_for_each
(
tmp1
,
&
server
->
smb_ses_list
)
{
list_for_each
(
tmp1
,
&
server
->
smb_ses_list
)
{
ses
=
list_entry
(
tmp1
,
struct
cifs_ses
,
smb_ses_list
);
ses
=
list_entry
(
tmp1
,
struct
cifs_ses
,
smb_ses_list
);
spin_lock
(
&
cifs_file_list_lock
);
list_for_each
(
tmp2
,
&
ses
->
tcon_list
)
{
list_for_each
(
tmp2
,
&
ses
->
tcon_list
)
{
tcon
=
list_entry
(
tmp2
,
struct
cifs_tcon
,
tcon
=
list_entry
(
tmp2
,
struct
cifs_tcon
,
tcon_list
);
tcon_list
);
spin_lock
(
&
tcon
->
open_file_lock
);
cifs_stats_inc
(
cifs_stats_inc
(
&
tcon
->
stats
.
cifs_stats
.
num_oplock_brks
);
&
tcon
->
stats
.
cifs_stats
.
num_oplock_brks
);
if
(
smb2_tcon_has_lease
(
tcon
,
rsp
,
lw
))
{
if
(
smb2_tcon_has_lease
(
tcon
,
rsp
,
lw
))
{
spin_unlock
(
&
cifs_file_list
_lock
);
spin_unlock
(
&
tcon
->
open_file
_lock
);
spin_unlock
(
&
cifs_tcp_ses_lock
);
spin_unlock
(
&
cifs_tcp_ses_lock
);
return
true
;
return
true
;
}
}
spin_unlock
(
&
tcon
->
open_file_lock
);
}
}
spin_unlock
(
&
cifs_file_list_lock
);
}
}
}
}
spin_unlock
(
&
cifs_tcp_ses_lock
);
spin_unlock
(
&
cifs_tcp_ses_lock
);
...
@@ -556,7 +556,7 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
...
@@ -556,7 +556,7 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
tcon
=
list_entry
(
tmp1
,
struct
cifs_tcon
,
tcon_list
);
tcon
=
list_entry
(
tmp1
,
struct
cifs_tcon
,
tcon_list
);
cifs_stats_inc
(
&
tcon
->
stats
.
cifs_stats
.
num_oplock_brks
);
cifs_stats_inc
(
&
tcon
->
stats
.
cifs_stats
.
num_oplock_brks
);
spin_lock
(
&
cifs_file_list
_lock
);
spin_lock
(
&
tcon
->
open_file
_lock
);
list_for_each
(
tmp2
,
&
tcon
->
openFileList
)
{
list_for_each
(
tmp2
,
&
tcon
->
openFileList
)
{
cfile
=
list_entry
(
tmp2
,
struct
cifsFileInfo
,
cfile
=
list_entry
(
tmp2
,
struct
cifsFileInfo
,
tlist
);
tlist
);
...
@@ -568,7 +568,7 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
...
@@ -568,7 +568,7 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
cifs_dbg
(
FYI
,
"file id match, oplock break
\n
"
);
cifs_dbg
(
FYI
,
"file id match, oplock break
\n
"
);
cinode
=
CIFS_I
(
cfile
->
dentry
->
d_inode
);
cinode
=
CIFS_I
(
cfile
->
dentry
->
d_inode
);
spin_lock
(
&
cfile
->
file_info_lock
);
if
(
!
CIFS_CACHE_WRITE
(
cinode
)
&&
if
(
!
CIFS_CACHE_WRITE
(
cinode
)
&&
rsp
->
OplockLevel
==
SMB2_OPLOCK_LEVEL_NONE
)
rsp
->
OplockLevel
==
SMB2_OPLOCK_LEVEL_NONE
)
cfile
->
oplock_break_cancelled
=
true
;
cfile
->
oplock_break_cancelled
=
true
;
...
@@ -590,14 +590,15 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
...
@@ -590,14 +590,15 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
clear_bit
(
clear_bit
(
CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2
,
CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2
,
&
cinode
->
flags
);
&
cinode
->
flags
);
spin_unlock
(
&
cfile
->
file_info_lock
);
queue_work
(
cifsoplockd_wq
,
&
cfile
->
oplock_break
);
queue_work
(
cifsiod_wq
,
&
cfile
->
oplock_break
);
spin_unlock
(
&
tcon
->
open_file_lock
);
spin_unlock
(
&
cifs_file_list_lock
);
spin_unlock
(
&
cifs_tcp_ses_lock
);
spin_unlock
(
&
cifs_tcp_ses_lock
);
return
true
;
return
true
;
}
}
spin_unlock
(
&
cifs_file_list
_lock
);
spin_unlock
(
&
tcon
->
open_file
_lock
);
spin_unlock
(
&
cifs_tcp_ses_lock
);
spin_unlock
(
&
cifs_tcp_ses_lock
);
cifs_dbg
(
FYI
,
"No matching file for oplock break
\n
"
);
cifs_dbg
(
FYI
,
"No matching file for oplock break
\n
"
);
return
true
;
return
true
;
...
@@ -607,3 +608,47 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
...
@@ -607,3 +608,47 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
cifs_dbg
(
FYI
,
"Can not process oplock break for non-existent connection
\n
"
);
cifs_dbg
(
FYI
,
"Can not process oplock break for non-existent connection
\n
"
);
return
false
;
return
false
;
}
}
void
smb2_cancelled_close_fid
(
struct
work_struct
*
work
)
{
struct
close_cancelled_open
*
cancelled
=
container_of
(
work
,
struct
close_cancelled_open
,
work
);
cifs_dbg
(
VFS
,
"Close unmatched open
\n
"
);
SMB2_close
(
0
,
cancelled
->
tcon
,
cancelled
->
fid
.
persistent_fid
,
cancelled
->
fid
.
volatile_fid
);
cifs_put_tcon
(
cancelled
->
tcon
);
kfree
(
cancelled
);
}
int
smb2_handle_cancelled_mid
(
char
*
buffer
,
struct
TCP_Server_Info
*
server
)
{
struct
smb2_hdr
*
hdr
=
(
struct
smb2_hdr
*
)
buffer
;
struct
smb2_create_rsp
*
rsp
=
(
struct
smb2_create_rsp
*
)
buffer
;
struct
cifs_tcon
*
tcon
;
struct
close_cancelled_open
*
cancelled
;
if
(
hdr
->
Command
!=
SMB2_CREATE
||
hdr
->
Status
!=
STATUS_SUCCESS
)
return
0
;
cancelled
=
kzalloc
(
sizeof
(
*
cancelled
),
GFP_KERNEL
);
if
(
!
cancelled
)
return
-
ENOMEM
;
tcon
=
smb2_find_smb_tcon
(
server
,
hdr
->
SessionId
,
hdr
->
TreeId
);
if
(
!
tcon
)
{
kfree
(
cancelled
);
return
-
ENOENT
;
}
cancelled
->
fid
.
persistent_fid
=
rsp
->
PersistentFileId
;
cancelled
->
fid
.
volatile_fid
=
rsp
->
VolatileFileId
;
cancelled
->
tcon
=
tcon
;
INIT_WORK
(
&
cancelled
->
work
,
smb2_cancelled_close_fid
);
queue_work
(
cifsiod_wq
,
&
cancelled
->
work
);
return
0
;
}
sources/3.16/smb2ops.c
View file @
7e23c0f8
...
@@ -228,7 +228,7 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon)
...
@@ -228,7 +228,7 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon)
le64_to_cpu
(
out_buf
->
LinkSpeed
));
le64_to_cpu
(
out_buf
->
LinkSpeed
));
}
else
}
else
cifs_dbg
(
VFS
,
"error %d on ioctl to get interface list
\n
"
,
rc
);
cifs_dbg
(
VFS
,
"error %d on ioctl to get interface list
\n
"
,
rc
);
kfree
(
out_buf
);
return
rc
;
return
rc
;
}
}
#endif
/* STATS2 */
#endif
/* STATS2 */
...
@@ -244,7 +244,6 @@ smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon)
...
@@ -244,7 +244,6 @@ smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon)
oparms
.
tcon
=
tcon
;
oparms
.
tcon
=
tcon
;
oparms
.
desired_access
=
FILE_READ_ATTRIBUTES
;
oparms
.
desired_access
=
FILE_READ_ATTRIBUTES
;
oparms
.
share_access
=
FILE_SHARE_ALL
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
create_options
=
0
;
oparms
.
create_options
=
0
;
oparms
.
fid
=
&
fid
;
oparms
.
fid
=
&
fid
;
...
@@ -279,7 +278,6 @@ smb2_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon)
...
@@ -279,7 +278,6 @@ smb2_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon)
oparms
.
tcon
=
tcon
;
oparms
.
tcon
=
tcon
;
oparms
.
desired_access
=
FILE_READ_ATTRIBUTES
;
oparms
.
desired_access
=
FILE_READ_ATTRIBUTES
;
oparms
.
share_access
=
FILE_SHARE_ALL
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
create_options
=
0
;
oparms
.
create_options
=
0
;
oparms
.
fid
=
&
fid
;
oparms
.
fid
=
&
fid
;
...
@@ -313,7 +311,6 @@ smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -313,7 +311,6 @@ smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
oparms
.
tcon
=
tcon
;
oparms
.
tcon
=
tcon
;
oparms
.
desired_access
=
FILE_READ_ATTRIBUTES
;
oparms
.
desired_access
=
FILE_READ_ATTRIBUTES
;
oparms
.
share_access
=
FILE_SHARE_ALL
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
create_options
=
0
;
oparms
.
create_options
=
0
;
oparms
.
fid
=
&
fid
;
oparms
.
fid
=
&
fid
;
...
@@ -643,6 +640,7 @@ smb2_clone_range(const unsigned int xid,
...
@@ -643,6 +640,7 @@ smb2_clone_range(const unsigned int xid,
cchunk_out:
cchunk_out:
kfree
(
pcchunk
);
kfree
(
pcchunk
);
kfree
(
retbuf
);
return
rc
;
return
rc
;
}
}
...
@@ -723,7 +721,6 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -723,7 +721,6 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
oparms
.
tcon
=
tcon
;
oparms
.
tcon
=
tcon
;
oparms
.
desired_access
=
FILE_READ_ATTRIBUTES
|
FILE_READ_DATA
;
oparms
.
desired_access
=
FILE_READ_ATTRIBUTES
|
FILE_READ_DATA
;
oparms
.
share_access
=
FILE_SHARE_ALL
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
create_options
=
0
;
oparms
.
create_options
=
0
;
oparms
.
fid
=
fid
;
oparms
.
fid
=
fid
;
...
@@ -732,7 +729,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -732,7 +729,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
rc
=
SMB2_open
(
xid
,
&
oparms
,
utf16_path
,
&
oplock
,
NULL
,
NULL
);
rc
=
SMB2_open
(
xid
,
&
oparms
,
utf16_path
,
&
oplock
,
NULL
,
NULL
);
kfree
(
utf16_path
);
kfree
(
utf16_path
);
if
(
rc
)
{
if
(
rc
)
{
cifs_dbg
(
VFS
,
"open dir failed
\n
"
);
cifs_dbg
(
FYI
,
"open dir failed rc=%d
\n
"
,
rc
);
return
rc
;
return
rc
;
}
}
...
@@ -742,7 +739,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -742,7 +739,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
rc
=
SMB2_query_directory
(
xid
,
tcon
,
fid
->
persistent_fid
,
rc
=
SMB2_query_directory
(
xid
,
tcon
,
fid
->
persistent_fid
,
fid
->
volatile_fid
,
0
,
srch_inf
);
fid
->
volatile_fid
,
0
,
srch_inf
);
if
(
rc
)
{
if
(
rc
)
{
cifs_dbg
(
VFS
,
"query directory failed
\n
"
);
cifs_dbg
(
FYI
,
"query directory failed rc=%d
\n
"
,
rc
);
SMB2_close
(
xid
,
tcon
,
fid
->
persistent_fid
,
fid
->
volatile_fid
);
SMB2_close
(
xid
,
tcon
,
fid
->
persistent_fid
,
fid
->
volatile_fid
);
}
}
return
rc
;
return
rc
;
...
@@ -811,7 +808,6 @@ smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -811,7 +808,6 @@ smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
oparms
.
tcon
=
tcon
;
oparms
.
tcon
=
tcon
;
oparms
.
desired_access
=
FILE_READ_ATTRIBUTES
;
oparms
.
desired_access
=
FILE_READ_ATTRIBUTES
;
oparms
.
share_access
=
FILE_SHARE_ALL
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
create_options
=
0
;
oparms
.
create_options
=
0
;
oparms
.
fid
=
&
fid
;
oparms
.
fid
=
&
fid
;
...
@@ -860,9 +856,12 @@ smb2_set_lease_key(struct inode *inode, struct cifs_fid *fid)
...
@@ -860,9 +856,12 @@ smb2_set_lease_key(struct inode *inode, struct cifs_fid *fid)
static
void
static
void
smb2_new_lease_key
(
struct
cifs_fid
*
fid
)
smb2_new_lease_key
(
struct
cifs_fid
*
fid
)
{
{
ge
t_random_bytes
(
fid
->
lease_key
,
SMB2_LEASE_KEY_SIZE
);
ge
nerate_random_uuid
(
fid
->
lease_key
);
}
}
#define SMB2_SYMLINK_STRUCT_SIZE \
(sizeof(struct smb2_err_rsp) - 1 + sizeof(struct smb2_symlink_err_rsp))
static
int
static
int
smb2_query_symlink
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
smb2_query_symlink
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
const
char
*
full_path
,
char
**
target_path
,
const
char
*
full_path
,
char
**
target_path
,
...
@@ -875,7 +874,10 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -875,7 +874,10 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
struct
cifs_fid
fid
;
struct
cifs_fid
fid
;
struct
smb2_err_rsp
*
err_buf
=
NULL
;
struct
smb2_err_rsp
*
err_buf
=
NULL
;
struct
smb2_symlink_err_rsp
*
symlink
;
struct
smb2_symlink_err_rsp
*
symlink
;
unsigned
int
sub_len
,
sub_offset
;
unsigned
int
sub_len
;
unsigned
int
sub_offset
;
unsigned
int
print_len
;
unsigned
int
print_offset
;
cifs_dbg
(
FYI
,
"%s: path: %s
\n
"
,
__func__
,
full_path
);
cifs_dbg
(
FYI
,
"%s: path: %s
\n
"
,
__func__
,
full_path
);
...
@@ -885,7 +887,6 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -885,7 +887,6 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
oparms
.
tcon
=
tcon
;
oparms
.
tcon
=
tcon
;
oparms
.
desired_access
=
FILE_READ_ATTRIBUTES
;
oparms
.
desired_access
=
FILE_READ_ATTRIBUTES
;
oparms
.
share_access
=
FILE_SHARE_ALL
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
create_options
=
0
;
oparms
.
create_options
=
0
;
oparms
.
fid
=
&
fid
;
oparms
.
fid
=
&
fid
;
...
@@ -897,11 +898,33 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -897,11 +898,33 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
kfree
(
utf16_path
);
kfree
(
utf16_path
);
return
-
ENOENT
;
return
-
ENOENT
;
}
}
if
(
le32_to_cpu
(
err_buf
->
ByteCount
)
<
sizeof
(
struct
smb2_symlink_err_rsp
)
||
get_rfc1002_length
(
err_buf
)
+
4
<
SMB2_SYMLINK_STRUCT_SIZE
)
{
kfree
(
utf16_path
);
return
-
ENOENT
;
}
/* open must fail on symlink - reset rc */
/* open must fail on symlink - reset rc */
rc
=
0
;
rc
=
0
;
symlink
=
(
struct
smb2_symlink_err_rsp
*
)
err_buf
->
ErrorData
;
symlink
=
(
struct
smb2_symlink_err_rsp
*
)
err_buf
->
ErrorData
;
sub_len
=
le16_to_cpu
(
symlink
->
SubstituteNameLength
);
sub_len
=
le16_to_cpu
(
symlink
->
SubstituteNameLength
);
sub_offset
=
le16_to_cpu
(
symlink
->
SubstituteNameOffset
);
sub_offset
=
le16_to_cpu
(
symlink
->
SubstituteNameOffset
);
print_len
=
le16_to_cpu
(
symlink
->
PrintNameLength
);
print_offset
=
le16_to_cpu
(
symlink
->
PrintNameOffset
);
if
(
get_rfc1002_length
(
err_buf
)
+
4
<
SMB2_SYMLINK_STRUCT_SIZE
+
sub_offset
+
sub_len
)
{
kfree
(
utf16_path
);
return
-
ENOENT
;
}
if
(
get_rfc1002_length
(
err_buf
)
+
4
<
SMB2_SYMLINK_STRUCT_SIZE
+
print_offset
+
print_len
)
{
kfree
(
utf16_path
);
return
-
ENOENT
;
}
*
target_path
=
cifs_strndup_from_utf16
(
*
target_path
=
cifs_strndup_from_utf16
(
(
char
*
)
symlink
->
PathBuffer
+
sub_offset
,
(
char
*
)
symlink
->
PathBuffer
+
sub_offset
,
sub_len
,
true
,
cifs_sb
->
local_nls
);
sub_len
,
true
,
cifs_sb
->
local_nls
);
...
@@ -1140,6 +1163,7 @@ struct smb_version_operations smb20_operations = {
...
@@ -1140,6 +1163,7 @@ struct smb_version_operations smb20_operations = {
.
clear_stats
=
smb2_clear_stats
,
.
clear_stats
=
smb2_clear_stats
,
.
print_stats
=
smb2_print_stats
,
.
print_stats
=
smb2_print_stats
,
.
is_oplock_break
=
smb2_is_valid_oplock_break
,
.
is_oplock_break
=
smb2_is_valid_oplock_break
,
.
handle_cancelled_mid
=
smb2_handle_cancelled_mid
,
.
downgrade_oplock
=
smb2_downgrade_oplock
,
.
downgrade_oplock
=
smb2_downgrade_oplock
,
.
need_neg
=
smb2_need_neg
,
.
need_neg
=
smb2_need_neg
,
.
negotiate
=
smb2_negotiate
,
.
negotiate
=
smb2_negotiate
,
...
@@ -1216,6 +1240,7 @@ struct smb_version_operations smb21_operations = {
...
@@ -1216,6 +1240,7 @@ struct smb_version_operations smb21_operations = {
.
clear_stats
=
smb2_clear_stats
,
.
clear_stats
=
smb2_clear_stats
,
.
print_stats
=
smb2_print_stats
,
.
print_stats
=
smb2_print_stats
,
.
is_oplock_break
=
smb2_is_valid_oplock_break
,
.
is_oplock_break
=
smb2_is_valid_oplock_break
,
.
handle_cancelled_mid
=
smb2_handle_cancelled_mid
,
.
downgrade_oplock
=
smb2_downgrade_oplock
,
.
downgrade_oplock
=
smb2_downgrade_oplock
,
.
need_neg
=
smb2_need_neg
,
.
need_neg
=
smb2_need_neg
,
.
negotiate
=
smb2_negotiate
,
.
negotiate
=
smb2_negotiate
,
...
@@ -1293,6 +1318,7 @@ struct smb_version_operations smb30_operations = {
...
@@ -1293,6 +1318,7 @@ struct smb_version_operations smb30_operations = {
.
print_stats
=
smb2_print_stats
,
.
print_stats
=
smb2_print_stats
,
.
dump_share_caps
=
smb2_dump_share_caps
,
.
dump_share_caps
=
smb2_dump_share_caps
,
.
is_oplock_break
=
smb2_is_valid_oplock_break
,
.
is_oplock_break
=
smb2_is_valid_oplock_break
,
.
handle_cancelled_mid
=
smb2_handle_cancelled_mid
,
.
downgrade_oplock
=
smb2_downgrade_oplock
,
.
downgrade_oplock
=
smb2_downgrade_oplock
,
.
need_neg
=
smb2_need_neg
,
.
need_neg
=
smb2_need_neg
,
.
negotiate
=
smb2_negotiate
,
.
negotiate
=
smb2_negotiate
,
...
...
sources/3.16/smb2pdu.c
View file @
7e23c0f8
...
@@ -102,7 +102,21 @@ smb2_hdr_assemble(struct smb2_hdr *hdr, __le16 smb2_cmd /* command */ ,
...
@@ -102,7 +102,21 @@ smb2_hdr_assemble(struct smb2_hdr *hdr, __le16 smb2_cmd /* command */ ,
hdr
->
ProtocolId
[
3
]
=
'B'
;
hdr
->
ProtocolId
[
3
]
=
'B'
;
hdr
->
StructureSize
=
cpu_to_le16
(
64
);
hdr
->
StructureSize
=
cpu_to_le16
(
64
);
hdr
->
Command
=
smb2_cmd
;
hdr
->
Command
=
smb2_cmd
;
hdr
->
CreditRequest
=
cpu_to_le16
(
2
);
/* BB make this dynamic */
if
(
tcon
&&
tcon
->
ses
&&
tcon
->
ses
->
server
)
{
struct
TCP_Server_Info
*
server
=
tcon
->
ses
->
server
;
spin_lock
(
&
server
->
req_lock
);
/* Request up to 2 credits but don't go over the limit. */
if
(
server
->
credits
>=
SMB2_MAX_CREDITS_AVAILABLE
)
hdr
->
CreditRequest
=
cpu_to_le16
(
0
);
else
hdr
->
CreditRequest
=
cpu_to_le16
(
min_t
(
int
,
SMB2_MAX_CREDITS_AVAILABLE
-
server
->
credits
,
2
));
spin_unlock
(
&
server
->
req_lock
);
}
else
{
hdr
->
CreditRequest
=
cpu_to_le16
(
2
);
}
hdr
->
ProcessId
=
cpu_to_le32
((
__u16
)
current
->
tgid
);
hdr
->
ProcessId
=
cpu_to_le32
((
__u16
)
current
->
tgid
);
if
(
!
tcon
)
if
(
!
tcon
)
...
@@ -268,7 +282,7 @@ out:
...
@@ -268,7 +282,7 @@ out:
case
SMB2_CHANGE_NOTIFY
:
case
SMB2_CHANGE_NOTIFY
:
case
SMB2_QUERY_INFO
:
case
SMB2_QUERY_INFO
:
case
SMB2_SET_INFO
:
case
SMB2_SET_INFO
:
r
eturn
-
EAGAIN
;
r
c
=
-
EAGAIN
;
}
}
unload_nls
(
nls_codepage
);
unload_nls
(
nls_codepage
);
return
rc
;
return
rc
;
...
@@ -465,22 +479,29 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
...
@@ -465,22 +479,29 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
{
{
int
rc
=
0
;
int
rc
=
0
;
struct
validate_negotiate_info_req
vneg_inbuf
;
struct
validate_negotiate_info_req
vneg_inbuf
;
struct
validate_negotiate_info_rsp
*
pneg_rsp
;
struct
validate_negotiate_info_rsp
*
pneg_rsp
=
NULL
;
u32
rsplen
;
u32
rsplen
;
cifs_dbg
(
FYI
,
"validate negotiate
\n
"
);
cifs_dbg
(
FYI
,
"validate negotiate
\n
"
);
/*
/*
* validation ioctl must be signed, so no point sending this if we
* validation ioctl must be signed, so no point sending this if we
* can not sign it. We could eventually change this to selectively
* can not sign it (ie are not known user). Even if signing is not
* required (enabled but not negotiated), in those cases we selectively
* sign just this, the first and only signed request on a connection.
* sign just this, the first and only signed request on a connection.
* This is good enough for now since a user who wants better security
* Having validation of negotiate info helps reduce attack vectors.
* would also enable signing on the mount. Having validation of
* negotiate info for signed connections helps reduce attack vectors
*/
*/
if
(
tcon
->
ses
->
se
rver
->
sign
==
false
)
if
(
tcon
->
ses
->
se
ssion_flags
&
SMB2_SESSION_FLAG_IS_GUEST
)
return
0
;
/* validation requires signing */
return
0
;
/* validation requires signing */
if
(
tcon
->
ses
->
user_name
==
NULL
)
{
cifs_dbg
(
FYI
,
"Can't validate negotiate: null user mount
\n
"
);
return
0
;
/* validation requires signing */
}
if
(
tcon
->
ses
->
session_flags
&
SMB2_SESSION_FLAG_IS_NULL
)
cifs_dbg
(
VFS
,
"Unexpected null user (anonymous) auth flag sent by server
\n
"
);
vneg_inbuf
.
Capabilities
=
vneg_inbuf
.
Capabilities
=
cpu_to_le32
(
tcon
->
ses
->
server
->
vals
->
req_capabilities
);
cpu_to_le32
(
tcon
->
ses
->
server
->
vals
->
req_capabilities
);
memcpy
(
vneg_inbuf
.
Guid
,
tcon
->
ses
->
server
->
client_guid
,
memcpy
(
vneg_inbuf
.
Guid
,
tcon
->
ses
->
server
->
client_guid
,
...
@@ -510,8 +531,13 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
...
@@ -510,8 +531,13 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
}
}
if
(
rsplen
!=
sizeof
(
struct
validate_negotiate_info_rsp
))
{
if
(
rsplen
!=
sizeof
(
struct
validate_negotiate_info_rsp
))
{
cifs_dbg
(
VFS
,
"invalid size of protocol negotiate response
\n
"
);
cifs_dbg
(
VFS
,
"invalid protocol negotiate response size: %d
\n
"
,
return
-
EIO
;
rsplen
);
/* relax check since Mac returns max bufsize allowed on ioctl */
if
((
rsplen
>
CIFSMaxBufSize
)
||
(
rsplen
<
sizeof
(
struct
validate_negotiate_info_rsp
)))
goto
err_rsp_free
;
}
}
/* check validate negotiate info response matches what we got earlier */
/* check validate negotiate info response matches what we got earlier */
...
@@ -530,10 +556,13 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
...
@@ -530,10 +556,13 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
/* validate negotiate successful */
/* validate negotiate successful */
cifs_dbg
(
FYI
,
"validate negotiate info successful
\n
"
);
cifs_dbg
(
FYI
,
"validate negotiate info successful
\n
"
);
kfree
(
pneg_rsp
);
return
0
;
return
0
;
vneg_out:
vneg_out:
cifs_dbg
(
VFS
,
"protocol revalidation - security settings mismatch
\n
"
);
cifs_dbg
(
VFS
,
"protocol revalidation - security settings mismatch
\n
"
);
err_rsp_free:
kfree
(
pneg_rsp
);
return
-
EIO
;
return
-
EIO
;
}
}
...
@@ -550,8 +579,9 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
...
@@ -550,8 +579,9 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
struct
TCP_Server_Info
*
server
=
ses
->
server
;
struct
TCP_Server_Info
*
server
=
ses
->
server
;
u16
blob_length
=
0
;
u16
blob_length
=
0
;
char
*
security_blob
;
char
*
security_blob
;
char
*
ntlmssp_blob
=
NULL
;
unsigned
char
*
ntlmssp_blob
=
NULL
;
bool
use_spnego
=
false
;
/* else use raw ntlmssp */
bool
use_spnego
=
false
;
/* else use raw ntlmssp */
u64
previous_session
=
ses
->
Suid
;
cifs_dbg
(
FYI
,
"Session Setup
\n
"
);
cifs_dbg
(
FYI
,
"Session Setup
\n
"
);
...
@@ -588,6 +618,10 @@ ssetup_ntlmssp_authenticate:
...
@@ -588,6 +618,10 @@ ssetup_ntlmssp_authenticate:
return
rc
;
return
rc
;
req
->
hdr
.
SessionId
=
0
;
/* First session, not a reauthenticate */
req
->
hdr
.
SessionId
=
0
;
/* First session, not a reauthenticate */
/* if reconnect, we need to send previous sess id, otherwise it is 0 */
req
->
PreviousSessionId
=
previous_session
;
req
->
VcNumber
=
0
;
/* MBZ */
req
->
VcNumber
=
0
;
/* MBZ */
/* to enable echos and oplocks */
/* to enable echos and oplocks */
req
->
hdr
.
CreditRequest
=
cpu_to_le16
(
3
);
req
->
hdr
.
CreditRequest
=
cpu_to_le16
(
3
);
...
@@ -631,13 +665,7 @@ ssetup_ntlmssp_authenticate:
...
@@ -631,13 +665,7 @@ ssetup_ntlmssp_authenticate:
}
}
}
else
if
(
phase
==
NtLmAuthenticate
)
{
}
else
if
(
phase
==
NtLmAuthenticate
)
{
req
->
hdr
.
SessionId
=
ses
->
Suid
;
req
->
hdr
.
SessionId
=
ses
->
Suid
;
ntlmssp_blob
=
kzalloc
(
sizeof
(
struct
_NEGOTIATE_MESSAGE
)
+
500
,
rc
=
build_ntlmssp_auth_blob
(
&
ntlmssp_blob
,
&
blob_length
,
ses
,
GFP_KERNEL
);
if
(
ntlmssp_blob
==
NULL
)
{
rc
=
-
ENOMEM
;
goto
ssetup_exit
;
}
rc
=
build_ntlmssp_auth_blob
(
ntlmssp_blob
,
&
blob_length
,
ses
,
nls_cp
);
nls_cp
);
if
(
rc
)
{
if
(
rc
)
{
cifs_dbg
(
FYI
,
"build_ntlmssp_auth_blob failed %d
\n
"
,
cifs_dbg
(
FYI
,
"build_ntlmssp_auth_blob failed %d
\n
"
,
...
@@ -830,9 +858,6 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
...
@@ -830,9 +858,6 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
else
else
return
-
EIO
;
return
-
EIO
;
if
(
tcon
&&
tcon
->
bad_network_name
)
return
-
ENOENT
;
unc_path
=
kmalloc
(
MAX_SHARENAME_LENGTH
*
2
,
GFP_KERNEL
);
unc_path
=
kmalloc
(
MAX_SHARENAME_LENGTH
*
2
,
GFP_KERNEL
);
if
(
unc_path
==
NULL
)
if
(
unc_path
==
NULL
)
return
-
ENOMEM
;
return
-
ENOMEM
;
...
@@ -844,6 +869,10 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
...
@@ -844,6 +869,10 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
return
-
EINVAL
;
return
-
EINVAL
;
}
}
/* SMB2 TREE_CONNECT request must be called with TreeId == 0 */
if
(
tcon
)
tcon
->
tid
=
0
;
rc
=
small_smb2_init
(
SMB2_TREE_CONNECT
,
tcon
,
(
void
**
)
&
req
);
rc
=
small_smb2_init
(
SMB2_TREE_CONNECT
,
tcon
,
(
void
**
)
&
req
);
if
(
rc
)
{
if
(
rc
)
{
kfree
(
unc_path
);
kfree
(
unc_path
);
...
@@ -886,15 +915,19 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
...
@@ -886,15 +915,19 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
goto
tcon_exit
;
goto
tcon_exit
;
}
}
if
(
rsp
->
ShareType
&
SMB2_SHARE_TYPE_DISK
)
switch
(
rsp
->
ShareType
)
{
case
SMB2_SHARE_TYPE_DISK
:
cifs_dbg
(
FYI
,
"connection to disk share
\n
"
);
cifs_dbg
(
FYI
,
"connection to disk share
\n
"
);
else
if
(
rsp
->
ShareType
&
SMB2_SHARE_TYPE_PIPE
)
{
break
;
case
SMB2_SHARE_TYPE_PIPE
:
tcon
->
ipc
=
true
;
tcon
->
ipc
=
true
;
cifs_dbg
(
FYI
,
"connection to pipe share
\n
"
);
cifs_dbg
(
FYI
,
"connection to pipe share
\n
"
);
}
else
if
(
rsp
->
ShareType
&
SMB2_SHARE_TYPE_PRINT
)
{
break
;
tcon
->
print
=
true
;
case
SMB2_SHARE_TYPE_PRINT
:
tcon
->
ipc
=
true
;
cifs_dbg
(
FYI
,
"connection to printer
\n
"
);
cifs_dbg
(
FYI
,
"connection to printer
\n
"
);
}
else
{
break
;
default:
cifs_dbg
(
VFS
,
"unknown share type %d
\n
"
,
rsp
->
ShareType
);
cifs_dbg
(
VFS
,
"unknown share type %d
\n
"
,
rsp
->
ShareType
);
rc
=
-
EOPNOTSUPP
;
rc
=
-
EOPNOTSUPP
;
goto
tcon_error_exit
;
goto
tcon_error_exit
;
...
@@ -922,8 +955,6 @@ tcon_exit:
...
@@ -922,8 +955,6 @@ tcon_exit:
tcon_error_exit:
tcon_error_exit:
if
(
rsp
->
hdr
.
Status
==
STATUS_BAD_NETWORK_NAME
)
{
if
(
rsp
->
hdr
.
Status
==
STATUS_BAD_NETWORK_NAME
)
{
cifs_dbg
(
VFS
,
"BAD_NETWORK_NAME: %s
\n
"
,
tree
);
cifs_dbg
(
VFS
,
"BAD_NETWORK_NAME: %s
\n
"
,
tree
);
if
(
tcon
)
tcon
->
bad_network_name
=
true
;
}
}
goto
tcon_exit
;
goto
tcon_exit
;
}
}
...
@@ -1094,7 +1125,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
...
@@ -1094,7 +1125,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
struct
TCP_Server_Info
*
server
;
struct
TCP_Server_Info
*
server
;
struct
cifs_tcon
*
tcon
=
oparms
->
tcon
;
struct
cifs_tcon
*
tcon
=
oparms
->
tcon
;
struct
cifs_ses
*
ses
=
tcon
->
ses
;
struct
cifs_ses
*
ses
=
tcon
->
ses
;
struct
kvec
iov
[
4
];
struct
kvec
iov
[
4
]
=
{{
NULL
,
0
}}
;
int
resp_buftype
;
int
resp_buftype
;
int
uni_path_len
;
int
uni_path_len
;
__le16
*
copy_path
=
NULL
;
__le16
*
copy_path
=
NULL
;
...
@@ -1122,7 +1153,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
...
@@ -1122,7 +1153,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
req
->
DesiredAccess
=
cpu_to_le32
(
oparms
->
desired_access
);
req
->
DesiredAccess
=
cpu_to_le32
(
oparms
->
desired_access
);
/* File attributes ignored on open (used in create though) */
/* File attributes ignored on open (used in create though) */
req
->
FileAttributes
=
cpu_to_le32
(
file_attributes
);
req
->
FileAttributes
=
cpu_to_le32
(
file_attributes
);
req
->
ShareAccess
=
cpu_to_le32
(
oparms
->
share_access
)
;
req
->
ShareAccess
=
FILE_SHARE_ALL_LE
;
req
->
CreateDisposition
=
cpu_to_le32
(
oparms
->
disposition
);
req
->
CreateDisposition
=
cpu_to_le32
(
oparms
->
disposition
);
req
->
CreateOptions
=
cpu_to_le32
(
oparms
->
create_options
&
CREATE_OPTIONS_MASK
);
req
->
CreateOptions
=
cpu_to_le32
(
oparms
->
create_options
&
CREATE_OPTIONS_MASK
);
uni_path_len
=
(
2
*
UniStrnlen
((
wchar_t
*
)
path
,
PATH_MAX
))
+
2
;
uni_path_len
=
(
2
*
UniStrnlen
((
wchar_t
*
)
path
,
PATH_MAX
))
+
2
;
...
@@ -1195,7 +1226,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
...
@@ -1195,7 +1226,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
if
(
rc
!=
0
)
{
if
(
rc
!=
0
)
{
cifs_stats_fail_inc
(
tcon
,
SMB2_CREATE_HE
);
cifs_stats_fail_inc
(
tcon
,
SMB2_CREATE_HE
);
if
(
err_buf
)
if
(
err_buf
&&
rsp
)
*
err_buf
=
kmemdup
(
rsp
,
get_rfc1002_length
(
rsp
)
+
4
,
*
err_buf
=
kmemdup
(
rsp
,
get_rfc1002_length
(
rsp
)
+
4
,
GFP_KERNEL
);
GFP_KERNEL
);
goto
creat_exit
;
goto
creat_exit
;
...
@@ -1281,8 +1312,12 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
...
@@ -1281,8 +1312,12 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
* than one credit. Windows typically sets this smaller, but for some
* than one credit. Windows typically sets this smaller, but for some
* ioctls it may be useful to allow server to send more. No point
* ioctls it may be useful to allow server to send more. No point
* limiting what the server can send as long as fits in one credit
* limiting what the server can send as long as fits in one credit
* Unfortunately - we can not handle more than CIFS_MAX_MSG_SIZE
* (by default, note that it can be overridden to make max larger)
* in responses (except for read responses which can be bigger.
* We may want to bump this limit up
*/
*/
req
->
MaxOutputResponse
=
cpu_to_le32
(
0xFF00
);
/* < 64K uses 1 credit */
req
->
MaxOutputResponse
=
cpu_to_le32
(
CIFSMaxBufSize
);
if
(
is_fsctl
)
if
(
is_fsctl
)
req
->
Flags
=
cpu_to_le32
(
SMB2_0_IOCTL_IS_FSCTL
);
req
->
Flags
=
cpu_to_le32
(
SMB2_0_IOCTL_IS_FSCTL
);
...
@@ -1307,6 +1342,9 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
...
@@ -1307,6 +1342,9 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
}
else
}
else
iov
[
0
].
iov_len
=
get_rfc1002_length
(
req
)
+
4
;
iov
[
0
].
iov_len
=
get_rfc1002_length
(
req
)
+
4
;
/* validate negotiate request must be signed - see MS-SMB2 3.2.5.5 */
if
(
opcode
==
FSCTL_VALIDATE_NEGOTIATE_INFO
)
req
->
hdr
.
Flags
|=
SMB2_FLAGS_SIGNED
;
rc
=
SendReceive2
(
xid
,
ses
,
iov
,
num_iovecs
,
&
resp_buftype
,
0
);
rc
=
SendReceive2
(
xid
,
ses
,
iov
,
num_iovecs
,
&
resp_buftype
,
0
);
rsp
=
(
struct
smb2_ioctl_rsp
*
)
iov
[
0
].
iov_base
;
rsp
=
(
struct
smb2_ioctl_rsp
*
)
iov
[
0
].
iov_base
;
...
@@ -1585,6 +1623,54 @@ smb2_echo_callback(struct mid_q_entry *mid)
...
@@ -1585,6 +1623,54 @@ smb2_echo_callback(struct mid_q_entry *mid)
add_credits
(
server
,
credits_received
,
CIFS_ECHO_OP
);
add_credits
(
server
,
credits_received
,
CIFS_ECHO_OP
);
}
}
void
smb2_reconnect_server
(
struct
work_struct
*
work
)
{
struct
TCP_Server_Info
*
server
=
container_of
(
work
,
struct
TCP_Server_Info
,
reconnect
.
work
);
struct
cifs_ses
*
ses
;
struct
cifs_tcon
*
tcon
,
*
tcon2
;
struct
list_head
tmp_list
;
int
tcon_exist
=
false
;
/* Prevent simultaneous reconnects that can corrupt tcon->rlist list */
mutex_lock
(
&
server
->
reconnect_mutex
);
INIT_LIST_HEAD
(
&
tmp_list
);
cifs_dbg
(
FYI
,
"Need negotiate, reconnecting tcons
\n
"
);
spin_lock
(
&
cifs_tcp_ses_lock
);
list_for_each_entry
(
ses
,
&
server
->
smb_ses_list
,
smb_ses_list
)
{
list_for_each_entry
(
tcon
,
&
ses
->
tcon_list
,
tcon_list
)
{
if
(
tcon
->
need_reconnect
)
{
tcon
->
tc_count
++
;
list_add_tail
(
&
tcon
->
rlist
,
&
tmp_list
);
tcon_exist
=
true
;
}
}
}
/*
* Get the reference to server struct to be sure that the last call of
* cifs_put_tcon() in the loop below won't release the server pointer.
*/
if
(
tcon_exist
)
server
->
srv_count
++
;
spin_unlock
(
&
cifs_tcp_ses_lock
);
list_for_each_entry_safe
(
tcon
,
tcon2
,
&
tmp_list
,
rlist
)
{
smb2_reconnect
(
SMB2_ECHO
,
tcon
);
list_del_init
(
&
tcon
->
rlist
);
cifs_put_tcon
(
tcon
);
}
cifs_dbg
(
FYI
,
"Reconnecting tcons finished
\n
"
);
mutex_unlock
(
&
server
->
reconnect_mutex
);
/* now we can safely release srv struct */
if
(
tcon_exist
)
cifs_put_tcp_session
(
server
,
1
);
}
int
int
SMB2_echo
(
struct
TCP_Server_Info
*
server
)
SMB2_echo
(
struct
TCP_Server_Info
*
server
)
{
{
...
@@ -1596,6 +1682,12 @@ SMB2_echo(struct TCP_Server_Info *server)
...
@@ -1596,6 +1682,12 @@ SMB2_echo(struct TCP_Server_Info *server)
cifs_dbg
(
FYI
,
"In echo request
\n
"
);
cifs_dbg
(
FYI
,
"In echo request
\n
"
);
if
(
server
->
tcpStatus
==
CifsNeedNegotiate
)
{
/* No need to send echo on newly established connections */
queue_delayed_work
(
cifsiod_wq
,
&
server
->
reconnect
,
0
);
return
rc
;
}
rc
=
small_smb2_init
(
SMB2_ECHO
,
NULL
,
(
void
**
)
&
req
);
rc
=
small_smb2_init
(
SMB2_ECHO
,
NULL
,
(
void
**
)
&
req
);
if
(
rc
)
if
(
rc
)
return
rc
;
return
rc
;
...
@@ -2297,6 +2389,22 @@ SMB2_rename(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -2297,6 +2389,22 @@ SMB2_rename(const unsigned int xid, struct cifs_tcon *tcon,
}
}
int
int
SMB2_rmdir
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
u64
persistent_fid
,
u64
volatile_fid
)
{
__u8
delete_pending
=
1
;
void
*
data
;
unsigned
int
size
;
data
=
&
delete_pending
;
size
=
1
;
/* sizeof __u8 */
return
send_set_info
(
xid
,
tcon
,
persistent_fid
,
volatile_fid
,
current
->
tgid
,
FILE_DISPOSITION_INFORMATION
,
1
,
&
data
,
&
size
);
}
int
SMB2_set_hardlink
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
SMB2_set_hardlink
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
u64
persistent_fid
,
u64
volatile_fid
,
__le16
*
target_file
)
u64
persistent_fid
,
u64
volatile_fid
,
__le16
*
target_file
)
{
{
...
@@ -2392,8 +2500,8 @@ copy_fs_info_to_kstatfs(struct smb2_fs_full_size_info *pfs_inf,
...
@@ -2392,8 +2500,8 @@ copy_fs_info_to_kstatfs(struct smb2_fs_full_size_info *pfs_inf,
kst
->
f_bsize
=
le32_to_cpu
(
pfs_inf
->
BytesPerSector
)
*
kst
->
f_bsize
=
le32_to_cpu
(
pfs_inf
->
BytesPerSector
)
*
le32_to_cpu
(
pfs_inf
->
SectorsPerAllocationUnit
);
le32_to_cpu
(
pfs_inf
->
SectorsPerAllocationUnit
);
kst
->
f_blocks
=
le64_to_cpu
(
pfs_inf
->
TotalAllocationUnits
);
kst
->
f_blocks
=
le64_to_cpu
(
pfs_inf
->
TotalAllocationUnits
);
kst
->
f_bfree
=
le64_to_cpu
(
pfs_inf
->
ActualAvailableAllocationUnits
);
kst
->
f_bfree
=
kst
->
f_bavail
=
kst
->
f_bavail
=
le64_to_cpu
(
pfs_inf
->
CallerAvailableAllocationUnits
);
le64_to_cpu
(
pfs_inf
->
CallerAvailableAllocationUnits
);
return
;
return
;
}
}
...
...
sources/3.16/smb2pdu.h
View file @
7e23c0f8
...
@@ -82,8 +82,8 @@
...
@@ -82,8 +82,8 @@
#define NUMBER_OF_SMB2_COMMANDS 0x0013
#define NUMBER_OF_SMB2_COMMANDS 0x0013
/*
BB FIXME - analyze following length BB
*/
/*
4 len + 52 transform hdr + 64 hdr + 56 create rsp
*/
#define MAX_SMB2_HDR_SIZE 0x
78
/* 4 len + 64 hdr + (2*24 wct) + 2 bct + 2 pad */
#define MAX_SMB2_HDR_SIZE 0x
00b0
#define SMB2_PROTO_NUMBER __constant_cpu_to_le32(0x424d53fe)
#define SMB2_PROTO_NUMBER __constant_cpu_to_le32(0x424d53fe)
...
@@ -245,7 +245,7 @@ struct smb2_sess_setup_req {
...
@@ -245,7 +245,7 @@ struct smb2_sess_setup_req {
__le32
Channel
;
__le32
Channel
;
__le16
SecurityBufferOffset
;
__le16
SecurityBufferOffset
;
__le16
SecurityBufferLength
;
__le16
SecurityBufferLength
;
__
le
64
PreviousSessionId
;
__
u
64
PreviousSessionId
;
__u8
Buffer
[
1
];
/* variable length GSS security buffer */
__u8
Buffer
[
1
];
/* variable length GSS security buffer */
}
__packed
;
}
__packed
;
...
...
sources/3.16/smb2proto.h
View file @
7e23c0f8
...
@@ -47,6 +47,10 @@ extern struct mid_q_entry *smb2_setup_request(struct cifs_ses *ses,
...
@@ -47,6 +47,10 @@ extern struct mid_q_entry *smb2_setup_request(struct cifs_ses *ses,
struct
smb_rqst
*
rqst
);
struct
smb_rqst
*
rqst
);
extern
struct
mid_q_entry
*
smb2_setup_async_request
(
extern
struct
mid_q_entry
*
smb2_setup_async_request
(
struct
TCP_Server_Info
*
server
,
struct
smb_rqst
*
rqst
);
struct
TCP_Server_Info
*
server
,
struct
smb_rqst
*
rqst
);
extern
struct
cifs_ses
*
smb2_find_smb_ses
(
struct
TCP_Server_Info
*
server
,
__u64
ses_id
);
extern
struct
cifs_tcon
*
smb2_find_smb_tcon
(
struct
TCP_Server_Info
*
server
,
__u64
ses_id
,
__u32
tid
);
extern
int
smb2_calc_signature
(
struct
smb_rqst
*
rqst
,
extern
int
smb2_calc_signature
(
struct
smb_rqst
*
rqst
,
struct
TCP_Server_Info
*
server
);
struct
TCP_Server_Info
*
server
);
extern
int
smb3_calc_signature
(
struct
smb_rqst
*
rqst
,
extern
int
smb3_calc_signature
(
struct
smb_rqst
*
rqst
,
...
@@ -89,6 +93,7 @@ extern int smb2_open_file(const unsigned int xid,
...
@@ -89,6 +93,7 @@ extern int smb2_open_file(const unsigned int xid,
extern
int
smb2_unlock_range
(
struct
cifsFileInfo
*
cfile
,
extern
int
smb2_unlock_range
(
struct
cifsFileInfo
*
cfile
,
struct
file_lock
*
flock
,
const
unsigned
int
xid
);
struct
file_lock
*
flock
,
const
unsigned
int
xid
);
extern
int
smb2_push_mandatory_locks
(
struct
cifsFileInfo
*
cfile
);
extern
int
smb2_push_mandatory_locks
(
struct
cifsFileInfo
*
cfile
);
extern
void
smb2_reconnect_server
(
struct
work_struct
*
work
);
/*
/*
* SMB2 Worker functions - most of protocol specific implementation details
* SMB2 Worker functions - most of protocol specific implementation details
...
@@ -134,6 +139,8 @@ extern int SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -134,6 +139,8 @@ extern int SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
extern
int
SMB2_rename
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
extern
int
SMB2_rename
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
u64
persistent_fid
,
u64
volatile_fid
,
u64
persistent_fid
,
u64
volatile_fid
,
__le16
*
target_file
);
__le16
*
target_file
);
extern
int
SMB2_rmdir
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
u64
persistent_fid
,
u64
volatile_fid
);
extern
int
SMB2_set_hardlink
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
extern
int
SMB2_set_hardlink
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
u64
persistent_fid
,
u64
volatile_fid
,
u64
persistent_fid
,
u64
volatile_fid
,
__le16
*
target_file
);
__le16
*
target_file
);
...
@@ -148,6 +155,9 @@ extern int SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -148,6 +155,9 @@ extern int SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
extern
int
SMB2_oplock_break
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
extern
int
SMB2_oplock_break
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
const
u64
persistent_fid
,
const
u64
volatile_fid
,
const
u64
persistent_fid
,
const
u64
volatile_fid
,
const
__u8
oplock_level
);
const
__u8
oplock_level
);
extern
int
smb2_handle_cancelled_mid
(
char
*
buffer
,
struct
TCP_Server_Info
*
server
);
void
smb2_cancelled_close_fid
(
struct
work_struct
*
work
);
extern
int
SMB2_QFS_info
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
extern
int
SMB2_QFS_info
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
u64
persistent_file_id
,
u64
volatile_file_id
,
u64
persistent_file_id
,
u64
volatile_file_id
,
struct
kstatfs
*
FSData
);
struct
kstatfs
*
FSData
);
...
...
sources/3.16/smb2transport.c
View file @
7e23c0f8
...
@@ -115,22 +115,68 @@ smb3_crypto_shash_allocate(struct TCP_Server_Info *server)
...
@@ -115,22 +115,68 @@ smb3_crypto_shash_allocate(struct TCP_Server_Info *server)
}
}
static
struct
cifs_ses
*
static
struct
cifs_ses
*
smb2_find_smb_ses
(
struct
smb2_hdr
*
smb2hdr
,
struct
TCP_Server_Info
*
server
)
smb2_find_smb_ses
_unlocked
(
struct
TCP_Server_Info
*
server
,
__u64
ses_id
)
{
{
struct
cifs_ses
*
ses
;
struct
cifs_ses
*
ses
;
spin_lock
(
&
cifs_tcp_ses_lock
);
list_for_each_entry
(
ses
,
&
server
->
smb_ses_list
,
smb_ses_list
)
{
list_for_each_entry
(
ses
,
&
server
->
smb_ses_list
,
smb_ses_list
)
{
if
(
ses
->
Suid
!=
s
mb2hdr
->
SessionI
d
)
if
(
ses
->
Suid
!=
s
es_i
d
)
continue
;
continue
;
spin_unlock
(
&
cifs_tcp_ses_lock
);
return
ses
;
return
ses
;
}
}
return
NULL
;
}
struct
cifs_ses
*
smb2_find_smb_ses
(
struct
TCP_Server_Info
*
server
,
__u64
ses_id
)
{
struct
cifs_ses
*
ses
;
spin_lock
(
&
cifs_tcp_ses_lock
);
ses
=
smb2_find_smb_ses_unlocked
(
server
,
ses_id
);
spin_unlock
(
&
cifs_tcp_ses_lock
);
spin_unlock
(
&
cifs_tcp_ses_lock
);
return
ses
;
}
static
struct
cifs_tcon
*
smb2_find_smb_sess_tcon_unlocked
(
struct
cifs_ses
*
ses
,
__u32
tid
)
{
struct
cifs_tcon
*
tcon
;
list_for_each_entry
(
tcon
,
&
ses
->
tcon_list
,
tcon_list
)
{
if
(
tcon
->
tid
!=
tid
)
continue
;
++
tcon
->
tc_count
;
return
tcon
;
}
return
NULL
;
return
NULL
;
}
}
/*
* Obtain tcon corresponding to the tid in the given
* cifs_ses
*/
struct
cifs_tcon
*
smb2_find_smb_tcon
(
struct
TCP_Server_Info
*
server
,
__u64
ses_id
,
__u32
tid
)
{
struct
cifs_ses
*
ses
;
struct
cifs_tcon
*
tcon
;
spin_lock
(
&
cifs_tcp_ses_lock
);
ses
=
smb2_find_smb_ses_unlocked
(
server
,
ses_id
);
if
(
!
ses
)
{
spin_unlock
(
&
cifs_tcp_ses_lock
);
return
NULL
;
}
tcon
=
smb2_find_smb_sess_tcon_unlocked
(
ses
,
tid
);
spin_unlock
(
&
cifs_tcp_ses_lock
);
return
tcon
;
}
int
int
smb2_calc_signature
(
struct
smb_rqst
*
rqst
,
struct
TCP_Server_Info
*
server
)
smb2_calc_signature
(
struct
smb_rqst
*
rqst
,
struct
TCP_Server_Info
*
server
)
...
@@ -143,7 +189,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
...
@@ -143,7 +189,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
struct
smb2_hdr
*
smb2_pdu
=
(
struct
smb2_hdr
*
)
iov
[
0
].
iov_base
;
struct
smb2_hdr
*
smb2_pdu
=
(
struct
smb2_hdr
*
)
iov
[
0
].
iov_base
;
struct
cifs_ses
*
ses
;
struct
cifs_ses
*
ses
;
ses
=
smb2_find_smb_ses
(
s
mb2_pdu
,
server
);
ses
=
smb2_find_smb_ses
(
s
erver
,
smb2_pdu
->
SessionId
);
if
(
!
ses
)
{
if
(
!
ses
)
{
cifs_dbg
(
VFS
,
"%s: Could not find session
\n
"
,
__func__
);
cifs_dbg
(
VFS
,
"%s: Could not find session
\n
"
,
__func__
);
return
0
;
return
0
;
...
@@ -314,7 +360,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
...
@@ -314,7 +360,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
struct
smb2_hdr
*
smb2_pdu
=
(
struct
smb2_hdr
*
)
iov
[
0
].
iov_base
;
struct
smb2_hdr
*
smb2_pdu
=
(
struct
smb2_hdr
*
)
iov
[
0
].
iov_base
;
struct
cifs_ses
*
ses
;
struct
cifs_ses
*
ses
;
ses
=
smb2_find_smb_ses
(
s
mb2_pdu
,
server
);
ses
=
smb2_find_smb_ses
(
s
erver
,
smb2_pdu
->
SessionId
);
if
(
!
ses
)
{
if
(
!
ses
)
{
cifs_dbg
(
VFS
,
"%s: Could not find session
\n
"
,
__func__
);
cifs_dbg
(
VFS
,
"%s: Could not find session
\n
"
,
__func__
);
return
0
;
return
0
;
...
...
sources/3.16/transport.c
View file @
7e23c0f8
...
@@ -773,9 +773,11 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
...
@@ -773,9 +773,11 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
rc
=
wait_for_response
(
ses
->
server
,
midQ
);
rc
=
wait_for_response
(
ses
->
server
,
midQ
);
if
(
rc
!=
0
)
{
if
(
rc
!=
0
)
{
cifs_dbg
(
FYI
,
"Cancelling wait for mid %llu
\n
"
,
midQ
->
mid
);
send_cancel
(
ses
->
server
,
buf
,
midQ
);
send_cancel
(
ses
->
server
,
buf
,
midQ
);
spin_lock
(
&
GlobalMid_Lock
);
spin_lock
(
&
GlobalMid_Lock
);
if
(
midQ
->
mid_state
==
MID_REQUEST_SUBMITTED
)
{
if
(
midQ
->
mid_state
==
MID_REQUEST_SUBMITTED
)
{
midQ
->
mid_flags
|=
MID_WAIT_CANCELLED
;
midQ
->
callback
=
DeleteMidQEntry
;
midQ
->
callback
=
DeleteMidQEntry
;
spin_unlock
(
&
GlobalMid_Lock
);
spin_unlock
(
&
GlobalMid_Lock
);
cifs_small_buf_release
(
buf
);
cifs_small_buf_release
(
buf
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment