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
9d798057
Commit
9d798057
authored
Jun 21, 2015
by
Pavel Shilovsky
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update CentOS 7.0 sources (3.10.0-229.1.2)
parent
2f82a4e6
Hide whitespace changes
Inline
Side-by-side
Showing
34 changed files
with
2164 additions
and
769 deletions
+2164
-769
cifs_fs_sb.h
sources/centos70/cifs_fs_sb.h
+1
-0
cifsacl.c
sources/centos70/cifsacl.c
+78
-27
cifsencrypt.c
sources/centos70/cifsencrypt.c
+24
-16
cifsfs.c
sources/centos70/cifsfs.c
+68
-58
cifsfs.h
sources/centos70/cifsfs.h
+19
-11
cifsglob.h
sources/centos70/cifsglob.h
+67
-6
cifspdu.h
sources/centos70/cifspdu.h
+63
-10
cifsproto.h
sources/centos70/cifsproto.h
+24
-14
cifssmb.c
sources/centos70/cifssmb.c
+183
-78
connect.c
sources/centos70/connect.c
+32
-8
dir.c
sources/centos70/dir.c
+34
-30
file.c
sources/centos70/file.c
+98
-32
fscache.c
sources/centos70/fscache.c
+7
-0
fscache.h
sources/centos70/fscache.h
+13
-0
inode.c
sources/centos70/inode.c
+239
-119
ioctl.c
sources/centos70/ioctl.c
+140
-19
link.c
sources/centos70/link.c
+167
-178
misc.c
sources/centos70/misc.c
+80
-16
netmisc.c
sources/centos70/netmisc.c
+9
-6
readdir.c
sources/centos70/readdir.c
+12
-33
sess.c
sources/centos70/sess.c
+2
-2
smb1ops.c
sources/centos70/smb1ops.c
+92
-29
smb2glob.h
sources/centos70/smb2glob.h
+3
-0
smb2inode.c
sources/centos70/smb2inode.c
+12
-4
smb2maperror.c
sources/centos70/smb2maperror.c
+1
-1
smb2misc.c
sources/centos70/smb2misc.c
+15
-3
smb2ops.c
sources/centos70/smb2ops.c
+291
-10
smb2pdu.c
sources/centos70/smb2pdu.c
+231
-16
smb2pdu.h
sources/centos70/smb2pdu.h
+71
-10
smb2proto.h
sources/centos70/smb2proto.h
+6
-1
smb2transport.c
sources/centos70/smb2transport.c
+9
-3
smbfsctl.h
sources/centos70/smbfsctl.h
+15
-1
transport.c
sources/centos70/transport.c
+17
-5
xattr.c
sources/centos70/xattr.c
+41
-23
No files found.
sources/centos70/cifs_fs_sb.h
View file @
9d798057
...
@@ -65,5 +65,6 @@ struct cifs_sb_info {
...
@@ -65,5 +65,6 @@ struct cifs_sb_info {
char
*
mountdata
;
/* options received at mount time or via DFS refs */
char
*
mountdata
;
/* options received at mount time or via DFS refs */
struct
backing_dev_info
bdi
;
struct
backing_dev_info
bdi
;
struct
delayed_work
prune_tlinks
;
struct
delayed_work
prune_tlinks
;
struct
rcu_head
rcu
;
};
};
#endif
/* _CIFS_FS_SB_H */
#endif
/* _CIFS_FS_SB_H */
sources/centos70/cifsacl.c
View file @
9d798057
...
@@ -865,8 +865,8 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
...
@@ -865,8 +865,8 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
return
rc
;
return
rc
;
}
}
st
atic
st
ruct
cifs_ntsd
*
get_cifs_acl_by_fid
(
struct
cifs_sb_info
*
cifs_sb
,
struct
cifs_ntsd
*
get_cifs_acl_by_fid
(
struct
cifs_sb_info
*
cifs_sb
,
__u16
fid
,
u32
*
pacllen
)
const
struct
cifs_fid
*
cifs
fid
,
u32
*
pacllen
)
{
{
struct
cifs_ntsd
*
pntsd
=
NULL
;
struct
cifs_ntsd
*
pntsd
=
NULL
;
unsigned
int
xid
;
unsigned
int
xid
;
...
@@ -877,7 +877,8 @@ static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
...
@@ -877,7 +877,8 @@ static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
return
ERR_CAST
(
tlink
);
return
ERR_CAST
(
tlink
);
xid
=
get_xid
();
xid
=
get_xid
();
rc
=
CIFSSMBGetCIFSACL
(
xid
,
tlink_tcon
(
tlink
),
fid
,
&
pntsd
,
pacllen
);
rc
=
CIFSSMBGetCIFSACL
(
xid
,
tlink_tcon
(
tlink
),
cifsfid
->
netfid
,
&
pntsd
,
pacllen
);
free_xid
(
xid
);
free_xid
(
xid
);
cifs_put_tlink
(
tlink
);
cifs_put_tlink
(
tlink
);
...
@@ -895,9 +896,10 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
...
@@ -895,9 +896,10 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
int
oplock
=
0
;
int
oplock
=
0
;
unsigned
int
xid
;
unsigned
int
xid
;
int
rc
,
create_options
=
0
;
int
rc
,
create_options
=
0
;
__u16
fid
;
struct
cifs_tcon
*
tcon
;
struct
cifs_tcon
*
tcon
;
struct
tcon_link
*
tlink
=
cifs_sb_tlink
(
cifs_sb
);
struct
tcon_link
*
tlink
=
cifs_sb_tlink
(
cifs_sb
);
struct
cifs_fid
fid
;
struct
cifs_open_parms
oparms
;
if
(
IS_ERR
(
tlink
))
if
(
IS_ERR
(
tlink
))
return
ERR_CAST
(
tlink
);
return
ERR_CAST
(
tlink
);
...
@@ -908,13 +910,20 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
...
@@ -908,13 +910,20 @@ static struct cifs_ntsd *get_cifs_acl_by_path(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
;
rc
=
CIFSSMBOpen
(
xid
,
tcon
,
path
,
FILE_OPEN
,
READ_CONTROL
,
oparms
.
tcon
=
tcon
;
FILE_SHARE_ALL
,
create_options
,
&
fid
,
&
oplock
,
oparms
.
cifs_sb
=
cifs_sb
;
NULL
,
cifs_sb
->
local_nls
,
oparms
.
desired_access
=
READ_CONTROL
;
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MAP_SPECIAL_CHR
);
oparms
.
share_access
=
FILE_SHARE_ALL
;
oparms
.
create_options
=
create_options
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
path
=
path
;
oparms
.
fid
=
&
fid
;
oparms
.
reconnect
=
false
;
rc
=
CIFS_open
(
xid
,
&
oparms
,
&
oplock
,
NULL
);
if
(
!
rc
)
{
if
(
!
rc
)
{
rc
=
CIFSSMBGetCIFSACL
(
xid
,
tcon
,
fid
,
&
pntsd
,
pacllen
);
rc
=
CIFSSMBGetCIFSACL
(
xid
,
tcon
,
fid
.
netfid
,
&
pntsd
,
pacllen
);
CIFSSMBClose
(
xid
,
tcon
,
fid
);
CIFSSMBClose
(
xid
,
tcon
,
fid
.
netfid
);
}
}
cifs_put_tlink
(
tlink
);
cifs_put_tlink
(
tlink
);
...
@@ -939,7 +948,7 @@ struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
...
@@ -939,7 +948,7 @@ struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
if
(
!
open_file
)
if
(
!
open_file
)
return
get_cifs_acl_by_path
(
cifs_sb
,
path
,
pacllen
);
return
get_cifs_acl_by_path
(
cifs_sb
,
path
,
pacllen
);
pntsd
=
get_cifs_acl_by_fid
(
cifs_sb
,
open_file
->
fid
.
net
fid
,
pacllen
);
pntsd
=
get_cifs_acl_by_fid
(
cifs_sb
,
&
open_file
->
fid
,
pacllen
);
cifsFileInfo_put
(
open_file
);
cifsFileInfo_put
(
open_file
);
return
pntsd
;
return
pntsd
;
}
}
...
@@ -951,10 +960,11 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
...
@@ -951,10 +960,11 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
int
oplock
=
0
;
int
oplock
=
0
;
unsigned
int
xid
;
unsigned
int
xid
;
int
rc
,
access_flags
,
create_options
=
0
;
int
rc
,
access_flags
,
create_options
=
0
;
__u16
fid
;
struct
cifs_tcon
*
tcon
;
struct
cifs_tcon
*
tcon
;
struct
cifs_sb_info
*
cifs_sb
=
CIFS_SB
(
inode
->
i_sb
);
struct
cifs_sb_info
*
cifs_sb
=
CIFS_SB
(
inode
->
i_sb
);
struct
tcon_link
*
tlink
=
cifs_sb_tlink
(
cifs_sb
);
struct
tcon_link
*
tlink
=
cifs_sb_tlink
(
cifs_sb
);
struct
cifs_fid
fid
;
struct
cifs_open_parms
oparms
;
if
(
IS_ERR
(
tlink
))
if
(
IS_ERR
(
tlink
))
return
PTR_ERR
(
tlink
);
return
PTR_ERR
(
tlink
);
...
@@ -970,19 +980,26 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
...
@@ -970,19 +980,26 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
else
else
access_flags
=
WRITE_DAC
;
access_flags
=
WRITE_DAC
;
rc
=
CIFSSMBOpen
(
xid
,
tcon
,
path
,
FILE_OPEN
,
access_flags
,
oparms
.
tcon
=
tcon
;
FILE_SHARE_ALL
,
create_options
,
&
fid
,
&
oplock
,
oparms
.
cifs_sb
=
cifs_sb
;
NULL
,
cifs_sb
->
local_nls
,
oparms
.
desired_access
=
access_flags
;
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MAP_SPECIAL_CHR
);
oparms
.
share_access
=
FILE_SHARE_ALL
;
oparms
.
create_options
=
create_options
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
path
=
path
;
oparms
.
fid
=
&
fid
;
oparms
.
reconnect
=
false
;
rc
=
CIFS_open
(
xid
,
&
oparms
,
&
oplock
,
NULL
);
if
(
rc
)
{
if
(
rc
)
{
cifs_dbg
(
VFS
,
"Unable to open file to set ACL
\n
"
);
cifs_dbg
(
VFS
,
"Unable to open file to set ACL
\n
"
);
goto
out
;
goto
out
;
}
}
rc
=
CIFSSMBSetCIFSACL
(
xid
,
tcon
,
fid
,
pnntsd
,
acllen
,
aclflag
);
rc
=
CIFSSMBSetCIFSACL
(
xid
,
tcon
,
fid
.
netfid
,
pnntsd
,
acllen
,
aclflag
);
cifs_dbg
(
NOISY
,
"SetCIFSACL rc = %d
\n
"
,
rc
);
cifs_dbg
(
NOISY
,
"SetCIFSACL rc = %d
\n
"
,
rc
);
CIFSSMBClose
(
xid
,
tcon
,
fid
);
CIFSSMBClose
(
xid
,
tcon
,
fid
.
netfid
);
out:
out:
free_xid
(
xid
);
free_xid
(
xid
);
cifs_put_tlink
(
tlink
);
cifs_put_tlink
(
tlink
);
...
@@ -992,19 +1009,31 @@ out:
...
@@ -992,19 +1009,31 @@ out:
/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
int
int
cifs_acl_to_fattr
(
struct
cifs_sb_info
*
cifs_sb
,
struct
cifs_fattr
*
fattr
,
cifs_acl_to_fattr
(
struct
cifs_sb_info
*
cifs_sb
,
struct
cifs_fattr
*
fattr
,
struct
inode
*
inode
,
const
char
*
path
,
const
__u16
*
pfid
)
struct
inode
*
inode
,
const
char
*
path
,
const
struct
cifs_fid
*
pfid
)
{
{
struct
cifs_ntsd
*
pntsd
=
NULL
;
struct
cifs_ntsd
*
pntsd
=
NULL
;
u32
acllen
=
0
;
u32
acllen
=
0
;
int
rc
=
0
;
int
rc
=
0
;
struct
tcon_link
*
tlink
=
cifs_sb_tlink
(
cifs_sb
);
struct
cifs_tcon
*
tcon
;
cifs_dbg
(
NOISY
,
"converting ACL to mode for %s
\n
"
,
path
);
cifs_dbg
(
NOISY
,
"converting ACL to mode for %s
\n
"
,
path
);
if
(
pfid
)
if
(
IS_ERR
(
tlink
))
pntsd
=
get_cifs_acl_by_fid
(
cifs_sb
,
*
pfid
,
&
acllen
);
return
PTR_ERR
(
tlink
);
else
tcon
=
tlink_tcon
(
tlink
);
pntsd
=
get_cifs_acl
(
cifs_sb
,
inode
,
path
,
&
acllen
);
if
(
pfid
&&
(
tcon
->
ses
->
server
->
ops
->
get_acl_by_fid
))
pntsd
=
tcon
->
ses
->
server
->
ops
->
get_acl_by_fid
(
cifs_sb
,
pfid
,
&
acllen
);
else
if
(
tcon
->
ses
->
server
->
ops
->
get_acl
)
pntsd
=
tcon
->
ses
->
server
->
ops
->
get_acl
(
cifs_sb
,
inode
,
path
,
&
acllen
);
else
{
cifs_put_tlink
(
tlink
);
return
-
EOPNOTSUPP
;
}
/* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
/* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
if
(
IS_ERR
(
pntsd
))
{
if
(
IS_ERR
(
pntsd
))
{
rc
=
PTR_ERR
(
pntsd
);
rc
=
PTR_ERR
(
pntsd
);
...
@@ -1016,6 +1045,8 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
...
@@ -1016,6 +1045,8 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
cifs_dbg
(
VFS
,
"parse sec desc failed rc = %d
\n
"
,
rc
);
cifs_dbg
(
VFS
,
"parse sec desc failed rc = %d
\n
"
,
rc
);
}
}
cifs_put_tlink
(
tlink
);
return
rc
;
return
rc
;
}
}
...
@@ -1029,15 +1060,30 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
...
@@ -1029,15 +1060,30 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
__u32
secdesclen
=
0
;
__u32
secdesclen
=
0
;
struct
cifs_ntsd
*
pntsd
=
NULL
;
/* acl obtained from server */
struct
cifs_ntsd
*
pntsd
=
NULL
;
/* acl obtained from server */
struct
cifs_ntsd
*
pnntsd
=
NULL
;
/* modified acl to be sent to server */
struct
cifs_ntsd
*
pnntsd
=
NULL
;
/* modified acl to be sent to server */
struct
cifs_sb_info
*
cifs_sb
=
CIFS_SB
(
inode
->
i_sb
);
struct
tcon_link
*
tlink
=
cifs_sb_tlink
(
cifs_sb
);
struct
cifs_tcon
*
tcon
;
if
(
IS_ERR
(
tlink
))
return
PTR_ERR
(
tlink
);
tcon
=
tlink_tcon
(
tlink
);
cifs_dbg
(
NOISY
,
"set ACL from mode for %s
\n
"
,
path
);
cifs_dbg
(
NOISY
,
"set ACL from mode for %s
\n
"
,
path
);
/* Get the security descriptor */
/* Get the security descriptor */
pntsd
=
get_cifs_acl
(
CIFS_SB
(
inode
->
i_sb
),
inode
,
path
,
&
secdesclen
);
if
(
tcon
->
ses
->
server
->
ops
->
get_acl
==
NULL
)
{
cifs_put_tlink
(
tlink
);
return
-
EOPNOTSUPP
;
}
pntsd
=
tcon
->
ses
->
server
->
ops
->
get_acl
(
cifs_sb
,
inode
,
path
,
&
secdesclen
);
if
(
IS_ERR
(
pntsd
))
{
if
(
IS_ERR
(
pntsd
))
{
rc
=
PTR_ERR
(
pntsd
);
rc
=
PTR_ERR
(
pntsd
);
cifs_dbg
(
VFS
,
"%s: error %d getting sec desc
\n
"
,
__func__
,
rc
);
cifs_dbg
(
VFS
,
"%s: error %d getting sec desc
\n
"
,
__func__
,
rc
);
goto
out
;
cifs_put_tlink
(
tlink
);
return
rc
;
}
}
/*
/*
...
@@ -1050,6 +1096,7 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
...
@@ -1050,6 +1096,7 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
pnntsd
=
kmalloc
(
secdesclen
,
GFP_KERNEL
);
pnntsd
=
kmalloc
(
secdesclen
,
GFP_KERNEL
);
if
(
!
pnntsd
)
{
if
(
!
pnntsd
)
{
kfree
(
pntsd
);
kfree
(
pntsd
);
cifs_put_tlink
(
tlink
);
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
...
@@ -1058,14 +1105,18 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
...
@@ -1058,14 +1105,18 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
cifs_dbg
(
NOISY
,
"build_sec_desc rc: %d
\n
"
,
rc
);
cifs_dbg
(
NOISY
,
"build_sec_desc rc: %d
\n
"
,
rc
);
if
(
tcon
->
ses
->
server
->
ops
->
set_acl
==
NULL
)
rc
=
-
EOPNOTSUPP
;
if
(
!
rc
)
{
if
(
!
rc
)
{
/* Set the security descriptor */
/* Set the security descriptor */
rc
=
set_cifs_acl
(
pnntsd
,
secdesclen
,
inode
,
path
,
aclflag
);
rc
=
tcon
->
ses
->
server
->
ops
->
set_acl
(
pnntsd
,
secdesclen
,
inode
,
path
,
aclflag
);
cifs_dbg
(
NOISY
,
"set_cifs_acl rc: %d
\n
"
,
rc
);
cifs_dbg
(
NOISY
,
"set_cifs_acl rc: %d
\n
"
,
rc
);
}
}
cifs_put_tlink
(
tlink
);
kfree
(
pnntsd
);
kfree
(
pnntsd
);
kfree
(
pntsd
);
kfree
(
pntsd
);
out:
return
rc
;
return
rc
;
}
}
sources/centos70/cifsencrypt.c
View file @
9d798057
...
@@ -548,7 +548,13 @@ static int
...
@@ -548,7 +548,13 @@ static int
CalcNTLMv2_response
(
const
struct
cifs_ses
*
ses
,
char
*
ntlmv2_hash
)
CalcNTLMv2_response
(
const
struct
cifs_ses
*
ses
,
char
*
ntlmv2_hash
)
{
{
int
rc
;
int
rc
;
unsigned
int
offset
=
CIFS_SESS_KEY_SIZE
+
8
;
struct
ntlmv2_resp
*
ntlmv2
=
(
struct
ntlmv2_resp
*
)
(
ses
->
auth_key
.
response
+
CIFS_SESS_KEY_SIZE
);
unsigned
int
hash_len
;
/* The MD5 hash starts at challenge_key.key */
hash_len
=
ses
->
auth_key
.
len
-
(
CIFS_SESS_KEY_SIZE
+
offsetof
(
struct
ntlmv2_resp
,
challenge
.
key
[
0
]));
if
(
!
ses
->
server
->
secmech
.
sdeschmacmd5
)
{
if
(
!
ses
->
server
->
secmech
.
sdeschmacmd5
)
{
cifs_dbg
(
VFS
,
"%s: can't generate ntlmv2 hash
\n
"
,
__func__
);
cifs_dbg
(
VFS
,
"%s: can't generate ntlmv2 hash
\n
"
,
__func__
);
...
@@ -556,7 +562,7 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
...
@@ -556,7 +562,7 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
}
}
rc
=
crypto_shash_setkey
(
ses
->
server
->
secmech
.
hmacmd5
,
rc
=
crypto_shash_setkey
(
ses
->
server
->
secmech
.
hmacmd5
,
ntlmv2_hash
,
CIFS_HMAC_MD5_HASH_SIZE
);
ntlmv2_hash
,
CIFS_HMAC_MD5_HASH_SIZE
);
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__
);
...
@@ -570,20 +576,21 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
...
@@ -570,20 +576,21 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
}
}
if
(
ses
->
server
->
negflavor
==
CIFS_NEGFLAVOR_EXTENDED
)
if
(
ses
->
server
->
negflavor
==
CIFS_NEGFLAVOR_EXTENDED
)
memcpy
(
ses
->
auth_key
.
response
+
offset
,
memcpy
(
ntlmv2
->
challenge
.
key
,
ses
->
ntlmssp
->
cryptkey
,
CIFS_SERVER_CHALLENGE_SIZE
);
ses
->
ntlmssp
->
cryptkey
,
CIFS_SERVER_CHALLENGE_SIZE
);
else
else
memcpy
(
ses
->
auth_key
.
response
+
offset
,
memcpy
(
ntlmv2
->
challenge
.
key
,
ses
->
server
->
cryptkey
,
CIFS_SERVER_CHALLENGE_SIZE
);
ses
->
server
->
cryptkey
,
CIFS_SERVER_CHALLENGE_SIZE
);
rc
=
crypto_shash_update
(
&
ses
->
server
->
secmech
.
sdeschmacmd5
->
shash
,
rc
=
crypto_shash_update
(
&
ses
->
server
->
secmech
.
sdeschmacmd5
->
shash
,
ses
->
auth_key
.
response
+
offset
,
ses
->
auth_key
.
len
-
offset
);
ntlmv2
->
challenge
.
key
,
hash_len
);
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__
);
return
rc
;
return
rc
;
}
}
/* Note that the MD5 digest over writes anon.challenge_key.key */
rc
=
crypto_shash_final
(
&
ses
->
server
->
secmech
.
sdeschmacmd5
->
shash
,
rc
=
crypto_shash_final
(
&
ses
->
server
->
secmech
.
sdeschmacmd5
->
shash
,
ses
->
auth_key
.
response
+
CIFS_SESS_KEY_SIZE
);
ntlmv2
->
ntlmv2_hash
);
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__
);
...
@@ -627,7 +634,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
...
@@ -627,7 +634,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
int
rc
;
int
rc
;
int
baselen
;
int
baselen
;
unsigned
int
tilen
;
unsigned
int
tilen
;
struct
ntlmv2_resp
*
buf
;
struct
ntlmv2_resp
*
ntlmv2
;
char
ntlmv2_hash
[
16
];
char
ntlmv2_hash
[
16
];
unsigned
char
*
tiblob
=
NULL
;
/* target info blob */
unsigned
char
*
tiblob
=
NULL
;
/* target info blob */
...
@@ -660,13 +667,14 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
...
@@ -660,13 +667,14 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
}
}
ses
->
auth_key
.
len
+=
baselen
;
ses
->
auth_key
.
len
+=
baselen
;
buf
=
(
struct
ntlmv2_resp
*
)
ntlmv2
=
(
struct
ntlmv2_resp
*
)
(
ses
->
auth_key
.
response
+
CIFS_SESS_KEY_SIZE
);
(
ses
->
auth_key
.
response
+
CIFS_SESS_KEY_SIZE
);
buf
->
blob_signature
=
cpu_to_le32
(
0x00000101
);
ntlmv2
->
blob_signature
=
cpu_to_le32
(
0x00000101
);
buf
->
reserved
=
0
;
ntlmv2
->
reserved
=
0
;
buf
->
time
=
cpu_to_le64
(
cifs_UnixTimeToNT
(
CURRENT_TIME
));
/* Must be within 5 minutes of the server */
get_random_bytes
(
&
buf
->
client_chal
,
sizeof
(
buf
->
client_chal
));
ntlmv2
->
time
=
cpu_to_le64
(
cifs_UnixTimeToNT
(
CURRENT_TIME
));
buf
->
reserved2
=
0
;
get_random_bytes
(
&
ntlmv2
->
client_chal
,
sizeof
(
ntlmv2
->
client_chal
));
ntlmv2
->
reserved2
=
0
;
memcpy
(
ses
->
auth_key
.
response
+
baselen
,
tiblob
,
tilen
);
memcpy
(
ses
->
auth_key
.
response
+
baselen
,
tiblob
,
tilen
);
...
@@ -706,7 +714,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
...
@@ -706,7 +714,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
}
}
rc
=
crypto_shash_update
(
&
ses
->
server
->
secmech
.
sdeschmacmd5
->
shash
,
rc
=
crypto_shash_update
(
&
ses
->
server
->
secmech
.
sdeschmacmd5
->
shash
,
ses
->
auth_key
.
response
+
CIFS_SESS_KEY_SIZE
,
ntlmv2
->
ntlmv2_hash
,
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__
);
...
...
sources/centos70/cifsfs.c
View file @
9d798057
...
@@ -87,10 +87,6 @@ extern mempool_t *cifs_mid_poolp;
...
@@ -87,10 +87,6 @@ extern mempool_t *cifs_mid_poolp;
struct
workqueue_struct
*
cifsiod_wq
;
struct
workqueue_struct
*
cifsiod_wq
;
#ifdef CONFIG_CIFS_SMB2
__u8
cifs_client_guid
[
SMB2_CLIENT_GUID_SIZE
];
#endif
/*
/*
* Bumps refcount for cifs super block.
* Bumps refcount for cifs super block.
* Note that it should be only called if a referece to VFS super block is
* Note that it should be only called if a referece to VFS super block is
...
@@ -120,14 +116,16 @@ cifs_read_super(struct super_block *sb)
...
@@ -120,14 +116,16 @@ cifs_read_super(struct super_block *sb)
{
{
struct
inode
*
inode
;
struct
inode
*
inode
;
struct
cifs_sb_info
*
cifs_sb
;
struct
cifs_sb_info
*
cifs_sb
;
struct
cifs_tcon
*
tcon
;
int
rc
=
0
;
int
rc
=
0
;
cifs_sb
=
CIFS_SB
(
sb
);
cifs_sb
=
CIFS_SB
(
sb
);
tcon
=
cifs_sb_master_tcon
(
cifs_sb
);
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_POSIXACL
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_POSIXACL
)
sb
->
s_flags
|=
MS_POSIXACL
;
sb
->
s_flags
|=
MS_POSIXACL
;
if
(
cifs_sb_master_tcon
(
cifs_sb
)
->
ses
->
capabilities
&
CAP_LARGE_FILES
)
if
(
tcon
->
ses
->
capabilities
&
tcon
->
ses
->
server
->
vals
->
cap_large_files
)
sb
->
s_maxbytes
=
MAX_LFS_FILESIZE
;
sb
->
s_maxbytes
=
MAX_LFS_FILESIZE
;
else
else
sb
->
s_maxbytes
=
MAX_NON_LFS
;
sb
->
s_maxbytes
=
MAX_NON_LFS
;
...
@@ -147,7 +145,7 @@ cifs_read_super(struct super_block *sb)
...
@@ -147,7 +145,7 @@ cifs_read_super(struct super_block *sb)
goto
out_no_root
;
goto
out_no_root
;
}
}
if
(
cifs_sb_master_tcon
(
cifs_sb
)
->
nocase
)
if
(
tcon
->
nocase
)
sb
->
s_d_op
=
&
cifs_ci_dentry_ops
;
sb
->
s_d_op
=
&
cifs_ci_dentry_ops
;
else
else
sb
->
s_d_op
=
&
cifs_dentry_ops
;
sb
->
s_d_op
=
&
cifs_dentry_ops
;
...
@@ -249,8 +247,9 @@ cifs_alloc_inode(struct super_block *sb)
...
@@ -249,8 +247,9 @@ cifs_alloc_inode(struct super_block *sb)
* server, can not assume caching of file data or metadata.
* server, can not assume caching of file data or metadata.
*/
*/
cifs_set_oplock_level
(
cifs_inode
,
0
);
cifs_set_oplock_level
(
cifs_inode
,
0
);
cifs_inode
->
delete_pending
=
false
;
cifs_inode
->
flags
=
0
;
cifs_inode
->
invalid_mapping
=
false
;
spin_lock_init
(
&
cifs_inode
->
writers_lock
);
cifs_inode
->
writers
=
0
;
cifs_inode
->
vfs_inode
.
i_blkbits
=
14
;
/* 2**14 = CIFS_MAX_MSGSIZE */
cifs_inode
->
vfs_inode
.
i_blkbits
=
14
;
/* 2**14 = CIFS_MAX_MSGSIZE */
cifs_inode
->
server_eof
=
0
;
cifs_inode
->
server_eof
=
0
;
cifs_inode
->
uniqueid
=
0
;
cifs_inode
->
uniqueid
=
0
;
...
@@ -295,7 +294,7 @@ cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server)
...
@@ -295,7 +294,7 @@ cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server)
struct
sockaddr_in
*
sa
=
(
struct
sockaddr_in
*
)
&
server
->
dstaddr
;
struct
sockaddr_in
*
sa
=
(
struct
sockaddr_in
*
)
&
server
->
dstaddr
;
struct
sockaddr_in6
*
sa6
=
(
struct
sockaddr_in6
*
)
&
server
->
dstaddr
;
struct
sockaddr_in6
*
sa6
=
(
struct
sockaddr_in6
*
)
&
server
->
dstaddr
;
seq_p
rintf
(
s
,
",addr="
);
seq_p
uts
(
s
,
",addr="
);
switch
(
server
->
dstaddr
.
ss_family
)
{
switch
(
server
->
dstaddr
.
ss_family
)
{
case
AF_INET
:
case
AF_INET
:
...
@@ -307,7 +306,7 @@ cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server)
...
@@ -307,7 +306,7 @@ cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server)
seq_printf
(
s
,
"%%%u"
,
sa6
->
sin6_scope_id
);
seq_printf
(
s
,
"%%%u"
,
sa6
->
sin6_scope_id
);
break
;
break
;
default:
default:
seq_p
rintf
(
s
,
"(unknown)"
);
seq_p
uts
(
s
,
"(unknown)"
);
}
}
}
}
...
@@ -317,45 +316,45 @@ cifs_show_security(struct seq_file *s, struct cifs_ses *ses)
...
@@ -317,45 +316,45 @@ cifs_show_security(struct seq_file *s, struct cifs_ses *ses)
if
(
ses
->
sectype
==
Unspecified
)
if
(
ses
->
sectype
==
Unspecified
)
return
;
return
;
seq_p
rintf
(
s
,
",sec="
);
seq_p
uts
(
s
,
",sec="
);
switch
(
ses
->
sectype
)
{
switch
(
ses
->
sectype
)
{
case
LANMAN
:
case
LANMAN
:
seq_p
rintf
(
s
,
"lanman"
);
seq_p
uts
(
s
,
"lanman"
);
break
;
break
;
case
NTLMv2
:
case
NTLMv2
:
seq_p
rintf
(
s
,
"ntlmv2"
);
seq_p
uts
(
s
,
"ntlmv2"
);
break
;
break
;
case
NTLM
:
case
NTLM
:
seq_p
rintf
(
s
,
"ntlm"
);
seq_p
uts
(
s
,
"ntlm"
);
break
;
break
;
case
Kerberos
:
case
Kerberos
:
seq_p
rintf
(
s
,
"krb5"
);
seq_p
uts
(
s
,
"krb5"
);
break
;
break
;
case
RawNTLMSSP
:
case
RawNTLMSSP
:
seq_p
rintf
(
s
,
"ntlmssp"
);
seq_p
uts
(
s
,
"ntlmssp"
);
break
;
break
;
default:
default:
/* shouldn't ever happen */
/* shouldn't ever happen */
seq_p
rintf
(
s
,
"unknown"
);
seq_p
uts
(
s
,
"unknown"
);
break
;
break
;
}
}
if
(
ses
->
sign
)
if
(
ses
->
sign
)
seq_p
rintf
(
s
,
"i"
);
seq_p
uts
(
s
,
"i"
);
}
}
static
void
static
void
cifs_show_cache_flavor
(
struct
seq_file
*
s
,
struct
cifs_sb_info
*
cifs_sb
)
cifs_show_cache_flavor
(
struct
seq_file
*
s
,
struct
cifs_sb_info
*
cifs_sb
)
{
{
seq_p
rintf
(
s
,
",cache="
);
seq_p
uts
(
s
,
",cache="
);
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_STRICT_IO
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_STRICT_IO
)
seq_p
rintf
(
s
,
"strict"
);
seq_p
uts
(
s
,
"strict"
);
else
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_DIRECT_IO
)
else
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_DIRECT_IO
)
seq_p
rintf
(
s
,
"none"
);
seq_p
uts
(
s
,
"none"
);
else
else
seq_p
rintf
(
s
,
"loose"
);
seq_p
uts
(
s
,
"loose"
);
}
}
static
void
static
void
...
@@ -388,7 +387,7 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
...
@@ -388,7 +387,7 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
cifs_show_cache_flavor
(
s
,
cifs_sb
);
cifs_show_cache_flavor
(
s
,
cifs_sb
);
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MULTIUSER
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MULTIUSER
)
seq_p
rintf
(
s
,
",multiuser"
);
seq_p
uts
(
s
,
",multiuser"
);
else
if
(
tcon
->
ses
->
user_name
)
else
if
(
tcon
->
ses
->
user_name
)
seq_printf
(
s
,
",username=%s"
,
tcon
->
ses
->
user_name
);
seq_printf
(
s
,
",username=%s"
,
tcon
->
ses
->
user_name
);
...
@@ -414,16 +413,16 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
...
@@ -414,16 +413,16 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
seq_printf
(
s
,
",uid=%u"
,
seq_printf
(
s
,
",uid=%u"
,
from_kuid_munged
(
&
init_user_ns
,
cifs_sb
->
mnt_uid
));
from_kuid_munged
(
&
init_user_ns
,
cifs_sb
->
mnt_uid
));
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_OVERR_UID
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_OVERR_UID
)
seq_p
rintf
(
s
,
",forceuid"
);
seq_p
uts
(
s
,
",forceuid"
);
else
else
seq_p
rintf
(
s
,
",noforceuid"
);
seq_p
uts
(
s
,
",noforceuid"
);
seq_printf
(
s
,
",gid=%u"
,
seq_printf
(
s
,
",gid=%u"
,
from_kgid_munged
(
&
init_user_ns
,
cifs_sb
->
mnt_gid
));
from_kgid_munged
(
&
init_user_ns
,
cifs_sb
->
mnt_gid
));
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_OVERR_GID
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_OVERR_GID
)
seq_p
rintf
(
s
,
",forcegid"
);
seq_p
uts
(
s
,
",forcegid"
);
else
else
seq_p
rintf
(
s
,
",noforcegid"
);
seq_p
uts
(
s
,
",noforcegid"
);
cifs_show_address
(
s
,
tcon
->
ses
->
server
);
cifs_show_address
(
s
,
tcon
->
ses
->
server
);
...
@@ -435,50 +434,50 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
...
@@ -435,50 +434,50 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
cifs_show_nls
(
s
,
cifs_sb
->
local_nls
);
cifs_show_nls
(
s
,
cifs_sb
->
local_nls
);
if
(
tcon
->
seal
)
if
(
tcon
->
seal
)
seq_p
rintf
(
s
,
",seal"
);
seq_p
uts
(
s
,
",seal"
);
if
(
tcon
->
nocase
)
if
(
tcon
->
nocase
)
seq_p
rintf
(
s
,
",nocase"
);
seq_p
uts
(
s
,
",nocase"
);
if
(
tcon
->
retry
)
if
(
tcon
->
retry
)
seq_p
rintf
(
s
,
",hard"
);
seq_p
uts
(
s
,
",hard"
);
if
(
tcon
->
unix_ext
)
if
(
tcon
->
unix_ext
)
seq_p
rintf
(
s
,
",unix"
);
seq_p
uts
(
s
,
",unix"
);
else
else
seq_p
rintf
(
s
,
",nounix"
);
seq_p
uts
(
s
,
",nounix"
);
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_POSIX_PATHS
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_POSIX_PATHS
)
seq_p
rintf
(
s
,
",posixpaths"
);
seq_p
uts
(
s
,
",posixpaths"
);
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_SET_UID
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_SET_UID
)
seq_p
rintf
(
s
,
",setuids"
);
seq_p
uts
(
s
,
",setuids"
);
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_SERVER_INUM
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_SERVER_INUM
)
seq_p
rintf
(
s
,
",serverino"
);
seq_p
uts
(
s
,
",serverino"
);
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_RWPIDFORWARD
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_RWPIDFORWARD
)
seq_p
rintf
(
s
,
",rwpidforward"
);
seq_p
uts
(
s
,
",rwpidforward"
);
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NOPOSIXBRL
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NOPOSIXBRL
)
seq_p
rintf
(
s
,
",forcemand"
);
seq_p
uts
(
s
,
",forcemand"
);
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NO_XATTR
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NO_XATTR
)
seq_p
rintf
(
s
,
",nouser_xattr"
);
seq_p
uts
(
s
,
",nouser_xattr"
);
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MAP_SPECIAL_CHR
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MAP_SPECIAL_CHR
)
seq_p
rintf
(
s
,
",mapchars"
);
seq_p
uts
(
s
,
",mapchars"
);
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_UNX_EMUL
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_UNX_EMUL
)
seq_p
rintf
(
s
,
",sfu"
);
seq_p
uts
(
s
,
",sfu"
);
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NO_BRL
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NO_BRL
)
seq_p
rintf
(
s
,
",nobrl"
);
seq_p
uts
(
s
,
",nobrl"
);
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_CIFS_ACL
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_CIFS_ACL
)
seq_p
rintf
(
s
,
",cifsacl"
);
seq_p
uts
(
s
,
",cifsacl"
);
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_DYNPERM
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_DYNPERM
)
seq_p
rintf
(
s
,
",dynperm"
);
seq_p
uts
(
s
,
",dynperm"
);
if
(
root
->
d_sb
->
s_flags
&
MS_POSIXACL
)
if
(
root
->
d_sb
->
s_flags
&
MS_POSIXACL
)
seq_p
rintf
(
s
,
",acl"
);
seq_p
uts
(
s
,
",acl"
);
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MF_SYMLINKS
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MF_SYMLINKS
)
seq_p
rintf
(
s
,
",mfsymlinks"
);
seq_p
uts
(
s
,
",mfsymlinks"
);
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_FSCACHE
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_FSCACHE
)
seq_p
rintf
(
s
,
",fsc"
);
seq_p
uts
(
s
,
",fsc"
);
if
((
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_STRICT_IO
)
&&
if
((
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_STRICT_IO
)
&&
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NOPOSIXBRL
))
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NOPOSIXBRL
))
seq_p
rintf
(
s
,
",wine"
);
seq_p
uts
(
s
,
",wine"
);
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NOSSYNC
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NOSSYNC
)
seq_p
rintf
(
s
,
",nostrictsync"
);
seq_p
uts
(
s
,
",nostrictsync"
);
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NO_PERM
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NO_PERM
)
seq_p
rintf
(
s
,
",noperm"
);
seq_p
uts
(
s
,
",noperm"
);
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_CIFS_BACKUPUID
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_CIFS_BACKUPUID
)
seq_printf
(
s
,
",backupuid=%u"
,
seq_printf
(
s
,
",backupuid=%u"
,
from_kuid_munged
(
&
init_user_ns
,
from_kuid_munged
(
&
init_user_ns
,
...
@@ -732,19 +731,26 @@ static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
...
@@ -732,19 +731,26 @@ static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
unsigned
long
nr_segs
,
loff_t
pos
)
unsigned
long
nr_segs
,
loff_t
pos
)
{
{
struct
inode
*
inode
=
file_inode
(
iocb
->
ki_filp
);
struct
inode
*
inode
=
file_inode
(
iocb
->
ki_filp
);
struct
cifsInodeInfo
*
cinode
=
CIFS_I
(
inode
);
ssize_t
written
;
ssize_t
written
;
int
rc
;
int
rc
;
written
=
cifs_get_writer
(
cinode
);
if
(
written
)
return
written
;
written
=
generic_file_aio_write
(
iocb
,
iov
,
nr_segs
,
pos
);
written
=
generic_file_aio_write
(
iocb
,
iov
,
nr_segs
,
pos
);
if
(
CIFS_CACHE_WRITE
(
CIFS_I
(
inode
)))
if
(
CIFS_CACHE_WRITE
(
CIFS_I
(
inode
)))
return
written
;
goto
out
;
rc
=
filemap_fdatawrite
(
inode
->
i_mapping
);
rc
=
filemap_fdatawrite
(
inode
->
i_mapping
);
if
(
rc
)
if
(
rc
)
cifs_dbg
(
FYI
,
"cifs_file_aio_write: %d rc on %p inode
\n
"
,
cifs_dbg
(
FYI
,
"cifs_file_aio_write: %d rc on %p inode
\n
"
,
rc
,
inode
);
rc
,
inode
);
out:
cifs_put_writer
(
cinode
);
return
written
;
return
written
;
}
}
...
@@ -815,6 +821,12 @@ static int cifs_setlease(struct file *file, long arg, struct file_lock **lease)
...
@@ -815,6 +821,12 @@ static int cifs_setlease(struct file *file, long arg, struct file_lock **lease)
return
-
EAGAIN
;
return
-
EAGAIN
;
}
}
static
int
cifs_rename
(
struct
inode
*
old_dir
,
struct
dentry
*
old
,
struct
inode
*
new_dir
,
struct
dentry
*
new
)
{
return
cifs_rename2
(
old_dir
,
old
,
new_dir
,
new
,
0
);
}
struct
file_system_type
cifs_fs_type
=
{
struct
file_system_type
cifs_fs_type
=
{
.
owner
=
THIS_MODULE
,
.
owner
=
THIS_MODULE
,
.
name
=
"cifs"
,
.
name
=
"cifs"
,
...
@@ -823,7 +835,8 @@ struct file_system_type cifs_fs_type = {
...
@@ -823,7 +835,8 @@ struct file_system_type cifs_fs_type = {
/* .fs_flags */
/* .fs_flags */
};
};
MODULE_ALIAS_FS
(
"cifs"
);
MODULE_ALIAS_FS
(
"cifs"
);
const
struct
inode_operations
cifs_dir_inode_ops
=
{
const
struct
inode_operations_wrapper
cifs_dir_inode_ops
=
{
.
ops
=
{
.
create
=
cifs_create
,
.
create
=
cifs_create
,
.
atomic_open
=
cifs_atomic_open
,
.
atomic_open
=
cifs_atomic_open
,
.
lookup
=
cifs_lookup
,
.
lookup
=
cifs_lookup
,
...
@@ -844,13 +857,14 @@ const struct inode_operations cifs_dir_inode_ops = {
...
@@ -844,13 +857,14 @@ const struct inode_operations cifs_dir_inode_ops = {
.
listxattr
=
cifs_listxattr
,
.
listxattr
=
cifs_listxattr
,
.
removexattr
=
cifs_removexattr
,
.
removexattr
=
cifs_removexattr
,
#endif
#endif
},
.
rename2
=
cifs_rename2
,
};
};
const
struct
inode_operations
cifs_file_inode_ops
=
{
const
struct
inode_operations
cifs_file_inode_ops
=
{
/* revalidate:cifs_revalidate, */
/* revalidate:cifs_revalidate, */
.
setattr
=
cifs_setattr
,
.
setattr
=
cifs_setattr
,
.
getattr
=
cifs_getattr
,
/* do we need this anymore? */
.
getattr
=
cifs_getattr
,
/* do we need this anymore? */
.
rename
=
cifs_rename
,
.
permission
=
cifs_permission
,
.
permission
=
cifs_permission
,
#ifdef CONFIG_CIFS_XATTR
#ifdef CONFIG_CIFS_XATTR
.
setxattr
=
cifs_setxattr
,
.
setxattr
=
cifs_setxattr
,
...
@@ -863,7 +877,7 @@ const struct inode_operations cifs_file_inode_ops = {
...
@@ -863,7 +877,7 @@ const struct inode_operations cifs_file_inode_ops = {
const
struct
inode_operations
cifs_symlink_inode_ops
=
{
const
struct
inode_operations
cifs_symlink_inode_ops
=
{
.
readlink
=
generic_readlink
,
.
readlink
=
generic_readlink
,
.
follow_link
=
cifs_follow_link
,
.
follow_link
=
cifs_follow_link
,
.
put_link
=
cifs
_put_link
,
.
put_link
=
kfree
_put_link
,
.
permission
=
cifs_permission
,
.
permission
=
cifs_permission
,
/* BB add the following two eventually */
/* BB add the following two eventually */
/* revalidate: cifs_revalidate,
/* revalidate: cifs_revalidate,
...
@@ -1006,7 +1020,7 @@ cifs_init_once(void *inode)
...
@@ -1006,7 +1020,7 @@ cifs_init_once(void *inode)
init_rwsem
(
&
cifsi
->
lock_sem
);
init_rwsem
(
&
cifsi
->
lock_sem
);
}
}
static
int
static
int
__init
cifs_init_inodecache
(
void
)
cifs_init_inodecache
(
void
)
{
{
cifs_inode_cachep
=
kmem_cache_create
(
"cifs_inode_cache"
,
cifs_inode_cachep
=
kmem_cache_create
(
"cifs_inode_cache"
,
...
@@ -1181,10 +1195,6 @@ init_cifs(void)
...
@@ -1181,10 +1195,6 @@ init_cifs(void)
spin_lock_init
(
&
cifs_file_list_lock
);
spin_lock_init
(
&
cifs_file_list_lock
);
spin_lock_init
(
&
GlobalMid_Lock
);
spin_lock_init
(
&
GlobalMid_Lock
);
#ifdef CONFIG_CIFS_SMB2
get_random_bytes
(
cifs_client_guid
,
SMB2_CLIENT_GUID_SIZE
);
#endif
if
(
cifs_max_pending
<
2
)
{
if
(
cifs_max_pending
<
2
)
{
cifs_max_pending
=
2
;
cifs_max_pending
=
2
;
cifs_dbg
(
FYI
,
"cifs_max_pending set to min of 2
\n
"
);
cifs_dbg
(
FYI
,
"cifs_max_pending set to min of 2
\n
"
);
...
...
sources/centos70/cifsfs.h
View file @
9d798057
...
@@ -22,20 +22,28 @@
...
@@ -22,20 +22,28 @@
#ifndef _CIFSFS_H
#ifndef _CIFSFS_H
#define _CIFSFS_H
#define _CIFSFS_H
#include <linux/hash.h>
#define ROOT_I 2
#define ROOT_I 2
/*
/*
* ino_t is 32-bits on 32-bit arch. We have to squash the 64-bit value down
* ino_t is 32-bits on 32-bit arch. We have to squash the 64-bit value down
* so that it will fit.
* so that it will fit. We use hash_64 to convert the value to 31 bits, and
* then add 1, to ensure that we don't end up with a 0 as the value.
*/
*/
#if BITS_PER_LONG == 64
static
inline
ino_t
static
inline
ino_t
cifs_uniqueid_to_ino_t
(
u64
fileid
)
cifs_uniqueid_to_ino_t
(
u64
fileid
)
{
{
ino_t
ino
=
(
ino_t
)
fileid
;
return
(
ino_t
)
fileid
;
if
(
sizeof
(
ino_t
)
<
sizeof
(
u64
))
ino
^=
fileid
>>
(
sizeof
(
u64
)
-
sizeof
(
ino_t
))
*
8
;
return
ino
;
}
}
#else
static
inline
ino_t
cifs_uniqueid_to_ino_t
(
u64
fileid
)
{
return
(
ino_t
)
hash_64
(
fileid
,
(
sizeof
(
ino_t
)
*
8
)
-
1
)
+
1
;
}
#endif
extern
struct
file_system_type
cifs_fs_type
;
extern
struct
file_system_type
cifs_fs_type
;
extern
const
struct
address_space_operations
cifs_addr_ops
;
extern
const
struct
address_space_operations
cifs_addr_ops
;
...
@@ -46,7 +54,7 @@ extern void cifs_sb_active(struct super_block *sb);
...
@@ -46,7 +54,7 @@ extern void cifs_sb_active(struct super_block *sb);
extern
void
cifs_sb_deactive
(
struct
super_block
*
sb
);
extern
void
cifs_sb_deactive
(
struct
super_block
*
sb
);
/* Functions related to inodes */
/* Functions related to inodes */
extern
const
struct
inode_operations
cifs_dir_inode_ops
;
extern
const
struct
inode_operations
_wrapper
cifs_dir_inode_ops
;
extern
struct
inode
*
cifs_root_iget
(
struct
super_block
*
);
extern
struct
inode
*
cifs_root_iget
(
struct
super_block
*
);
extern
int
cifs_create
(
struct
inode
*
,
struct
dentry
*
,
umode_t
,
extern
int
cifs_create
(
struct
inode
*
,
struct
dentry
*
,
umode_t
,
bool
excl
);
bool
excl
);
...
@@ -60,13 +68,15 @@ extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *);
...
@@ -60,13 +68,15 @@ extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *);
extern
int
cifs_mknod
(
struct
inode
*
,
struct
dentry
*
,
umode_t
,
dev_t
);
extern
int
cifs_mknod
(
struct
inode
*
,
struct
dentry
*
,
umode_t
,
dev_t
);
extern
int
cifs_mkdir
(
struct
inode
*
,
struct
dentry
*
,
umode_t
);
extern
int
cifs_mkdir
(
struct
inode
*
,
struct
dentry
*
,
umode_t
);
extern
int
cifs_rmdir
(
struct
inode
*
,
struct
dentry
*
);
extern
int
cifs_rmdir
(
struct
inode
*
,
struct
dentry
*
);
extern
int
cifs_rename
(
struct
inode
*
,
struct
dentry
*
,
struct
inode
*
,
extern
int
cifs_rename
2
(
struct
inode
*
,
struct
dentry
*
,
struct
inode
*
,
struct
dentry
*
);
struct
dentry
*
,
unsigned
int
);
extern
int
cifs_revalidate_file_attr
(
struct
file
*
filp
);
extern
int
cifs_revalidate_file_attr
(
struct
file
*
filp
);
extern
int
cifs_revalidate_dentry_attr
(
struct
dentry
*
);
extern
int
cifs_revalidate_dentry_attr
(
struct
dentry
*
);
extern
int
cifs_revalidate_file
(
struct
file
*
filp
);
extern
int
cifs_revalidate_file
(
struct
file
*
filp
);
extern
int
cifs_revalidate_dentry
(
struct
dentry
*
);
extern
int
cifs_revalidate_dentry
(
struct
dentry
*
);
extern
int
cifs_invalidate_mapping
(
struct
inode
*
inode
);
extern
int
cifs_invalidate_mapping
(
struct
inode
*
inode
);
extern
int
cifs_revalidate_mapping
(
struct
inode
*
inode
);
extern
int
cifs_zap_mapping
(
struct
inode
*
inode
);
extern
int
cifs_getattr
(
struct
vfsmount
*
,
struct
dentry
*
,
struct
kstat
*
);
extern
int
cifs_getattr
(
struct
vfsmount
*
,
struct
dentry
*
,
struct
kstat
*
);
extern
int
cifs_setattr
(
struct
dentry
*
,
struct
iattr
*
);
extern
int
cifs_setattr
(
struct
dentry
*
,
struct
iattr
*
);
...
@@ -115,8 +125,6 @@ extern struct vfsmount *cifs_dfs_d_automount(struct path *path);
...
@@ -115,8 +125,6 @@ extern struct vfsmount *cifs_dfs_d_automount(struct path *path);
/* Functions related to symlinks */
/* Functions related to symlinks */
extern
void
*
cifs_follow_link
(
struct
dentry
*
direntry
,
struct
nameidata
*
nd
);
extern
void
*
cifs_follow_link
(
struct
dentry
*
direntry
,
struct
nameidata
*
nd
);
extern
void
cifs_put_link
(
struct
dentry
*
direntry
,
struct
nameidata
*
nd
,
void
*
);
extern
int
cifs_readlink
(
struct
dentry
*
direntry
,
char
__user
*
buffer
,
extern
int
cifs_readlink
(
struct
dentry
*
direntry
,
char
__user
*
buffer
,
int
buflen
);
int
buflen
);
extern
int
cifs_symlink
(
struct
inode
*
inode
,
struct
dentry
*
direntry
,
extern
int
cifs_symlink
(
struct
inode
*
inode
,
struct
dentry
*
direntry
,
...
@@ -132,5 +140,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
...
@@ -132,5 +140,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
extern
const
struct
export_operations
cifs_export_ops
;
extern
const
struct
export_operations
cifs_export_ops
;
#endif
/* CONFIG_CIFS_NFSD_EXPORT */
#endif
/* CONFIG_CIFS_NFSD_EXPORT */
#define CIFS_VERSION "2.0
1
"
#define CIFS_VERSION "2.0
3
"
#endif
/* _CIFSFS_H */
#endif
/* _CIFSFS_H */
sources/centos70/cifsglob.h
View file @
9d798057
...
@@ -228,6 +228,8 @@ struct smb_version_operations {
...
@@ -228,6 +228,8 @@ 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
*
);
void
(
*
downgrade_oplock
)(
struct
TCP_Server_Info
*
,
struct
cifsInodeInfo
*
,
bool
);
/* process transaction2 response */
/* process transaction2 response */
bool
(
*
check_trans2
)(
struct
mid_q_entry
*
,
struct
TCP_Server_Info
*
,
bool
(
*
check_trans2
)(
struct
mid_q_entry
*
,
struct
TCP_Server_Info
*
,
char
*
,
int
);
char
*
,
int
);
...
@@ -261,7 +263,7 @@ struct smb_version_operations {
...
@@ -261,7 +263,7 @@ struct smb_version_operations {
/* query path data from the server */
/* query path data from the server */
int
(
*
query_path_info
)(
const
unsigned
int
,
struct
cifs_tcon
*
,
int
(
*
query_path_info
)(
const
unsigned
int
,
struct
cifs_tcon
*
,
struct
cifs_sb_info
*
,
const
char
*
,
struct
cifs_sb_info
*
,
const
char
*
,
FILE_ALL_INFO
*
,
bool
*
);
FILE_ALL_INFO
*
,
bool
*
,
bool
*
);
/* query file data from the server */
/* query file data from the server */
int
(
*
query_file_info
)(
const
unsigned
int
,
struct
cifs_tcon
*
,
int
(
*
query_file_info
)(
const
unsigned
int
,
struct
cifs_tcon
*
,
struct
cifs_fid
*
,
FILE_ALL_INFO
*
);
struct
cifs_fid
*
,
FILE_ALL_INFO
*
);
...
@@ -278,6 +280,8 @@ struct smb_version_operations {
...
@@ -278,6 +280,8 @@ struct smb_version_operations {
/* set attributes */
/* set attributes */
int
(
*
set_file_info
)(
struct
inode
*
,
const
char
*
,
FILE_BASIC_INFO
*
,
int
(
*
set_file_info
)(
struct
inode
*
,
const
char
*
,
FILE_BASIC_INFO
*
,
const
unsigned
int
);
const
unsigned
int
);
int
(
*
set_compression
)(
const
unsigned
int
,
struct
cifs_tcon
*
,
struct
cifsFileInfo
*
);
/* check if we can send an echo or nor */
/* check if we can send an echo or nor */
bool
(
*
can_echo
)(
struct
TCP_Server_Info
*
);
bool
(
*
can_echo
)(
struct
TCP_Server_Info
*
);
/* send echo request */
/* send echo request */
...
@@ -369,8 +373,12 @@ struct smb_version_operations {
...
@@ -369,8 +373,12 @@ struct smb_version_operations {
void
(
*
new_lease_key
)(
struct
cifs_fid
*
);
void
(
*
new_lease_key
)(
struct
cifs_fid
*
);
int
(
*
generate_signingkey
)(
struct
cifs_ses
*
);
int
(
*
generate_signingkey
)(
struct
cifs_ses
*
);
int
(
*
calc_signature
)(
struct
smb_rqst
*
,
struct
TCP_Server_Info
*
);
int
(
*
calc_signature
)(
struct
smb_rqst
*
,
struct
TCP_Server_Info
*
);
int
(
*
query_mf_symlink
)(
const
unsigned
char
*
,
char
*
,
unsigned
int
*
,
int
(
*
query_mf_symlink
)(
unsigned
int
,
struct
cifs_tcon
*
,
struct
cifs_sb_info
*
,
unsigned
int
);
struct
cifs_sb_info
*
,
const
unsigned
char
*
,
char
*
,
unsigned
int
*
);
int
(
*
create_mf_symlink
)(
unsigned
int
,
struct
cifs_tcon
*
,
struct
cifs_sb_info
*
,
const
unsigned
char
*
,
char
*
,
unsigned
int
*
);
/* if we can do cache read operations */
/* if we can do cache read operations */
bool
(
*
is_read_op
)(
__u32
);
bool
(
*
is_read_op
)(
__u32
);
/* set oplock level for the inode */
/* set oplock level for the inode */
...
@@ -380,6 +388,22 @@ struct smb_version_operations {
...
@@ -380,6 +388,22 @@ struct smb_version_operations {
char
*
(
*
create_lease_buf
)(
u8
*
,
u8
);
char
*
(
*
create_lease_buf
)(
u8
*
,
u8
);
/* parse lease context buffer and return oplock/epoch info */
/* parse lease context buffer and return oplock/epoch info */
__u8
(
*
parse_lease_buf
)(
void
*
,
unsigned
int
*
);
__u8
(
*
parse_lease_buf
)(
void
*
,
unsigned
int
*
);
int
(
*
clone_range
)(
const
unsigned
int
,
struct
cifsFileInfo
*
src_file
,
struct
cifsFileInfo
*
target_file
,
u64
src_off
,
u64
len
,
u64
dest_off
);
int
(
*
validate_negotiate
)(
const
unsigned
int
,
struct
cifs_tcon
*
);
ssize_t
(
*
query_all_EAs
)(
const
unsigned
int
,
struct
cifs_tcon
*
,
const
unsigned
char
*
,
const
unsigned
char
*
,
char
*
,
size_t
,
const
struct
nls_table
*
,
int
);
int
(
*
set_EA
)(
const
unsigned
int
,
struct
cifs_tcon
*
,
const
char
*
,
const
char
*
,
const
void
*
,
const
__u16
,
const
struct
nls_table
*
,
int
);
struct
cifs_ntsd
*
(
*
get_acl
)(
struct
cifs_sb_info
*
,
struct
inode
*
,
const
char
*
,
u32
*
);
struct
cifs_ntsd
*
(
*
get_acl_by_fid
)(
struct
cifs_sb_info
*
,
const
struct
cifs_fid
*
,
u32
*
);
int
(
*
set_acl
)(
struct
cifs_ntsd
*
,
__u32
,
struct
inode
*
,
const
char
*
,
int
);
};
};
struct
smb_version_values
{
struct
smb_version_values
{
...
@@ -535,6 +559,7 @@ struct TCP_Server_Info {
...
@@ -535,6 +559,7 @@ struct TCP_Server_Info {
int
echo_credits
;
/* echo reserved slots */
int
echo_credits
;
/* echo reserved slots */
int
oplock_credits
;
/* oplock break reserved slots */
int
oplock_credits
;
/* oplock break reserved slots */
bool
echoes
:
1
;
/* enable echoes */
bool
echoes
:
1
;
/* enable echoes */
__u8
client_guid
[
SMB2_CLIENT_GUID_SIZE
];
/* Client GUID */
#endif
#endif
u16
dialect
;
/* dialect index that server chose */
u16
dialect
;
/* dialect index that server chose */
bool
oplocks
:
1
;
/* enable oplocks */
bool
oplocks
:
1
;
/* enable oplocks */
...
@@ -621,11 +646,34 @@ set_credits(struct TCP_Server_Info *server, const int val)
...
@@ -621,11 +646,34 @@ set_credits(struct TCP_Server_Info *server, const int val)
}
}
static
inline
__u64
static
inline
__u64
get_next_mid
(
struct
TCP_Server_Info
*
server
)
get_next_mid
64
(
struct
TCP_Server_Info
*
server
)
{
{
return
server
->
ops
->
get_next_mid
(
server
);
return
server
->
ops
->
get_next_mid
(
server
);
}
}
static
inline
__le16
get_next_mid
(
struct
TCP_Server_Info
*
server
)
{
__u16
mid
=
get_next_mid64
(
server
);
/*
* The value in the SMB header should be little endian for easy
* on-the-wire decoding.
*/
return
cpu_to_le16
(
mid
);
}
static
inline
__u16
get_mid
(
const
struct
smb_hdr
*
smb
)
{
return
le16_to_cpu
(
smb
->
Mid
);
}
static
inline
bool
compare_mid
(
__u16
mid
,
const
struct
smb_hdr
*
smb
)
{
return
mid
==
le16_to_cpu
(
smb
->
Mid
);
}
/*
/*
* When the server supports very large reads and writes via POSIX extensions,
* When the server supports very large reads and writes via POSIX extensions,
* we can allow up to 2^24-1, minus the size of a READ/WRITE_AND_X header, not
* we can allow up to 2^24-1, minus the size of a READ/WRITE_AND_X header, not
...
@@ -829,6 +877,11 @@ struct cifs_tcon {
...
@@ -829,6 +877,11 @@ struct cifs_tcon {
__u32
maximal_access
;
__u32
maximal_access
;
__u32
vol_serial_number
;
__u32
vol_serial_number
;
__le64
vol_create_time
;
__le64
vol_create_time
;
__u32
ss_flags
;
/* sector size flags */
__u32
perf_sector_size
;
/* best sector size for perf */
__u32
max_chunks
;
__u32
max_bytes_chunk
;
__u32
max_bytes_copy
;
#endif
/* CONFIG_CIFS_SMB2 */
#endif
/* CONFIG_CIFS_SMB2 */
#ifdef CONFIG_CIFS_FSCACHE
#ifdef CONFIG_CIFS_FSCACHE
u64
resource_id
;
/* server resource id */
u64
resource_id
;
/* server resource id */
...
@@ -1069,8 +1122,15 @@ struct cifsInodeInfo {
...
@@ -1069,8 +1122,15 @@ struct cifsInodeInfo {
__u32
cifsAttrs
;
/* e.g. DOS archive bit, sparse, compressed, system */
__u32
cifsAttrs
;
/* e.g. DOS archive bit, sparse, compressed, system */
unsigned
int
oplock
;
/* oplock/lease level we have */
unsigned
int
oplock
;
/* oplock/lease level we have */
unsigned
int
epoch
;
/* used to track lease state changes */
unsigned
int
epoch
;
/* used to track lease state changes */
bool
delete_pending
;
/* DELETE_ON_CLOSE is set */
#define CIFS_INODE_PENDING_OPLOCK_BREAK (0)
/* oplock break in progress */
bool
invalid_mapping
;
/* pagecache is invalid */
#define CIFS_INODE_PENDING_WRITERS (1)
/* Writes in progress */
#define CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2 (2)
/* Downgrade oplock to L2 */
#define CIFS_INO_DELETE_PENDING (3)
/* delete pending on server */
#define CIFS_INO_INVALID_MAPPING (4)
/* pagecache is invalid */
#define CIFS_INO_LOCK (5)
/* lock bit for synchronization */
unsigned
long
flags
;
spinlock_t
writers_lock
;
unsigned
int
writers
;
/* Number of writers on this inode */
unsigned
long
time
;
/* jiffies of last update of inode */
unsigned
long
time
;
/* jiffies of last update of inode */
u64
server_eof
;
/* current file size on server -- protected by i_lock */
u64
server_eof
;
/* current file size on server -- protected by i_lock */
u64
uniqueid
;
/* server inode number */
u64
uniqueid
;
/* server inode number */
...
@@ -1277,6 +1337,7 @@ struct dfs_info3_param {
...
@@ -1277,6 +1337,7 @@ struct dfs_info3_param {
#define CIFS_FATTR_DELETE_PENDING 0x2
#define CIFS_FATTR_DELETE_PENDING 0x2
#define CIFS_FATTR_NEED_REVAL 0x4
#define CIFS_FATTR_NEED_REVAL 0x4
#define CIFS_FATTR_INO_COLLISION 0x8
#define CIFS_FATTR_INO_COLLISION 0x8
#define CIFS_FATTR_UNKNOWN_NLINK 0x10
struct
cifs_fattr
{
struct
cifs_fattr
{
u32
cf_flags
;
u32
cf_flags
;
...
...
sources/centos70/cifspdu.h
View file @
9d798057
...
@@ -436,7 +436,7 @@ struct smb_hdr {
...
@@ -436,7 +436,7 @@ struct smb_hdr {
__u16
Tid
;
__u16
Tid
;
__le16
Pid
;
__le16
Pid
;
__u16
Uid
;
__u16
Uid
;
__
u
16
Mid
;
__
le
16
Mid
;
__u8
WordCount
;
__u8
WordCount
;
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
...
@@ -705,7 +705,13 @@ struct ntlmssp2_name {
...
@@ -705,7 +705,13 @@ struct ntlmssp2_name {
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
struct
ntlmv2_resp
{
struct
ntlmv2_resp
{
char
ntlmv2_hash
[
CIFS_ENCPWD_SIZE
];
union
{
char
ntlmv2_hash
[
CIFS_ENCPWD_SIZE
];
struct
{
__u8
reserved
[
8
];
__u8
key
[
CIFS_SERVER_CHALLENGE_SIZE
];
}
__attribute__
((
packed
))
challenge
;
}
__attribute__
((
packed
));
__le32
blob_signature
;
__le32
blob_signature
;
__u32
reserved
;
__u32
reserved
;
__le64
time
;
__le64
time
;
...
@@ -1360,6 +1366,35 @@ typedef struct smb_com_transaction_ioctl_req {
...
@@ -1360,6 +1366,35 @@ typedef struct smb_com_transaction_ioctl_req {
__u8
Data
[
1
];
__u8
Data
[
1
];
}
__attribute__
((
packed
))
TRANSACT_IOCTL_REQ
;
}
__attribute__
((
packed
))
TRANSACT_IOCTL_REQ
;
typedef
struct
smb_com_transaction_compr_ioctl_req
{
struct
smb_hdr
hdr
;
/* wct = 23 */
__u8
MaxSetupCount
;
__u16
Reserved
;
__le32
TotalParameterCount
;
__le32
TotalDataCount
;
__le32
MaxParameterCount
;
__le32
MaxDataCount
;
__le32
ParameterCount
;
__le32
ParameterOffset
;
__le32
DataCount
;
__le32
DataOffset
;
__u8
SetupCount
;
/* four setup words follow subcommand */
/* SNIA spec incorrectly included spurious pad here */
__le16
SubCommand
;
/* 2 = IOCTL/FSCTL */
__le32
FunctionCode
;
__u16
Fid
;
__u8
IsFsctl
;
/* 1 = File System Control 0 = device control (IOCTL) */
__u8
IsRootFlag
;
/* 1 = apply command to root of share (must be DFS) */
__le16
ByteCount
;
__u8
Pad
[
3
];
__le16
compression_state
;
/* See below for valid flags */
}
__attribute__
((
packed
))
TRANSACT_COMPR_IOCTL_REQ
;
/* compression state flags */
#define COMPRESSION_FORMAT_NONE 0x0000
#define COMPRESSION_FORMAT_DEFAULT 0x0001
#define COMPRESSION_FORMAT_LZNT1 0x0002
typedef
struct
smb_com_transaction_ioctl_rsp
{
typedef
struct
smb_com_transaction_ioctl_rsp
{
struct
smb_hdr
hdr
;
/* wct = 19 */
struct
smb_hdr
hdr
;
/* wct = 19 */
__u8
Reserved
[
3
];
__u8
Reserved
[
3
];
...
@@ -1499,15 +1534,30 @@ struct file_notify_information {
...
@@ -1499,15 +1534,30 @@ struct file_notify_information {
__u8
FileName
[
0
];
__u8
FileName
[
0
];
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
struct
reparse_data
{
/* For IO_REPARSE_TAG_SYMLINK */
__u32
ReparseTag
;
struct
reparse_symlink_data
{
__u16
ReparseDataLength
;
__le32
ReparseTag
;
__le16
ReparseDataLength
;
__u16
Reserved
;
__u16
Reserved
;
__u16
SubstituteNameOffset
;
__le16
SubstituteNameOffset
;
__u16
SubstituteNameLength
;
__le16
SubstituteNameLength
;
__u16
PrintNameOffset
;
__le16
PrintNameOffset
;
__u16
PrintNameLength
;
__le16
PrintNameLength
;
__u32
Flags
;
__le32
Flags
;
char
PathBuffer
[
0
];
}
__attribute__
((
packed
));
/* For IO_REPARSE_TAG_NFS */
#define NFS_SPECFILE_LNK 0x00000000014B4E4C
#define NFS_SPECFILE_CHR 0x0000000000524843
#define NFS_SPECFILE_BLK 0x00000000004B4C42
#define NFS_SPECFILE_FIFO 0x000000004F464946
#define NFS_SPECFILE_SOCK 0x000000004B434F53
struct
reparse_posix_data
{
__le32
ReparseTag
;
__le16
ReparseDataLength
;
__u16
Reserved
;
__le64
InodeType
;
/* LNK, FIFO, CHR etc. */
char
PathBuffer
[
0
];
char
PathBuffer
[
0
];
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
...
@@ -2208,6 +2258,9 @@ typedef struct {
...
@@ -2208,6 +2258,9 @@ typedef struct {
__le32
DeviceCharacteristics
;
__le32
DeviceCharacteristics
;
}
__attribute__
((
packed
))
FILE_SYSTEM_DEVICE_INFO
;
/* device info level 0x104 */
}
__attribute__
((
packed
))
FILE_SYSTEM_DEVICE_INFO
;
/* device info level 0x104 */
/* minimum includes first three fields, and empty FS Name */
#define MIN_FS_ATTR_INFO_SIZE 12
typedef
struct
{
typedef
struct
{
__le32
Attributes
;
__le32
Attributes
;
__le32
MaxPathNameComponentLength
;
__le32
MaxPathNameComponentLength
;
...
...
sources/centos70/cifsproto.h
View file @
9d798057
...
@@ -127,6 +127,9 @@ extern u64 cifs_UnixTimeToNT(struct timespec);
...
@@ -127,6 +127,9 @@ extern u64 cifs_UnixTimeToNT(struct timespec);
extern
struct
timespec
cnvrtDosUnixTm
(
__le16
le_date
,
__le16
le_time
,
extern
struct
timespec
cnvrtDosUnixTm
(
__le16
le_date
,
__le16
le_time
,
int
offset
);
int
offset
);
extern
void
cifs_set_oplock_level
(
struct
cifsInodeInfo
*
cinode
,
__u32
oplock
);
extern
void
cifs_set_oplock_level
(
struct
cifsInodeInfo
*
cinode
,
__u32
oplock
);
extern
int
cifs_get_writer
(
struct
cifsInodeInfo
*
cinode
);
extern
void
cifs_put_writer
(
struct
cifsInodeInfo
*
cinode
);
extern
void
cifs_done_oplock_break
(
struct
cifsInodeInfo
*
cinode
);
extern
int
cifs_unlock_range
(
struct
cifsFileInfo
*
cfile
,
extern
int
cifs_unlock_range
(
struct
cifsFileInfo
*
cfile
,
struct
file_lock
*
flock
,
const
unsigned
int
xid
);
struct
file_lock
*
flock
,
const
unsigned
int
xid
);
extern
int
cifs_push_mandatory_locks
(
struct
cifsFileInfo
*
cfile
);
extern
int
cifs_push_mandatory_locks
(
struct
cifsFileInfo
*
cfile
);
...
@@ -151,7 +154,7 @@ extern struct inode *cifs_iget(struct super_block *sb,
...
@@ -151,7 +154,7 @@ extern struct inode *cifs_iget(struct super_block *sb,
extern
int
cifs_get_inode_info
(
struct
inode
**
inode
,
const
char
*
full_path
,
extern
int
cifs_get_inode_info
(
struct
inode
**
inode
,
const
char
*
full_path
,
FILE_ALL_INFO
*
data
,
struct
super_block
*
sb
,
FILE_ALL_INFO
*
data
,
struct
super_block
*
sb
,
int
xid
,
const
__u16
*
fid
);
int
xid
,
const
struct
cifs_fid
*
fid
);
extern
int
cifs_get_inode_info_unix
(
struct
inode
**
pinode
,
extern
int
cifs_get_inode_info_unix
(
struct
inode
**
pinode
,
const
unsigned
char
*
search_path
,
const
unsigned
char
*
search_path
,
struct
super_block
*
sb
,
unsigned
int
xid
);
struct
super_block
*
sb
,
unsigned
int
xid
);
...
@@ -162,11 +165,13 @@ extern int cifs_rename_pending_delete(const char *full_path,
...
@@ -162,11 +165,13 @@ extern int cifs_rename_pending_delete(const char *full_path,
const
unsigned
int
xid
);
const
unsigned
int
xid
);
extern
int
cifs_acl_to_fattr
(
struct
cifs_sb_info
*
cifs_sb
,
extern
int
cifs_acl_to_fattr
(
struct
cifs_sb_info
*
cifs_sb
,
struct
cifs_fattr
*
fattr
,
struct
inode
*
inode
,
struct
cifs_fattr
*
fattr
,
struct
inode
*
inode
,
const
char
*
path
,
const
__u16
*
pfid
);
const
char
*
path
,
const
struct
cifs_fid
*
pfid
);
extern
int
id_mode_to_cifs_acl
(
struct
inode
*
inode
,
const
char
*
path
,
__u64
,
extern
int
id_mode_to_cifs_acl
(
struct
inode
*
inode
,
const
char
*
path
,
__u64
,
kuid_t
,
kgid_t
);
kuid_t
,
kgid_t
);
extern
struct
cifs_ntsd
*
get_cifs_acl
(
struct
cifs_sb_info
*
,
struct
inode
*
,
extern
struct
cifs_ntsd
*
get_cifs_acl
(
struct
cifs_sb_info
*
,
struct
inode
*
,
const
char
*
,
u32
*
);
const
char
*
,
u32
*
);
extern
struct
cifs_ntsd
*
get_cifs_acl_by_fid
(
struct
cifs_sb_info
*
,
const
struct
cifs_fid
*
,
u32
*
);
extern
int
set_cifs_acl
(
struct
cifs_ntsd
*
,
__u32
,
struct
inode
*
,
extern
int
set_cifs_acl
(
struct
cifs_ntsd
*
,
__u32
,
struct
inode
*
,
const
char
*
,
int
);
const
char
*
,
int
);
...
@@ -360,11 +365,10 @@ extern int CIFSSMBUnixQuerySymLink(const unsigned int xid,
...
@@ -360,11 +365,10 @@ extern int CIFSSMBUnixQuerySymLink(const unsigned int xid,
extern
int
CIFSSMBQuerySymLink
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
extern
int
CIFSSMBQuerySymLink
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
__u16
fid
,
char
**
symlinkinfo
,
__u16
fid
,
char
**
symlinkinfo
,
const
struct
nls_table
*
nls_codepage
);
const
struct
nls_table
*
nls_codepage
);
extern
int
CIFSSMBOpen
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
extern
int
CIFSSMB_set_compression
(
const
unsigned
int
xid
,
const
char
*
fileName
,
const
int
disposition
,
struct
cifs_tcon
*
tcon
,
__u16
fid
);
const
int
access_flags
,
const
int
share_flags
,
const
int
omode
,
extern
int
CIFS_open
(
const
unsigned
int
xid
,
struct
cifs_open_parms
*
oparms
,
__u16
*
netfid
,
int
*
pOplock
,
FILE_ALL_INFO
*
,
int
*
oplock
,
FILE_ALL_INFO
*
buf
);
const
struct
nls_table
*
nls_codepage
,
int
remap
);
extern
int
SMBLegacyOpen
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
extern
int
SMBLegacyOpen
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
const
char
*
fileName
,
const
int
disposition
,
const
char
*
fileName
,
const
int
disposition
,
const
int
access_flags
,
const
int
omode
,
const
int
access_flags
,
const
int
omode
,
...
@@ -474,10 +478,11 @@ extern int CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -474,10 +478,11 @@ extern int CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
extern
int
CIFSGetExtAttr
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
extern
int
CIFSGetExtAttr
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
const
int
netfid
,
__u64
*
pExtAttrBits
,
__u64
*
pMask
);
const
int
netfid
,
__u64
*
pExtAttrBits
,
__u64
*
pMask
);
extern
void
cifs_autodisable_serverino
(
struct
cifs_sb_info
*
cifs_sb
);
extern
void
cifs_autodisable_serverino
(
struct
cifs_sb_info
*
cifs_sb
);
extern
bool
CIFSCouldBeMFSymlink
(
const
struct
cifs_fattr
*
fattr
);
extern
bool
couldbe_mf_symlink
(
const
struct
cifs_fattr
*
fattr
);
extern
int
CIFSCheckMFSymlink
(
struct
cifs_fattr
*
fattr
,
extern
int
check_mf_symlink
(
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
const
unsigned
char
*
path
,
struct
cifs_sb_info
*
cifs_sb
,
struct
cifs_sb_info
*
cifs_sb
,
unsigned
int
xid
);
struct
cifs_fattr
*
fattr
,
const
unsigned
char
*
path
);
extern
int
mdfour
(
unsigned
char
*
,
unsigned
char
*
,
int
);
extern
int
mdfour
(
unsigned
char
*
,
unsigned
char
*
,
int
);
extern
int
E_md4hash
(
const
unsigned
char
*
passwd
,
unsigned
char
*
p16
,
extern
int
E_md4hash
(
const
unsigned
char
*
passwd
,
unsigned
char
*
p16
,
const
struct
nls_table
*
codepage
);
const
struct
nls_table
*
codepage
);
...
@@ -494,7 +499,12 @@ void cifs_writev_complete(struct work_struct *work);
...
@@ -494,7 +499,12 @@ void cifs_writev_complete(struct work_struct *work);
struct
cifs_writedata
*
cifs_writedata_alloc
(
unsigned
int
nr_pages
,
struct
cifs_writedata
*
cifs_writedata_alloc
(
unsigned
int
nr_pages
,
work_func_t
complete
);
work_func_t
complete
);
void
cifs_writedata_release
(
struct
kref
*
refcount
);
void
cifs_writedata_release
(
struct
kref
*
refcount
);
int
open_query_close_cifs_symlink
(
const
unsigned
char
*
path
,
char
*
pbuf
,
int
cifs_query_mf_symlink
(
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
unsigned
int
*
pbytes_read
,
struct
cifs_sb_info
*
cifs_sb
,
struct
cifs_sb_info
*
cifs_sb
,
unsigned
int
xid
);
const
unsigned
char
*
path
,
char
*
pbuf
,
unsigned
int
*
pbytes_read
);
int
cifs_create_mf_symlink
(
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
struct
cifs_sb_info
*
cifs_sb
,
const
unsigned
char
*
path
,
char
*
pbuf
,
unsigned
int
*
pbytes_written
);
#endif
/* _CIFSPROTO_H */
#endif
/* _CIFSPROTO_H */
sources/centos70/cifssmb.c
View file @
9d798057
...
@@ -1280,104 +1280,124 @@ OldOpenRetry:
...
@@ -1280,104 +1280,124 @@ OldOpenRetry:
}
}
int
int
CIFSSMBOpen
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
CIFS_open
(
const
unsigned
int
xid
,
struct
cifs_open_parms
*
oparms
,
int
*
oplock
,
const
char
*
fileName
,
const
int
openDisposition
,
FILE_ALL_INFO
*
buf
)
const
int
access_flags
,
const
int
share_flags
,
const
int
create_options
,
__u16
*
netfid
,
int
*
pOplock
,
FILE_ALL_INFO
*
pfile_info
,
const
struct
nls_table
*
nls_codepage
,
int
remap
)
{
{
int
rc
=
-
EACCES
;
int
rc
=
-
EACCES
;
OPEN_REQ
*
pSMB
=
NULL
;
OPEN_REQ
*
req
=
NULL
;
OPEN_RSP
*
pSMBr
=
NULL
;
OPEN_RSP
*
rsp
=
NULL
;
int
bytes_returned
;
int
bytes_returned
;
int
name_len
;
int
name_len
;
__u16
count
;
__u16
count
;
struct
cifs_sb_info
*
cifs_sb
=
oparms
->
cifs_sb
;
struct
cifs_tcon
*
tcon
=
oparms
->
tcon
;
int
remap
=
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MAP_SPECIAL_CHR
;
const
struct
nls_table
*
nls
=
cifs_sb
->
local_nls
;
int
create_options
=
oparms
->
create_options
;
int
desired_access
=
oparms
->
desired_access
;
int
disposition
=
oparms
->
disposition
;
const
char
*
path
=
oparms
->
path
;
openRetry:
openRetry:
rc
=
smb_init
(
SMB_COM_NT_CREATE_ANDX
,
24
,
tcon
,
(
void
**
)
&
pSMB
,
rc
=
smb_init
(
SMB_COM_NT_CREATE_ANDX
,
24
,
tcon
,
(
void
**
)
&
req
,
(
void
**
)
&
pSMBr
);
(
void
**
)
&
rsp
);
if
(
rc
)
if
(
rc
)
return
rc
;
return
rc
;
pSMB
->
AndXCommand
=
0xFF
;
/* none */
/* no commands go after this */
req
->
AndXCommand
=
0xFF
;
if
(
pSMB
->
hdr
.
Flags2
&
SMBFLG2_UNICODE
)
{
if
(
req
->
hdr
.
Flags2
&
SMBFLG2_UNICODE
)
{
count
=
1
;
/* account for one byte pad to word boundary */
/* account for one byte pad to word boundary */
name_len
=
count
=
1
;
cifsConvertToUTF16
((
__le16
*
)
(
pSMB
->
fileName
+
1
),
name_len
=
cifsConvertToUTF16
((
__le16
*
)(
req
->
fileName
+
1
),
fileName
,
PATH_MAX
,
nls_codepage
,
remap
);
path
,
PATH_MAX
,
nls
,
remap
);
name_len
++
;
/* trailing null */
/* trailing null */
name_len
++
;
name_len
*=
2
;
name_len
*=
2
;
pSMB
->
NameLength
=
cpu_to_le16
(
name_len
);
req
->
NameLength
=
cpu_to_le16
(
name_len
);
}
else
{
/* BB improve check for buffer overruns BB */
}
else
{
count
=
0
;
/* no pad */
/* BB improve check for buffer overruns BB */
name_len
=
strnlen
(
fileName
,
PATH_MAX
);
/* no pad */
name_len
++
;
/* trailing null */
count
=
0
;
pSMB
->
NameLength
=
cpu_to_le16
(
name_len
);
name_len
=
strnlen
(
path
,
PATH_MAX
);
strncpy
(
pSMB
->
fileName
,
fileName
,
name_len
);
/* trailing null */
name_len
++
;
req
->
NameLength
=
cpu_to_le16
(
name_len
);
strncpy
(
req
->
fileName
,
path
,
name_len
);
}
}
if
(
*
pOplock
&
REQ_OPLOCK
)
pSMB
->
OpenFlags
=
cpu_to_le32
(
REQ_OPLOCK
);
if
(
*
oplock
&
REQ_OPLOCK
)
else
if
(
*
pOplock
&
REQ_BATCHOPLOCK
)
req
->
OpenFlags
=
cpu_to_le32
(
REQ_OPLOCK
);
pSMB
->
OpenFlags
=
cpu_to_le32
(
REQ_BATCHOPLOCK
);
else
if
(
*
oplock
&
REQ_BATCHOPLOCK
)
pSMB
->
DesiredAccess
=
cpu_to_le32
(
access_flags
);
req
->
OpenFlags
=
cpu_to_le32
(
REQ_BATCHOPLOCK
);
pSMB
->
AllocationSize
=
0
;
/* set file as system file if special file such
req
->
DesiredAccess
=
cpu_to_le32
(
desired_access
);
as fifo and server expecting SFU style and
req
->
AllocationSize
=
0
;
no Unix extensions */
/*
* Set file as system file if special file such as fifo and server
* expecting SFU style and no Unix extensions.
*/
if
(
create_options
&
CREATE_OPTION_SPECIAL
)
if
(
create_options
&
CREATE_OPTION_SPECIAL
)
pSMB
->
FileAttributes
=
cpu_to_le32
(
ATTR_SYSTEM
);
req
->
FileAttributes
=
cpu_to_le32
(
ATTR_SYSTEM
);
else
else
pSMB
->
FileAttributes
=
cpu_to_le32
(
ATTR_NORMAL
);
req
->
FileAttributes
=
cpu_to_le32
(
ATTR_NORMAL
);
/* XP does not handle ATTR_POSIX_SEMANTICS */
/*
/* but it helps speed up case sensitive checks for other
* XP does not handle ATTR_POSIX_SEMANTICS but it helps speed up case
servers such as Samba */
* sensitive checks for other servers such as Samba.
*/
if
(
tcon
->
ses
->
capabilities
&
CAP_UNIX
)
if
(
tcon
->
ses
->
capabilities
&
CAP_UNIX
)
pSMB
->
FileAttributes
|=
cpu_to_le32
(
ATTR_POSIX_SEMANTICS
);
req
->
FileAttributes
|=
cpu_to_le32
(
ATTR_POSIX_SEMANTICS
);
if
(
create_options
&
CREATE_OPTION_READONLY
)
if
(
create_options
&
CREATE_OPTION_READONLY
)
pSMB
->
FileAttributes
|=
cpu_to_le32
(
ATTR_READONLY
);
req
->
FileAttributes
|=
cpu_to_le32
(
ATTR_READONLY
);
req
->
ShareAccess
=
cpu_to_le32
(
oparms
->
share_access
);
req
->
CreateDisposition
=
cpu_to_le32
(
disposition
);
req
->
CreateOptions
=
cpu_to_le32
(
create_options
&
CREATE_OPTIONS_MASK
);
pSMB
->
ShareAccess
=
cpu_to_le32
(
share_flags
);
pSMB
->
CreateDisposition
=
cpu_to_le32
(
openDisposition
);
pSMB
->
CreateOptions
=
cpu_to_le32
(
create_options
&
CREATE_OPTIONS_MASK
);
/* BB Expirement with various impersonation levels and verify */
/* BB Expirement with various impersonation levels and verify */
pSMB
->
ImpersonationLevel
=
cpu_to_le32
(
SECURITY_IMPERSONATION
);
req
->
ImpersonationLevel
=
cpu_to_le32
(
SECURITY_IMPERSONATION
);
pSMB
->
SecurityFlags
=
req
->
SecurityFlags
=
SECURITY_CONTEXT_TRACKING
|
SECURITY_EFFECTIVE_ONLY
;
SECURITY_CONTEXT_TRACKING
|
SECURITY_EFFECTIVE_ONLY
;
count
+=
name_len
;
count
+=
name_len
;
inc_rfc1001_len
(
pSMB
,
count
);
inc_rfc1001_len
(
req
,
count
);
pSMB
->
ByteCount
=
cpu_to_le16
(
count
);
req
->
ByteCount
=
cpu_to_le16
(
count
);
/* long_op set to 1 to allow for oplock break timeouts */
rc
=
SendReceive
(
xid
,
tcon
->
ses
,
(
struct
smb_hdr
*
)
req
,
rc
=
SendReceive
(
xid
,
tcon
->
ses
,
(
struct
smb_hdr
*
)
pSMB
,
(
struct
smb_hdr
*
)
rsp
,
&
bytes_returned
,
0
);
(
struct
smb_hdr
*
)
pSMBr
,
&
bytes_returned
,
0
);
cifs_stats_inc
(
&
tcon
->
stats
.
cifs_stats
.
num_opens
);
cifs_stats_inc
(
&
tcon
->
stats
.
cifs_stats
.
num_opens
);
if
(
rc
)
{
if
(
rc
)
{
cifs_dbg
(
FYI
,
"Error in Open = %d
\n
"
,
rc
);
cifs_dbg
(
FYI
,
"Error in Open = %d
\n
"
,
rc
);
}
else
{
cifs_buf_release
(
req
);
*
pOplock
=
pSMBr
->
OplockLevel
;
/* 1 byte no need to le_to_cpu */
if
(
rc
==
-
EAGAIN
)
*
netfid
=
pSMBr
->
Fid
;
/* cifs fid stays in le */
goto
openRetry
;
/* Let caller know file was created so we can set the mode. */
return
rc
;
/* Do we care about the CreateAction in any other cases? */
if
(
cpu_to_le32
(
FILE_CREATE
)
==
pSMBr
->
CreateAction
)
*
pOplock
|=
CIFS_CREATE_ACTION
;
if
(
pfile_info
)
{
memcpy
((
char
*
)
pfile_info
,
(
char
*
)
&
pSMBr
->
CreationTime
,
36
/* CreationTime to Attributes */
);
/* the file_info buf is endian converted by caller */
pfile_info
->
AllocationSize
=
pSMBr
->
AllocationSize
;
pfile_info
->
EndOfFile
=
pSMBr
->
EndOfFile
;
pfile_info
->
NumberOfLinks
=
cpu_to_le32
(
1
);
pfile_info
->
DeletePending
=
0
;
}
}
}
cifs_buf_release
(
pSMB
);
/* 1 byte no need to le_to_cpu */
if
(
rc
==
-
EAGAIN
)
*
oplock
=
rsp
->
OplockLevel
;
goto
openRetry
;
/* cifs fid stays in le */
oparms
->
fid
->
netfid
=
rsp
->
Fid
;
/* Let caller know file was created so we can set the mode. */
/* Do we care about the CreateAction in any other cases? */
if
(
cpu_to_le32
(
FILE_CREATE
)
==
rsp
->
CreateAction
)
*
oplock
|=
CIFS_CREATE_ACTION
;
if
(
buf
)
{
/* copy from CreationTime to Attributes */
memcpy
((
char
*
)
buf
,
(
char
*
)
&
rsp
->
CreationTime
,
36
);
/* the file_info buf is endian converted by caller */
buf
->
AllocationSize
=
rsp
->
AllocationSize
;
buf
->
EndOfFile
=
rsp
->
EndOfFile
;
buf
->
NumberOfLinks
=
cpu_to_le32
(
1
);
buf
->
DeletePending
=
0
;
}
cifs_buf_release
(
req
);
return
rc
;
return
rc
;
}
}
...
@@ -3090,7 +3110,8 @@ CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -3090,7 +3110,8 @@ CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
bool
is_unicode
;
bool
is_unicode
;
unsigned
int
sub_len
;
unsigned
int
sub_len
;
char
*
sub_start
;
char
*
sub_start
;
struct
reparse_data
*
reparse_buf
;
struct
reparse_symlink_data
*
reparse_buf
;
struct
reparse_posix_data
*
posix_buf
;
__u32
data_offset
,
data_count
;
__u32
data_offset
,
data_count
;
char
*
end_of_smb
;
char
*
end_of_smb
;
...
@@ -3139,20 +3160,47 @@ CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -3139,20 +3160,47 @@ CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
goto
qreparse_out
;
goto
qreparse_out
;
}
}
end_of_smb
=
2
+
get_bcc
(
&
pSMBr
->
hdr
)
+
(
char
*
)
&
pSMBr
->
ByteCount
;
end_of_smb
=
2
+
get_bcc
(
&
pSMBr
->
hdr
)
+
(
char
*
)
&
pSMBr
->
ByteCount
;
reparse_buf
=
(
struct
reparse_data
*
)
reparse_buf
=
(
struct
reparse_
symlink_
data
*
)
((
char
*
)
&
pSMBr
->
hdr
.
Protocol
+
data_offset
);
((
char
*
)
&
pSMBr
->
hdr
.
Protocol
+
data_offset
);
if
((
char
*
)
reparse_buf
>=
end_of_smb
)
{
if
((
char
*
)
reparse_buf
>=
end_of_smb
)
{
rc
=
-
EIO
;
rc
=
-
EIO
;
goto
qreparse_out
;
goto
qreparse_out
;
}
}
if
((
reparse_buf
->
PathBuffer
+
reparse_buf
->
PrintNameOffset
+
if
(
reparse_buf
->
ReparseTag
==
cpu_to_le32
(
IO_REPARSE_TAG_NFS
))
{
reparse_buf
->
PrintNameLength
)
>
end_of_smb
)
{
cifs_dbg
(
FYI
,
"NFS style reparse tag
\n
"
);
posix_buf
=
(
struct
reparse_posix_data
*
)
reparse_buf
;
if
(
posix_buf
->
InodeType
!=
cpu_to_le64
(
NFS_SPECFILE_LNK
))
{
cifs_dbg
(
FYI
,
"unsupported file type 0x%llx
\n
"
,
le64_to_cpu
(
posix_buf
->
InodeType
));
rc
=
-
EOPNOTSUPP
;
goto
qreparse_out
;
}
is_unicode
=
true
;
sub_len
=
le16_to_cpu
(
reparse_buf
->
ReparseDataLength
);
if
(
posix_buf
->
PathBuffer
+
sub_len
>
end_of_smb
)
{
cifs_dbg
(
FYI
,
"reparse buf beyond SMB
\n
"
);
rc
=
-
EIO
;
goto
qreparse_out
;
}
*
symlinkinfo
=
cifs_strndup_from_utf16
(
posix_buf
->
PathBuffer
,
sub_len
,
is_unicode
,
nls_codepage
);
goto
qreparse_out
;
}
else
if
(
reparse_buf
->
ReparseTag
!=
cpu_to_le32
(
IO_REPARSE_TAG_SYMLINK
))
{
rc
=
-
EOPNOTSUPP
;
goto
qreparse_out
;
}
/* Reparse tag is NTFS symlink */
sub_start
=
le16_to_cpu
(
reparse_buf
->
SubstituteNameOffset
)
+
reparse_buf
->
PathBuffer
;
sub_len
=
le16_to_cpu
(
reparse_buf
->
SubstituteNameLength
);
if
(
sub_start
+
sub_len
>
end_of_smb
)
{
cifs_dbg
(
FYI
,
"reparse buf beyond SMB
\n
"
);
cifs_dbg
(
FYI
,
"reparse buf beyond SMB
\n
"
);
rc
=
-
EIO
;
rc
=
-
EIO
;
goto
qreparse_out
;
goto
qreparse_out
;
}
}
sub_start
=
reparse_buf
->
SubstituteNameOffset
+
reparse_buf
->
PathBuffer
;
sub_len
=
reparse_buf
->
SubstituteNameLength
;
if
(
pSMBr
->
hdr
.
Flags2
&
SMBFLG2_UNICODE
)
if
(
pSMBr
->
hdr
.
Flags2
&
SMBFLG2_UNICODE
)
is_unicode
=
true
;
is_unicode
=
true
;
else
else
...
@@ -3173,6 +3221,60 @@ qreparse_out:
...
@@ -3173,6 +3221,60 @@ qreparse_out:
return
rc
;
return
rc
;
}
}
int
CIFSSMB_set_compression
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
__u16
fid
)
{
int
rc
=
0
;
int
bytes_returned
;
struct
smb_com_transaction_compr_ioctl_req
*
pSMB
;
struct
smb_com_transaction_ioctl_rsp
*
pSMBr
;
cifs_dbg
(
FYI
,
"Set compression for %u
\n
"
,
fid
);
rc
=
smb_init
(
SMB_COM_NT_TRANSACT
,
23
,
tcon
,
(
void
**
)
&
pSMB
,
(
void
**
)
&
pSMBr
);
if
(
rc
)
return
rc
;
pSMB
->
compression_state
=
cpu_to_le16
(
COMPRESSION_FORMAT_DEFAULT
);
pSMB
->
TotalParameterCount
=
0
;
pSMB
->
TotalDataCount
=
__constant_cpu_to_le32
(
2
);
pSMB
->
MaxParameterCount
=
0
;
pSMB
->
MaxDataCount
=
0
;
pSMB
->
MaxSetupCount
=
4
;
pSMB
->
Reserved
=
0
;
pSMB
->
ParameterOffset
=
0
;
pSMB
->
DataCount
=
__constant_cpu_to_le32
(
2
);
pSMB
->
DataOffset
=
cpu_to_le32
(
offsetof
(
struct
smb_com_transaction_compr_ioctl_req
,
compression_state
)
-
4
);
/* 84 */
pSMB
->
SetupCount
=
4
;
pSMB
->
SubCommand
=
__constant_cpu_to_le16
(
NT_TRANSACT_IOCTL
);
pSMB
->
ParameterCount
=
0
;
pSMB
->
FunctionCode
=
__constant_cpu_to_le32
(
FSCTL_SET_COMPRESSION
);
pSMB
->
IsFsctl
=
1
;
/* FSCTL */
pSMB
->
IsRootFlag
=
0
;
pSMB
->
Fid
=
fid
;
/* file handle always le */
/* 3 byte pad, followed by 2 byte compress state */
pSMB
->
ByteCount
=
__constant_cpu_to_le16
(
5
);
inc_rfc1001_len
(
pSMB
,
5
);
rc
=
SendReceive
(
xid
,
tcon
->
ses
,
(
struct
smb_hdr
*
)
pSMB
,
(
struct
smb_hdr
*
)
pSMBr
,
&
bytes_returned
,
0
);
if
(
rc
)
cifs_dbg
(
FYI
,
"Send error in SetCompression = %d
\n
"
,
rc
);
cifs_buf_release
(
pSMB
);
/*
* Note: On -EAGAIN error only caller can retry on handle based calls
* since file handle passed in no longer valid.
*/
return
rc
;
}
#ifdef CONFIG_CIFS_POSIX
#ifdef CONFIG_CIFS_POSIX
/*Convert an Access Control Entry from wire format to local POSIX xattr format*/
/*Convert an Access Control Entry from wire format to local POSIX xattr format*/
...
@@ -3930,7 +4032,7 @@ QFileInfoRetry:
...
@@ -3930,7 +4032,7 @@ QFileInfoRetry:
rc
=
SendReceive
(
xid
,
tcon
->
ses
,
(
struct
smb_hdr
*
)
pSMB
,
rc
=
SendReceive
(
xid
,
tcon
->
ses
,
(
struct
smb_hdr
*
)
pSMB
,
(
struct
smb_hdr
*
)
pSMBr
,
&
bytes_returned
,
0
);
(
struct
smb_hdr
*
)
pSMBr
,
&
bytes_returned
,
0
);
if
(
rc
)
{
if
(
rc
)
{
cifs_dbg
(
FYI
,
"Send error in Q
PathInfo = %d
\n
"
,
rc
);
cifs_dbg
(
FYI
,
"Send error in Q
FileInfo = %d
"
,
rc
);
}
else
{
/* decode response */
}
else
{
/* decode response */
rc
=
validate_t2
((
struct
smb_t2_rsp
*
)
pSMBr
);
rc
=
validate_t2
((
struct
smb_t2_rsp
*
)
pSMBr
);
...
@@ -4099,7 +4201,7 @@ UnixQFileInfoRetry:
...
@@ -4099,7 +4201,7 @@ UnixQFileInfoRetry:
rc
=
SendReceive
(
xid
,
tcon
->
ses
,
(
struct
smb_hdr
*
)
pSMB
,
rc
=
SendReceive
(
xid
,
tcon
->
ses
,
(
struct
smb_hdr
*
)
pSMB
,
(
struct
smb_hdr
*
)
pSMBr
,
&
bytes_returned
,
0
);
(
struct
smb_hdr
*
)
pSMBr
,
&
bytes_returned
,
0
);
if
(
rc
)
{
if
(
rc
)
{
cifs_dbg
(
FYI
,
"Send error in
QPathInfo = %d
\n
"
,
rc
);
cifs_dbg
(
FYI
,
"Send error in
UnixQFileInfo = %d
"
,
rc
);
}
else
{
/* decode response */
}
else
{
/* decode response */
rc
=
validate_t2
((
struct
smb_t2_rsp
*
)
pSMBr
);
rc
=
validate_t2
((
struct
smb_t2_rsp
*
)
pSMBr
);
...
@@ -4183,7 +4285,7 @@ UnixQPathInfoRetry:
...
@@ -4183,7 +4285,7 @@ UnixQPathInfoRetry:
rc
=
SendReceive
(
xid
,
tcon
->
ses
,
(
struct
smb_hdr
*
)
pSMB
,
rc
=
SendReceive
(
xid
,
tcon
->
ses
,
(
struct
smb_hdr
*
)
pSMB
,
(
struct
smb_hdr
*
)
pSMBr
,
&
bytes_returned
,
0
);
(
struct
smb_hdr
*
)
pSMBr
,
&
bytes_returned
,
0
);
if
(
rc
)
{
if
(
rc
)
{
cifs_dbg
(
FYI
,
"Send error in
QPathInfo = %d
\n
"
,
rc
);
cifs_dbg
(
FYI
,
"Send error in
UnixQPathInfo = %d
"
,
rc
);
}
else
{
/* decode response */
}
else
{
/* decode response */
rc
=
validate_t2
((
struct
smb_t2_rsp
*
)
pSMBr
);
rc
=
validate_t2
((
struct
smb_t2_rsp
*
)
pSMBr
);
...
@@ -6102,6 +6204,9 @@ QAllEAsRetry:
...
@@ -6102,6 +6204,9 @@ QAllEAsRetry:
cifs_dbg
(
FYI
,
"ea length %d
\n
"
,
list_len
);
cifs_dbg
(
FYI
,
"ea length %d
\n
"
,
list_len
);
if
(
list_len
<=
8
)
{
if
(
list_len
<=
8
)
{
cifs_dbg
(
FYI
,
"empty EA list returned from server
\n
"
);
cifs_dbg
(
FYI
,
"empty EA list returned from server
\n
"
);
/* didn't find the named attribute */
if
(
ea_name
)
rc
=
-
ENODATA
;
goto
QAllEAsOut
;
goto
QAllEAsOut
;
}
}
...
...
sources/centos70/connect.c
View file @
9d798057
...
@@ -2149,6 +2149,9 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
...
@@ -2149,6 +2149,9 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
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
get_random_bytes
(
tcp_ses
->
client_guid
,
SMB2_CLIENT_GUID_SIZE
);
#endif
/*
/*
* at this point we are the only ones with the pointer
* at this point we are the only ones with the pointer
* to the struct since the kernel thread not created yet
* to the struct since the kernel thread not created yet
...
@@ -2230,7 +2233,7 @@ static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
...
@@ -2230,7 +2233,7 @@ static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
vol
->
username
?
vol
->
username
:
""
,
vol
->
username
?
vol
->
username
:
""
,
CIFS_MAX_USERNAME_LEN
))
CIFS_MAX_USERNAME_LEN
))
return
0
;
return
0
;
if
(
strlen
(
vol
->
username
)
!=
0
&&
if
(
(
vol
->
username
&&
strlen
(
vol
->
username
)
!=
0
)
&&
ses
->
password
!=
NULL
&&
ses
->
password
!=
NULL
&&
strncmp
(
ses
->
password
,
strncmp
(
ses
->
password
,
vol
->
password
?
vol
->
password
:
""
,
vol
->
password
?
vol
->
password
:
""
,
...
@@ -2247,6 +2250,8 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
...
@@ -2247,6 +2250,8 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
spin_lock
(
&
cifs_tcp_ses_lock
);
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
->
status
==
CifsExiting
)
continue
;
if
(
!
match_session
(
ses
,
vol
))
if
(
!
match_session
(
ses
,
vol
))
continue
;
continue
;
++
ses
->
ses_count
;
++
ses
->
ses_count
;
...
@@ -2260,24 +2265,37 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
...
@@ -2260,24 +2265,37 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
static
void
static
void
cifs_put_smb_ses
(
struct
cifs_ses
*
ses
)
cifs_put_smb_ses
(
struct
cifs_ses
*
ses
)
{
{
unsigned
int
xid
;
unsigned
int
rc
,
xid
;
struct
TCP_Server_Info
*
server
=
ses
->
server
;
struct
TCP_Server_Info
*
server
=
ses
->
server
;
cifs_dbg
(
FYI
,
"%s: ses_count=%d
\n
"
,
__func__
,
ses
->
ses_count
);
cifs_dbg
(
FYI
,
"%s: ses_count=%d
\n
"
,
__func__
,
ses
->
ses_count
);
spin_lock
(
&
cifs_tcp_ses_lock
);
spin_lock
(
&
cifs_tcp_ses_lock
);
if
(
ses
->
status
==
CifsExiting
)
{
spin_unlock
(
&
cifs_tcp_ses_lock
);
return
;
}
if
(
--
ses
->
ses_count
>
0
)
{
if
(
--
ses
->
ses_count
>
0
)
{
spin_unlock
(
&
cifs_tcp_ses_lock
);
spin_unlock
(
&
cifs_tcp_ses_lock
);
return
;
return
;
}
}
if
(
ses
->
status
==
CifsGood
)
list_del_init
(
&
ses
->
smb_ses_list
)
;
ses
->
status
=
CifsExiting
;
spin_unlock
(
&
cifs_tcp_ses_lock
);
spin_unlock
(
&
cifs_tcp_ses_lock
);
if
(
ses
->
status
==
Cifs
Good
&&
server
->
ops
->
logoff
)
{
if
(
ses
->
status
==
Cifs
Exiting
&&
server
->
ops
->
logoff
)
{
xid
=
get_xid
();
xid
=
get_xid
();
server
->
ops
->
logoff
(
xid
,
ses
);
rc
=
server
->
ops
->
logoff
(
xid
,
ses
);
if
(
rc
)
cifs_dbg
(
VFS
,
"%s: Session Logoff failure rc=%d
\n
"
,
__func__
,
rc
);
_free_xid
(
xid
);
_free_xid
(
xid
);
}
}
spin_lock
(
&
cifs_tcp_ses_lock
);
list_del_init
(
&
ses
->
smb_ses_list
);
spin_unlock
(
&
cifs_tcp_ses_lock
);
sesInfoFree
(
ses
);
sesInfoFree
(
ses
);
cifs_put_tcp_session
(
server
);
cifs_put_tcp_session
(
server
);
}
}
...
@@ -3760,6 +3778,13 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
...
@@ -3760,6 +3778,13 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
return
rc
;
return
rc
;
}
}
static
void
delayed_free
(
struct
rcu_head
*
p
)
{
struct
cifs_sb_info
*
sbi
=
container_of
(
p
,
struct
cifs_sb_info
,
rcu
);
unload_nls
(
sbi
->
local_nls
);
kfree
(
sbi
);
}
void
void
cifs_umount
(
struct
cifs_sb_info
*
cifs_sb
)
cifs_umount
(
struct
cifs_sb_info
*
cifs_sb
)
{
{
...
@@ -3784,8 +3809,7 @@ cifs_umount(struct cifs_sb_info *cifs_sb)
...
@@ -3784,8 +3809,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
);
unload_nls
(
cifs_sb
->
local_nls
);
call_rcu
(
&
cifs_sb
->
rcu
,
delayed_free
);
kfree
(
cifs_sb
);
}
}
int
int
...
...
sources/centos70/dir.c
View file @
9d798057
...
@@ -383,7 +383,7 @@ cifs_create_get_file_info:
...
@@ -383,7 +383,7 @@ cifs_create_get_file_info:
xid
);
xid
);
else
{
else
{
rc
=
cifs_get_inode_info
(
&
newinode
,
full_path
,
buf
,
inode
->
i_sb
,
rc
=
cifs_get_inode_info
(
&
newinode
,
full_path
,
buf
,
inode
->
i_sb
,
xid
,
&
fid
->
net
fid
);
xid
,
fid
);
if
(
newinode
)
{
if
(
newinode
)
{
if
(
server
->
ops
->
set_lease_key
)
if
(
server
->
ops
->
set_lease_key
)
server
->
ops
->
set_lease_key
(
newinode
,
fid
);
server
->
ops
->
set_lease_key
(
newinode
,
fid
);
...
@@ -570,12 +570,13 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
...
@@ -570,12 +570,13 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
int
create_options
=
CREATE_NOT_DIR
|
CREATE_OPTION_SPECIAL
;
int
create_options
=
CREATE_NOT_DIR
|
CREATE_OPTION_SPECIAL
;
struct
cifs_sb_info
*
cifs_sb
;
struct
cifs_sb_info
*
cifs_sb
;
struct
tcon_link
*
tlink
;
struct
tcon_link
*
tlink
;
struct
cifs_tcon
*
pT
con
;
struct
cifs_tcon
*
t
con
;
struct
cifs_io_parms
io_parms
;
struct
cifs_io_parms
io_parms
;
char
*
full_path
=
NULL
;
char
*
full_path
=
NULL
;
struct
inode
*
newinode
=
NULL
;
struct
inode
*
newinode
=
NULL
;
int
oplock
=
0
;
int
oplock
=
0
;
u16
fileHandle
;
struct
cifs_fid
fid
;
struct
cifs_open_parms
oparms
;
FILE_ALL_INFO
*
buf
=
NULL
;
FILE_ALL_INFO
*
buf
=
NULL
;
unsigned
int
bytes_written
;
unsigned
int
bytes_written
;
struct
win_dev
*
pdev
;
struct
win_dev
*
pdev
;
...
@@ -588,7 +589,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
...
@@ -588,7 +589,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
if
(
IS_ERR
(
tlink
))
if
(
IS_ERR
(
tlink
))
return
PTR_ERR
(
tlink
);
return
PTR_ERR
(
tlink
);
pT
con
=
tlink_tcon
(
tlink
);
t
con
=
tlink_tcon
(
tlink
);
xid
=
get_xid
();
xid
=
get_xid
();
...
@@ -598,7 +599,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
...
@@ -598,7 +599,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
goto
mknod_out
;
goto
mknod_out
;
}
}
if
(
pT
con
->
unix_ext
)
{
if
(
t
con
->
unix_ext
)
{
struct
cifs_unix_set_info_args
args
=
{
struct
cifs_unix_set_info_args
args
=
{
.
mode
=
mode
&
~
current_umask
(),
.
mode
=
mode
&
~
current_umask
(),
.
ctime
=
NO_CHANGE_64
,
.
ctime
=
NO_CHANGE_64
,
...
@@ -613,7 +614,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
...
@@ -613,7 +614,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
args
.
uid
=
INVALID_UID
;
/* no change */
args
.
uid
=
INVALID_UID
;
/* no change */
args
.
gid
=
INVALID_GID
;
/* no change */
args
.
gid
=
INVALID_GID
;
/* no change */
}
}
rc
=
CIFSSMBUnixSetPathInfo
(
xid
,
pT
con
,
full_path
,
&
args
,
rc
=
CIFSSMBUnixSetPathInfo
(
xid
,
t
con
,
full_path
,
&
args
,
cifs_sb
->
local_nls
,
cifs_sb
->
local_nls
,
cifs_sb
->
mnt_cifs_flags
&
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MAP_SPECIAL_CHR
);
CIFS_MOUNT_MAP_SPECIAL_CHR
);
...
@@ -644,42 +645,45 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
...
@@ -644,42 +645,45 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
if
(
backup_cred
(
cifs_sb
))
if
(
backup_cred
(
cifs_sb
))
create_options
|=
CREATE_OPEN_BACKUP_INTENT
;
create_options
|=
CREATE_OPEN_BACKUP_INTENT
;
rc
=
CIFSSMBOpen
(
xid
,
pTcon
,
full_path
,
FILE_CREATE
,
GENERIC_WRITE
,
oparms
.
tcon
=
tcon
;
FILE_SHARE_ALL
,
create_options
,
&
fileHandle
,
&
oplock
,
oparms
.
cifs_sb
=
cifs_sb
;
buf
,
cifs_sb
->
local_nls
,
oparms
.
desired_access
=
GENERIC_WRITE
;
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MAP_SPECIAL_CHR
);
oparms
.
share_access
=
FILE_SHARE_ALL
;
oparms
.
create_options
=
create_options
;
oparms
.
disposition
=
FILE_CREATE
;
oparms
.
path
=
full_path
;
oparms
.
fid
=
&
fid
;
oparms
.
reconnect
=
false
;
rc
=
CIFS_open
(
xid
,
&
oparms
,
&
oplock
,
buf
);
if
(
rc
)
if
(
rc
)
goto
mknod_out
;
goto
mknod_out
;
/* BB Do not bother to decode buf since no local inode yet to put
/*
* timestamps in, but we can reuse it safely */
* BB Do not bother to decode buf since no local inode yet to put
* timestamps in, but we can reuse it safely.
*/
pdev
=
(
struct
win_dev
*
)
buf
;
pdev
=
(
struct
win_dev
*
)
buf
;
io_parms
.
netfid
=
fi
leHandle
;
io_parms
.
netfid
=
fi
d
.
netfid
;
io_parms
.
pid
=
current
->
tgid
;
io_parms
.
pid
=
current
->
tgid
;
io_parms
.
tcon
=
pT
con
;
io_parms
.
tcon
=
t
con
;
io_parms
.
offset
=
0
;
io_parms
.
offset
=
0
;
io_parms
.
length
=
sizeof
(
struct
win_dev
);
io_parms
.
length
=
sizeof
(
struct
win_dev
);
if
(
S_ISCHR
(
mode
))
{
if
(
S_ISCHR
(
mode
))
{
memcpy
(
pdev
->
type
,
"IntxCHR"
,
8
);
memcpy
(
pdev
->
type
,
"IntxCHR"
,
8
);
pdev
->
major
=
pdev
->
major
=
cpu_to_le64
(
MAJOR
(
device_number
));
cpu_to_le64
(
MAJOR
(
device_number
));
pdev
->
minor
=
cpu_to_le64
(
MINOR
(
device_number
));
pdev
->
minor
=
rc
=
CIFSSMBWrite
(
xid
,
&
io_parms
,
&
bytes_written
,
(
char
*
)
pdev
,
cpu_to_le64
(
MINOR
(
device_number
));
NULL
,
0
);
rc
=
CIFSSMBWrite
(
xid
,
&
io_parms
,
&
bytes_written
,
(
char
*
)
pdev
,
NULL
,
0
);
}
else
if
(
S_ISBLK
(
mode
))
{
}
else
if
(
S_ISBLK
(
mode
))
{
memcpy
(
pdev
->
type
,
"IntxBLK"
,
8
);
memcpy
(
pdev
->
type
,
"IntxBLK"
,
8
);
pdev
->
major
=
pdev
->
major
=
cpu_to_le64
(
MAJOR
(
device_number
));
cpu_to_le64
(
MAJOR
(
device_number
));
pdev
->
minor
=
cpu_to_le64
(
MINOR
(
device_number
));
pdev
->
minor
=
rc
=
CIFSSMBWrite
(
xid
,
&
io_parms
,
&
bytes_written
,
(
char
*
)
pdev
,
cpu_to_le64
(
MINOR
(
device_number
));
NULL
,
0
);
rc
=
CIFSSMBWrite
(
xid
,
&
io_parms
,
&
bytes_written
,
(
char
*
)
pdev
,
NULL
,
0
);
}
/* else if (S_ISFIFO) */
}
/* else if (S_ISFIFO) */
CIFSSMBClose
(
xid
,
pTcon
,
fileHandle
);
CIFSSMBClose
(
xid
,
tcon
,
fid
.
netfid
);
d_drop
(
direntry
);
d_drop
(
direntry
);
/* FIXME: add code here to set EAs */
/* FIXME: add code here to set EAs */
...
@@ -761,7 +765,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
...
@@ -761,7 +765,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
/* if it was once a directory (but how can we tell?) we could do
/* if it was once a directory (but how can we tell?) we could do
shrink_dcache_parent(direntry); */
shrink_dcache_parent(direntry); */
}
else
if
(
rc
!=
-
EACCES
)
{
}
else
if
(
rc
!=
-
EACCES
)
{
cifs_dbg
(
VFS
,
"Unexpected lookup error %d
\n
"
,
rc
);
cifs_dbg
(
FYI
,
"Unexpected lookup error %d
\n
"
,
rc
);
/* We special case check for Access Denied - since that
/* We special case check for Access Denied - since that
is a common return code */
is a common return code */
}
}
...
...
sources/centos70/file.c
View file @
9d798057
...
@@ -247,7 +247,7 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
...
@@ -247,7 +247,7 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
xid
);
xid
);
else
else
rc
=
cifs_get_inode_info
(
&
inode
,
full_path
,
buf
,
inode
->
i_sb
,
rc
=
cifs_get_inode_info
(
&
inode
,
full_path
,
buf
,
inode
->
i_sb
,
xid
,
&
fid
->
net
fid
);
xid
,
fid
);
out:
out:
kfree
(
buf
);
kfree
(
buf
);
...
@@ -338,7 +338,7 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
...
@@ -338,7 +338,7 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
spin_unlock
(
&
cifs_file_list_lock
);
spin_unlock
(
&
cifs_file_list_lock
);
if
(
fid
->
purge_cache
)
if
(
fid
->
purge_cache
)
cifs_
invalidate
_mapping
(
inode
);
cifs_
zap
_mapping
(
inode
);
file
->
private_data
=
cfile
;
file
->
private_data
=
cfile
;
return
cfile
;
return
cfile
;
...
@@ -369,6 +369,7 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
...
@@ -369,6 +369,7 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
struct
cifsLockInfo
*
li
,
*
tmp
;
struct
cifsLockInfo
*
li
,
*
tmp
;
struct
cifs_fid
fid
;
struct
cifs_fid
fid
;
struct
cifs_pending_open
open
;
struct
cifs_pending_open
open
;
bool
oplock_break_cancelled
;
spin_lock
(
&
cifs_file_list_lock
);
spin_lock
(
&
cifs_file_list_lock
);
if
(
--
cifs_file
->
count
>
0
)
{
if
(
--
cifs_file
->
count
>
0
)
{
...
@@ -395,12 +396,12 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
...
@@ -395,12 +396,12 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
* again and get at least level II oplock.
* again and get at least level II oplock.
*/
*/
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_STRICT_IO
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_STRICT_IO
)
CIFS_I
(
inode
)
->
invalid_mapping
=
true
;
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
(
&
cifs_file_list_lock
);
cancel_work_sync
(
&
cifs_file
->
oplock_break
);
oplock_break_cancelled
=
cancel_work_sync
(
&
cifs_file
->
oplock_break
);
if
(
!
tcon
->
need_reconnect
&&
!
cifs_file
->
invalidHandle
)
{
if
(
!
tcon
->
need_reconnect
&&
!
cifs_file
->
invalidHandle
)
{
struct
TCP_Server_Info
*
server
=
tcon
->
ses
->
server
;
struct
TCP_Server_Info
*
server
=
tcon
->
ses
->
server
;
...
@@ -412,6 +413,9 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
...
@@ -412,6 +413,9 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
_free_xid
(
xid
);
_free_xid
(
xid
);
}
}
if
(
oplock_break_cancelled
)
cifs_done_oplock_break
(
cifsi
);
cifs_del_pending_open
(
&
open
);
cifs_del_pending_open
(
&
open
);
/*
/*
...
@@ -686,7 +690,7 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
...
@@ -686,7 +690,7 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
/*
/*
* Can not refresh inode by passing in file_info buf to be returned by
* Can not refresh inode by passing in file_info buf to be returned by
*
CIFSSMBO
pen and then calling get_inode_info with returned buf since
*
ops->o
pen and then calling get_inode_info with returned buf since
* file might have write behind data that needs to be flushed and server
* file might have write behind data that needs to be flushed and server
* version of file size can be stale. If we knew for sure that inode was
* version of file size can be stale. If we knew for sure that inode was
* not dirty locally we could do this.
* not dirty locally we could do this.
...
@@ -1537,7 +1541,7 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type,
...
@@ -1537,7 +1541,7 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type,
*/
*/
if
(
!
CIFS_CACHE_WRITE
(
CIFS_I
(
inode
))
&&
if
(
!
CIFS_CACHE_WRITE
(
CIFS_I
(
inode
))
&&
CIFS_CACHE_READ
(
CIFS_I
(
inode
)))
{
CIFS_CACHE_READ
(
CIFS_I
(
inode
)))
{
cifs_
invalidate
_mapping
(
inode
);
cifs_
zap
_mapping
(
inode
);
cifs_dbg
(
FYI
,
"Set no oplock for inode=%p due to mand locks
\n
"
,
cifs_dbg
(
FYI
,
"Set no oplock for inode=%p due to mand locks
\n
"
,
inode
);
inode
);
CIFS_I
(
inode
)
->
oplock
=
0
;
CIFS_I
(
inode
)
->
oplock
=
0
;
...
@@ -2226,7 +2230,7 @@ int cifs_strict_fsync(struct file *file, loff_t start, loff_t end,
...
@@ -2226,7 +2230,7 @@ int cifs_strict_fsync(struct file *file, loff_t start, loff_t end,
file
->
f_path
.
dentry
->
d_name
.
name
,
datasync
);
file
->
f_path
.
dentry
->
d_name
.
name
,
datasync
);
if
(
!
CIFS_CACHE_READ
(
CIFS_I
(
inode
)))
{
if
(
!
CIFS_CACHE_READ
(
CIFS_I
(
inode
)))
{
rc
=
cifs_
invalidate
_mapping
(
inode
);
rc
=
cifs_
zap
_mapping
(
inode
);
if
(
rc
)
{
if
(
rc
)
{
cifs_dbg
(
FYI
,
"rc: %d during invalidate phase
\n
"
,
rc
);
cifs_dbg
(
FYI
,
"rc: %d during invalidate phase
\n
"
,
rc
);
rc
=
0
;
/* don't care about it in fsync */
rc
=
0
;
/* don't care about it in fsync */
...
@@ -2570,7 +2574,7 @@ ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov,
...
@@ -2570,7 +2574,7 @@ ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov,
written
=
cifs_iovec_write
(
iocb
->
ki_filp
,
iov
,
nr_segs
,
&
pos
);
written
=
cifs_iovec_write
(
iocb
->
ki_filp
,
iov
,
nr_segs
,
&
pos
);
if
(
written
>
0
)
{
if
(
written
>
0
)
{
CIFS_I
(
inode
)
->
invalid_mapping
=
true
;
set_bit
(
CIFS_INO_INVALID_MAPPING
,
&
CIFS_I
(
inode
)
->
flags
)
;
iocb
->
ki_pos
=
pos
;
iocb
->
ki_pos
=
pos
;
}
}
...
@@ -2587,31 +2591,33 @@ cifs_writev(struct kiocb *iocb, const struct iovec *iov,
...
@@ -2587,31 +2591,33 @@ cifs_writev(struct kiocb *iocb, const struct iovec *iov,
struct
cifsInodeInfo
*
cinode
=
CIFS_I
(
inode
);
struct
cifsInodeInfo
*
cinode
=
CIFS_I
(
inode
);
struct
TCP_Server_Info
*
server
=
tlink_tcon
(
cfile
->
tlink
)
->
ses
->
server
;
struct
TCP_Server_Info
*
server
=
tlink_tcon
(
cfile
->
tlink
)
->
ses
->
server
;
ssize_t
rc
=
-
EACCES
;
ssize_t
rc
=
-
EACCES
;
loff_t
lock_pos
=
iocb
->
ki_pos
;
BUG_ON
(
iocb
->
ki_pos
!=
pos
);
/*
/*
* 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
);
if
(
!
cifs_find_lock_conflict
(
cfile
,
pos
,
iov_length
(
iov
,
nr_segs
),
mutex_lock
(
&
inode
->
i_mutex
);
if
(
file
->
f_flags
&
O_APPEND
)
lock_pos
=
i_size_read
(
inode
);
if
(
!
cifs_find_lock_conflict
(
cfile
,
lock_pos
,
iov_length
(
iov
,
nr_segs
),
server
->
vals
->
exclusive_lock_type
,
NULL
,
server
->
vals
->
exclusive_lock_type
,
NULL
,
CIFS_WRITE_OP
))
{
CIFS_WRITE_OP
))
{
mutex_lock
(
&
inode
->
i_mutex
);
rc
=
__generic_file_aio_write
(
iocb
,
iov
,
nr_segs
,
rc
=
__generic_file_aio_write
(
iocb
,
iov
,
nr_segs
,
&
iocb
->
ki_pos
);
&
iocb
->
ki_pos
);
mutex_unlock
(
&
inode
->
i_mutex
);
mutex_unlock
(
&
inode
->
i_mutex
);
}
if
(
rc
>
0
||
rc
==
-
EIOCBQUEUED
)
{
if
(
rc
>
0
)
{
ssize_t
err
;
ssize_t
err
;
err
=
generic_write_sync
(
file
,
pos
,
rc
);
err
=
generic_write_sync
(
file
,
iocb
->
ki_pos
-
rc
,
rc
);
if
(
err
<
0
&&
rc
>
0
)
if
(
err
<
0
)
rc
=
err
;
rc
=
err
;
}
}
else
{
mutex_unlock
(
&
inode
->
i_mutex
);
}
}
up_read
(
&
cinode
->
lock_sem
);
up_read
(
&
cinode
->
lock_sem
);
return
rc
;
return
rc
;
}
}
...
@@ -2628,12 +2634,20 @@ cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov,
...
@@ -2628,12 +2634,20 @@ cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov,
struct
cifs_tcon
*
tcon
=
tlink_tcon
(
cfile
->
tlink
);
struct
cifs_tcon
*
tcon
=
tlink_tcon
(
cfile
->
tlink
);
ssize_t
written
;
ssize_t
written
;
written
=
cifs_get_writer
(
cinode
);
if
(
written
)
return
written
;
if
(
CIFS_CACHE_WRITE
(
cinode
))
{
if
(
CIFS_CACHE_WRITE
(
cinode
))
{
if
(
cap_unix
(
tcon
->
ses
)
&&
if
(
cap_unix
(
tcon
->
ses
)
&&
(
CIFS_UNIX_FCNTL_CAP
&
le64_to_cpu
(
tcon
->
fsUnixInfo
.
Capability
))
(
CIFS_UNIX_FCNTL_CAP
&
le64_to_cpu
(
tcon
->
fsUnixInfo
.
Capability
))
&&
((
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NOPOSIXBRL
)
==
0
))
&&
((
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NOPOSIXBRL
)
==
0
))
{
return
generic_file_aio_write
(
iocb
,
iov
,
nr_segs
,
pos
);
written
=
generic_file_aio_write
(
return
cifs_writev
(
iocb
,
iov
,
nr_segs
,
pos
);
iocb
,
iov
,
nr_segs
,
pos
);
goto
out
;
}
written
=
cifs_writev
(
iocb
,
iov
,
nr_segs
,
pos
);
goto
out
;
}
}
/*
/*
* For non-oplocked files in strict cache mode we need to write the data
* For non-oplocked files in strict cache mode we need to write the data
...
@@ -2648,11 +2662,13 @@ cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov,
...
@@ -2648,11 +2662,13 @@ cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov,
* request comes - break it on the client to prevent reading
* request comes - break it on the client to prevent reading
* an old data.
* an old data.
*/
*/
cifs_
invalidate
_mapping
(
inode
);
cifs_
zap
_mapping
(
inode
);
cifs_dbg
(
FYI
,
"Set no oplock for inode=%p after a write operation
\n
"
,
cifs_dbg
(
FYI
,
"Set no oplock for inode=%p after a write operation
\n
"
,
inode
);
inode
);
cinode
->
oplock
=
0
;
cinode
->
oplock
=
0
;
}
}
out:
cifs_put_writer
(
cinode
);
return
written
;
return
written
;
}
}
...
@@ -2905,7 +2921,7 @@ cifs_iovec_read(struct file *file, const struct iovec *iov,
...
@@ -2905,7 +2921,7 @@ cifs_iovec_read(struct file *file, const struct iovec *iov,
cifs_uncached_readv_complete
);
cifs_uncached_readv_complete
);
if
(
!
rdata
)
{
if
(
!
rdata
)
{
rc
=
-
ENOMEM
;
rc
=
-
ENOMEM
;
goto
error
;
break
;
}
}
rc
=
cifs_read_allocate_pages
(
rdata
,
npages
);
rc
=
cifs_read_allocate_pages
(
rdata
,
npages
);
...
@@ -3145,7 +3161,7 @@ int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
...
@@ -3145,7 +3161,7 @@ int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
xid
=
get_xid
();
xid
=
get_xid
();
if
(
!
CIFS_CACHE_READ
(
CIFS_I
(
inode
)))
{
if
(
!
CIFS_CACHE_READ
(
CIFS_I
(
inode
)))
{
rc
=
cifs_
invalidate
_mapping
(
inode
);
rc
=
cifs_
zap
_mapping
(
inode
);
if
(
rc
)
if
(
rc
)
return
rc
;
return
rc
;
}
}
...
@@ -3302,6 +3318,9 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
...
@@ -3302,6 +3318,9 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
/*
/*
* Reads as many pages as possible from fscache. Returns -ENOBUFS
* Reads as many pages as possible from fscache. Returns -ENOBUFS
* immediately if the cookie is negative
* immediately if the cookie is negative
*
* After this point, every page in the list might have PG_fscache set,
* so we will need to clean that up off of every page we don't use.
*/
*/
rc
=
cifs_readpages_from_fscache
(
mapping
->
host
,
mapping
,
page_list
,
rc
=
cifs_readpages_from_fscache
(
mapping
->
host
,
mapping
,
page_list
,
&
num_pages
);
&
num_pages
);
...
@@ -3424,9 +3443,17 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
...
@@ -3424,9 +3443,17 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
kref_put
(
&
rdata
->
refcount
,
cifs_readdata_release
);
kref_put
(
&
rdata
->
refcount
,
cifs_readdata_release
);
}
}
/* Any pages that have been shown to fscache but didn't get added to
* the pagecache must be uncached before they get returned to the
* allocator.
*/
cifs_fscache_readpages_cancel
(
mapping
->
host
,
page_list
);
return
rc
;
return
rc
;
}
}
/*
* cifs_readpage_worker must be called with the page pinned
*/
static
int
cifs_readpage_worker
(
struct
file
*
file
,
struct
page
*
page
,
static
int
cifs_readpage_worker
(
struct
file
*
file
,
struct
page
*
page
,
loff_t
*
poffset
)
loff_t
*
poffset
)
{
{
...
@@ -3438,7 +3465,6 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
...
@@ -3438,7 +3465,6 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
if
(
rc
==
0
)
if
(
rc
==
0
)
goto
read_complete
;
goto
read_complete
;
page_cache_get
(
page
);
read_data
=
kmap
(
page
);
read_data
=
kmap
(
page
);
/* for reads over a certain size could initiate async read ahead */
/* for reads over a certain size could initiate async read ahead */
...
@@ -3465,7 +3491,7 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
...
@@ -3465,7 +3491,7 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
io_error:
io_error:
kunmap
(
page
);
kunmap
(
page
);
page_cache_releas
e
(
page
);
unlock_pag
e
(
page
);
read_complete:
read_complete:
return
rc
;
return
rc
;
...
@@ -3490,8 +3516,6 @@ static int cifs_readpage(struct file *file, struct page *page)
...
@@ -3490,8 +3516,6 @@ static int cifs_readpage(struct file *file, struct page *page)
rc
=
cifs_readpage_worker
(
file
,
page
,
&
offset
);
rc
=
cifs_readpage_worker
(
file
,
page
,
&
offset
);
unlock_page
(
page
);
free_xid
(
xid
);
free_xid
(
xid
);
return
rc
;
return
rc
;
}
}
...
@@ -3545,6 +3569,7 @@ static int cifs_write_begin(struct file *file, struct address_space *mapping,
...
@@ -3545,6 +3569,7 @@ static int cifs_write_begin(struct file *file, struct address_space *mapping,
loff_t
pos
,
unsigned
len
,
unsigned
flags
,
loff_t
pos
,
unsigned
len
,
unsigned
flags
,
struct
page
**
pagep
,
void
**
fsdata
)
struct
page
**
pagep
,
void
**
fsdata
)
{
{
int
oncethru
=
0
;
pgoff_t
index
=
pos
>>
PAGE_CACHE_SHIFT
;
pgoff_t
index
=
pos
>>
PAGE_CACHE_SHIFT
;
loff_t
offset
=
pos
&
(
PAGE_CACHE_SIZE
-
1
);
loff_t
offset
=
pos
&
(
PAGE_CACHE_SIZE
-
1
);
loff_t
page_start
=
pos
&
PAGE_MASK
;
loff_t
page_start
=
pos
&
PAGE_MASK
;
...
@@ -3554,6 +3579,7 @@ static int cifs_write_begin(struct file *file, struct address_space *mapping,
...
@@ -3554,6 +3579,7 @@ static int cifs_write_begin(struct file *file, struct address_space *mapping,
cifs_dbg
(
FYI
,
"write_begin from %lld len %d
\n
"
,
(
long
long
)
pos
,
len
);
cifs_dbg
(
FYI
,
"write_begin from %lld len %d
\n
"
,
(
long
long
)
pos
,
len
);
start:
page
=
grab_cache_page_write_begin
(
mapping
,
index
,
flags
);
page
=
grab_cache_page_write_begin
(
mapping
,
index
,
flags
);
if
(
!
page
)
{
if
(
!
page
)
{
rc
=
-
ENOMEM
;
rc
=
-
ENOMEM
;
...
@@ -3595,13 +3621,16 @@ static int cifs_write_begin(struct file *file, struct address_space *mapping,
...
@@ -3595,13 +3621,16 @@ static int cifs_write_begin(struct file *file, struct address_space *mapping,
}
}
}
}
if
((
file
->
f_flags
&
O_ACCMODE
)
!=
O_WRONLY
)
{
if
((
file
->
f_flags
&
O_ACCMODE
)
!=
O_WRONLY
&&
!
oncethru
)
{
/*
/*
* might as well read a page, it is fast enough. If we get
* might as well read a page, it is fast enough. If we get
* an error, we don't need to return it. cifs_write_end will
* an error, we don't need to return it. cifs_write_end will
* do a sync write instead since PG_uptodate isn't set.
* do a sync write instead since PG_uptodate isn't set.
*/
*/
cifs_readpage_worker
(
file
,
page
,
&
page_start
);
cifs_readpage_worker
(
file
,
page
,
&
page_start
);
page_cache_release
(
page
);
oncethru
=
1
;
goto
start
;
}
else
{
}
else
{
/* we could try using another file handle if there is one -
/* we could try using another file handle if there is one -
but how would we lock it to prevent close of that handle
but how would we lock it to prevent close of that handle
...
@@ -3650,6 +3679,13 @@ static int cifs_launder_page(struct page *page)
...
@@ -3650,6 +3679,13 @@ static int cifs_launder_page(struct page *page)
return
rc
;
return
rc
;
}
}
static
int
cifs_pending_writers_wait
(
void
*
unused
)
{
schedule
();
return
0
;
}
void
cifs_oplock_break
(
struct
work_struct
*
work
)
void
cifs_oplock_break
(
struct
work_struct
*
work
)
{
{
struct
cifsFileInfo
*
cfile
=
container_of
(
work
,
struct
cifsFileInfo
,
struct
cifsFileInfo
*
cfile
=
container_of
(
work
,
struct
cifsFileInfo
,
...
@@ -3657,8 +3693,15 @@ void cifs_oplock_break(struct work_struct *work)
...
@@ -3657,8 +3693,15 @@ void cifs_oplock_break(struct work_struct *work)
struct
inode
*
inode
=
cfile
->
dentry
->
d_inode
;
struct
inode
*
inode
=
cfile
->
dentry
->
d_inode
;
struct
cifsInodeInfo
*
cinode
=
CIFS_I
(
inode
);
struct
cifsInodeInfo
*
cinode
=
CIFS_I
(
inode
);
struct
cifs_tcon
*
tcon
=
tlink_tcon
(
cfile
->
tlink
);
struct
cifs_tcon
*
tcon
=
tlink_tcon
(
cfile
->
tlink
);
struct
TCP_Server_Info
*
server
=
tcon
->
ses
->
server
;
int
rc
=
0
;
int
rc
=
0
;
wait_on_bit
(
&
cinode
->
flags
,
CIFS_INODE_PENDING_WRITERS
,
cifs_pending_writers_wait
,
TASK_UNINTERRUPTIBLE
);
server
->
ops
->
downgrade_oplock
(
server
,
cinode
,
test_bit
(
CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2
,
&
cinode
->
flags
));
if
(
!
CIFS_CACHE_WRITE
(
cinode
)
&&
CIFS_CACHE_READ
(
cinode
)
&&
if
(
!
CIFS_CACHE_WRITE
(
cinode
)
&&
CIFS_CACHE_READ
(
cinode
)
&&
cifs_has_mand_locks
(
cinode
))
{
cifs_has_mand_locks
(
cinode
))
{
cifs_dbg
(
FYI
,
"Reset oplock to None for inode=%p due to mand locks
\n
"
,
cifs_dbg
(
FYI
,
"Reset oplock to None for inode=%p due to mand locks
\n
"
,
...
@@ -3675,7 +3718,7 @@ void cifs_oplock_break(struct work_struct *work)
...
@@ -3675,7 +3718,7 @@ void cifs_oplock_break(struct work_struct *work)
if
(
!
CIFS_CACHE_READ
(
cinode
))
{
if
(
!
CIFS_CACHE_READ
(
cinode
))
{
rc
=
filemap_fdatawait
(
inode
->
i_mapping
);
rc
=
filemap_fdatawait
(
inode
->
i_mapping
);
mapping_set_error
(
inode
->
i_mapping
,
rc
);
mapping_set_error
(
inode
->
i_mapping
,
rc
);
cifs_
invalidate
_mapping
(
inode
);
cifs_
zap
_mapping
(
inode
);
}
}
cifs_dbg
(
FYI
,
"Oplock flush inode %p rc %d
\n
"
,
inode
,
rc
);
cifs_dbg
(
FYI
,
"Oplock flush inode %p rc %d
\n
"
,
inode
,
rc
);
}
}
...
@@ -3695,8 +3738,30 @@ void cifs_oplock_break(struct work_struct *work)
...
@@ -3695,8 +3738,30 @@ void cifs_oplock_break(struct work_struct *work)
cinode
);
cinode
);
cifs_dbg
(
FYI
,
"Oplock release rc = %d
\n
"
,
rc
);
cifs_dbg
(
FYI
,
"Oplock release rc = %d
\n
"
,
rc
);
}
}
cifs_done_oplock_break
(
cinode
);
}
/*
* The presence of cifs_direct_io() in the address space ops vector
* allowes open() O_DIRECT flags which would have failed otherwise.
*
* In the non-cached mode (mount with cache=none), we shunt off direct read and write requests
* so this method should never be called.
*
* Direct IO is not yet supported in the cached mode.
*/
static
ssize_t
cifs_direct_io
(
int
rw
,
struct
kiocb
*
iocb
,
const
struct
iovec
*
iov
,
loff_t
pos
,
unsigned
long
nr_segs
)
{
/*
* FIXME
* Eventually need to support direct IO for non forcedirectio mounts
*/
return
-
EINVAL
;
}
}
const
struct
address_space_operations
cifs_addr_ops
=
{
const
struct
address_space_operations
cifs_addr_ops
=
{
.
readpage
=
cifs_readpage
,
.
readpage
=
cifs_readpage
,
.
readpages
=
cifs_readpages
,
.
readpages
=
cifs_readpages
,
...
@@ -3706,6 +3771,7 @@ const struct address_space_operations cifs_addr_ops = {
...
@@ -3706,6 +3771,7 @@ const struct address_space_operations cifs_addr_ops = {
.
write_end
=
cifs_write_end
,
.
write_end
=
cifs_write_end
,
.
set_page_dirty
=
__set_page_dirty_nobuffers
,
.
set_page_dirty
=
__set_page_dirty_nobuffers
,
.
releasepage
=
cifs_release_page
,
.
releasepage
=
cifs_release_page
,
.
direct_IO
=
cifs_direct_io
,
.
invalidatepage
=
cifs_invalidate_page
,
.
invalidatepage
=
cifs_invalidate_page
,
.
launder_page
=
cifs_launder_page
,
.
launder_page
=
cifs_launder_page
,
};
};
...
...
sources/centos70/fscache.c
View file @
9d798057
...
@@ -223,6 +223,13 @@ void __cifs_readpage_to_fscache(struct inode *inode, struct page *page)
...
@@ -223,6 +223,13 @@ void __cifs_readpage_to_fscache(struct inode *inode, struct page *page)
fscache_uncache_page
(
CIFS_I
(
inode
)
->
fscache
,
page
);
fscache_uncache_page
(
CIFS_I
(
inode
)
->
fscache
,
page
);
}
}
void
__cifs_fscache_readpages_cancel
(
struct
inode
*
inode
,
struct
list_head
*
pages
)
{
cifs_dbg
(
FYI
,
"%s: (fsc: %p, i: %p)
\n
"
,
__func__
,
CIFS_I
(
inode
)
->
fscache
,
inode
);
fscache_readpages_cancel
(
CIFS_I
(
inode
)
->
fscache
,
pages
);
}
void
__cifs_fscache_invalidate_page
(
struct
page
*
page
,
struct
inode
*
inode
)
void
__cifs_fscache_invalidate_page
(
struct
page
*
page
,
struct
inode
*
inode
)
{
{
struct
cifsInodeInfo
*
cifsi
=
CIFS_I
(
inode
);
struct
cifsInodeInfo
*
cifsi
=
CIFS_I
(
inode
);
...
...
sources/centos70/fscache.h
View file @
9d798057
...
@@ -54,6 +54,7 @@ extern int __cifs_readpages_from_fscache(struct inode *,
...
@@ -54,6 +54,7 @@ extern int __cifs_readpages_from_fscache(struct inode *,
struct
address_space
*
,
struct
address_space
*
,
struct
list_head
*
,
struct
list_head
*
,
unsigned
*
);
unsigned
*
);
extern
void
__cifs_fscache_readpages_cancel
(
struct
inode
*
,
struct
list_head
*
);
extern
void
__cifs_readpage_to_fscache
(
struct
inode
*
,
struct
page
*
);
extern
void
__cifs_readpage_to_fscache
(
struct
inode
*
,
struct
page
*
);
...
@@ -91,6 +92,13 @@ static inline void cifs_readpage_to_fscache(struct inode *inode,
...
@@ -91,6 +92,13 @@ static inline void cifs_readpage_to_fscache(struct inode *inode,
__cifs_readpage_to_fscache
(
inode
,
page
);
__cifs_readpage_to_fscache
(
inode
,
page
);
}
}
static
inline
void
cifs_fscache_readpages_cancel
(
struct
inode
*
inode
,
struct
list_head
*
pages
)
{
if
(
CIFS_I
(
inode
)
->
fscache
)
return
__cifs_fscache_readpages_cancel
(
inode
,
pages
);
}
#else
/* CONFIG_CIFS_FSCACHE */
#else
/* CONFIG_CIFS_FSCACHE */
static
inline
int
cifs_fscache_register
(
void
)
{
return
0
;
}
static
inline
int
cifs_fscache_register
(
void
)
{
return
0
;
}
static
inline
void
cifs_fscache_unregister
(
void
)
{}
static
inline
void
cifs_fscache_unregister
(
void
)
{}
...
@@ -131,6 +139,11 @@ static inline int cifs_readpages_from_fscache(struct inode *inode,
...
@@ -131,6 +139,11 @@ static inline int cifs_readpages_from_fscache(struct inode *inode,
static
inline
void
cifs_readpage_to_fscache
(
struct
inode
*
inode
,
static
inline
void
cifs_readpage_to_fscache
(
struct
inode
*
inode
,
struct
page
*
page
)
{}
struct
page
*
page
)
{}
static
inline
void
cifs_fscache_readpages_cancel
(
struct
inode
*
inode
,
struct
list_head
*
pages
)
{
}
#endif
/* CONFIG_CIFS_FSCACHE */
#endif
/* CONFIG_CIFS_FSCACHE */
#endif
/* _CIFS_FSCACHE_H */
#endif
/* _CIFS_FSCACHE_H */
sources/centos70/inode.c
View file @
9d798057
...
@@ -22,6 +22,7 @@
...
@@ -22,6 +22,7 @@
#include <linux/stat.h>
#include <linux/stat.h>
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/pagemap.h>
#include <linux/pagemap.h>
#include <linux/freezer.h>
#include <asm/div64.h>
#include <asm/div64.h>
#include "cifsfs.h"
#include "cifsfs.h"
#include "cifspdu.h"
#include "cifspdu.h"
...
@@ -70,8 +71,9 @@ static void cifs_set_ops(struct inode *inode)
...
@@ -70,8 +71,9 @@ static void cifs_set_ops(struct inode *inode)
#else
/* NO DFS support, treat as a directory */
#else
/* NO DFS support, treat as a directory */
{
{
#endif
#endif
inode
->
i_op
=
&
cifs_dir_inode_ops
;
inode
->
i_op
=
&
cifs_dir_inode_ops
.
ops
;
inode
->
i_fop
=
&
cifs_dir_ops
;
inode
->
i_fop
=
&
cifs_dir_ops
;
inode
->
i_flags
|=
S_IOPS_WRAPPER
;
}
}
break
;
break
;
case
S_IFLNK
:
case
S_IFLNK
:
...
@@ -117,7 +119,34 @@ cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr)
...
@@ -117,7 +119,34 @@ cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr)
cifs_dbg
(
FYI
,
"%s: invalidating inode %llu mapping
\n
"
,
cifs_dbg
(
FYI
,
"%s: invalidating inode %llu mapping
\n
"
,
__func__
,
cifs_i
->
uniqueid
);
__func__
,
cifs_i
->
uniqueid
);
cifs_i
->
invalid_mapping
=
true
;
set_bit
(
CIFS_INO_INVALID_MAPPING
,
&
cifs_i
->
flags
);
}
/*
* copy nlink to the inode, unless it wasn't provided. Provide
* sane values if we don't have an existing one and none was provided
*/
static
void
cifs_nlink_fattr_to_inode
(
struct
inode
*
inode
,
struct
cifs_fattr
*
fattr
)
{
/*
* if we're in a situation where we can't trust what we
* got from the server (readdir, some non-unix cases)
* fake reasonable values
*/
if
(
fattr
->
cf_flags
&
CIFS_FATTR_UNKNOWN_NLINK
)
{
/* only provide fake values on a new inode */
if
(
inode
->
i_state
&
I_NEW
)
{
if
(
fattr
->
cf_cifsattrs
&
ATTR_DIRECTORY
)
set_nlink
(
inode
,
2
);
else
set_nlink
(
inode
,
1
);
}
return
;
}
/* we trust the server, so update it */
set_nlink
(
inode
,
fattr
->
cf_nlink
);
}
}
/* populate an inode with info from a cifs_fattr struct */
/* populate an inode with info from a cifs_fattr struct */
...
@@ -134,7 +163,7 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
...
@@ -134,7 +163,7 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
inode
->
i_mtime
=
fattr
->
cf_mtime
;
inode
->
i_mtime
=
fattr
->
cf_mtime
;
inode
->
i_ctime
=
fattr
->
cf_ctime
;
inode
->
i_ctime
=
fattr
->
cf_ctime
;
inode
->
i_rdev
=
fattr
->
cf_rdev
;
inode
->
i_rdev
=
fattr
->
cf_rdev
;
set_nlink
(
inode
,
fattr
->
cf_nlink
);
cifs_nlink_fattr_to_inode
(
inode
,
fattr
);
inode
->
i_uid
=
fattr
->
cf_uid
;
inode
->
i_uid
=
fattr
->
cf_uid
;
inode
->
i_gid
=
fattr
->
cf_gid
;
inode
->
i_gid
=
fattr
->
cf_gid
;
...
@@ -150,7 +179,10 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
...
@@ -150,7 +179,10 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
else
else
cifs_i
->
time
=
jiffies
;
cifs_i
->
time
=
jiffies
;
cifs_i
->
delete_pending
=
fattr
->
cf_flags
&
CIFS_FATTR_DELETE_PENDING
;
if
(
fattr
->
cf_flags
&
CIFS_FATTR_DELETE_PENDING
)
set_bit
(
CIFS_INO_DELETE_PENDING
,
&
cifs_i
->
flags
);
else
clear_bit
(
CIFS_INO_DELETE_PENDING
,
&
cifs_i
->
flags
);
cifs_i
->
server_eof
=
fattr
->
cf_eof
;
cifs_i
->
server_eof
=
fattr
->
cf_eof
;
/*
/*
...
@@ -356,9 +388,10 @@ int cifs_get_inode_info_unix(struct inode **pinode,
...
@@ -356,9 +388,10 @@ int cifs_get_inode_info_unix(struct inode **pinode,
/* check for Minshall+French symlinks */
/* check for Minshall+French symlinks */
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MF_SYMLINKS
)
{
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MF_SYMLINKS
)
{
int
tmprc
=
CIFSCheckMFSymlink
(
&
fattr
,
full_path
,
cifs_sb
,
xid
);
int
tmprc
=
check_mf_symlink
(
xid
,
tcon
,
cifs_sb
,
&
fattr
,
full_path
);
if
(
tmprc
)
if
(
tmprc
)
cifs_dbg
(
FYI
,
"
CIFSCheckMFS
ymlink: %d
\n
"
,
tmprc
);
cifs_dbg
(
FYI
,
"
check_mf_s
ymlink: %d
\n
"
,
tmprc
);
}
}
if
(
*
pinode
==
NULL
)
{
if
(
*
pinode
==
NULL
)
{
...
@@ -376,18 +409,20 @@ int cifs_get_inode_info_unix(struct inode **pinode,
...
@@ -376,18 +409,20 @@ int cifs_get_inode_info_unix(struct inode **pinode,
}
}
static
int
static
int
cifs_sfu_type
(
struct
cifs_fattr
*
fattr
,
const
unsigned
char
*
path
,
cifs_sfu_type
(
struct
cifs_fattr
*
fattr
,
const
char
*
path
,
struct
cifs_sb_info
*
cifs_sb
,
unsigned
int
xid
)
struct
cifs_sb_info
*
cifs_sb
,
unsigned
int
xid
)
{
{
int
rc
;
int
rc
;
int
oplock
=
0
;
int
oplock
=
0
;
__u16
netfid
;
struct
tcon_link
*
tlink
;
struct
tcon_link
*
tlink
;
struct
cifs_tcon
*
tcon
;
struct
cifs_tcon
*
tcon
;
struct
cifs_fid
fid
;
struct
cifs_open_parms
oparms
;
struct
cifs_io_parms
io_parms
;
struct
cifs_io_parms
io_parms
;
char
buf
[
24
];
char
buf
[
24
];
unsigned
int
bytes_read
;
unsigned
int
bytes_read
;
char
*
pbuf
;
char
*
pbuf
;
int
buf_type
=
CIFS_NO_BUFFER
;
pbuf
=
buf
;
pbuf
=
buf
;
...
@@ -408,62 +443,70 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
...
@@ -408,62 +443,70 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
return
PTR_ERR
(
tlink
);
return
PTR_ERR
(
tlink
);
tcon
=
tlink_tcon
(
tlink
);
tcon
=
tlink_tcon
(
tlink
);
rc
=
CIFSSMBOpen
(
xid
,
tcon
,
path
,
FILE_OPEN
,
GENERIC_READ
,
oparms
.
tcon
=
tcon
;
FILE_SHARE_ALL
,
CREATE_NOT_DIR
,
&
netfid
,
&
oplock
,
oparms
.
cifs_sb
=
cifs_sb
;
NULL
,
cifs_sb
->
local_nls
,
oparms
.
desired_access
=
GENERIC_READ
;
cifs_sb
->
mnt_cifs_flags
&
oparms
.
share_access
=
FILE_SHARE_ALL
;
CIFS_MOUNT_MAP_SPECIAL_CHR
)
;
oparms
.
create_options
=
CREATE_NOT_DIR
;
if
(
rc
==
0
)
{
oparms
.
disposition
=
FILE_OPEN
;
int
buf_type
=
CIFS_NO_BUFFER
;
oparms
.
path
=
path
;
/* Read header */
oparms
.
fid
=
&
fid
;
io_parms
.
netfid
=
netfid
;
oparms
.
reconnect
=
false
;
io_parms
.
pid
=
current
->
tgid
;
io_parms
.
tcon
=
tcon
;
rc
=
CIFS_open
(
xid
,
&
oparms
,
&
oplock
,
NULL
)
;
io_parms
.
offset
=
0
;
if
(
rc
)
{
io_parms
.
length
=
24
;
cifs_put_tlink
(
tlink
)
;
r
c
=
CIFSSMBRead
(
xid
,
&
io_parms
,
&
bytes_read
,
&
pbuf
,
r
eturn
rc
;
&
buf_type
);
}
if
((
rc
==
0
)
&&
(
bytes_read
>=
8
))
{
if
(
memcmp
(
"IntxBLK"
,
pbuf
,
8
)
==
0
)
{
/* Read header */
cifs_dbg
(
FYI
,
"Block device
\n
"
)
;
io_parms
.
netfid
=
fid
.
netfid
;
fattr
->
cf_mode
|=
S_IFBLK
;
io_parms
.
pid
=
current
->
tgid
;
fattr
->
cf_dtype
=
DT_BLK
;
io_parms
.
tcon
=
tcon
;
if
(
bytes_read
==
24
)
{
io_parms
.
offset
=
0
;
/* we have enough to decode dev num */
io_parms
.
length
=
24
;
__u64
mjr
;
/* major */
__u64
mnr
;
/* minor */
rc
=
CIFSSMBRead
(
xid
,
&
io_parms
,
&
bytes_read
,
&
pbuf
,
&
buf_type
);
mjr
=
le64_to_cpu
(
*
(
__le64
*
)(
pbuf
+
8
));
if
((
rc
==
0
)
&&
(
bytes_read
>=
8
))
{
mnr
=
le64_to_cpu
(
*
(
__le64
*
)(
pbuf
+
16
));
if
(
memcmp
(
"IntxBLK"
,
pbuf
,
8
)
==
0
)
{
fattr
->
cf_rdev
=
MKDEV
(
mjr
,
mnr
);
cifs_dbg
(
FYI
,
"Block device
\n
"
);
}
fattr
->
cf_mode
|=
S_IFBLK
;
}
else
if
(
memcmp
(
"IntxCHR"
,
pbuf
,
8
)
==
0
)
{
fattr
->
cf_dtype
=
DT_BLK
;
cifs_dbg
(
FYI
,
"Char device
\n
"
);
if
(
bytes_read
==
24
)
{
fattr
->
cf_mode
|=
S_IFCHR
;
/* we have enough to decode dev num */
fattr
->
cf_dtype
=
DT_CHR
;
__u64
mjr
;
/* major */
if
(
bytes_read
==
24
)
{
__u64
mnr
;
/* minor */
/* we have enough to decode dev num */
mjr
=
le64_to_cpu
(
*
(
__le64
*
)(
pbuf
+
8
));
__u64
mjr
;
/* major */
mnr
=
le64_to_cpu
(
*
(
__le64
*
)(
pbuf
+
16
));
__u64
mnr
;
/* minor */
fattr
->
cf_rdev
=
MKDEV
(
mjr
,
mnr
);
mjr
=
le64_to_cpu
(
*
(
__le64
*
)(
pbuf
+
8
));
}
mnr
=
le64_to_cpu
(
*
(
__le64
*
)(
pbuf
+
16
));
}
else
if
(
memcmp
(
"IntxCHR"
,
pbuf
,
8
)
==
0
)
{
fattr
->
cf_rdev
=
MKDEV
(
mjr
,
mnr
);
cifs_dbg
(
FYI
,
"Char device
\n
"
);
}
fattr
->
cf_mode
|=
S_IFCHR
;
}
else
if
(
memcmp
(
"IntxLNK"
,
pbuf
,
7
)
==
0
)
{
fattr
->
cf_dtype
=
DT_CHR
;
cifs_dbg
(
FYI
,
"Symlink
\n
"
);
if
(
bytes_read
==
24
)
{
fattr
->
cf_mode
|=
S_IFLNK
;
/* we have enough to decode dev num */
fattr
->
cf_dtype
=
DT_LNK
;
__u64
mjr
;
/* major */
}
else
{
__u64
mnr
;
/* minor */
fattr
->
cf_mode
|=
S_IFREG
;
/* file? */
mjr
=
le64_to_cpu
(
*
(
__le64
*
)(
pbuf
+
8
));
fattr
->
cf_dtype
=
DT_REG
;
mnr
=
le64_to_cpu
(
*
(
__le64
*
)(
pbuf
+
16
))
;
rc
=
-
EOPNOTSUPP
;
fattr
->
cf_rdev
=
MKDEV
(
mjr
,
mnr
)
;
}
}
}
else
if
(
memcmp
(
"IntxLNK"
,
pbuf
,
7
)
==
0
)
{
cifs_dbg
(
FYI
,
"Symlink
\n
"
);
fattr
->
cf_mode
|=
S_IFLNK
;
fattr
->
cf_dtype
=
DT_LNK
;
}
else
{
}
else
{
fattr
->
cf_mode
|=
S_IFREG
;
/*
then it is a file
*/
fattr
->
cf_mode
|=
S_IFREG
;
/*
file?
*/
fattr
->
cf_dtype
=
DT_REG
;
fattr
->
cf_dtype
=
DT_REG
;
rc
=
-
EOPNOTSUPP
;
/* or some unknown SFU type */
rc
=
-
EOPNOTSUPP
;
}
}
CIFSSMBClose
(
xid
,
tcon
,
netfid
);
}
else
{
fattr
->
cf_mode
|=
S_IFREG
;
/* then it is a file */
fattr
->
cf_dtype
=
DT_REG
;
rc
=
-
EOPNOTSUPP
;
/* or some unknown SFU type */
}
}
CIFSSMBClose
(
xid
,
tcon
,
fid
.
netfid
);
cifs_put_tlink
(
tlink
);
cifs_put_tlink
(
tlink
);
return
rc
;
return
rc
;
}
}
...
@@ -490,10 +533,15 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
...
@@ -490,10 +533,15 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
return
PTR_ERR
(
tlink
);
return
PTR_ERR
(
tlink
);
tcon
=
tlink_tcon
(
tlink
);
tcon
=
tlink_tcon
(
tlink
);
rc
=
CIFSSMBQAllEAs
(
xid
,
tcon
,
path
,
"SETFILEBITS"
,
if
(
tcon
->
ses
->
server
->
ops
->
query_all_EAs
==
NULL
)
{
ea_value
,
4
/* size of buf */
,
cifs_sb
->
local_nls
,
cifs_put_tlink
(
tlink
);
cifs_sb
->
mnt_cifs_flags
&
return
-
EOPNOTSUPP
;
CIFS_MOUNT_MAP_SPECIAL_CHR
);
}
rc
=
tcon
->
ses
->
server
->
ops
->
query_all_EAs
(
xid
,
tcon
,
path
,
"SETFILEBITS"
,
ea_value
,
4
/* size of buf */
,
cifs_sb
->
local_nls
,
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MAP_SPECIAL_CHR
);
cifs_put_tlink
(
tlink
);
cifs_put_tlink
(
tlink
);
if
(
rc
<
0
)
if
(
rc
<
0
)
return
(
int
)
rc
;
return
(
int
)
rc
;
...
@@ -515,7 +563,8 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
...
@@ -515,7 +563,8 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
static
void
static
void
cifs_all_info_to_fattr
(
struct
cifs_fattr
*
fattr
,
FILE_ALL_INFO
*
info
,
cifs_all_info_to_fattr
(
struct
cifs_fattr
*
fattr
,
FILE_ALL_INFO
*
info
,
struct
cifs_sb_info
*
cifs_sb
,
bool
adjust_tz
)
struct
cifs_sb_info
*
cifs_sb
,
bool
adjust_tz
,
bool
symlink
)
{
{
struct
cifs_tcon
*
tcon
=
cifs_sb_master_tcon
(
cifs_sb
);
struct
cifs_tcon
*
tcon
=
cifs_sb_master_tcon
(
cifs_sb
);
...
@@ -541,18 +590,20 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
...
@@ -541,18 +590,20 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
fattr
->
cf_bytes
=
le64_to_cpu
(
info
->
AllocationSize
);
fattr
->
cf_bytes
=
le64_to_cpu
(
info
->
AllocationSize
);
fattr
->
cf_createtime
=
le64_to_cpu
(
info
->
CreationTime
);
fattr
->
cf_createtime
=
le64_to_cpu
(
info
->
CreationTime
);
if
(
fattr
->
cf_cifsattrs
&
ATTR_DIRECTORY
)
{
fattr
->
cf_nlink
=
le32_to_cpu
(
info
->
NumberOfLinks
);
if
(
symlink
)
{
fattr
->
cf_mode
=
S_IFLNK
;
fattr
->
cf_dtype
=
DT_LNK
;
}
else
if
(
fattr
->
cf_cifsattrs
&
ATTR_DIRECTORY
)
{
fattr
->
cf_mode
=
S_IFDIR
|
cifs_sb
->
mnt_dir_mode
;
fattr
->
cf_mode
=
S_IFDIR
|
cifs_sb
->
mnt_dir_mode
;
fattr
->
cf_dtype
=
DT_DIR
;
fattr
->
cf_dtype
=
DT_DIR
;
/*
/*
* Server can return wrong NumberOfLinks value for directories
* Server can return wrong NumberOfLinks value for directories
* when Unix extensions are disabled - fake it.
* when Unix extensions are disabled - fake it.
*/
*/
fattr
->
cf_nlink
=
2
;
if
(
!
tcon
->
unix_ext
)
}
else
if
(
fattr
->
cf_cifsattrs
&
ATTR_REPARSE
)
{
fattr
->
cf_flags
|=
CIFS_FATTR_UNKNOWN_NLINK
;
fattr
->
cf_mode
=
S_IFLNK
;
fattr
->
cf_dtype
=
DT_LNK
;
fattr
->
cf_nlink
=
le32_to_cpu
(
info
->
NumberOfLinks
);
}
else
{
}
else
{
fattr
->
cf_mode
=
S_IFREG
|
cifs_sb
->
mnt_file_mode
;
fattr
->
cf_mode
=
S_IFREG
|
cifs_sb
->
mnt_file_mode
;
fattr
->
cf_dtype
=
DT_REG
;
fattr
->
cf_dtype
=
DT_REG
;
...
@@ -561,11 +612,15 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
...
@@ -561,11 +612,15 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
if
(
fattr
->
cf_cifsattrs
&
ATTR_READONLY
)
if
(
fattr
->
cf_cifsattrs
&
ATTR_READONLY
)
fattr
->
cf_mode
&=
~
(
S_IWUGO
);
fattr
->
cf_mode
&=
~
(
S_IWUGO
);
fattr
->
cf_nlink
=
le32_to_cpu
(
info
->
NumberOfLinks
);
/*
if
(
fattr
->
cf_nlink
<
1
)
{
* Don't accept zero nlink from non-unix servers unless
cifs_dbg
(
1
,
"replacing bogus file nlink value %u
\n
"
,
* delete is pending. Instead mark it as unknown.
*/
if
((
fattr
->
cf_nlink
<
1
)
&&
!
tcon
->
unix_ext
&&
!
info
->
DeletePending
)
{
cifs_dbg
(
1
,
"bogus file nlink value %u
\n
"
,
fattr
->
cf_nlink
);
fattr
->
cf_nlink
);
fattr
->
cf_
nlink
=
1
;
fattr
->
cf_
flags
|=
CIFS_FATTR_UNKNOWN_NLINK
;
}
}
}
}
...
@@ -593,7 +648,8 @@ cifs_get_file_info(struct file *filp)
...
@@ -593,7 +648,8 @@ cifs_get_file_info(struct file *filp)
rc
=
server
->
ops
->
query_file_info
(
xid
,
tcon
,
&
cfile
->
fid
,
&
find_data
);
rc
=
server
->
ops
->
query_file_info
(
xid
,
tcon
,
&
cfile
->
fid
,
&
find_data
);
switch
(
rc
)
{
switch
(
rc
)
{
case
0
:
case
0
:
cifs_all_info_to_fattr
(
&
fattr
,
&
find_data
,
cifs_sb
,
false
);
cifs_all_info_to_fattr
(
&
fattr
,
&
find_data
,
cifs_sb
,
false
,
false
);
break
;
break
;
case
-
EREMOTE
:
case
-
EREMOTE
:
cifs_create_dfs_fattr
(
&
fattr
,
inode
->
i_sb
);
cifs_create_dfs_fattr
(
&
fattr
,
inode
->
i_sb
);
...
@@ -627,7 +683,7 @@ cgfi_exit:
...
@@ -627,7 +683,7 @@ cgfi_exit:
int
int
cifs_get_inode_info
(
struct
inode
**
inode
,
const
char
*
full_path
,
cifs_get_inode_info
(
struct
inode
**
inode
,
const
char
*
full_path
,
FILE_ALL_INFO
*
data
,
struct
super_block
*
sb
,
int
xid
,
FILE_ALL_INFO
*
data
,
struct
super_block
*
sb
,
int
xid
,
const
__u16
*
fid
)
const
struct
cifs_fid
*
fid
)
{
{
bool
validinum
=
false
;
bool
validinum
=
false
;
__u16
srchflgs
;
__u16
srchflgs
;
...
@@ -640,6 +696,7 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
...
@@ -640,6 +696,7 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
bool
adjust_tz
=
false
;
bool
adjust_tz
=
false
;
struct
cifs_fattr
fattr
;
struct
cifs_fattr
fattr
;
struct
cifs_search_info
*
srchinf
=
NULL
;
struct
cifs_search_info
*
srchinf
=
NULL
;
bool
symlink
=
false
;
tlink
=
cifs_sb_tlink
(
cifs_sb
);
tlink
=
cifs_sb_tlink
(
cifs_sb
);
if
(
IS_ERR
(
tlink
))
if
(
IS_ERR
(
tlink
))
...
@@ -669,12 +726,12 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
...
@@ -669,12 +726,12 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
}
}
data
=
(
FILE_ALL_INFO
*
)
buf
;
data
=
(
FILE_ALL_INFO
*
)
buf
;
rc
=
server
->
ops
->
query_path_info
(
xid
,
tcon
,
cifs_sb
,
full_path
,
rc
=
server
->
ops
->
query_path_info
(
xid
,
tcon
,
cifs_sb
,
full_path
,
data
,
&
adjust_tz
);
data
,
&
adjust_tz
,
&
symlink
);
}
}
if
(
!
rc
)
{
if
(
!
rc
)
{
cifs_all_info_to_fattr
(
&
fattr
,
(
FILE_ALL_INFO
*
)
data
,
cifs_sb
,
cifs_all_info_to_fattr
(
&
fattr
,
data
,
cifs_sb
,
adjust_tz
,
adjust_tz
);
symlink
);
}
else
if
(
rc
==
-
EREMOTE
)
{
}
else
if
(
rc
==
-
EREMOTE
)
{
cifs_create_dfs_fattr
(
&
fattr
,
sb
);
cifs_create_dfs_fattr
(
&
fattr
,
sb
);
rc
=
0
;
rc
=
0
;
...
@@ -763,9 +820,10 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
...
@@ -763,9 +820,10 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
/* check for Minshall+French symlinks */
/* check for Minshall+French symlinks */
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MF_SYMLINKS
)
{
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MF_SYMLINKS
)
{
tmprc
=
CIFSCheckMFSymlink
(
&
fattr
,
full_path
,
cifs_sb
,
xid
);
tmprc
=
check_mf_symlink
(
xid
,
tcon
,
cifs_sb
,
&
fattr
,
full_path
);
if
(
tmprc
)
if
(
tmprc
)
cifs_dbg
(
FYI
,
"
CIFSCheckMFS
ymlink: %d
\n
"
,
tmprc
);
cifs_dbg
(
FYI
,
"
check_mf_s
ymlink: %d
\n
"
,
tmprc
);
}
}
if
(
!*
inode
)
{
if
(
!*
inode
)
{
...
@@ -994,7 +1052,8 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
...
@@ -994,7 +1052,8 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
{
{
int
oplock
=
0
;
int
oplock
=
0
;
int
rc
;
int
rc
;
__u16
netfid
;
struct
cifs_fid
fid
;
struct
cifs_open_parms
oparms
;
struct
inode
*
inode
=
dentry
->
d_inode
;
struct
inode
*
inode
=
dentry
->
d_inode
;
struct
cifsInodeInfo
*
cifsInode
=
CIFS_I
(
inode
);
struct
cifsInodeInfo
*
cifsInode
=
CIFS_I
(
inode
);
struct
cifs_sb_info
*
cifs_sb
=
CIFS_SB
(
inode
->
i_sb
);
struct
cifs_sb_info
*
cifs_sb
=
CIFS_SB
(
inode
->
i_sb
);
...
@@ -1017,10 +1076,17 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
...
@@ -1017,10 +1076,17 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
goto
out
;
goto
out
;
}
}
rc
=
CIFSSMBOpen
(
xid
,
tcon
,
full_path
,
FILE_OPEN
,
oparms
.
tcon
=
tcon
;
DELETE
|
FILE_WRITE_ATTRIBUTES
,
FILE_SHARE_ALL
,
CREATE_NOT_DIR
,
oparms
.
cifs_sb
=
cifs_sb
;
&
netfid
,
&
oplock
,
NULL
,
cifs_sb
->
local_nls
,
oparms
.
desired_access
=
DELETE
|
FILE_WRITE_ATTRIBUTES
;
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MAP_SPECIAL_CHR
);
oparms
.
share_access
=
FILE_SHARE_ALL
;
oparms
.
create_options
=
CREATE_NOT_DIR
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
path
=
full_path
;
oparms
.
fid
=
&
fid
;
oparms
.
reconnect
=
false
;
rc
=
CIFS_open
(
xid
,
&
oparms
,
&
oplock
,
NULL
);
if
(
rc
!=
0
)
if
(
rc
!=
0
)
goto
out
;
goto
out
;
...
@@ -1041,7 +1107,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
...
@@ -1041,7 +1107,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
goto
out_close
;
goto
out_close
;
}
}
info_buf
->
Attributes
=
cpu_to_le32
(
dosattr
);
info_buf
->
Attributes
=
cpu_to_le32
(
dosattr
);
rc
=
CIFSSMBSetFileInfo
(
xid
,
tcon
,
info_buf
,
netfid
,
rc
=
CIFSSMBSetFileInfo
(
xid
,
tcon
,
info_buf
,
fid
.
netfid
,
current
->
tgid
);
current
->
tgid
);
/* although we would like to mark the file hidden
/* although we would like to mark the file hidden
if that fails we will still try to rename it */
if that fails we will still try to rename it */
...
@@ -1052,7 +1118,8 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
...
@@ -1052,7 +1118,8 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
}
}
/* rename the file */
/* rename the file */
rc
=
CIFSSMBRenameOpenFile
(
xid
,
tcon
,
netfid
,
NULL
,
cifs_sb
->
local_nls
,
rc
=
CIFSSMBRenameOpenFile
(
xid
,
tcon
,
fid
.
netfid
,
NULL
,
cifs_sb
->
local_nls
,
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
)
{
...
@@ -1061,8 +1128,8 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
...
@@ -1061,8 +1128,8 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
}
}
/* try to set DELETE_ON_CLOSE */
/* try to set DELETE_ON_CLOSE */
if
(
!
cifsInode
->
delete_pending
)
{
if
(
!
test_bit
(
CIFS_INO_DELETE_PENDING
,
&
cifsInode
->
flags
)
)
{
rc
=
CIFSSMBSetFileDisposition
(
xid
,
tcon
,
true
,
netfid
,
rc
=
CIFSSMBSetFileDisposition
(
xid
,
tcon
,
true
,
fid
.
netfid
,
current
->
tgid
);
current
->
tgid
);
/*
/*
* some samba versions return -ENOENT when we try to set the
* some samba versions return -ENOENT when we try to set the
...
@@ -1078,11 +1145,11 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
...
@@ -1078,11 +1145,11 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
rc
=
-
ETXTBSY
;
rc
=
-
ETXTBSY
;
goto
undo_rename
;
goto
undo_rename
;
}
}
cifsInode
->
delete_pending
=
true
;
set_bit
(
CIFS_INO_DELETE_PENDING
,
&
cifsInode
->
flags
)
;
}
}
out_close:
out_close:
CIFSSMBClose
(
xid
,
tcon
,
netfid
);
CIFSSMBClose
(
xid
,
tcon
,
fid
.
netfid
);
out:
out:
kfree
(
info_buf
);
kfree
(
info_buf
);
cifs_put_tlink
(
tlink
);
cifs_put_tlink
(
tlink
);
...
@@ -1094,13 +1161,13 @@ out:
...
@@ -1094,13 +1161,13 @@ out:
* them anyway.
* them anyway.
*/
*/
undo_rename:
undo_rename:
CIFSSMBRenameOpenFile
(
xid
,
tcon
,
netfid
,
dentry
->
d_name
.
name
,
CIFSSMBRenameOpenFile
(
xid
,
tcon
,
fid
.
netfid
,
dentry
->
d_name
.
name
,
cifs_sb
->
local_nls
,
cifs_sb
->
mnt_cifs_flags
&
cifs_sb
->
local_nls
,
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MAP_SPECIAL_CHR
);
CIFS_MOUNT_MAP_SPECIAL_CHR
);
undo_setattr:
undo_setattr:
if
(
dosattr
!=
origattr
)
{
if
(
dosattr
!=
origattr
)
{
info_buf
->
Attributes
=
cpu_to_le32
(
origattr
);
info_buf
->
Attributes
=
cpu_to_le32
(
origattr
);
if
(
!
CIFSSMBSetFileInfo
(
xid
,
tcon
,
info_buf
,
netfid
,
if
(
!
CIFSSMBSetFileInfo
(
xid
,
tcon
,
info_buf
,
fid
.
netfid
,
current
->
tgid
))
current
->
tgid
))
cifsInode
->
cifsAttrs
=
origattr
;
cifsInode
->
cifsAttrs
=
origattr
;
}
}
...
@@ -1513,7 +1580,8 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
...
@@ -1513,7 +1580,8 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
struct
tcon_link
*
tlink
;
struct
tcon_link
*
tlink
;
struct
cifs_tcon
*
tcon
;
struct
cifs_tcon
*
tcon
;
struct
TCP_Server_Info
*
server
;
struct
TCP_Server_Info
*
server
;
__u16
srcfid
;
struct
cifs_fid
fid
;
struct
cifs_open_parms
oparms
;
int
oplock
,
rc
;
int
oplock
,
rc
;
tlink
=
cifs_sb_tlink
(
cifs_sb
);
tlink
=
cifs_sb_tlink
(
cifs_sb
);
...
@@ -1540,17 +1608,24 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
...
@@ -1540,17 +1608,24 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
if
(
to_dentry
->
d_parent
!=
from_dentry
->
d_parent
)
if
(
to_dentry
->
d_parent
!=
from_dentry
->
d_parent
)
goto
do_rename_exit
;
goto
do_rename_exit
;
oparms
.
tcon
=
tcon
;
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 */
rc
=
CIFSSMBOpen
(
xid
,
tcon
,
from_path
,
FILE_OPEN
,
DELETE
,
FILE_SHARE_ALL
,
oparms
.
desired_access
=
DELETE
;
CREATE_NOT_DIR
,
&
srcfid
,
&
oplock
,
NULL
,
oparms
.
share_access
=
FILE_SHARE_ALL
;
cifs_sb
->
local_nls
,
cifs_sb
->
mnt_cifs_flags
&
oparms
.
create_options
=
CREATE_NOT_DIR
;
CIFS_MOUNT_MAP_SPECIAL_CHR
);
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
path
=
from_path
;
oparms
.
fid
=
&
fid
;
oparms
.
reconnect
=
false
;
rc
=
CIFS_open
(
xid
,
&
oparms
,
&
oplock
,
NULL
);
if
(
rc
==
0
)
{
if
(
rc
==
0
)
{
rc
=
CIFSSMBRenameOpenFile
(
xid
,
tcon
,
src
fid
,
rc
=
CIFSSMBRenameOpenFile
(
xid
,
tcon
,
fid
.
net
fid
,
(
const
char
*
)
to_dentry
->
d_name
.
name
,
(
const
char
*
)
to_dentry
->
d_name
.
name
,
cifs_sb
->
local_nls
,
cifs_sb
->
mnt_cifs_flags
&
cifs_sb
->
local_nls
,
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MAP_SPECIAL_CHR
);
CIFS_MOUNT_MAP_SPECIAL_CHR
);
CIFSSMBClose
(
xid
,
tcon
,
src
fid
);
CIFSSMBClose
(
xid
,
tcon
,
fid
.
net
fid
);
}
}
do_rename_exit:
do_rename_exit:
cifs_put_tlink
(
tlink
);
cifs_put_tlink
(
tlink
);
...
@@ -1558,8 +1633,9 @@ do_rename_exit:
...
@@ -1558,8 +1633,9 @@ do_rename_exit:
}
}
int
int
cifs_rename
(
struct
inode
*
source_dir
,
struct
dentry
*
source_dentry
,
cifs_rename2
(
struct
inode
*
source_dir
,
struct
dentry
*
source_dentry
,
struct
inode
*
target_dir
,
struct
dentry
*
target_dentry
)
struct
inode
*
target_dir
,
struct
dentry
*
target_dentry
,
unsigned
int
flags
)
{
{
char
*
from_name
=
NULL
;
char
*
from_name
=
NULL
;
char
*
to_name
=
NULL
;
char
*
to_name
=
NULL
;
...
@@ -1571,6 +1647,9 @@ cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
...
@@ -1571,6 +1647,9 @@ cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
unsigned
int
xid
;
unsigned
int
xid
;
int
rc
,
tmprc
;
int
rc
,
tmprc
;
if
(
flags
&
~
RENAME_NOREPLACE
)
return
-
EINVAL
;
cifs_sb
=
CIFS_SB
(
source_dir
->
i_sb
);
cifs_sb
=
CIFS_SB
(
source_dir
->
i_sb
);
tlink
=
cifs_sb_tlink
(
cifs_sb
);
tlink
=
cifs_sb_tlink
(
cifs_sb
);
if
(
IS_ERR
(
tlink
))
if
(
IS_ERR
(
tlink
))
...
@@ -1598,6 +1677,12 @@ cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
...
@@ -1598,6 +1677,12 @@ cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
rc
=
cifs_do_rename
(
xid
,
source_dentry
,
from_name
,
target_dentry
,
rc
=
cifs_do_rename
(
xid
,
source_dentry
,
from_name
,
target_dentry
,
to_name
);
to_name
);
/*
* No-replace is the natural behavior for CIFS, so skip unlink hacks.
*/
if
(
flags
&
RENAME_NOREPLACE
)
goto
cifs_rename_exit
;
if
(
rc
==
-
EEXIST
&&
tcon
->
unix_ext
)
{
if
(
rc
==
-
EEXIST
&&
tcon
->
unix_ext
)
{
/*
/*
* Are src and dst hardlinks of same inode? We can only tell
* Are src and dst hardlinks of same inode? We can only tell
...
@@ -1672,6 +1757,9 @@ cifs_inode_needs_reval(struct inode *inode)
...
@@ -1672,6 +1757,9 @@ cifs_inode_needs_reval(struct inode *inode)
if
(
cifs_i
->
time
==
0
)
if
(
cifs_i
->
time
==
0
)
return
true
;
return
true
;
if
(
!
cifs_sb
->
actimeo
)
return
true
;
if
(
!
time_in_range
(
jiffies
,
cifs_i
->
time
,
if
(
!
time_in_range
(
jiffies
,
cifs_i
->
time
,
cifs_i
->
time
+
cifs_sb
->
actimeo
))
cifs_i
->
time
+
cifs_sb
->
actimeo
))
return
true
;
return
true
;
...
@@ -1691,23 +1779,62 @@ int
...
@@ -1691,23 +1779,62 @@ int
cifs_invalidate_mapping
(
struct
inode
*
inode
)
cifs_invalidate_mapping
(
struct
inode
*
inode
)
{
{
int
rc
=
0
;
int
rc
=
0
;
struct
cifsInodeInfo
*
cifs_i
=
CIFS_I
(
inode
);
cifs_i
->
invalid_mapping
=
false
;
if
(
inode
->
i_mapping
&&
inode
->
i_mapping
->
nrpages
!=
0
)
{
if
(
inode
->
i_mapping
&&
inode
->
i_mapping
->
nrpages
!=
0
)
{
rc
=
invalidate_inode_pages2
(
inode
->
i_mapping
);
rc
=
invalidate_inode_pages2
(
inode
->
i_mapping
);
if
(
rc
)
{
if
(
rc
)
cifs_dbg
(
VFS
,
"%s: could not invalidate inode %p
\n
"
,
cifs_dbg
(
VFS
,
"%s: could not invalidate inode %p
\n
"
,
__func__
,
inode
);
__func__
,
inode
);
cifs_i
->
invalid_mapping
=
true
;
}
}
}
cifs_fscache_reset_inode_cookie
(
inode
);
cifs_fscache_reset_inode_cookie
(
inode
);
return
rc
;
return
rc
;
}
}
/**
* cifs_wait_bit_killable - helper for functions that are sleeping on bit locks
* @word: long word containing the bit lock
*/
static
int
cifs_wait_bit_killable
(
void
*
word
)
{
if
(
fatal_signal_pending
(
current
))
return
-
ERESTARTSYS
;
freezable_schedule_unsafe
();
return
0
;
}
int
cifs_revalidate_mapping
(
struct
inode
*
inode
)
{
int
rc
;
unsigned
long
*
flags
=
&
CIFS_I
(
inode
)
->
flags
;
rc
=
wait_on_bit_lock
(
flags
,
CIFS_INO_LOCK
,
cifs_wait_bit_killable
,
TASK_KILLABLE
);
if
(
rc
)
return
rc
;
if
(
test_and_clear_bit
(
CIFS_INO_INVALID_MAPPING
,
flags
))
{
rc
=
cifs_invalidate_mapping
(
inode
);
if
(
rc
)
set_bit
(
CIFS_INO_INVALID_MAPPING
,
flags
);
}
clear_bit_unlock
(
CIFS_INO_LOCK
,
flags
);
smp_mb__after_clear_bit
();
wake_up_bit
(
flags
,
CIFS_INO_LOCK
);
return
rc
;
}
int
cifs_zap_mapping
(
struct
inode
*
inode
)
{
set_bit
(
CIFS_INO_INVALID_MAPPING
,
&
CIFS_I
(
inode
)
->
flags
);
return
cifs_revalidate_mapping
(
inode
);
}
int
cifs_revalidate_file_attr
(
struct
file
*
filp
)
int
cifs_revalidate_file_attr
(
struct
file
*
filp
)
{
{
int
rc
=
0
;
int
rc
=
0
;
...
@@ -1774,9 +1901,7 @@ int cifs_revalidate_file(struct file *filp)
...
@@ -1774,9 +1901,7 @@ int cifs_revalidate_file(struct file *filp)
if
(
rc
)
if
(
rc
)
return
rc
;
return
rc
;
if
(
CIFS_I
(
inode
)
->
invalid_mapping
)
return
cifs_revalidate_mapping
(
inode
);
rc
=
cifs_invalidate_mapping
(
inode
);
return
rc
;
}
}
/* revalidate a dentry's inode attributes */
/* revalidate a dentry's inode attributes */
...
@@ -1789,9 +1914,7 @@ int cifs_revalidate_dentry(struct dentry *dentry)
...
@@ -1789,9 +1914,7 @@ int cifs_revalidate_dentry(struct dentry *dentry)
if
(
rc
)
if
(
rc
)
return
rc
;
return
rc
;
if
(
CIFS_I
(
inode
)
->
invalid_mapping
)
return
cifs_revalidate_mapping
(
inode
);
rc
=
cifs_invalidate_mapping
(
inode
);
return
rc
;
}
}
int
cifs_getattr
(
struct
vfsmount
*
mnt
,
struct
dentry
*
dentry
,
int
cifs_getattr
(
struct
vfsmount
*
mnt
,
struct
dentry
*
dentry
,
...
@@ -1858,14 +1981,11 @@ static int cifs_truncate_page(struct address_space *mapping, loff_t from)
...
@@ -1858,14 +1981,11 @@ static int cifs_truncate_page(struct address_space *mapping, loff_t from)
static
void
cifs_setsize
(
struct
inode
*
inode
,
loff_t
offset
)
static
void
cifs_setsize
(
struct
inode
*
inode
,
loff_t
offset
)
{
{
loff_t
oldsize
;
spin_lock
(
&
inode
->
i_lock
);
spin_lock
(
&
inode
->
i_lock
);
oldsize
=
inode
->
i_size
;
i_size_write
(
inode
,
offset
);
i_size_write
(
inode
,
offset
);
spin_unlock
(
&
inode
->
i_lock
);
spin_unlock
(
&
inode
->
i_lock
);
truncate_pagecache
(
inode
,
o
ldsize
,
o
ffset
);
truncate_pagecache
(
inode
,
offset
);
}
}
static
int
static
int
...
...
sources/centos70/ioctl.c
View file @
9d798057
...
@@ -3,7 +3,7 @@
...
@@ -3,7 +3,7 @@
*
*
* vfs operations that deal with io control
* vfs operations that deal with io control
*
*
* Copyright (C) International Business Machines Corp., 2005,20
07
* Copyright (C) International Business Machines Corp., 2005,20
13
* Author(s): Steve French (sfrench@us.ibm.com)
* Author(s): Steve French (sfrench@us.ibm.com)
*
*
* This library is free software; you can redistribute it and/or modify
* This library is free software; you can redistribute it and/or modify
...
@@ -22,25 +22,121 @@
...
@@ -22,25 +22,121 @@
*/
*/
#include <linux/fs.h>
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/mount.h>
#include <linux/mm.h>
#include <linux/pagemap.h>
#include "cifspdu.h"
#include "cifspdu.h"
#include "cifsglob.h"
#include "cifsglob.h"
#include "cifsproto.h"
#include "cifsproto.h"
#include "cifs_debug.h"
#include "cifs_debug.h"
#include "cifsfs.h"
#include "cifsfs.h"
#define CIFS_IOCTL_MAGIC 0xCF
#define CIFS_IOC_COPYCHUNK_FILE _IOW(CIFS_IOCTL_MAGIC, 3, int)
static
long
cifs_ioctl_clone
(
unsigned
int
xid
,
struct
file
*
dst_file
,
unsigned
long
srcfd
,
u64
off
,
u64
len
,
u64
destoff
)
{
int
rc
;
struct
cifsFileInfo
*
smb_file_target
=
dst_file
->
private_data
;
struct
inode
*
target_inode
=
file_inode
(
dst_file
);
struct
cifs_tcon
*
target_tcon
;
struct
fd
src_file
;
struct
cifsFileInfo
*
smb_file_src
;
struct
inode
*
src_inode
;
struct
cifs_tcon
*
src_tcon
;
cifs_dbg
(
FYI
,
"ioctl clone range
\n
"
);
/* the destination must be opened for writing */
if
(
!
(
dst_file
->
f_mode
&
FMODE_WRITE
))
{
cifs_dbg
(
FYI
,
"file target not open for write
\n
"
);
return
-
EINVAL
;
}
/* check if target volume is readonly and take reference */
rc
=
mnt_want_write_file
(
dst_file
);
if
(
rc
)
{
cifs_dbg
(
FYI
,
"mnt_want_write failed with rc %d
\n
"
,
rc
);
return
rc
;
}
src_file
=
fdget
(
srcfd
);
if
(
!
src_file
.
file
)
{
rc
=
-
EBADF
;
goto
out_drop_write
;
}
if
((
!
src_file
.
file
->
private_data
)
||
(
!
dst_file
->
private_data
))
{
rc
=
-
EBADF
;
cifs_dbg
(
VFS
,
"missing cifsFileInfo on copy range src file
\n
"
);
goto
out_fput
;
}
rc
=
-
EXDEV
;
smb_file_target
=
dst_file
->
private_data
;
smb_file_src
=
src_file
.
file
->
private_data
;
src_tcon
=
tlink_tcon
(
smb_file_src
->
tlink
);
target_tcon
=
tlink_tcon
(
smb_file_target
->
tlink
);
/* check if source and target are on same tree connection */
if
(
src_tcon
!=
target_tcon
)
{
cifs_dbg
(
VFS
,
"file copy src and target on different volume
\n
"
);
goto
out_fput
;
}
src_inode
=
file_inode
(
src_file
.
file
);
rc
=
-
EINVAL
;
if
(
S_ISDIR
(
src_inode
->
i_mode
))
goto
out_fput
;
/*
* Note: cifs case is easier than btrfs since server responsible for
* checks for proper open modes and file type and if it wants
* server could even support copy of range where source = target
*/
lock_two_nondirectories
(
target_inode
,
src_inode
);
/* determine range to clone */
rc
=
-
EINVAL
;
if
(
off
+
len
>
src_inode
->
i_size
||
off
+
len
<
off
)
goto
out_unlock
;
if
(
len
==
0
)
len
=
src_inode
->
i_size
-
off
;
cifs_dbg
(
FYI
,
"about to flush pages
\n
"
);
/* should we flush first and last page first */
truncate_inode_pages_range
(
&
target_inode
->
i_data
,
destoff
,
PAGE_CACHE_ALIGN
(
destoff
+
len
)
-
1
);
if
(
target_tcon
->
ses
->
server
->
ops
->
clone_range
)
rc
=
target_tcon
->
ses
->
server
->
ops
->
clone_range
(
xid
,
smb_file_src
,
smb_file_target
,
off
,
len
,
destoff
);
/* force revalidate of size and timestamps of target file now
that target is updated on the server */
CIFS_I
(
target_inode
)
->
time
=
0
;
out_unlock:
/* although unlocking in the reverse order from locking is not
strictly necessary here it is a little cleaner to be consistent */
unlock_two_nondirectories
(
src_inode
,
target_inode
);
out_fput:
fdput
(
src_file
);
out_drop_write:
mnt_drop_write_file
(
dst_file
);
return
rc
;
}
long
cifs_ioctl
(
struct
file
*
filep
,
unsigned
int
command
,
unsigned
long
arg
)
long
cifs_ioctl
(
struct
file
*
filep
,
unsigned
int
command
,
unsigned
long
arg
)
{
{
struct
inode
*
inode
=
file_inode
(
filep
);
struct
inode
*
inode
=
file_inode
(
filep
);
int
rc
=
-
ENOTTY
;
/* strange error - but the precedent */
int
rc
=
-
ENOTTY
;
/* strange error - but the precedent */
unsigned
int
xid
;
unsigned
int
xid
;
struct
cifs_sb_info
*
cifs_sb
;
struct
cifs_sb_info
*
cifs_sb
;
#ifdef CONFIG_CIFS_POSIX
struct
cifsFileInfo
*
pSMBFile
=
filep
->
private_data
;
struct
cifsFileInfo
*
pSMBFile
=
filep
->
private_data
;
struct
cifs_tcon
*
tcon
;
struct
cifs_tcon
*
tcon
;
__u64
ExtAttrBits
=
0
;
__u64
ExtAttrBits
=
0
;
__u64
ExtAttrMask
=
0
;
__u64
caps
;
__u64
caps
;
#endif
/* CONFIG_CIFS_POSIX */
xid
=
get_xid
();
xid
=
get_xid
();
...
@@ -49,13 +145,14 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
...
@@ -49,13 +145,14 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
cifs_sb
=
CIFS_SB
(
inode
->
i_sb
);
cifs_sb
=
CIFS_SB
(
inode
->
i_sb
);
switch
(
command
)
{
switch
(
command
)
{
#ifdef CONFIG_CIFS_POSIX
case
FS_IOC_GETFLAGS
:
case
FS_IOC_GETFLAGS
:
if
(
pSMBFile
==
NULL
)
if
(
pSMBFile
==
NULL
)
break
;
break
;
tcon
=
tlink_tcon
(
pSMBFile
->
tlink
);
tcon
=
tlink_tcon
(
pSMBFile
->
tlink
);
caps
=
le64_to_cpu
(
tcon
->
fsUnixInfo
.
Capability
);
caps
=
le64_to_cpu
(
tcon
->
fsUnixInfo
.
Capability
);
#ifdef CONFIG_CIFS_POSIX
if
(
CIFS_UNIX_EXTATTR_CAP
&
caps
)
{
if
(
CIFS_UNIX_EXTATTR_CAP
&
caps
)
{
__u64
ExtAttrMask
=
0
;
rc
=
CIFSGetExtAttr
(
xid
,
tcon
,
rc
=
CIFSGetExtAttr
(
xid
,
tcon
,
pSMBFile
->
fid
.
netfid
,
pSMBFile
->
fid
.
netfid
,
&
ExtAttrBits
,
&
ExtAttrMask
);
&
ExtAttrBits
,
&
ExtAttrMask
);
...
@@ -63,29 +160,53 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
...
@@ -63,29 +160,53 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
rc
=
put_user
(
ExtAttrBits
&
rc
=
put_user
(
ExtAttrBits
&
FS_FL_USER_VISIBLE
,
FS_FL_USER_VISIBLE
,
(
int
__user
*
)
arg
);
(
int
__user
*
)
arg
);
if
(
rc
!=
EOPNOTSUPP
)
break
;
}
#endif
/* CONFIG_CIFS_POSIX */
rc
=
0
;
if
(
CIFS_I
(
inode
)
->
cifsAttrs
&
ATTR_COMPRESSED
)
{
/* add in the compressed bit */
ExtAttrBits
=
FS_COMPR_FL
;
rc
=
put_user
(
ExtAttrBits
&
FS_FL_USER_VISIBLE
,
(
int
__user
*
)
arg
);
}
}
break
;
break
;
case
FS_IOC_SETFLAGS
:
case
FS_IOC_SETFLAGS
:
if
(
pSMBFile
==
NULL
)
if
(
pSMBFile
==
NULL
)
break
;
break
;
tcon
=
tlink_tcon
(
pSMBFile
->
tlink
);
tcon
=
tlink_tcon
(
pSMBFile
->
tlink
);
caps
=
le64_to_cpu
(
tcon
->
fsUnixInfo
.
Capability
);
caps
=
le64_to_cpu
(
tcon
->
fsUnixInfo
.
Capability
);
if
(
CIFS_UNIX_EXTATTR_CAP
&
caps
)
{
if
(
get_user
(
ExtAttrBits
,
(
int
__user
*
)
arg
))
{
if
(
get_user
(
ExtAttrBits
,
(
int
__user
*
)
arg
))
{
rc
=
-
EFAULT
;
rc
=
-
EFAULT
;
break
;
break
;
}
}
/*
* rc = CIFSGetExtAttr(xid, tcon,
/*
* pSMBFile->fid.netfid,
* if (CIFS_UNIX_EXTATTR_CAP & caps)
* extAttrBits,
* rc = CIFSSetExtAttr(xid, tcon,
* &ExtAttrMask);
* pSMBFile->fid.netfid,
*/
* extAttrBits,
* &ExtAttrMask);
* if (rc != EOPNOTSUPP)
* break;
*/
/* Currently only flag we can set is compressed flag */
if
((
ExtAttrBits
&
FS_COMPR_FL
)
==
0
)
break
;
/* Try to set compress flag */
if
(
tcon
->
ses
->
server
->
ops
->
set_compression
)
{
rc
=
tcon
->
ses
->
server
->
ops
->
set_compression
(
xid
,
tcon
,
pSMBFile
);
cifs_dbg
(
FYI
,
"set compress flag rc %d
\n
"
,
rc
);
}
}
cifs_dbg
(
FYI
,
"set flags not implemented yet
\n
"
);
break
;
break
;
#endif
/* CONFIG_CIFS_POSIX */
case
CIFS_IOC_COPYCHUNK_FILE
:
rc
=
cifs_ioctl_clone
(
xid
,
filep
,
arg
,
0
,
0
,
0
);
break
;
default:
default:
cifs_dbg
(
FYI
,
"unsupported ioctl
\n
"
);
cifs_dbg
(
FYI
,
"unsupported ioctl
\n
"
);
break
;
break
;
...
...
sources/centos70/link.c
View file @
9d798057
...
@@ -29,6 +29,10 @@
...
@@ -29,6 +29,10 @@
#include "cifs_debug.h"
#include "cifs_debug.h"
#include "cifs_fs_sb.h"
#include "cifs_fs_sb.h"
/*
* M-F Symlink Functions - Begin
*/
#define CIFS_MF_SYMLINK_LEN_OFFSET (4+1)
#define CIFS_MF_SYMLINK_LEN_OFFSET (4+1)
#define CIFS_MF_SYMLINK_MD5_OFFSET (CIFS_MF_SYMLINK_LEN_OFFSET+(4+1))
#define CIFS_MF_SYMLINK_MD5_OFFSET (CIFS_MF_SYMLINK_LEN_OFFSET+(4+1))
#define CIFS_MF_SYMLINK_LINK_OFFSET (CIFS_MF_SYMLINK_MD5_OFFSET+(32+1))
#define CIFS_MF_SYMLINK_LINK_OFFSET (CIFS_MF_SYMLINK_MD5_OFFSET+(32+1))
...
@@ -91,10 +95,8 @@ symlink_hash_err:
...
@@ -91,10 +95,8 @@ symlink_hash_err:
}
}
static
int
static
int
CIFSParseMFSymlink
(
const
u8
*
buf
,
parse_mf_symlink
(
const
u8
*
buf
,
unsigned
int
buf_len
,
unsigned
int
*
_link_len
,
unsigned
int
buf_len
,
char
**
_link_str
)
unsigned
int
*
_link_len
,
char
**
_link_str
)
{
{
int
rc
;
int
rc
;
unsigned
int
link_len
;
unsigned
int
link_len
;
...
@@ -137,7 +139,7 @@ CIFSParseMFSymlink(const u8 *buf,
...
@@ -137,7 +139,7 @@ CIFSParseMFSymlink(const u8 *buf,
}
}
static
int
static
int
CIFSFormatMFS
ymlink
(
u8
*
buf
,
unsigned
int
buf_len
,
const
char
*
link_str
)
format_mf_s
ymlink
(
u8
*
buf
,
unsigned
int
buf_len
,
const
char
*
link_str
)
{
{
int
rc
;
int
rc
;
unsigned
int
link_len
;
unsigned
int
link_len
;
...
@@ -180,214 +182,118 @@ CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str)
...
@@ -180,214 +182,118 @@ CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str)
return
0
;
return
0
;
}
}
bool
couldbe_mf_symlink
(
const
struct
cifs_fattr
*
fattr
)
{
if
(
!
S_ISREG
(
fattr
->
cf_mode
))
/* it's not a symlink */
return
false
;
if
(
fattr
->
cf_eof
!=
CIFS_MF_SYMLINK_FILE_SIZE
)
/* it's not a symlink */
return
false
;
return
true
;
}
static
int
static
int
CIFSCreateMFSymL
ink
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
create_mf_syml
ink
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
const
char
*
fromName
,
const
char
*
to
Name
,
struct
cifs_sb_info
*
cifs_sb
,
const
char
*
from
Name
,
struct
cifs_sb_info
*
cifs_sb
)
const
char
*
toName
)
{
{
int
rc
;
int
rc
;
int
oplock
=
0
;
int
remap
;
int
create_options
=
CREATE_NOT_DIR
;
__u16
netfid
=
0
;
u8
*
buf
;
u8
*
buf
;
unsigned
int
bytes_written
=
0
;
unsigned
int
bytes_written
=
0
;
struct
cifs_io_parms
io_parms
;
struct
nls_table
*
nls_codepage
;
nls_codepage
=
cifs_sb
->
local_nls
;
remap
=
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MAP_SPECIAL_CHR
;
buf
=
kmalloc
(
CIFS_MF_SYMLINK_FILE_SIZE
,
GFP_KERNEL
);
buf
=
kmalloc
(
CIFS_MF_SYMLINK_FILE_SIZE
,
GFP_KERNEL
);
if
(
!
buf
)
if
(
!
buf
)
return
-
ENOMEM
;
return
-
ENOMEM
;
rc
=
CIFSFormatMFSymlink
(
buf
,
CIFS_MF_SYMLINK_FILE_SIZE
,
toName
);
rc
=
format_mf_symlink
(
buf
,
CIFS_MF_SYMLINK_FILE_SIZE
,
toName
);
if
(
rc
!=
0
)
{
if
(
rc
)
kfree
(
buf
);
goto
out
;
return
rc
;
}
if
(
backup_cred
(
cifs_sb
))
create_options
|=
CREATE_OPEN_BACKUP_INTENT
;
rc
=
CIFSSMBOpen
(
xid
,
tcon
,
fromName
,
FILE_CREATE
,
GENERIC_WRITE
,
FILE_SHARE_ALL
,
create_options
,
&
netfid
,
&
oplock
,
NULL
,
nls_codepage
,
remap
);
if
(
rc
!=
0
)
{
kfree
(
buf
);
return
rc
;
}
i
o_parms
.
netfid
=
netfid
;
i
f
(
tcon
->
ses
->
server
->
ops
->
create_mf_symlink
)
io_parms
.
pid
=
current
->
tgid
;
rc
=
tcon
->
ses
->
server
->
ops
->
create_mf_symlink
(
xid
,
tcon
,
io_parms
.
tcon
=
tcon
;
cifs_sb
,
fromName
,
buf
,
&
bytes_written
)
;
io_parms
.
offset
=
0
;
else
io_parms
.
length
=
CIFS_MF_SYMLINK_FILE_SIZE
;
rc
=
-
EOPNOTSUPP
;
rc
=
CIFSSMBWrite
(
xid
,
&
io_parms
,
&
bytes_written
,
buf
,
NULL
,
0
);
if
(
rc
)
CIFSSMBClose
(
xid
,
tcon
,
netfid
);
goto
out
;
kfree
(
buf
);
if
(
rc
!=
0
)
return
rc
;
if
(
bytes_written
!=
CIFS_MF_SYMLINK_FILE_SIZE
)
if
(
bytes_written
!=
CIFS_MF_SYMLINK_FILE_SIZE
)
return
-
EIO
;
rc
=
-
EIO
;
out:
return
0
;
kfree
(
buf
);
return
rc
;
}
}
static
int
static
int
CIFSQueryMFSymL
ink
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
query_mf_syml
ink
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
const
unsigned
char
*
searchName
,
char
**
symlinkinfo
,
struct
cifs_sb_info
*
cifs_sb
,
const
unsigned
char
*
path
,
const
struct
nls_table
*
nls_codepage
,
int
remap
)
char
**
symlinkinfo
)
{
{
int
rc
;
int
rc
;
int
oplock
=
0
;
u8
*
buf
=
NULL
;
__u16
netfid
=
0
;
u8
*
buf
;
char
*
pbuf
;
unsigned
int
bytes_read
=
0
;
int
buf_type
=
CIFS_NO_BUFFER
;
unsigned
int
link_len
=
0
;
unsigned
int
link_len
=
0
;
struct
cifs_io_parms
io_parms
;
unsigned
int
bytes_read
=
0
;
FILE_ALL_INFO
file_info
;
rc
=
CIFSSMBOpen
(
xid
,
tcon
,
searchName
,
FILE_OPEN
,
GENERIC_READ
,
FILE_SHARE_ALL
,
CREATE_NOT_DIR
,
&
netfid
,
&
oplock
,
&
file_info
,
nls_codepage
,
remap
);
if
(
rc
!=
0
)
return
rc
;
if
(
file_info
.
EndOfFile
!=
cpu_to_le64
(
CIFS_MF_SYMLINK_FILE_SIZE
))
{
CIFSSMBClose
(
xid
,
tcon
,
netfid
);
/* it's not a symlink */
return
-
EINVAL
;
}
buf
=
kmalloc
(
CIFS_MF_SYMLINK_FILE_SIZE
,
GFP_KERNEL
);
buf
=
kmalloc
(
CIFS_MF_SYMLINK_FILE_SIZE
,
GFP_KERNEL
);
if
(
!
buf
)
if
(
!
buf
)
return
-
ENOMEM
;
return
-
ENOMEM
;
pbuf
=
buf
;
io_parms
.
netfid
=
netfid
;
io_parms
.
pid
=
current
->
tgid
;
io_parms
.
tcon
=
tcon
;
io_parms
.
offset
=
0
;
io_parms
.
length
=
CIFS_MF_SYMLINK_FILE_SIZE
;
rc
=
CIFSSMBRead
(
xid
,
&
io_parms
,
&
bytes_read
,
&
pbuf
,
&
buf_type
);
CIFSSMBClose
(
xid
,
tcon
,
netfid
);
if
(
rc
!=
0
)
{
kfree
(
buf
);
return
rc
;
}
rc
=
CIFSParseMFSymlink
(
buf
,
bytes_read
,
&
link_len
,
symlinkinfo
);
kfree
(
buf
);
if
(
rc
!=
0
)
return
rc
;
return
0
;
}
bool
if
(
tcon
->
ses
->
server
->
ops
->
query_mf_symlink
)
CIFSCouldBeMFSymlink
(
const
struct
cifs_fattr
*
fattr
)
rc
=
tcon
->
ses
->
server
->
ops
->
query_mf_symlink
(
xid
,
tcon
,
{
cifs_sb
,
path
,
buf
,
&
bytes_read
);
if
(
!
(
fattr
->
cf_mode
&
S_IFREG
))
else
/* it's not a symlink */
rc
=
-
ENOSYS
;
return
false
;
if
(
fattr
->
cf_eof
!=
CIFS_MF_SYMLINK_FILE_SIZE
)
/* it's not a symlink */
return
false
;
return
true
;
}
int
open_query_close_cifs_symlink
(
const
unsigned
char
*
path
,
char
*
pbuf
,
unsigned
int
*
pbytes_read
,
struct
cifs_sb_info
*
cifs_sb
,
unsigned
int
xid
)
{
int
rc
;
int
oplock
=
0
;
__u16
netfid
=
0
;
struct
tcon_link
*
tlink
;
struct
cifs_tcon
*
ptcon
;
struct
cifs_io_parms
io_parms
;
int
buf_type
=
CIFS_NO_BUFFER
;
FILE_ALL_INFO
file_info
;
tlink
=
cifs_sb_tlink
(
cifs_sb
);
if
(
IS_ERR
(
tlink
))
return
PTR_ERR
(
tlink
);
ptcon
=
tlink_tcon
(
tlink
);
rc
=
CIFSSMBOpen
(
xid
,
ptcon
,
path
,
FILE_OPEN
,
GENERIC_READ
,
if
(
rc
)
FILE_SHARE_ALL
,
CREATE_NOT_DIR
,
&
netfid
,
&
oplock
,
goto
out
;
&
file_info
,
cifs_sb
->
local_nls
,
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MAP_SPECIAL_CHR
);
if
(
rc
!=
0
)
{
cifs_put_tlink
(
tlink
);
return
rc
;
}
if
(
file_info
.
EndOfFile
!=
cpu_to_le64
(
CIFS_MF_SYMLINK_FILE_SIZE
))
{
if
(
bytes_read
==
0
)
{
/* not a symlink */
CIFSSMBClose
(
xid
,
ptcon
,
netfid
);
rc
=
-
EINVAL
;
cifs_put_tlink
(
tlink
);
goto
out
;
/* it's not a symlink */
return
rc
;
}
}
io_parms
.
netfid
=
netfid
;
rc
=
parse_mf_symlink
(
buf
,
bytes_read
,
&
link_len
,
symlinkinfo
);
io_parms
.
pid
=
current
->
tgid
;
out:
io_parms
.
tcon
=
ptcon
;
kfree
(
buf
);
io_parms
.
offset
=
0
;
io_parms
.
length
=
CIFS_MF_SYMLINK_FILE_SIZE
;
rc
=
CIFSSMBRead
(
xid
,
&
io_parms
,
pbytes_read
,
&
pbuf
,
&
buf_type
);
CIFSSMBClose
(
xid
,
ptcon
,
netfid
);
cifs_put_tlink
(
tlink
);
return
rc
;
return
rc
;
}
}
int
int
CIFSCheckMFSymlink
(
struct
cifs_fattr
*
fattr
,
check_mf_symlink
(
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
const
unsigned
char
*
path
,
struct
cifs_sb_info
*
cifs_sb
,
struct
cifs_fattr
*
fattr
,
struct
cifs_sb_info
*
cifs_sb
,
unsigned
int
xid
)
const
unsigned
char
*
path
)
{
{
int
rc
=
0
;
int
rc
;
u8
*
buf
=
NULL
;
u8
*
buf
=
NULL
;
unsigned
int
link_len
=
0
;
unsigned
int
link_len
=
0
;
unsigned
int
bytes_read
=
0
;
unsigned
int
bytes_read
=
0
;
struct
cifs_tcon
*
ptcon
;
if
(
!
CIFSCouldBeMFS
ymlink
(
fattr
))
if
(
!
couldbe_mf_s
ymlink
(
fattr
))
/* it's not a symlink */
/* it's not a symlink */
return
0
;
return
0
;
buf
=
kmalloc
(
CIFS_MF_SYMLINK_FILE_SIZE
,
GFP_KERNEL
);
buf
=
kmalloc
(
CIFS_MF_SYMLINK_FILE_SIZE
,
GFP_KERNEL
);
if
(
!
buf
)
{
if
(
!
buf
)
rc
=
-
ENOMEM
;
return
-
ENOMEM
;
goto
out
;
}
ptcon
=
tlink_tcon
(
cifs_sb_tlink
(
cifs_sb
));
if
(
tcon
->
ses
->
server
->
ops
->
query_mf_symlink
)
if
((
ptcon
->
ses
)
&&
(
ptcon
->
ses
->
server
->
ops
->
query_mf_symlink
))
rc
=
tcon
->
ses
->
server
->
ops
->
query_mf_symlink
(
xid
,
tcon
,
rc
=
ptcon
->
ses
->
server
->
ops
->
query_mf_symlink
(
path
,
buf
,
cifs_sb
,
path
,
buf
,
&
bytes_read
);
&
bytes_read
,
cifs_sb
,
xid
);
else
else
goto
out
;
rc
=
-
ENOSYS
;
if
(
rc
!=
0
)
if
(
rc
)
goto
out
;
goto
out
;
if
(
bytes_read
==
0
)
/* not a symlink */
if
(
bytes_read
==
0
)
/* not a symlink */
goto
out
;
goto
out
;
rc
=
CIFSParseMFS
ymlink
(
buf
,
bytes_read
,
&
link_len
,
NULL
);
rc
=
parse_mf_s
ymlink
(
buf
,
bytes_read
,
&
link_len
,
NULL
);
if
(
rc
==
-
EINVAL
)
{
if
(
rc
==
-
EINVAL
)
{
/* it's not a symlink */
/* it's not a symlink */
rc
=
0
;
rc
=
0
;
...
@@ -407,6 +313,97 @@ out:
...
@@ -407,6 +313,97 @@ out:
return
rc
;
return
rc
;
}
}
/*
* SMB 1.0 Protocol specific functions
*/
int
cifs_query_mf_symlink
(
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
struct
cifs_sb_info
*
cifs_sb
,
const
unsigned
char
*
path
,
char
*
pbuf
,
unsigned
int
*
pbytes_read
)
{
int
rc
;
int
oplock
=
0
;
struct
cifs_fid
fid
;
struct
cifs_open_parms
oparms
;
struct
cifs_io_parms
io_parms
;
int
buf_type
=
CIFS_NO_BUFFER
;
FILE_ALL_INFO
file_info
;
oparms
.
tcon
=
tcon
;
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
desired_access
=
GENERIC_READ
;
oparms
.
share_access
=
FILE_SHARE_ALL
;
oparms
.
create_options
=
CREATE_NOT_DIR
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
path
=
path
;
oparms
.
fid
=
&
fid
;
oparms
.
reconnect
=
false
;
rc
=
CIFS_open
(
xid
,
&
oparms
,
&
oplock
,
&
file_info
);
if
(
rc
)
return
rc
;
if
(
file_info
.
EndOfFile
!=
cpu_to_le64
(
CIFS_MF_SYMLINK_FILE_SIZE
))
/* it's not a symlink */
goto
out
;
io_parms
.
netfid
=
fid
.
netfid
;
io_parms
.
pid
=
current
->
tgid
;
io_parms
.
tcon
=
tcon
;
io_parms
.
offset
=
0
;
io_parms
.
length
=
CIFS_MF_SYMLINK_FILE_SIZE
;
rc
=
CIFSSMBRead
(
xid
,
&
io_parms
,
pbytes_read
,
&
pbuf
,
&
buf_type
);
out:
CIFSSMBClose
(
xid
,
tcon
,
fid
.
netfid
);
return
rc
;
}
int
cifs_create_mf_symlink
(
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
struct
cifs_sb_info
*
cifs_sb
,
const
unsigned
char
*
path
,
char
*
pbuf
,
unsigned
int
*
pbytes_written
)
{
int
rc
;
int
oplock
=
0
;
struct
cifs_fid
fid
;
struct
cifs_open_parms
oparms
;
struct
cifs_io_parms
io_parms
;
int
create_options
=
CREATE_NOT_DIR
;
if
(
backup_cred
(
cifs_sb
))
create_options
|=
CREATE_OPEN_BACKUP_INTENT
;
oparms
.
tcon
=
tcon
;
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
desired_access
=
GENERIC_WRITE
;
oparms
.
share_access
=
FILE_SHARE_ALL
;
oparms
.
create_options
=
create_options
;
oparms
.
disposition
=
FILE_CREATE
;
oparms
.
path
=
path
;
oparms
.
fid
=
&
fid
;
oparms
.
reconnect
=
false
;
rc
=
CIFS_open
(
xid
,
&
oparms
,
&
oplock
,
NULL
);
if
(
rc
)
return
rc
;
io_parms
.
netfid
=
fid
.
netfid
;
io_parms
.
pid
=
current
->
tgid
;
io_parms
.
tcon
=
tcon
;
io_parms
.
offset
=
0
;
io_parms
.
length
=
CIFS_MF_SYMLINK_FILE_SIZE
;
rc
=
CIFSSMBWrite
(
xid
,
&
io_parms
,
pbytes_written
,
pbuf
,
NULL
,
0
);
CIFSSMBClose
(
xid
,
tcon
,
fid
.
netfid
);
return
rc
;
}
/*
* M-F Symlink Functions - End
*/
int
int
cifs_hardlink
(
struct
dentry
*
old_file
,
struct
inode
*
inode
,
cifs_hardlink
(
struct
dentry
*
old_file
,
struct
inode
*
inode
,
struct
dentry
*
direntry
)
struct
dentry
*
direntry
)
...
@@ -442,8 +439,10 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
...
@@ -442,8 +439,10 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
CIFS_MOUNT_MAP_SPECIAL_CHR
);
CIFS_MOUNT_MAP_SPECIAL_CHR
);
else
{
else
{
server
=
tcon
->
ses
->
server
;
server
=
tcon
->
ses
->
server
;
if
(
!
server
->
ops
->
create_hardlink
)
if
(
!
server
->
ops
->
create_hardlink
)
{
return
-
ENOSYS
;
rc
=
-
ENOSYS
;
goto
cifs_hl_exit
;
}
rc
=
server
->
ops
->
create_hardlink
(
xid
,
tcon
,
from_name
,
to_name
,
rc
=
server
->
ops
->
create_hardlink
(
xid
,
tcon
,
from_name
,
to_name
,
cifs_sb
);
cifs_sb
);
if
((
rc
==
-
EIO
)
||
(
rc
==
-
EINVAL
))
if
((
rc
==
-
EIO
)
||
(
rc
==
-
EINVAL
))
...
@@ -534,10 +533,8 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
...
@@ -534,10 +533,8 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
* and fallback to UNIX Extensions Symlinks.
* and fallback to UNIX Extensions Symlinks.
*/
*/
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MF_SYMLINKS
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MF_SYMLINKS
)
rc
=
CIFSQueryMFSymLink
(
xid
,
tcon
,
full_path
,
&
target_path
,
rc
=
query_mf_symlink
(
xid
,
tcon
,
cifs_sb
,
full_path
,
cifs_sb
->
local_nls
,
&
target_path
);
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MAP_SPECIAL_CHR
);
if
(
rc
!=
0
&&
server
->
ops
->
query_symlink
)
if
(
rc
!=
0
&&
server
->
ops
->
query_symlink
)
rc
=
server
->
ops
->
query_symlink
(
xid
,
tcon
,
full_path
,
rc
=
server
->
ops
->
query_symlink
(
xid
,
tcon
,
full_path
,
...
@@ -588,8 +585,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
...
@@ -588,8 +585,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
/* BB what if DFS and this volume is on different share? BB */
/* BB what if DFS and this volume is on different share? BB */
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MF_SYMLINKS
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MF_SYMLINKS
)
rc
=
CIFSCreateMFSymLink
(
xid
,
pTcon
,
full_path
,
symname
,
rc
=
create_mf_symlink
(
xid
,
pTcon
,
cifs_sb
,
full_path
,
symname
);
cifs_sb
);
else
if
(
pTcon
->
unix_ext
)
else
if
(
pTcon
->
unix_ext
)
rc
=
CIFSUnixCreateSymLink
(
xid
,
pTcon
,
full_path
,
symname
,
rc
=
CIFSUnixCreateSymLink
(
xid
,
pTcon
,
full_path
,
symname
,
cifs_sb
->
local_nls
);
cifs_sb
->
local_nls
);
...
@@ -618,10 +614,3 @@ symlink_exit:
...
@@ -618,10 +614,3 @@ symlink_exit:
free_xid
(
xid
);
free_xid
(
xid
);
return
rc
;
return
rc
;
}
}
void
cifs_put_link
(
struct
dentry
*
direntry
,
struct
nameidata
*
nd
,
void
*
cookie
)
{
char
*
p
=
nd_get_link
(
nd
);
if
(
!
IS_ERR
(
p
))
kfree
(
p
);
}
sources/centos70/misc.c
View file @
9d798057
...
@@ -278,7 +278,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
...
@@ -278,7 +278,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
}
}
static
int
static
int
check_smb_hdr
(
struct
smb_hdr
*
smb
,
__u16
mid
)
check_smb_hdr
(
struct
smb_hdr
*
smb
)
{
{
/* does it have the right SMB "signature" ? */
/* does it have the right SMB "signature" ? */
if
(
*
(
__le32
*
)
smb
->
Protocol
!=
cpu_to_le32
(
0x424d53ff
))
{
if
(
*
(
__le32
*
)
smb
->
Protocol
!=
cpu_to_le32
(
0x424d53ff
))
{
...
@@ -287,13 +287,6 @@ check_smb_hdr(struct smb_hdr *smb, __u16 mid)
...
@@ -287,13 +287,6 @@ check_smb_hdr(struct smb_hdr *smb, __u16 mid)
return
1
;
return
1
;
}
}
/* Make sure that message ids match */
if
(
mid
!=
smb
->
Mid
)
{
cifs_dbg
(
VFS
,
"Mids do not match. received=%u expected=%u
\n
"
,
smb
->
Mid
,
mid
);
return
1
;
}
/* if it's a response then accept */
/* if it's a response then accept */
if
(
smb
->
Flags
&
SMBFLG_RESPONSE
)
if
(
smb
->
Flags
&
SMBFLG_RESPONSE
)
return
0
;
return
0
;
...
@@ -302,7 +295,8 @@ check_smb_hdr(struct smb_hdr *smb, __u16 mid)
...
@@ -302,7 +295,8 @@ check_smb_hdr(struct smb_hdr *smb, __u16 mid)
if
(
smb
->
Command
==
SMB_COM_LOCKING_ANDX
)
if
(
smb
->
Command
==
SMB_COM_LOCKING_ANDX
)
return
0
;
return
0
;
cifs_dbg
(
VFS
,
"Server sent request, not response. mid=%u
\n
"
,
smb
->
Mid
);
cifs_dbg
(
VFS
,
"Server sent request, not response. mid=%u
\n
"
,
get_mid
(
smb
));
return
1
;
return
1
;
}
}
...
@@ -310,7 +304,6 @@ int
...
@@ -310,7 +304,6 @@ int
checkSMB
(
char
*
buf
,
unsigned
int
total_read
)
checkSMB
(
char
*
buf
,
unsigned
int
total_read
)
{
{
struct
smb_hdr
*
smb
=
(
struct
smb_hdr
*
)
buf
;
struct
smb_hdr
*
smb
=
(
struct
smb_hdr
*
)
buf
;
__u16
mid
=
smb
->
Mid
;
__u32
rfclen
=
be32_to_cpu
(
smb
->
smb_buf_length
);
__u32
rfclen
=
be32_to_cpu
(
smb
->
smb_buf_length
);
__u32
clc_len
;
/* calculated length */
__u32
clc_len
;
/* calculated length */
cifs_dbg
(
FYI
,
"checkSMB Length: 0x%x, smb_buf_length: 0x%x
\n
"
,
cifs_dbg
(
FYI
,
"checkSMB Length: 0x%x, smb_buf_length: 0x%x
\n
"
,
...
@@ -348,7 +341,7 @@ checkSMB(char *buf, unsigned int total_read)
...
@@ -348,7 +341,7 @@ checkSMB(char *buf, unsigned int total_read)
}
}
/* otherwise, there is enough to get to the BCC */
/* otherwise, there is enough to get to the BCC */
if
(
check_smb_hdr
(
smb
,
mid
))
if
(
check_smb_hdr
(
smb
))
return
-
EIO
;
return
-
EIO
;
clc_len
=
smbCalcSize
(
smb
);
clc_len
=
smbCalcSize
(
smb
);
...
@@ -359,6 +352,7 @@ checkSMB(char *buf, unsigned int total_read)
...
@@ -359,6 +352,7 @@ checkSMB(char *buf, unsigned int total_read)
}
}
if
(
4
+
rfclen
!=
clc_len
)
{
if
(
4
+
rfclen
!=
clc_len
)
{
__u16
mid
=
get_mid
(
smb
);
/* check if bcc wrapped around for large read responses */
/* check if bcc wrapped around for large read responses */
if
((
rfclen
>
64
*
1024
)
&&
(
rfclen
>
clc_len
))
{
if
((
rfclen
>
64
*
1024
)
&&
(
rfclen
>
clc_len
))
{
/* check if lengths match mod 64K */
/* check if lengths match mod 64K */
...
@@ -366,11 +360,11 @@ checkSMB(char *buf, unsigned int total_read)
...
@@ -366,11 +360,11 @@ checkSMB(char *buf, unsigned int total_read)
return
0
;
/* bcc wrapped */
return
0
;
/* bcc wrapped */
}
}
cifs_dbg
(
FYI
,
"Calculated size %u vs length %u mismatch for mid=%u
\n
"
,
cifs_dbg
(
FYI
,
"Calculated size %u vs length %u mismatch for mid=%u
\n
"
,
clc_len
,
4
+
rfclen
,
smb
->
M
id
);
clc_len
,
4
+
rfclen
,
m
id
);
if
(
4
+
rfclen
<
clc_len
)
{
if
(
4
+
rfclen
<
clc_len
)
{
cifs_dbg
(
VFS
,
"RFC1001 size %u smaller than SMB for mid=%u
\n
"
,
cifs_dbg
(
VFS
,
"RFC1001 size %u smaller than SMB for mid=%u
\n
"
,
rfclen
,
smb
->
M
id
);
rfclen
,
m
id
);
return
-
EIO
;
return
-
EIO
;
}
else
if
(
rfclen
>
clc_len
+
512
)
{
}
else
if
(
rfclen
>
clc_len
+
512
)
{
/*
/*
...
@@ -383,7 +377,7 @@ checkSMB(char *buf, unsigned int total_read)
...
@@ -383,7 +377,7 @@ checkSMB(char *buf, unsigned int total_read)
* data to 512 bytes.
* data to 512 bytes.
*/
*/
cifs_dbg
(
VFS
,
"RFC1001 size %u more than 512 bytes larger than SMB for mid=%u
\n
"
,
cifs_dbg
(
VFS
,
"RFC1001 size %u more than 512 bytes larger than SMB for mid=%u
\n
"
,
rfclen
,
smb
->
M
id
);
rfclen
,
m
id
);
return
-
EIO
;
return
-
EIO
;
}
}
}
}
...
@@ -472,8 +466,22 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
...
@@ -472,8 +466,22 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
cifs_dbg
(
FYI
,
"file id match, oplock break
\n
"
);
cifs_dbg
(
FYI
,
"file id match, oplock break
\n
"
);
pCifsInode
=
CIFS_I
(
netfile
->
dentry
->
d_inode
);
pCifsInode
=
CIFS_I
(
netfile
->
dentry
->
d_inode
);
cifs_set_oplock_level
(
pCifsInode
,
set_bit
(
CIFS_INODE_PENDING_OPLOCK_BREAK
,
pSMB
->
OplockLevel
?
OPLOCK_READ
:
0
);
&
pCifsInode
->
flags
);
/*
* Set flag if the server downgrades the oplock
* to L2 else clear.
*/
if
(
pSMB
->
OplockLevel
)
set_bit
(
CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2
,
&
pCifsInode
->
flags
);
else
clear_bit
(
CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2
,
&
pCifsInode
->
flags
);
queue_work
(
cifsiod_wq
,
queue_work
(
cifsiod_wq
,
&
netfile
->
oplock_break
);
&
netfile
->
oplock_break
);
netfile
->
oplock_break_cancelled
=
false
;
netfile
->
oplock_break_cancelled
=
false
;
...
@@ -557,6 +565,62 @@ void cifs_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock)
...
@@ -557,6 +565,62 @@ void cifs_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock)
cinode
->
oplock
=
0
;
cinode
->
oplock
=
0
;
}
}
static
int
cifs_oplock_break_wait
(
void
*
unused
)
{
schedule
();
return
signal_pending
(
current
)
?
-
ERESTARTSYS
:
0
;
}
/*
* We wait for oplock breaks to be processed before we attempt to perform
* writes.
*/
int
cifs_get_writer
(
struct
cifsInodeInfo
*
cinode
)
{
int
rc
;
start:
rc
=
wait_on_bit
(
&
cinode
->
flags
,
CIFS_INODE_PENDING_OPLOCK_BREAK
,
cifs_oplock_break_wait
,
TASK_KILLABLE
);
if
(
rc
)
return
rc
;
spin_lock
(
&
cinode
->
writers_lock
);
if
(
!
cinode
->
writers
)
set_bit
(
CIFS_INODE_PENDING_WRITERS
,
&
cinode
->
flags
);
cinode
->
writers
++
;
/* Check to see if we have started servicing an oplock break */
if
(
test_bit
(
CIFS_INODE_PENDING_OPLOCK_BREAK
,
&
cinode
->
flags
))
{
cinode
->
writers
--
;
if
(
cinode
->
writers
==
0
)
{
clear_bit
(
CIFS_INODE_PENDING_WRITERS
,
&
cinode
->
flags
);
wake_up_bit
(
&
cinode
->
flags
,
CIFS_INODE_PENDING_WRITERS
);
}
spin_unlock
(
&
cinode
->
writers_lock
);
goto
start
;
}
spin_unlock
(
&
cinode
->
writers_lock
);
return
0
;
}
void
cifs_put_writer
(
struct
cifsInodeInfo
*
cinode
)
{
spin_lock
(
&
cinode
->
writers_lock
);
cinode
->
writers
--
;
if
(
cinode
->
writers
==
0
)
{
clear_bit
(
CIFS_INODE_PENDING_WRITERS
,
&
cinode
->
flags
);
wake_up_bit
(
&
cinode
->
flags
,
CIFS_INODE_PENDING_WRITERS
);
}
spin_unlock
(
&
cinode
->
writers_lock
);
}
void
cifs_done_oplock_break
(
struct
cifsInodeInfo
*
cinode
)
{
clear_bit
(
CIFS_INODE_PENDING_OPLOCK_BREAK
,
&
cinode
->
flags
);
wake_up_bit
(
&
cinode
->
flags
,
CIFS_INODE_PENDING_OPLOCK_BREAK
);
}
bool
bool
backup_cred
(
struct
cifs_sb_info
*
cifs_sb
)
backup_cred
(
struct
cifs_sb_info
*
cifs_sb
)
{
{
...
...
sources/centos70/netmisc.c
View file @
9d798057
...
@@ -51,7 +51,7 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = {
...
@@ -51,7 +51,7 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = {
{
ERRnoaccess
,
-
EACCES
},
{
ERRnoaccess
,
-
EACCES
},
{
ERRbadfid
,
-
EBADF
},
{
ERRbadfid
,
-
EBADF
},
{
ERRbadmcb
,
-
EIO
},
{
ERRbadmcb
,
-
EIO
},
{
ERRnomem
,
-
E
NOMEM
},
{
ERRnomem
,
-
E
REMOTEIO
},
{
ERRbadmem
,
-
EFAULT
},
{
ERRbadmem
,
-
EFAULT
},
{
ERRbadenv
,
-
EFAULT
},
{
ERRbadenv
,
-
EFAULT
},
{
ERRbadformat
,
-
EINVAL
},
{
ERRbadformat
,
-
EINVAL
},
...
@@ -780,7 +780,9 @@ static const struct {
...
@@ -780,7 +780,9 @@ static const struct {
ERRDOS
,
ERRnoaccess
,
0xc0000290
},
{
ERRDOS
,
ERRnoaccess
,
0xc0000290
},
{
ERRDOS
,
ERRbadfunc
,
0xc000029c
},
{
ERRDOS
,
ERRbadfunc
,
0xc000029c
},
{
ERRDOS
,
ERRsymlink
,
NT_STATUS_STOPPED_ON_SYMLINK
},
{
ERRDOS
,
ERRsymlink
,
NT_STATUS_STOPPED_ON_SYMLINK
},
{
ERRDOS
,
ERRinvlevel
,
0x007c0001
},
};
ERRDOS
,
ERRinvlevel
,
0x007c0001
},
{
0
,
0
,
0
}
};
/*****************************************************************************
/*****************************************************************************
Print an error message from the status code
Print an error message from the status code
...
@@ -793,8 +795,8 @@ cifs_print_status(__u32 status_code)
...
@@ -793,8 +795,8 @@ cifs_print_status(__u32 status_code)
while
(
nt_errs
[
idx
].
nt_errstr
!=
NULL
)
{
while
(
nt_errs
[
idx
].
nt_errstr
!=
NULL
)
{
if
(((
nt_errs
[
idx
].
nt_errcode
)
&
0xFFFFFF
)
==
if
(((
nt_errs
[
idx
].
nt_errcode
)
&
0xFFFFFF
)
==
(
status_code
&
0xFFFFFF
))
{
(
status_code
&
0xFFFFFF
))
{
pr
intk
(
KERN_NOTICE
"Status code returned 0x%08x %s
\n
"
,
pr
_notice
(
"Status code returned 0x%08x %s
\n
"
,
status_code
,
nt_errs
[
idx
].
nt_errstr
);
status_code
,
nt_errs
[
idx
].
nt_errstr
);
}
}
idx
++
;
idx
++
;
}
}
...
@@ -939,8 +941,9 @@ cifs_UnixTimeToNT(struct timespec t)
...
@@ -939,8 +941,9 @@ cifs_UnixTimeToNT(struct timespec t)
return
(
u64
)
t
.
tv_sec
*
10000000
+
t
.
tv_nsec
/
100
+
NTFS_TIME_OFFSET
;
return
(
u64
)
t
.
tv_sec
*
10000000
+
t
.
tv_nsec
/
100
+
NTFS_TIME_OFFSET
;
}
}
static
int
total_days_of_prev_months
[]
=
static
const
int
total_days_of_prev_months
[]
=
{
{
0
,
31
,
59
,
90
,
120
,
151
,
181
,
212
,
243
,
273
,
304
,
334
};
0
,
31
,
59
,
90
,
120
,
151
,
181
,
212
,
243
,
273
,
304
,
334
};
struct
timespec
cnvrtDosUnixTm
(
__le16
le_date
,
__le16
le_time
,
int
offset
)
struct
timespec
cnvrtDosUnixTm
(
__le16
le_date
,
__le16
le_time
,
int
offset
)
{
{
...
...
sources/centos70/readdir.c
View file @
9d798057
...
@@ -134,22 +134,6 @@ out:
...
@@ -134,22 +134,6 @@ out:
dput
(
dentry
);
dput
(
dentry
);
}
}
/*
* Is it possible that this directory might turn out to be a DFS referral
* once we go to try and use it?
*/
static
bool
cifs_dfs_is_possible
(
struct
cifs_sb_info
*
cifs_sb
)
{
#ifdef CONFIG_CIFS_DFS_UPCALL
struct
cifs_tcon
*
tcon
=
cifs_sb_master_tcon
(
cifs_sb
);
if
(
tcon
->
Flags
&
SMB_SHARE_IS_IN_DFS
)
return
true
;
#endif
return
false
;
}
static
void
static
void
cifs_fill_common_info
(
struct
cifs_fattr
*
fattr
,
struct
cifs_sb_info
*
cifs_sb
)
cifs_fill_common_info
(
struct
cifs_fattr
*
fattr
,
struct
cifs_sb_info
*
cifs_sb
)
{
{
...
@@ -159,27 +143,22 @@ cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb)
...
@@ -159,27 +143,22 @@ cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb)
if
(
fattr
->
cf_cifsattrs
&
ATTR_DIRECTORY
)
{
if
(
fattr
->
cf_cifsattrs
&
ATTR_DIRECTORY
)
{
fattr
->
cf_mode
=
S_IFDIR
|
cifs_sb
->
mnt_dir_mode
;
fattr
->
cf_mode
=
S_IFDIR
|
cifs_sb
->
mnt_dir_mode
;
fattr
->
cf_dtype
=
DT_DIR
;
fattr
->
cf_dtype
=
DT_DIR
;
/*
* Windows CIFS servers generally make DFS referrals look
* like directories in FIND_* responses with the reparse
* attribute flag also set (since DFS junctions are
* reparse points). We must revalidate at least these
* directory inodes before trying to use them (if
* they are DFS we will get PATH_NOT_COVERED back
* when queried directly and can then try to connect
* to the DFS target)
*/
if
(
cifs_dfs_is_possible
(
cifs_sb
)
&&
(
fattr
->
cf_cifsattrs
&
ATTR_REPARSE
))
fattr
->
cf_flags
|=
CIFS_FATTR_NEED_REVAL
;
}
else
if
(
fattr
->
cf_cifsattrs
&
ATTR_REPARSE
)
{
fattr
->
cf_mode
=
S_IFLNK
;
fattr
->
cf_dtype
=
DT_LNK
;
}
else
{
}
else
{
fattr
->
cf_mode
=
S_IFREG
|
cifs_sb
->
mnt_file_mode
;
fattr
->
cf_mode
=
S_IFREG
|
cifs_sb
->
mnt_file_mode
;
fattr
->
cf_dtype
=
DT_REG
;
fattr
->
cf_dtype
=
DT_REG
;
}
}
/*
* We need to revalidate it further to make a decision about whether it
* is a symbolic link, DFS referral or a reparse point with a direct
* access like junctions, deduplicated files, NFS symlinks.
*/
if
(
fattr
->
cf_cifsattrs
&
ATTR_REPARSE
)
fattr
->
cf_flags
|=
CIFS_FATTR_NEED_REVAL
;
/* non-unix readdir doesn't provide nlink */
fattr
->
cf_flags
|=
CIFS_FATTR_UNKNOWN_NLINK
;
if
(
fattr
->
cf_cifsattrs
&
ATTR_READONLY
)
if
(
fattr
->
cf_cifsattrs
&
ATTR_READONLY
)
fattr
->
cf_mode
&=
~
S_IWUGO
;
fattr
->
cf_mode
&=
~
S_IWUGO
;
...
@@ -769,7 +748,7 @@ static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir,
...
@@ -769,7 +748,7 @@ static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir,
}
}
if
((
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MF_SYMLINKS
)
&&
if
((
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MF_SYMLINKS
)
&&
CIFSCouldBeMFS
ymlink
(
&
fattr
))
couldbe_mf_s
ymlink
(
&
fattr
))
/*
/*
* trying to get the type and mode can be slow,
* trying to get the type and mode can be slow,
* so just call those regular files for now, and mark
* so just call those regular files for now, and mark
...
...
sources/centos70/sess.c
View file @
9d798057
...
@@ -500,9 +500,9 @@ select_sectype(struct TCP_Server_Info *server, enum securityEnum requested)
...
@@ -500,9 +500,9 @@ select_sectype(struct TCP_Server_Info *server, enum securityEnum requested)
return
NTLMv2
;
return
NTLMv2
;
if
(
global_secflags
&
CIFSSEC_MAY_NTLM
)
if
(
global_secflags
&
CIFSSEC_MAY_NTLM
)
return
NTLM
;
return
NTLM
;
/* Fallthrough */
default:
default:
return
Unspecified
;
/* Fallthrough to attempt LANMAN authentication next */
break
;
}
}
case
CIFS_NEGFLAVOR_LANMAN
:
case
CIFS_NEGFLAVOR_LANMAN
:
switch
(
requested
)
{
switch
(
requested
)
{
...
...
sources/centos70/smb1ops.c
View file @
9d798057
...
@@ -67,7 +67,7 @@ send_nt_cancel(struct TCP_Server_Info *server, void *buf,
...
@@ -67,7 +67,7 @@ send_nt_cancel(struct TCP_Server_Info *server, void *buf,
mutex_unlock
(
&
server
->
srv_mutex
);
mutex_unlock
(
&
server
->
srv_mutex
);
cifs_dbg
(
FYI
,
"issued NT_CANCEL for mid %u, rc = %d
\n
"
,
cifs_dbg
(
FYI
,
"issued NT_CANCEL for mid %u, rc = %d
\n
"
,
in_buf
->
Mid
,
rc
);
get_mid
(
in_buf
)
,
rc
);
return
rc
;
return
rc
;
}
}
...
@@ -101,7 +101,7 @@ cifs_find_mid(struct TCP_Server_Info *server, char *buffer)
...
@@ -101,7 +101,7 @@ cifs_find_mid(struct TCP_Server_Info *server, char *buffer)
spin_lock
(
&
GlobalMid_Lock
);
spin_lock
(
&
GlobalMid_Lock
);
list_for_each_entry
(
mid
,
&
server
->
pending_mid_q
,
qhead
)
{
list_for_each_entry
(
mid
,
&
server
->
pending_mid_q
,
qhead
)
{
if
(
mid
->
mid
==
buf
->
Mid
&&
if
(
compare_mid
(
mid
->
mid
,
buf
)
&&
mid
->
mid_state
==
MID_REQUEST_SUBMITTED
&&
mid
->
mid_state
==
MID_REQUEST_SUBMITTED
&&
le16_to_cpu
(
mid
->
command
)
==
buf
->
Command
)
{
le16_to_cpu
(
mid
->
command
)
==
buf
->
Command
)
{
spin_unlock
(
&
GlobalMid_Lock
);
spin_unlock
(
&
GlobalMid_Lock
);
...
@@ -372,6 +372,16 @@ coalesce_t2(char *second_buf, struct smb_hdr *target_hdr)
...
@@ -372,6 +372,16 @@ coalesce_t2(char *second_buf, struct smb_hdr *target_hdr)
return
0
;
return
0
;
}
}
static
void
cifs_downgrade_oplock
(
struct
TCP_Server_Info
*
server
,
struct
cifsInodeInfo
*
cinode
,
bool
set_level2
)
{
if
(
set_level2
)
cifs_set_oplock_level
(
cinode
,
OPLOCK_READ
);
else
cifs_set_oplock_level
(
cinode
,
0
);
}
static
bool
static
bool
cifs_check_trans2
(
struct
mid_q_entry
*
mid
,
struct
TCP_Server_Info
*
server
,
cifs_check_trans2
(
struct
mid_q_entry
*
mid
,
struct
TCP_Server_Info
*
server
,
char
*
buf
,
int
malformed
)
char
*
buf
,
int
malformed
)
...
@@ -534,10 +544,12 @@ cifs_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -534,10 +544,12 @@ cifs_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
static
int
static
int
cifs_query_path_info
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
cifs_query_path_info
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
struct
cifs_sb_info
*
cifs_sb
,
const
char
*
full_path
,
struct
cifs_sb_info
*
cifs_sb
,
const
char
*
full_path
,
FILE_ALL_INFO
*
data
,
bool
*
adjustTZ
)
FILE_ALL_INFO
*
data
,
bool
*
adjustTZ
,
bool
*
symlink
)
{
{
int
rc
;
int
rc
;
*
symlink
=
false
;
/* could do find first instead but this returns more info */
/* could do find first instead but this returns more info */
rc
=
CIFSSMBQPathInfo
(
xid
,
tcon
,
full_path
,
data
,
0
/* not legacy */
,
rc
=
CIFSSMBQPathInfo
(
xid
,
tcon
,
full_path
,
data
,
0
/* not legacy */
,
cifs_sb
->
local_nls
,
cifs_sb
->
mnt_cifs_flags
&
cifs_sb
->
local_nls
,
cifs_sb
->
mnt_cifs_flags
&
...
@@ -554,6 +566,31 @@ cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -554,6 +566,31 @@ cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
CIFS_MOUNT_MAP_SPECIAL_CHR
);
CIFS_MOUNT_MAP_SPECIAL_CHR
);
*
adjustTZ
=
true
;
*
adjustTZ
=
true
;
}
}
if
(
!
rc
&&
(
le32_to_cpu
(
data
->
Attributes
)
&
ATTR_REPARSE
))
{
int
tmprc
;
int
oplock
=
0
;
struct
cifs_fid
fid
;
struct
cifs_open_parms
oparms
;
oparms
.
tcon
=
tcon
;
oparms
.
cifs_sb
=
cifs_sb
;
oparms
.
desired_access
=
FILE_READ_ATTRIBUTES
;
oparms
.
share_access
=
FILE_SHARE_ALL
;
oparms
.
create_options
=
0
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
path
=
full_path
;
oparms
.
fid
=
&
fid
;
oparms
.
reconnect
=
false
;
/* Need to check if this is a symbolic link or not */
tmprc
=
CIFS_open
(
xid
,
&
oparms
,
&
oplock
,
NULL
);
if
(
tmprc
==
-
EOPNOTSUPP
)
*
symlink
=
true
;
else
CIFSSMBClose
(
xid
,
tcon
,
fid
.
netfid
);
}
return
rc
;
return
rc
;
}
}
...
@@ -686,13 +723,7 @@ cifs_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
...
@@ -686,13 +723,7 @@ cifs_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
oparms
->
cifs_sb
->
local_nls
,
oparms
->
cifs_sb
->
local_nls
,
oparms
->
cifs_sb
->
mnt_cifs_flags
oparms
->
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MAP_SPECIAL_CHR
);
&
CIFS_MOUNT_MAP_SPECIAL_CHR
);
return
CIFSSMBOpen
(
xid
,
oparms
->
tcon
,
oparms
->
path
,
return
CIFS_open
(
xid
,
oparms
,
oplock
,
buf
);
oparms
->
disposition
,
oparms
->
desired_access
,
oparms
->
share_access
,
oparms
->
create_options
,
&
oparms
->
fid
->
netfid
,
oplock
,
buf
,
oparms
->
cifs_sb
->
local_nls
,
oparms
->
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MAP_SPECIAL_CHR
);
}
}
static
void
static
void
...
@@ -743,8 +774,9 @@ smb_set_file_info(struct inode *inode, const char *full_path,
...
@@ -743,8 +774,9 @@ smb_set_file_info(struct inode *inode, const char *full_path,
{
{
int
oplock
=
0
;
int
oplock
=
0
;
int
rc
;
int
rc
;
__u16
netfid
;
__u32
netpid
;
__u32
netpid
;
struct
cifs_fid
fid
;
struct
cifs_open_parms
oparms
;
struct
cifsFileInfo
*
open_file
;
struct
cifsFileInfo
*
open_file
;
struct
cifsInodeInfo
*
cinode
=
CIFS_I
(
inode
);
struct
cifsInodeInfo
*
cinode
=
CIFS_I
(
inode
);
struct
cifs_sb_info
*
cifs_sb
=
CIFS_SB
(
inode
->
i_sb
);
struct
cifs_sb_info
*
cifs_sb
=
CIFS_SB
(
inode
->
i_sb
);
...
@@ -754,7 +786,7 @@ smb_set_file_info(struct inode *inode, const char *full_path,
...
@@ -754,7 +786,7 @@ smb_set_file_info(struct inode *inode, const char *full_path,
/* if the file is already open for write, just use that fileid */
/* if the file is already open for write, just use that fileid */
open_file
=
find_writable_file
(
cinode
,
true
);
open_file
=
find_writable_file
(
cinode
,
true
);
if
(
open_file
)
{
if
(
open_file
)
{
netfid
=
open_file
->
fid
.
netfid
;
fid
.
netfid
=
open_file
->
fid
.
netfid
;
netpid
=
open_file
->
pid
;
netpid
=
open_file
->
pid
;
tcon
=
tlink_tcon
(
open_file
->
tlink
);
tcon
=
tlink_tcon
(
open_file
->
tlink
);
goto
set_via_filehandle
;
goto
set_via_filehandle
;
...
@@ -778,13 +810,18 @@ smb_set_file_info(struct inode *inode, const char *full_path,
...
@@ -778,13 +810,18 @@ smb_set_file_info(struct inode *inode, const char *full_path,
goto
out
;
goto
out
;
}
}
cifs_dbg
(
FYI
,
"calling SetFileInfo since SetPathInfo for times not supported by this server
\n
"
);
oparms
.
tcon
=
tcon
;
rc
=
CIFSSMBOpen
(
xid
,
tcon
,
full_path
,
FILE_OPEN
,
oparms
.
cifs_sb
=
cifs_sb
;
SYNCHRONIZE
|
FILE_WRITE_ATTRIBUTES
,
FILE_SHARE_ALL
,
oparms
.
desired_access
=
SYNCHRONIZE
|
FILE_WRITE_ATTRIBUTES
;
CREATE_NOT_DIR
,
&
netfid
,
&
oplock
,
NULL
,
oparms
.
share_access
=
FILE_SHARE_ALL
;
cifs_sb
->
local_nls
,
oparms
.
create_options
=
CREATE_NOT_DIR
;
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MAP_SPECIAL_CHR
);
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
path
=
full_path
;
oparms
.
fid
=
&
fid
;
oparms
.
reconnect
=
false
;
cifs_dbg
(
FYI
,
"calling SetFileInfo since SetPathInfo for times not supported by this server
\n
"
);
rc
=
CIFS_open
(
xid
,
&
oparms
,
&
oplock
,
NULL
);
if
(
rc
!=
0
)
{
if
(
rc
!=
0
)
{
if
(
rc
==
-
EIO
)
if
(
rc
==
-
EIO
)
rc
=
-
EINVAL
;
rc
=
-
EINVAL
;
...
@@ -794,12 +831,12 @@ smb_set_file_info(struct inode *inode, const char *full_path,
...
@@ -794,12 +831,12 @@ smb_set_file_info(struct inode *inode, const char *full_path,
netpid
=
current
->
tgid
;
netpid
=
current
->
tgid
;
set_via_filehandle:
set_via_filehandle:
rc
=
CIFSSMBSetFileInfo
(
xid
,
tcon
,
buf
,
netfid
,
netpid
);
rc
=
CIFSSMBSetFileInfo
(
xid
,
tcon
,
buf
,
fid
.
netfid
,
netpid
);
if
(
!
rc
)
if
(
!
rc
)
cinode
->
cifsAttrs
=
le32_to_cpu
(
buf
->
Attributes
);
cinode
->
cifsAttrs
=
le32_to_cpu
(
buf
->
Attributes
);
if
(
open_file
==
NULL
)
if
(
open_file
==
NULL
)
CIFSSMBClose
(
xid
,
tcon
,
netfid
);
CIFSSMBClose
(
xid
,
tcon
,
fid
.
netfid
);
else
else
cifsFileInfo_put
(
open_file
);
cifsFileInfo_put
(
open_file
);
out:
out:
...
@@ -809,6 +846,13 @@ out:
...
@@ -809,6 +846,13 @@ out:
}
}
static
int
static
int
cifs_set_compression
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
struct
cifsFileInfo
*
cfile
)
{
return
CIFSSMB_set_compression
(
xid
,
tcon
,
cfile
->
fid
.
netfid
);
}
static
int
cifs_query_dir_first
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
cifs_query_dir_first
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
const
char
*
path
,
struct
cifs_sb_info
*
cifs_sb
,
const
char
*
path
,
struct
cifs_sb_info
*
cifs_sb
,
struct
cifs_fid
*
fid
,
__u16
search_flags
,
struct
cifs_fid
*
fid
,
__u16
search_flags
,
...
@@ -917,7 +961,8 @@ cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -917,7 +961,8 @@ cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
{
{
int
rc
;
int
rc
;
int
oplock
=
0
;
int
oplock
=
0
;
__u16
netfid
;
struct
cifs_fid
fid
;
struct
cifs_open_parms
oparms
;
cifs_dbg
(
FYI
,
"%s: path: %s
\n
"
,
__func__
,
full_path
);
cifs_dbg
(
FYI
,
"%s: path: %s
\n
"
,
__func__
,
full_path
);
...
@@ -933,22 +978,28 @@ cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -933,22 +978,28 @@ cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
goto
out
;
goto
out
;
}
}
rc
=
CIFSSMBOpen
(
xid
,
tcon
,
full_path
,
FILE_OPEN
,
oparms
.
tcon
=
tcon
;
FILE_READ_ATTRIBUTES
,
FILE_SHARE_ALL
,
oparms
.
cifs_sb
=
cifs_sb
;
OPEN_REPARSE_POINT
,
&
netfid
,
&
oplock
,
NULL
,
oparms
.
desired_access
=
FILE_READ_ATTRIBUTES
;
cifs_sb
->
local_nls
,
oparms
.
share_access
=
FILE_SHARE_ALL
;
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MAP_SPECIAL_CHR
);
oparms
.
create_options
=
OPEN_REPARSE_POINT
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
path
=
full_path
;
oparms
.
fid
=
&
fid
;
oparms
.
reconnect
=
false
;
rc
=
CIFS_open
(
xid
,
&
oparms
,
&
oplock
,
NULL
);
if
(
rc
)
if
(
rc
)
goto
out
;
goto
out
;
rc
=
CIFSSMBQuerySymLink
(
xid
,
tcon
,
netfid
,
target_path
,
rc
=
CIFSSMBQuerySymLink
(
xid
,
tcon
,
fid
.
netfid
,
target_path
,
cifs_sb
->
local_nls
);
cifs_sb
->
local_nls
);
if
(
rc
)
if
(
rc
)
goto
out_close
;
goto
out_close
;
convert_delimiter
(
*
target_path
,
'/'
);
convert_delimiter
(
*
target_path
,
'/'
);
out_close:
out_close:
CIFSSMBClose
(
xid
,
tcon
,
netfid
);
CIFSSMBClose
(
xid
,
tcon
,
fid
.
netfid
);
out:
out:
if
(
!
rc
)
if
(
!
rc
)
cifs_dbg
(
FYI
,
"%s: target path: %s
\n
"
,
__func__
,
*
target_path
);
cifs_dbg
(
FYI
,
"%s: target path: %s
\n
"
,
__func__
,
*
target_path
);
...
@@ -981,6 +1032,7 @@ struct smb_version_operations smb1_operations = {
...
@@ -981,6 +1032,7 @@ struct smb_version_operations smb1_operations = {
.
clear_stats
=
cifs_clear_stats
,
.
clear_stats
=
cifs_clear_stats
,
.
print_stats
=
cifs_print_stats
,
.
print_stats
=
cifs_print_stats
,
.
is_oplock_break
=
is_valid_oplock_break
,
.
is_oplock_break
=
is_valid_oplock_break
,
.
downgrade_oplock
=
cifs_downgrade_oplock
,
.
check_trans2
=
cifs_check_trans2
,
.
check_trans2
=
cifs_check_trans2
,
.
need_neg
=
cifs_need_neg
,
.
need_neg
=
cifs_need_neg
,
.
negotiate
=
cifs_negotiate
,
.
negotiate
=
cifs_negotiate
,
...
@@ -999,6 +1051,7 @@ struct smb_version_operations smb1_operations = {
...
@@ -999,6 +1051,7 @@ struct smb_version_operations smb1_operations = {
.
set_path_size
=
CIFSSMBSetEOF
,
.
set_path_size
=
CIFSSMBSetEOF
,
.
set_file_size
=
CIFSSMBSetFileSize
,
.
set_file_size
=
CIFSSMBSetFileSize
,
.
set_file_info
=
smb_set_file_info
,
.
set_file_info
=
smb_set_file_info
,
.
set_compression
=
cifs_set_compression
,
.
echo
=
CIFSSMBEcho
,
.
echo
=
CIFSSMBEcho
,
.
mkdir
=
CIFSSMBMkDir
,
.
mkdir
=
CIFSSMBMkDir
,
.
mkdir_setinfo
=
cifs_mkdir_setinfo
,
.
mkdir_setinfo
=
cifs_mkdir_setinfo
,
...
@@ -1025,8 +1078,18 @@ struct smb_version_operations smb1_operations = {
...
@@ -1025,8 +1078,18 @@ struct smb_version_operations smb1_operations = {
.
mand_lock
=
cifs_mand_lock
,
.
mand_lock
=
cifs_mand_lock
,
.
mand_unlock_range
=
cifs_unlock_range
,
.
mand_unlock_range
=
cifs_unlock_range
,
.
push_mand_locks
=
cifs_push_mandatory_locks
,
.
push_mand_locks
=
cifs_push_mandatory_locks
,
.
query_mf_symlink
=
open_query_close_cifs_symlink
,
.
query_mf_symlink
=
cifs_query_mf_symlink
,
.
create_mf_symlink
=
cifs_create_mf_symlink
,
.
is_read_op
=
cifs_is_read_op
,
.
is_read_op
=
cifs_is_read_op
,
#ifdef CONFIG_CIFS_XATTR
.
query_all_EAs
=
CIFSSMBQAllEAs
,
.
set_EA
=
CIFSSMBSetEA
,
#endif
/* CIFS_XATTR */
#ifdef CONFIG_CIFS_ACL
.
get_acl
=
get_cifs_acl
,
.
get_acl_by_fid
=
get_cifs_acl_by_fid
,
.
set_acl
=
set_cifs_acl
,
#endif
/* CIFS_ACL */
};
};
struct
smb_version_values
smb1_values
=
{
struct
smb_version_values
smb1_values
=
{
...
...
sources/centos70/smb2glob.h
View file @
9d798057
...
@@ -57,4 +57,7 @@
...
@@ -57,4 +57,7 @@
#define SMB2_CMACAES_SIZE (16)
#define SMB2_CMACAES_SIZE (16)
#define SMB3_SIGNKEY_SIZE (16)
#define SMB3_SIGNKEY_SIZE (16)
/* Maximum buffer size value we can send with 1 credit */
#define SMB2_MAX_BUFFER_SIZE 65536
#endif
/* _SMB2_GLOB_H */
#endif
/* _SMB2_GLOB_H */
sources/centos70/smb2inode.c
View file @
9d798057
...
@@ -124,12 +124,13 @@ move_smb2_info_to_cifs(FILE_ALL_INFO *dst, struct smb2_file_all_info *src)
...
@@ -124,12 +124,13 @@ move_smb2_info_to_cifs(FILE_ALL_INFO *dst, struct smb2_file_all_info *src)
int
int
smb2_query_path_info
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
smb2_query_path_info
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
struct
cifs_sb_info
*
cifs_sb
,
const
char
*
full_path
,
struct
cifs_sb_info
*
cifs_sb
,
const
char
*
full_path
,
FILE_ALL_INFO
*
data
,
bool
*
adjust_tz
)
FILE_ALL_INFO
*
data
,
bool
*
adjust_tz
,
bool
*
symlink
)
{
{
int
rc
;
int
rc
;
struct
smb2_file_all_info
*
smb2_data
;
struct
smb2_file_all_info
*
smb2_data
;
*
adjust_tz
=
false
;
*
adjust_tz
=
false
;
*
symlink
=
false
;
smb2_data
=
kzalloc
(
sizeof
(
struct
smb2_file_all_info
)
+
MAX_NAME
*
2
,
smb2_data
=
kzalloc
(
sizeof
(
struct
smb2_file_all_info
)
+
MAX_NAME
*
2
,
GFP_KERNEL
);
GFP_KERNEL
);
...
@@ -137,9 +138,16 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -137,9 +138,16 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
return
-
ENOMEM
;
return
-
ENOMEM
;
rc
=
smb2_open_op_close
(
xid
,
tcon
,
cifs_sb
,
full_path
,
rc
=
smb2_open_op_close
(
xid
,
tcon
,
cifs_sb
,
full_path
,
FILE_READ_ATTRIBUTES
,
FILE_OPEN
,
FILE_READ_ATTRIBUTES
,
FILE_OPEN
,
0
,
OPEN_REPARSE_POINT
,
smb2_data
,
smb2_data
,
SMB2_OP_QUERY_INFO
);
SMB2_OP_QUERY_INFO
);
if
(
rc
==
-
EOPNOTSUPP
)
{
*
symlink
=
true
;
/* Failed on a symbolic link - query a reparse point info */
rc
=
smb2_open_op_close
(
xid
,
tcon
,
cifs_sb
,
full_path
,
FILE_READ_ATTRIBUTES
,
FILE_OPEN
,
OPEN_REPARSE_POINT
,
smb2_data
,
SMB2_OP_QUERY_INFO
);
}
if
(
rc
)
if
(
rc
)
goto
out
;
goto
out
;
...
...
sources/centos70/smb2maperror.c
View file @
9d798057
...
@@ -306,7 +306,7 @@ static const struct status_to_posix_error smb2_error_map_table[] = {
...
@@ -306,7 +306,7 @@ static const struct status_to_posix_error smb2_error_map_table[] = {
{
STATUS_NONEXISTENT_SECTOR
,
-
EIO
,
"STATUS_NONEXISTENT_SECTOR"
},
{
STATUS_NONEXISTENT_SECTOR
,
-
EIO
,
"STATUS_NONEXISTENT_SECTOR"
},
{
STATUS_MORE_PROCESSING_REQUIRED
,
-
EIO
,
{
STATUS_MORE_PROCESSING_REQUIRED
,
-
EIO
,
"STATUS_MORE_PROCESSING_REQUIRED"
},
"STATUS_MORE_PROCESSING_REQUIRED"
},
{
STATUS_NO_MEMORY
,
-
E
NOMEM
,
"STATUS_NO_MEMORY"
},
{
STATUS_NO_MEMORY
,
-
E
REMOTEIO
,
"STATUS_NO_MEMORY"
},
{
STATUS_CONFLICTING_ADDRESSES
,
-
EADDRINUSE
,
{
STATUS_CONFLICTING_ADDRESSES
,
-
EADDRINUSE
,
"STATUS_CONFLICTING_ADDRESSES"
},
"STATUS_CONFLICTING_ADDRESSES"
},
{
STATUS_NOT_MAPPED_VIEW
,
-
EIO
,
"STATUS_NOT_MAPPED_VIEW"
},
{
STATUS_NOT_MAPPED_VIEW
,
-
EIO
,
"STATUS_NOT_MAPPED_VIEW"
},
...
...
sources/centos70/smb2misc.c
View file @
9d798057
...
@@ -575,9 +575,21 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
...
@@ -575,9 +575,21 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
else
else
cfile
->
oplock_break_cancelled
=
false
;
cfile
->
oplock_break_cancelled
=
false
;
server
->
ops
->
set_oplock_level
(
cinode
,
set_bit
(
CIFS_INODE_PENDING_OPLOCK_BREAK
,
rsp
->
OplockLevel
?
SMB2_OPLOCK_LEVEL_II
:
0
,
&
cinode
->
flags
);
0
,
NULL
);
/*
* Set flag if the server downgrades the oplock
* to L2 else clear.
*/
if
(
rsp
->
OplockLevel
)
set_bit
(
CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2
,
&
cinode
->
flags
);
else
clear_bit
(
CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2
,
&
cinode
->
flags
);
queue_work
(
cifsiod_wq
,
&
cfile
->
oplock_break
);
queue_work
(
cifsiod_wq
,
&
cfile
->
oplock_break
);
...
...
sources/centos70/smb2ops.c
View file @
9d798057
...
@@ -182,11 +182,8 @@ smb2_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *volume_info)
...
@@ -182,11 +182,8 @@ smb2_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *volume_info)
/* start with specified wsize, or default */
/* start with specified wsize, or default */
wsize
=
volume_info
->
wsize
?
volume_info
->
wsize
:
CIFS_DEFAULT_IOSIZE
;
wsize
=
volume_info
->
wsize
?
volume_info
->
wsize
:
CIFS_DEFAULT_IOSIZE
;
wsize
=
min_t
(
unsigned
int
,
wsize
,
server
->
max_write
);
wsize
=
min_t
(
unsigned
int
,
wsize
,
server
->
max_write
);
/*
/* set it to the maximum buffer size value we can send with 1 credit */
* limit write size to 2 ** 16, because we don't support multicredit
wsize
=
min_t
(
unsigned
int
,
wsize
,
SMB2_MAX_BUFFER_SIZE
);
* requests now.
*/
wsize
=
min_t
(
unsigned
int
,
wsize
,
2
<<
15
);
return
wsize
;
return
wsize
;
}
}
...
@@ -200,15 +197,102 @@ smb2_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *volume_info)
...
@@ -200,15 +197,102 @@ smb2_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *volume_info)
/* start with specified rsize, or default */
/* start with specified rsize, or default */
rsize
=
volume_info
->
rsize
?
volume_info
->
rsize
:
CIFS_DEFAULT_IOSIZE
;
rsize
=
volume_info
->
rsize
?
volume_info
->
rsize
:
CIFS_DEFAULT_IOSIZE
;
rsize
=
min_t
(
unsigned
int
,
rsize
,
server
->
max_read
);
rsize
=
min_t
(
unsigned
int
,
rsize
,
server
->
max_read
);
/*
/* set it to the maximum buffer size value we can send with 1 credit */
* limit write size to 2 ** 16, because we don't support multicredit
rsize
=
min_t
(
unsigned
int
,
rsize
,
SMB2_MAX_BUFFER_SIZE
);
* requests now.
*/
rsize
=
min_t
(
unsigned
int
,
rsize
,
2
<<
15
);
return
rsize
;
return
rsize
;
}
}
#ifdef CONFIG_CIFS_STATS2
static
int
SMB3_request_interfaces
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
)
{
int
rc
;
unsigned
int
ret_data_len
=
0
;
struct
network_interface_info_ioctl_rsp
*
out_buf
;
rc
=
SMB2_ioctl
(
xid
,
tcon
,
NO_FILE_ID
,
NO_FILE_ID
,
FSCTL_QUERY_NETWORK_INTERFACE_INFO
,
true
/* is_fsctl */
,
NULL
/* no data input */
,
0
/* no data input */
,
(
char
**
)
&
out_buf
,
&
ret_data_len
);
if
((
rc
==
0
)
&&
(
ret_data_len
>
0
))
{
/* Dump info on first interface */
cifs_dbg
(
FYI
,
"Adapter Capability 0x%x
\t
"
,
le32_to_cpu
(
out_buf
->
Capability
));
cifs_dbg
(
FYI
,
"Link Speed %lld
\n
"
,
le64_to_cpu
(
out_buf
->
LinkSpeed
));
}
else
cifs_dbg
(
VFS
,
"error %d on ioctl to get interface list
\n
"
,
rc
);
return
rc
;
}
#endif
/* STATS2 */
static
void
smb3_qfs_tcon
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
)
{
int
rc
;
__le16
srch_path
=
0
;
/* Null - open root of share */
u8
oplock
=
SMB2_OPLOCK_LEVEL_NONE
;
struct
cifs_open_parms
oparms
;
struct
cifs_fid
fid
;
oparms
.
tcon
=
tcon
;
oparms
.
desired_access
=
FILE_READ_ATTRIBUTES
;
oparms
.
share_access
=
FILE_SHARE_ALL
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
create_options
=
0
;
oparms
.
fid
=
&
fid
;
oparms
.
reconnect
=
false
;
rc
=
SMB2_open
(
xid
,
&
oparms
,
&
srch_path
,
&
oplock
,
NULL
,
NULL
);
if
(
rc
)
return
;
#ifdef CONFIG_CIFS_STATS2
SMB3_request_interfaces
(
xid
,
tcon
);
#endif
/* STATS2 */
SMB2_QFS_attr
(
xid
,
tcon
,
fid
.
persistent_fid
,
fid
.
volatile_fid
,
FS_ATTRIBUTE_INFORMATION
);
SMB2_QFS_attr
(
xid
,
tcon
,
fid
.
persistent_fid
,
fid
.
volatile_fid
,
FS_DEVICE_INFORMATION
);
SMB2_QFS_attr
(
xid
,
tcon
,
fid
.
persistent_fid
,
fid
.
volatile_fid
,
FS_SECTOR_SIZE_INFORMATION
);
/* SMB3 specific */
SMB2_close
(
xid
,
tcon
,
fid
.
persistent_fid
,
fid
.
volatile_fid
);
return
;
}
static
void
smb2_qfs_tcon
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
)
{
int
rc
;
__le16
srch_path
=
0
;
/* Null - open root of share */
u8
oplock
=
SMB2_OPLOCK_LEVEL_NONE
;
struct
cifs_open_parms
oparms
;
struct
cifs_fid
fid
;
oparms
.
tcon
=
tcon
;
oparms
.
desired_access
=
FILE_READ_ATTRIBUTES
;
oparms
.
share_access
=
FILE_SHARE_ALL
;
oparms
.
disposition
=
FILE_OPEN
;
oparms
.
create_options
=
0
;
oparms
.
fid
=
&
fid
;
oparms
.
reconnect
=
false
;
rc
=
SMB2_open
(
xid
,
&
oparms
,
&
srch_path
,
&
oplock
,
NULL
,
NULL
);
if
(
rc
)
return
;
SMB2_QFS_attr
(
xid
,
tcon
,
fid
.
persistent_fid
,
fid
.
volatile_fid
,
FS_ATTRIBUTE_INFORMATION
);
SMB2_QFS_attr
(
xid
,
tcon
,
fid
.
persistent_fid
,
fid
.
volatile_fid
,
FS_DEVICE_INFORMATION
);
SMB2_close
(
xid
,
tcon
,
fid
.
persistent_fid
,
fid
.
volatile_fid
);
return
;
}
static
int
static
int
smb2_is_path_accessible
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
smb2_is_path_accessible
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
struct
cifs_sb_info
*
cifs_sb
,
const
char
*
full_path
)
struct
cifs_sb_info
*
cifs_sb
,
const
char
*
full_path
)
...
@@ -305,7 +389,19 @@ smb2_dump_share_caps(struct seq_file *m, struct cifs_tcon *tcon)
...
@@ -305,7 +389,19 @@ smb2_dump_share_caps(struct seq_file *m, struct cifs_tcon *tcon)
seq_puts
(
m
,
" ASYMMETRIC,"
);
seq_puts
(
m
,
" ASYMMETRIC,"
);
if
(
tcon
->
capabilities
==
0
)
if
(
tcon
->
capabilities
==
0
)
seq_puts
(
m
,
" None"
);
seq_puts
(
m
,
" None"
);
if
(
tcon
->
ss_flags
&
SSINFO_FLAGS_ALIGNED_DEVICE
)
seq_puts
(
m
,
" Aligned,"
);
if
(
tcon
->
ss_flags
&
SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE
)
seq_puts
(
m
,
" Partition Aligned,"
);
if
(
tcon
->
ss_flags
&
SSINFO_FLAGS_NO_SEEK_PENALTY
)
seq_puts
(
m
,
" SSD,"
);
if
(
tcon
->
ss_flags
&
SSINFO_FLAGS_TRIM_ENABLED
)
seq_puts
(
m
,
" TRIM-support,"
);
seq_printf
(
m
,
"
\t
Share Flags: 0x%x"
,
tcon
->
share_flags
);
seq_printf
(
m
,
"
\t
Share Flags: 0x%x"
,
tcon
->
share_flags
);
if
(
tcon
->
perf_sector_size
)
seq_printf
(
m
,
"
\t
Optimal sector size: 0x%x"
,
tcon
->
perf_sector_size
);
}
}
static
void
static
void
...
@@ -395,6 +491,157 @@ smb2_close_file(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -395,6 +491,157 @@ smb2_close_file(const unsigned int xid, struct cifs_tcon *tcon,
}
}
static
int
static
int
SMB2_request_res_key
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
u64
persistent_fid
,
u64
volatile_fid
,
struct
copychunk_ioctl
*
pcchunk
)
{
int
rc
;
unsigned
int
ret_data_len
;
struct
resume_key_req
*
res_key
;
rc
=
SMB2_ioctl
(
xid
,
tcon
,
persistent_fid
,
volatile_fid
,
FSCTL_SRV_REQUEST_RESUME_KEY
,
true
/* is_fsctl */
,
NULL
,
0
/* no input */
,
(
char
**
)
&
res_key
,
&
ret_data_len
);
if
(
rc
)
{
cifs_dbg
(
VFS
,
"refcpy ioctl error %d getting resume key
\n
"
,
rc
);
goto
req_res_key_exit
;
}
if
(
ret_data_len
<
sizeof
(
struct
resume_key_req
))
{
cifs_dbg
(
VFS
,
"Invalid refcopy resume key length
\n
"
);
rc
=
-
EINVAL
;
goto
req_res_key_exit
;
}
memcpy
(
pcchunk
->
SourceKey
,
res_key
->
ResumeKey
,
COPY_CHUNK_RES_KEY_SIZE
);
req_res_key_exit:
kfree
(
res_key
);
return
rc
;
}
static
int
smb2_clone_range
(
const
unsigned
int
xid
,
struct
cifsFileInfo
*
srcfile
,
struct
cifsFileInfo
*
trgtfile
,
u64
src_off
,
u64
len
,
u64
dest_off
)
{
int
rc
;
unsigned
int
ret_data_len
;
struct
copychunk_ioctl
*
pcchunk
;
struct
copychunk_ioctl_rsp
*
retbuf
=
NULL
;
struct
cifs_tcon
*
tcon
;
int
chunks_copied
=
0
;
bool
chunk_sizes_updated
=
false
;
pcchunk
=
kmalloc
(
sizeof
(
struct
copychunk_ioctl
),
GFP_KERNEL
);
if
(
pcchunk
==
NULL
)
return
-
ENOMEM
;
cifs_dbg
(
FYI
,
"in smb2_clone_range - about to call request res key
\n
"
);
/* Request a key from the server to identify the source of the copy */
rc
=
SMB2_request_res_key
(
xid
,
tlink_tcon
(
srcfile
->
tlink
),
srcfile
->
fid
.
persistent_fid
,
srcfile
->
fid
.
volatile_fid
,
pcchunk
);
/* Note: request_res_key sets res_key null only if rc !=0 */
if
(
rc
)
goto
cchunk_out
;
/* For now array only one chunk long, will make more flexible later */
pcchunk
->
ChunkCount
=
__constant_cpu_to_le32
(
1
);
pcchunk
->
Reserved
=
0
;
pcchunk
->
Reserved2
=
0
;
tcon
=
tlink_tcon
(
trgtfile
->
tlink
);
while
(
len
>
0
)
{
pcchunk
->
SourceOffset
=
cpu_to_le64
(
src_off
);
pcchunk
->
TargetOffset
=
cpu_to_le64
(
dest_off
);
pcchunk
->
Length
=
cpu_to_le32
(
min_t
(
u32
,
len
,
tcon
->
max_bytes_chunk
));
/* Request server copy to target from src identified by key */
rc
=
SMB2_ioctl
(
xid
,
tcon
,
trgtfile
->
fid
.
persistent_fid
,
trgtfile
->
fid
.
volatile_fid
,
FSCTL_SRV_COPYCHUNK_WRITE
,
true
/* is_fsctl */
,
(
char
*
)
pcchunk
,
sizeof
(
struct
copychunk_ioctl
),
(
char
**
)
&
retbuf
,
&
ret_data_len
);
if
(
rc
==
0
)
{
if
(
ret_data_len
!=
sizeof
(
struct
copychunk_ioctl_rsp
))
{
cifs_dbg
(
VFS
,
"invalid cchunk response size
\n
"
);
rc
=
-
EIO
;
goto
cchunk_out
;
}
if
(
retbuf
->
TotalBytesWritten
==
0
)
{
cifs_dbg
(
FYI
,
"no bytes copied
\n
"
);
rc
=
-
EIO
;
goto
cchunk_out
;
}
/*
* Check if server claimed to write more than we asked
*/
if
(
le32_to_cpu
(
retbuf
->
TotalBytesWritten
)
>
le32_to_cpu
(
pcchunk
->
Length
))
{
cifs_dbg
(
VFS
,
"invalid copy chunk response
\n
"
);
rc
=
-
EIO
;
goto
cchunk_out
;
}
if
(
le32_to_cpu
(
retbuf
->
ChunksWritten
)
!=
1
)
{
cifs_dbg
(
VFS
,
"invalid num chunks written
\n
"
);
rc
=
-
EIO
;
goto
cchunk_out
;
}
chunks_copied
++
;
src_off
+=
le32_to_cpu
(
retbuf
->
TotalBytesWritten
);
dest_off
+=
le32_to_cpu
(
retbuf
->
TotalBytesWritten
);
len
-=
le32_to_cpu
(
retbuf
->
TotalBytesWritten
);
cifs_dbg
(
FYI
,
"Chunks %d PartialChunk %d Total %d
\n
"
,
le32_to_cpu
(
retbuf
->
ChunksWritten
),
le32_to_cpu
(
retbuf
->
ChunkBytesWritten
),
le32_to_cpu
(
retbuf
->
TotalBytesWritten
));
}
else
if
(
rc
==
-
EINVAL
)
{
if
(
ret_data_len
!=
sizeof
(
struct
copychunk_ioctl_rsp
))
goto
cchunk_out
;
cifs_dbg
(
FYI
,
"MaxChunks %d BytesChunk %d MaxCopy %d
\n
"
,
le32_to_cpu
(
retbuf
->
ChunksWritten
),
le32_to_cpu
(
retbuf
->
ChunkBytesWritten
),
le32_to_cpu
(
retbuf
->
TotalBytesWritten
));
/*
* Check if this is the first request using these sizes,
* (ie check if copy succeed once with original sizes
* and check if the server gave us different sizes after
* we already updated max sizes on previous request).
* if not then why is the server returning an error now
*/
if
((
chunks_copied
!=
0
)
||
chunk_sizes_updated
)
goto
cchunk_out
;
/* Check that server is not asking us to grow size */
if
(
le32_to_cpu
(
retbuf
->
ChunkBytesWritten
)
<
tcon
->
max_bytes_chunk
)
tcon
->
max_bytes_chunk
=
le32_to_cpu
(
retbuf
->
ChunkBytesWritten
);
else
goto
cchunk_out
;
/* server gave us bogus size */
/* No need to change MaxChunks since already set to 1 */
chunk_sizes_updated
=
true
;
}
}
cchunk_out:
kfree
(
pcchunk
);
return
rc
;
}
static
int
smb2_flush_file
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
smb2_flush_file
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
struct
cifs_fid
*
fid
)
struct
cifs_fid
*
fid
)
{
{
...
@@ -447,6 +694,14 @@ smb2_set_file_size(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -447,6 +694,14 @@ smb2_set_file_size(const unsigned int xid, struct cifs_tcon *tcon,
}
}
static
int
static
int
smb2_set_compression
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
struct
cifsFileInfo
*
cfile
)
{
return
SMB2_set_compression
(
xid
,
tcon
,
cfile
->
fid
.
persistent_fid
,
cfile
->
fid
.
volatile_fid
);
}
static
int
smb2_query_dir_first
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
smb2_query_dir_first
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
const
char
*
path
,
struct
cifs_sb_info
*
cifs_sb
,
const
char
*
path
,
struct
cifs_sb_info
*
cifs_sb
,
struct
cifs_fid
*
fid
,
__u16
search_flags
,
struct
cifs_fid
*
fid
,
__u16
search_flags
,
...
@@ -656,6 +911,17 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -656,6 +911,17 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
}
}
static
void
static
void
smb2_downgrade_oplock
(
struct
TCP_Server_Info
*
server
,
struct
cifsInodeInfo
*
cinode
,
bool
set_level2
)
{
if
(
set_level2
)
server
->
ops
->
set_oplock_level
(
cinode
,
SMB2_OPLOCK_LEVEL_II
,
0
,
NULL
);
else
server
->
ops
->
set_oplock_level
(
cinode
,
0
,
0
,
NULL
);
}
static
void
smb2_set_oplock_level
(
struct
cifsInodeInfo
*
cinode
,
__u32
oplock
,
smb2_set_oplock_level
(
struct
cifsInodeInfo
*
cinode
,
__u32
oplock
,
unsigned
int
epoch
,
bool
*
purge_cache
)
unsigned
int
epoch
,
bool
*
purge_cache
)
{
{
...
@@ -787,6 +1053,7 @@ smb2_create_lease_buf(u8 *lease_key, u8 oplock)
...
@@ -787,6 +1053,7 @@ smb2_create_lease_buf(u8 *lease_key, u8 oplock)
buf
->
ccontext
.
NameOffset
=
cpu_to_le16
(
offsetof
buf
->
ccontext
.
NameOffset
=
cpu_to_le16
(
offsetof
(
struct
create_lease
,
Name
));
(
struct
create_lease
,
Name
));
buf
->
ccontext
.
NameLength
=
cpu_to_le16
(
4
);
buf
->
ccontext
.
NameLength
=
cpu_to_le16
(
4
);
/* SMB2_CREATE_REQUEST_LEASE is "RqLs" */
buf
->
Name
[
0
]
=
'R'
;
buf
->
Name
[
0
]
=
'R'
;
buf
->
Name
[
1
]
=
'q'
;
buf
->
Name
[
1
]
=
'q'
;
buf
->
Name
[
2
]
=
'L'
;
buf
->
Name
[
2
]
=
'L'
;
...
@@ -813,6 +1080,7 @@ smb3_create_lease_buf(u8 *lease_key, u8 oplock)
...
@@ -813,6 +1080,7 @@ smb3_create_lease_buf(u8 *lease_key, u8 oplock)
buf
->
ccontext
.
NameOffset
=
cpu_to_le16
(
offsetof
buf
->
ccontext
.
NameOffset
=
cpu_to_le16
(
offsetof
(
struct
create_lease_v2
,
Name
));
(
struct
create_lease_v2
,
Name
));
buf
->
ccontext
.
NameLength
=
cpu_to_le16
(
4
);
buf
->
ccontext
.
NameLength
=
cpu_to_le16
(
4
);
/* SMB2_CREATE_REQUEST_LEASE is "RqLs" */
buf
->
Name
[
0
]
=
'R'
;
buf
->
Name
[
0
]
=
'R'
;
buf
->
Name
[
1
]
=
'q'
;
buf
->
Name
[
1
]
=
'q'
;
buf
->
Name
[
2
]
=
'L'
;
buf
->
Name
[
2
]
=
'L'
;
...
@@ -861,6 +1129,7 @@ struct smb_version_operations smb20_operations = {
...
@@ -861,6 +1129,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
,
.
downgrade_oplock
=
smb2_downgrade_oplock
,
.
need_neg
=
smb2_need_neg
,
.
need_neg
=
smb2_need_neg
,
.
negotiate
=
smb2_negotiate
,
.
negotiate
=
smb2_negotiate
,
.
negotiate_wsize
=
smb2_negotiate_wsize
,
.
negotiate_wsize
=
smb2_negotiate_wsize
,
...
@@ -869,6 +1138,7 @@ struct smb_version_operations smb20_operations = {
...
@@ -869,6 +1138,7 @@ struct smb_version_operations smb20_operations = {
.
logoff
=
SMB2_logoff
,
.
logoff
=
SMB2_logoff
,
.
tree_connect
=
SMB2_tcon
,
.
tree_connect
=
SMB2_tcon
,
.
tree_disconnect
=
SMB2_tdis
,
.
tree_disconnect
=
SMB2_tdis
,
.
qfs_tcon
=
smb2_qfs_tcon
,
.
is_path_accessible
=
smb2_is_path_accessible
,
.
is_path_accessible
=
smb2_is_path_accessible
,
.
can_echo
=
smb2_can_echo
,
.
can_echo
=
smb2_can_echo
,
.
echo
=
SMB2_echo
,
.
echo
=
SMB2_echo
,
...
@@ -878,6 +1148,7 @@ struct smb_version_operations smb20_operations = {
...
@@ -878,6 +1148,7 @@ struct smb_version_operations smb20_operations = {
.
set_path_size
=
smb2_set_path_size
,
.
set_path_size
=
smb2_set_path_size
,
.
set_file_size
=
smb2_set_file_size
,
.
set_file_size
=
smb2_set_file_size
,
.
set_file_info
=
smb2_set_file_info
,
.
set_file_info
=
smb2_set_file_info
,
.
set_compression
=
smb2_set_compression
,
.
mkdir
=
smb2_mkdir
,
.
mkdir
=
smb2_mkdir
,
.
mkdir_setinfo
=
smb2_mkdir_setinfo
,
.
mkdir_setinfo
=
smb2_mkdir_setinfo
,
.
rmdir
=
smb2_rmdir
,
.
rmdir
=
smb2_rmdir
,
...
@@ -911,6 +1182,7 @@ struct smb_version_operations smb20_operations = {
...
@@ -911,6 +1182,7 @@ struct smb_version_operations smb20_operations = {
.
set_oplock_level
=
smb2_set_oplock_level
,
.
set_oplock_level
=
smb2_set_oplock_level
,
.
create_lease_buf
=
smb2_create_lease_buf
,
.
create_lease_buf
=
smb2_create_lease_buf
,
.
parse_lease_buf
=
smb2_parse_lease_buf
,
.
parse_lease_buf
=
smb2_parse_lease_buf
,
.
clone_range
=
smb2_clone_range
,
};
};
struct
smb_version_operations
smb21_operations
=
{
struct
smb_version_operations
smb21_operations
=
{
...
@@ -932,6 +1204,7 @@ struct smb_version_operations smb21_operations = {
...
@@ -932,6 +1204,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
,
.
downgrade_oplock
=
smb2_downgrade_oplock
,
.
need_neg
=
smb2_need_neg
,
.
need_neg
=
smb2_need_neg
,
.
negotiate
=
smb2_negotiate
,
.
negotiate
=
smb2_negotiate
,
.
negotiate_wsize
=
smb2_negotiate_wsize
,
.
negotiate_wsize
=
smb2_negotiate_wsize
,
...
@@ -940,6 +1213,7 @@ struct smb_version_operations smb21_operations = {
...
@@ -940,6 +1213,7 @@ struct smb_version_operations smb21_operations = {
.
logoff
=
SMB2_logoff
,
.
logoff
=
SMB2_logoff
,
.
tree_connect
=
SMB2_tcon
,
.
tree_connect
=
SMB2_tcon
,
.
tree_disconnect
=
SMB2_tdis
,
.
tree_disconnect
=
SMB2_tdis
,
.
qfs_tcon
=
smb2_qfs_tcon
,
.
is_path_accessible
=
smb2_is_path_accessible
,
.
is_path_accessible
=
smb2_is_path_accessible
,
.
can_echo
=
smb2_can_echo
,
.
can_echo
=
smb2_can_echo
,
.
echo
=
SMB2_echo
,
.
echo
=
SMB2_echo
,
...
@@ -949,6 +1223,7 @@ struct smb_version_operations smb21_operations = {
...
@@ -949,6 +1223,7 @@ struct smb_version_operations smb21_operations = {
.
set_path_size
=
smb2_set_path_size
,
.
set_path_size
=
smb2_set_path_size
,
.
set_file_size
=
smb2_set_file_size
,
.
set_file_size
=
smb2_set_file_size
,
.
set_file_info
=
smb2_set_file_info
,
.
set_file_info
=
smb2_set_file_info
,
.
set_compression
=
smb2_set_compression
,
.
mkdir
=
smb2_mkdir
,
.
mkdir
=
smb2_mkdir
,
.
mkdir_setinfo
=
smb2_mkdir_setinfo
,
.
mkdir_setinfo
=
smb2_mkdir_setinfo
,
.
rmdir
=
smb2_rmdir
,
.
rmdir
=
smb2_rmdir
,
...
@@ -982,6 +1257,7 @@ struct smb_version_operations smb21_operations = {
...
@@ -982,6 +1257,7 @@ struct smb_version_operations smb21_operations = {
.
set_oplock_level
=
smb21_set_oplock_level
,
.
set_oplock_level
=
smb21_set_oplock_level
,
.
create_lease_buf
=
smb2_create_lease_buf
,
.
create_lease_buf
=
smb2_create_lease_buf
,
.
parse_lease_buf
=
smb2_parse_lease_buf
,
.
parse_lease_buf
=
smb2_parse_lease_buf
,
.
clone_range
=
smb2_clone_range
,
};
};
struct
smb_version_operations
smb30_operations
=
{
struct
smb_version_operations
smb30_operations
=
{
...
@@ -1004,6 +1280,7 @@ struct smb_version_operations smb30_operations = {
...
@@ -1004,6 +1280,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
,
.
downgrade_oplock
=
smb2_downgrade_oplock
,
.
need_neg
=
smb2_need_neg
,
.
need_neg
=
smb2_need_neg
,
.
negotiate
=
smb2_negotiate
,
.
negotiate
=
smb2_negotiate
,
.
negotiate_wsize
=
smb2_negotiate_wsize
,
.
negotiate_wsize
=
smb2_negotiate_wsize
,
...
@@ -1012,6 +1289,7 @@ struct smb_version_operations smb30_operations = {
...
@@ -1012,6 +1289,7 @@ struct smb_version_operations smb30_operations = {
.
logoff
=
SMB2_logoff
,
.
logoff
=
SMB2_logoff
,
.
tree_connect
=
SMB2_tcon
,
.
tree_connect
=
SMB2_tcon
,
.
tree_disconnect
=
SMB2_tdis
,
.
tree_disconnect
=
SMB2_tdis
,
.
qfs_tcon
=
smb3_qfs_tcon
,
.
is_path_accessible
=
smb2_is_path_accessible
,
.
is_path_accessible
=
smb2_is_path_accessible
,
.
can_echo
=
smb2_can_echo
,
.
can_echo
=
smb2_can_echo
,
.
echo
=
SMB2_echo
,
.
echo
=
SMB2_echo
,
...
@@ -1021,6 +1299,7 @@ struct smb_version_operations smb30_operations = {
...
@@ -1021,6 +1299,7 @@ struct smb_version_operations smb30_operations = {
.
set_path_size
=
smb2_set_path_size
,
.
set_path_size
=
smb2_set_path_size
,
.
set_file_size
=
smb2_set_file_size
,
.
set_file_size
=
smb2_set_file_size
,
.
set_file_info
=
smb2_set_file_info
,
.
set_file_info
=
smb2_set_file_info
,
.
set_compression
=
smb2_set_compression
,
.
mkdir
=
smb2_mkdir
,
.
mkdir
=
smb2_mkdir
,
.
mkdir_setinfo
=
smb2_mkdir_setinfo
,
.
mkdir_setinfo
=
smb2_mkdir_setinfo
,
.
rmdir
=
smb2_rmdir
,
.
rmdir
=
smb2_rmdir
,
...
@@ -1055,6 +1334,8 @@ struct smb_version_operations smb30_operations = {
...
@@ -1055,6 +1334,8 @@ struct smb_version_operations smb30_operations = {
.
set_oplock_level
=
smb3_set_oplock_level
,
.
set_oplock_level
=
smb3_set_oplock_level
,
.
create_lease_buf
=
smb3_create_lease_buf
,
.
create_lease_buf
=
smb3_create_lease_buf
,
.
parse_lease_buf
=
smb3_parse_lease_buf
,
.
parse_lease_buf
=
smb3_parse_lease_buf
,
.
clone_range
=
smb2_clone_range
,
.
validate_negotiate
=
smb3_validate_negotiate
,
};
};
struct
smb_version_values
smb20_values
=
{
struct
smb_version_values
smb20_values
=
{
...
...
sources/centos70/smb2pdu.c
View file @
9d798057
...
@@ -375,7 +375,12 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
...
@@ -375,7 +375,12 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
req
->
Capabilities
=
cpu_to_le32
(
ses
->
server
->
vals
->
req_capabilities
);
req
->
Capabilities
=
cpu_to_le32
(
ses
->
server
->
vals
->
req_capabilities
);
memcpy
(
req
->
ClientGUID
,
cifs_client_guid
,
SMB2_CLIENT_GUID_SIZE
);
/* ClientGUID must be zero for SMB2.02 dialect */
if
(
ses
->
server
->
vals
->
protocol_id
==
SMB20_PROT_ID
)
memset
(
req
->
ClientGUID
,
0
,
SMB2_CLIENT_GUID_SIZE
);
else
memcpy
(
req
->
ClientGUID
,
server
->
client_guid
,
SMB2_CLIENT_GUID_SIZE
);
iov
[
0
].
iov_base
=
(
char
*
)
req
;
iov
[
0
].
iov_base
=
(
char
*
)
req
;
/* 4 for rfc1002 length field */
/* 4 for rfc1002 length field */
...
@@ -413,7 +418,9 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
...
@@ -413,7 +418,9 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
/* SMB2 only has an extended negflavor */
/* SMB2 only has an extended negflavor */
server
->
negflavor
=
CIFS_NEGFLAVOR_EXTENDED
;
server
->
negflavor
=
CIFS_NEGFLAVOR_EXTENDED
;
server
->
maxBuf
=
le32_to_cpu
(
rsp
->
MaxTransactSize
);
/* set it to the maximum buffer size value we can send with 1 credit */
server
->
maxBuf
=
min_t
(
unsigned
int
,
le32_to_cpu
(
rsp
->
MaxTransactSize
),
SMB2_MAX_BUFFER_SIZE
);
server
->
max_read
=
le32_to_cpu
(
rsp
->
MaxReadSize
);
server
->
max_read
=
le32_to_cpu
(
rsp
->
MaxReadSize
);
server
->
max_write
=
le32_to_cpu
(
rsp
->
MaxWriteSize
);
server
->
max_write
=
le32_to_cpu
(
rsp
->
MaxWriteSize
);
/* BB Do we need to validate the SecurityMode? */
/* BB Do we need to validate the SecurityMode? */
...
@@ -454,6 +461,82 @@ neg_exit:
...
@@ -454,6 +461,82 @@ neg_exit:
return
rc
;
return
rc
;
}
}
int
smb3_validate_negotiate
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
)
{
int
rc
=
0
;
struct
validate_negotiate_info_req
vneg_inbuf
;
struct
validate_negotiate_info_rsp
*
pneg_rsp
;
u32
rsplen
;
cifs_dbg
(
FYI
,
"validate negotiate
\n
"
);
/*
* validation ioctl must be signed, so no point sending this if we
* can not sign it. We could eventually change this to selectively
* 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
* would also enable signing on the mount. Having validation of
* negotiate info for signed connections helps reduce attack vectors
*/
if
(
tcon
->
ses
->
server
->
sign
==
false
)
return
0
;
/* validation requires signing */
vneg_inbuf
.
Capabilities
=
cpu_to_le32
(
tcon
->
ses
->
server
->
vals
->
req_capabilities
);
memcpy
(
vneg_inbuf
.
Guid
,
tcon
->
ses
->
server
->
client_guid
,
SMB2_CLIENT_GUID_SIZE
);
if
(
tcon
->
ses
->
sign
)
vneg_inbuf
.
SecurityMode
=
cpu_to_le16
(
SMB2_NEGOTIATE_SIGNING_REQUIRED
);
else
if
(
global_secflags
&
CIFSSEC_MAY_SIGN
)
vneg_inbuf
.
SecurityMode
=
cpu_to_le16
(
SMB2_NEGOTIATE_SIGNING_ENABLED
);
else
vneg_inbuf
.
SecurityMode
=
0
;
vneg_inbuf
.
DialectCount
=
cpu_to_le16
(
1
);
vneg_inbuf
.
Dialects
[
0
]
=
cpu_to_le16
(
tcon
->
ses
->
server
->
vals
->
protocol_id
);
rc
=
SMB2_ioctl
(
xid
,
tcon
,
NO_FILE_ID
,
NO_FILE_ID
,
FSCTL_VALIDATE_NEGOTIATE_INFO
,
true
/* is_fsctl */
,
(
char
*
)
&
vneg_inbuf
,
sizeof
(
struct
validate_negotiate_info_req
),
(
char
**
)
&
pneg_rsp
,
&
rsplen
);
if
(
rc
!=
0
)
{
cifs_dbg
(
VFS
,
"validate protocol negotiate failed: %d
\n
"
,
rc
);
return
-
EIO
;
}
if
(
rsplen
!=
sizeof
(
struct
validate_negotiate_info_rsp
))
{
cifs_dbg
(
VFS
,
"invalid size of protocol negotiate response
\n
"
);
return
-
EIO
;
}
/* check validate negotiate info response matches what we got earlier */
if
(
pneg_rsp
->
Dialect
!=
cpu_to_le16
(
tcon
->
ses
->
server
->
vals
->
protocol_id
))
goto
vneg_out
;
if
(
pneg_rsp
->
SecurityMode
!=
cpu_to_le16
(
tcon
->
ses
->
server
->
sec_mode
))
goto
vneg_out
;
/* do not validate server guid because not saved at negprot time yet */
if
((
le32_to_cpu
(
pneg_rsp
->
Capabilities
)
|
SMB2_NT_FIND
|
SMB2_LARGE_FILES
)
!=
tcon
->
ses
->
server
->
capabilities
)
goto
vneg_out
;
/* validate negotiate successful */
cifs_dbg
(
FYI
,
"validate negotiate info successful
\n
"
);
return
0
;
vneg_out:
cifs_dbg
(
VFS
,
"protocol revalidation - security settings mismatch
\n
"
);
return
-
EIO
;
}
int
int
SMB2_sess_setup
(
const
unsigned
int
xid
,
struct
cifs_ses
*
ses
,
SMB2_sess_setup
(
const
unsigned
int
xid
,
struct
cifs_ses
*
ses
,
const
struct
nls_table
*
nls_cp
)
const
struct
nls_table
*
nls_cp
)
...
@@ -630,6 +713,8 @@ ssetup_ntlmssp_authenticate:
...
@@ -630,6 +713,8 @@ ssetup_ntlmssp_authenticate:
goto
ssetup_exit
;
goto
ssetup_exit
;
ses
->
session_flags
=
le16_to_cpu
(
rsp
->
SessionFlags
);
ses
->
session_flags
=
le16_to_cpu
(
rsp
->
SessionFlags
);
if
(
ses
->
session_flags
&
SMB2_SESSION_FLAG_ENCRYPT_DATA
)
cifs_dbg
(
VFS
,
"SMB3 encryption not supported yet
\n
"
);
ssetup_exit:
ssetup_exit:
free_rsp_buf
(
resp_buftype
,
rsp
);
free_rsp_buf
(
resp_buftype
,
rsp
);
...
@@ -687,6 +772,10 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses)
...
@@ -687,6 +772,10 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses)
else
else
return
-
EIO
;
return
-
EIO
;
/* no need to send SMB logoff if uid already closed due to reconnect */
if
(
ses
->
need_reconnect
)
goto
smb2_session_already_dead
;
rc
=
small_smb2_init
(
SMB2_LOGOFF
,
NULL
,
(
void
**
)
&
req
);
rc
=
small_smb2_init
(
SMB2_LOGOFF
,
NULL
,
(
void
**
)
&
req
);
if
(
rc
)
if
(
rc
)
return
rc
;
return
rc
;
...
@@ -701,6 +790,8 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses)
...
@@ -701,6 +790,8 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses)
* No tcon so can't do
* No tcon so can't do
* cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]);
* cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]);
*/
*/
smb2_session_already_dead:
return
rc
;
return
rc
;
}
}
...
@@ -711,6 +802,14 @@ static inline void cifs_stats_fail_inc(struct cifs_tcon *tcon, uint16_t code)
...
@@ -711,6 +802,14 @@ static inline void cifs_stats_fail_inc(struct cifs_tcon *tcon, uint16_t code)
#define MAX_SHARENAME_LENGTH (255
/* server */
+ 80
/* share */
+ 1
/* NULL */
)
#define MAX_SHARENAME_LENGTH (255
/* server */
+ 80
/* share */
+ 1
/* NULL */
)
/* These are similar values to what Windows uses */
static
inline
void
init_copy_chunk_defaults
(
struct
cifs_tcon
*
tcon
)
{
tcon
->
max_chunks
=
256
;
tcon
->
max_bytes_chunk
=
1048576
;
tcon
->
max_bytes_copy
=
16777216
;
}
int
int
SMB2_tcon
(
const
unsigned
int
xid
,
struct
cifs_ses
*
ses
,
const
char
*
tree
,
SMB2_tcon
(
const
unsigned
int
xid
,
struct
cifs_ses
*
ses
,
const
char
*
tree
,
struct
cifs_tcon
*
tcon
,
const
struct
nls_table
*
cp
)
struct
cifs_tcon
*
tcon
,
const
struct
nls_table
*
cp
)
...
@@ -812,7 +911,9 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
...
@@ -812,7 +911,9 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
if
((
rsp
->
Capabilities
&
SMB2_SHARE_CAP_DFS
)
&&
if
((
rsp
->
Capabilities
&
SMB2_SHARE_CAP_DFS
)
&&
((
tcon
->
share_flags
&
SHI1005_FLAGS_DFS
)
==
0
))
((
tcon
->
share_flags
&
SHI1005_FLAGS_DFS
)
==
0
))
cifs_dbg
(
VFS
,
"DFS capability contradicts DFS flag
\n
"
);
cifs_dbg
(
VFS
,
"DFS capability contradicts DFS flag
\n
"
);
init_copy_chunk_defaults
(
tcon
);
if
(
tcon
->
ses
->
server
->
ops
->
validate_negotiate
)
rc
=
tcon
->
ses
->
server
->
ops
->
validate_negotiate
(
xid
,
tcon
);
tcon_exit:
tcon_exit:
free_rsp_buf
(
resp_buftype
,
rsp
);
free_rsp_buf
(
resp_buftype
,
rsp
);
kfree
(
unc_path
);
kfree
(
unc_path
);
...
@@ -821,7 +922,8 @@ tcon_exit:
...
@@ -821,7 +922,8 @@ 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
);
tcon
->
bad_network_name
=
true
;
if
(
tcon
)
tcon
->
bad_network_name
=
true
;
}
}
goto
tcon_exit
;
goto
tcon_exit
;
}
}
...
@@ -871,6 +973,7 @@ create_durable_buf(void)
...
@@ -871,6 +973,7 @@ create_durable_buf(void)
buf
->
ccontext
.
NameOffset
=
cpu_to_le16
(
offsetof
buf
->
ccontext
.
NameOffset
=
cpu_to_le16
(
offsetof
(
struct
create_durable
,
Name
));
(
struct
create_durable
,
Name
));
buf
->
ccontext
.
NameLength
=
cpu_to_le16
(
4
);
buf
->
ccontext
.
NameLength
=
cpu_to_le16
(
4
);
/* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DHnQ" */
buf
->
Name
[
0
]
=
'D'
;
buf
->
Name
[
0
]
=
'D'
;
buf
->
Name
[
1
]
=
'H'
;
buf
->
Name
[
1
]
=
'H'
;
buf
->
Name
[
2
]
=
'n'
;
buf
->
Name
[
2
]
=
'n'
;
...
@@ -895,6 +998,7 @@ create_reconnect_durable_buf(struct cifs_fid *fid)
...
@@ -895,6 +998,7 @@ create_reconnect_durable_buf(struct cifs_fid *fid)
buf
->
ccontext
.
NameLength
=
cpu_to_le16
(
4
);
buf
->
ccontext
.
NameLength
=
cpu_to_le16
(
4
);
buf
->
Data
.
Fid
.
PersistentFileId
=
fid
->
persistent_fid
;
buf
->
Data
.
Fid
.
PersistentFileId
=
fid
->
persistent_fid
;
buf
->
Data
.
Fid
.
VolatileFileId
=
fid
->
volatile_fid
;
buf
->
Data
.
Fid
.
VolatileFileId
=
fid
->
volatile_fid
;
/* SMB2_CREATE_DURABLE_HANDLE_RECONNECT is "DHnC" */
buf
->
Name
[
0
]
=
'D'
;
buf
->
Name
[
0
]
=
'D'
;
buf
->
Name
[
1
]
=
'H'
;
buf
->
Name
[
1
]
=
'H'
;
buf
->
Name
[
2
]
=
'n'
;
buf
->
Name
[
2
]
=
'n'
;
...
@@ -994,6 +1098,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
...
@@ -994,6 +1098,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
int
rc
=
0
;
int
rc
=
0
;
unsigned
int
num_iovecs
=
2
;
unsigned
int
num_iovecs
=
2
;
__u32
file_attributes
=
0
;
__u32
file_attributes
=
0
;
char
*
dhc_buf
=
NULL
,
*
lc_buf
=
NULL
;
cifs_dbg
(
FYI
,
"create/open
\n
"
);
cifs_dbg
(
FYI
,
"create/open
\n
"
);
...
@@ -1060,6 +1165,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
...
@@ -1060,6 +1165,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
kfree
(
copy_path
);
kfree
(
copy_path
);
return
rc
;
return
rc
;
}
}
lc_buf
=
iov
[
num_iovecs
-
1
].
iov_base
;
}
}
if
(
*
oplock
==
SMB2_OPLOCK_LEVEL_BATCH
)
{
if
(
*
oplock
==
SMB2_OPLOCK_LEVEL_BATCH
)
{
...
@@ -1074,9 +1180,10 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
...
@@ -1074,9 +1180,10 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
if
(
rc
)
{
if
(
rc
)
{
cifs_small_buf_release
(
req
);
cifs_small_buf_release
(
req
);
kfree
(
copy_path
);
kfree
(
copy_path
);
kfree
(
iov
[
num_iovecs
-
1
].
iov_base
);
kfree
(
lc_buf
);
return
rc
;
return
rc
;
}
}
dhc_buf
=
iov
[
num_iovecs
-
1
].
iov_base
;
}
}
rc
=
SendReceive2
(
xid
,
ses
,
iov
,
num_iovecs
,
&
resp_buftype
,
0
);
rc
=
SendReceive2
(
xid
,
ses
,
iov
,
num_iovecs
,
&
resp_buftype
,
0
);
...
@@ -1108,6 +1215,8 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
...
@@ -1108,6 +1215,8 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
*
oplock
=
rsp
->
OplockLevel
;
*
oplock
=
rsp
->
OplockLevel
;
creat_exit:
creat_exit:
kfree
(
copy_path
);
kfree
(
copy_path
);
kfree
(
lc_buf
);
kfree
(
dhc_buf
);
free_rsp_buf
(
resp_buftype
,
rsp
);
free_rsp_buf
(
resp_buftype
,
rsp
);
return
rc
;
return
rc
;
}
}
...
@@ -1131,6 +1240,7 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
...
@@ -1131,6 +1240,7 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
cifs_dbg
(
FYI
,
"SMB2 IOCTL
\n
"
);
cifs_dbg
(
FYI
,
"SMB2 IOCTL
\n
"
);
*
out_data
=
NULL
;
/* zero out returned data len, in case of error */
/* zero out returned data len, in case of error */
if
(
plen
)
if
(
plen
)
*
plen
=
0
;
*
plen
=
0
;
...
@@ -1176,19 +1286,38 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
...
@@ -1176,19 +1286,38 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
req
->
Flags
=
0
;
req
->
Flags
=
0
;
iov
[
0
].
iov_base
=
(
char
*
)
req
;
iov
[
0
].
iov_base
=
(
char
*
)
req
;
/* 4 for rfc1002 length field */
iov
[
0
].
iov_len
=
get_rfc1002_length
(
req
)
+
4
;
if
(
indatalen
)
/*
inc_rfc1001_len
(
req
,
indatalen
);
* If no input data, the size of ioctl struct in
* protocol spec still includes a 1 byte data buffer,
* but if input data passed to ioctl, we do not
* want to double count this, so we do not send
* the dummy one byte of data in iovec[0] if sending
* input data (in iovec[1]). We also must add 4 bytes
* in first iovec to allow for rfc1002 length field.
*/
if
(
indatalen
)
{
iov
[
0
].
iov_len
=
get_rfc1002_length
(
req
)
+
4
-
1
;
inc_rfc1001_len
(
req
,
indatalen
-
1
);
}
else
iov
[
0
].
iov_len
=
get_rfc1002_length
(
req
)
+
4
;
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
;
if
(
rc
!=
0
)
{
if
(
(
rc
!=
0
)
&&
(
rc
!=
-
EINVAL
)
)
{
if
(
tcon
)
if
(
tcon
)
cifs_stats_fail_inc
(
tcon
,
SMB2_IOCTL_HE
);
cifs_stats_fail_inc
(
tcon
,
SMB2_IOCTL_HE
);
goto
ioctl_exit
;
goto
ioctl_exit
;
}
else
if
(
rc
==
-
EINVAL
)
{
if
((
opcode
!=
FSCTL_SRV_COPYCHUNK_WRITE
)
&&
(
opcode
!=
FSCTL_SRV_COPYCHUNK
))
{
if
(
tcon
)
cifs_stats_fail_inc
(
tcon
,
SMB2_IOCTL_HE
);
goto
ioctl_exit
;
}
}
}
/* check if caller wants to look at return data or just return rc */
/* check if caller wants to look at return data or just return rc */
...
@@ -1228,6 +1357,31 @@ ioctl_exit:
...
@@ -1228,6 +1357,31 @@ ioctl_exit:
return
rc
;
return
rc
;
}
}
/*
* Individual callers to ioctl worker function follow
*/
int
SMB2_set_compression
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
u64
persistent_fid
,
u64
volatile_fid
)
{
int
rc
;
struct
compress_ioctl
fsctl_input
;
char
*
ret_data
=
NULL
;
fsctl_input
.
CompressionState
=
__constant_cpu_to_le16
(
COMPRESSION_FORMAT_DEFAULT
);
rc
=
SMB2_ioctl
(
xid
,
tcon
,
persistent_fid
,
volatile_fid
,
FSCTL_SET_COMPRESSION
,
true
/* is_fsctl */
,
(
char
*
)
&
fsctl_input
/* data input */
,
2
/* in data len */
,
&
ret_data
/* out data */
,
NULL
);
cifs_dbg
(
FYI
,
"set compression rc %d
\n
"
,
rc
);
return
rc
;
}
int
int
SMB2_close
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
SMB2_close
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
u64
persistent_fid
,
u64
volatile_fid
)
u64
persistent_fid
,
u64
volatile_fid
)
...
@@ -2099,11 +2253,9 @@ send_set_info(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -2099,11 +2253,9 @@ send_set_info(const unsigned int xid, struct cifs_tcon *tcon,
rc
=
SendReceive2
(
xid
,
ses
,
iov
,
num
,
&
resp_buftype
,
0
);
rc
=
SendReceive2
(
xid
,
ses
,
iov
,
num
,
&
resp_buftype
,
0
);
rsp
=
(
struct
smb2_set_info_rsp
*
)
iov
[
0
].
iov_base
;
rsp
=
(
struct
smb2_set_info_rsp
*
)
iov
[
0
].
iov_base
;
if
(
rc
!=
0
)
{
if
(
rc
!=
0
)
cifs_stats_fail_inc
(
tcon
,
SMB2_SET_INFO_HE
);
cifs_stats_fail_inc
(
tcon
,
SMB2_SET_INFO_HE
);
goto
out
;
}
out:
free_rsp_buf
(
resp_buftype
,
rsp
);
free_rsp_buf
(
resp_buftype
,
rsp
);
kfree
(
iov
);
kfree
(
iov
);
return
rc
;
return
rc
;
...
@@ -2294,7 +2446,7 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -2294,7 +2446,7 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
rc
=
SendReceive2
(
xid
,
ses
,
&
iov
,
1
,
&
resp_buftype
,
0
);
rc
=
SendReceive2
(
xid
,
ses
,
&
iov
,
1
,
&
resp_buftype
,
0
);
if
(
rc
)
{
if
(
rc
)
{
cifs_stats_fail_inc
(
tcon
,
SMB2_QUERY_INFO_HE
);
cifs_stats_fail_inc
(
tcon
,
SMB2_QUERY_INFO_HE
);
goto
qinf_exit
;
goto
q
fs
inf_exit
;
}
}
rsp
=
(
struct
smb2_query_info_rsp
*
)
iov
.
iov_base
;
rsp
=
(
struct
smb2_query_info_rsp
*
)
iov
.
iov_base
;
...
@@ -2306,7 +2458,70 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -2306,7 +2458,70 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
if
(
!
rc
)
if
(
!
rc
)
copy_fs_info_to_kstatfs
(
info
,
fsdata
);
copy_fs_info_to_kstatfs
(
info
,
fsdata
);
qinf_exit:
qfsinf_exit:
free_rsp_buf
(
resp_buftype
,
iov
.
iov_base
);
return
rc
;
}
int
SMB2_QFS_attr
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
u64
persistent_fid
,
u64
volatile_fid
,
int
level
)
{
struct
smb2_query_info_rsp
*
rsp
=
NULL
;
struct
kvec
iov
;
int
rc
=
0
;
int
resp_buftype
,
max_len
,
min_len
;
struct
cifs_ses
*
ses
=
tcon
->
ses
;
unsigned
int
rsp_len
,
offset
;
if
(
level
==
FS_DEVICE_INFORMATION
)
{
max_len
=
sizeof
(
FILE_SYSTEM_DEVICE_INFO
);
min_len
=
sizeof
(
FILE_SYSTEM_DEVICE_INFO
);
}
else
if
(
level
==
FS_ATTRIBUTE_INFORMATION
)
{
max_len
=
sizeof
(
FILE_SYSTEM_ATTRIBUTE_INFO
);
min_len
=
MIN_FS_ATTR_INFO_SIZE
;
}
else
if
(
level
==
FS_SECTOR_SIZE_INFORMATION
)
{
max_len
=
sizeof
(
struct
smb3_fs_ss_info
);
min_len
=
sizeof
(
struct
smb3_fs_ss_info
);
}
else
{
cifs_dbg
(
FYI
,
"Invalid qfsinfo level %d
\n
"
,
level
);
return
-
EINVAL
;
}
rc
=
build_qfs_info_req
(
&
iov
,
tcon
,
level
,
max_len
,
persistent_fid
,
volatile_fid
);
if
(
rc
)
return
rc
;
rc
=
SendReceive2
(
xid
,
ses
,
&
iov
,
1
,
&
resp_buftype
,
0
);
if
(
rc
)
{
cifs_stats_fail_inc
(
tcon
,
SMB2_QUERY_INFO_HE
);
goto
qfsattr_exit
;
}
rsp
=
(
struct
smb2_query_info_rsp
*
)
iov
.
iov_base
;
rsp_len
=
le32_to_cpu
(
rsp
->
OutputBufferLength
);
offset
=
le16_to_cpu
(
rsp
->
OutputBufferOffset
);
rc
=
validate_buf
(
offset
,
rsp_len
,
&
rsp
->
hdr
,
min_len
);
if
(
rc
)
goto
qfsattr_exit
;
if
(
level
==
FS_ATTRIBUTE_INFORMATION
)
memcpy
(
&
tcon
->
fsAttrInfo
,
4
/* RFC1001 len */
+
offset
+
(
char
*
)
&
rsp
->
hdr
,
min_t
(
unsigned
int
,
rsp_len
,
max_len
));
else
if
(
level
==
FS_DEVICE_INFORMATION
)
memcpy
(
&
tcon
->
fsDevInfo
,
4
/* RFC1001 len */
+
offset
+
(
char
*
)
&
rsp
->
hdr
,
sizeof
(
FILE_SYSTEM_DEVICE_INFO
));
else
if
(
level
==
FS_SECTOR_SIZE_INFORMATION
)
{
struct
smb3_fs_ss_info
*
ss_info
=
(
struct
smb3_fs_ss_info
*
)
(
4
/* RFC1001 len */
+
offset
+
(
char
*
)
&
rsp
->
hdr
);
tcon
->
ss_flags
=
le32_to_cpu
(
ss_info
->
Flags
);
tcon
->
perf_sector_size
=
le32_to_cpu
(
ss_info
->
PhysicalBytesPerSectorForPerf
);
}
qfsattr_exit:
free_rsp_buf
(
resp_buftype
,
iov
.
iov_base
);
free_rsp_buf
(
resp_buftype
,
iov
.
iov_base
);
return
rc
;
return
rc
;
}
}
...
...
sources/centos70/smb2pdu.h
View file @
9d798057
...
@@ -122,6 +122,23 @@ struct smb2_pdu {
...
@@ -122,6 +122,23 @@ struct smb2_pdu {
__le16
StructureSize2
;
/* size of wct area (varies, request specific) */
__le16
StructureSize2
;
/* size of wct area (varies, request specific) */
}
__packed
;
}
__packed
;
struct
smb2_transform_hdr
{
__be32
smb2_buf_length
;
/* big endian on wire */
/* length is only two or three bytes - with
one or two byte type preceding it that MBZ */
__u8
ProtocolId
[
4
];
/* 0xFD 'S' 'M' 'B' */
__u8
Signature
[
16
];
__u8
Nonce
[
11
];
__u8
Reserved
[
5
];
__le32
OriginalMessageSize
;
__u16
Reserved1
;
__le16
EncryptionAlgorithm
;
__u64
SessionId
;
}
__packed
;
/* Encryption Algorithms */
#define SMB2_ENCRYPTION_AES128_CCM __constant_cpu_to_le16(0x0001)
/*
/*
* SMB2 flag definitions
* SMB2 flag definitions
*/
*/
...
@@ -166,8 +183,6 @@ struct smb2_symlink_err_rsp {
...
@@ -166,8 +183,6 @@ struct smb2_symlink_err_rsp {
#define SMB2_CLIENT_GUID_SIZE 16
#define SMB2_CLIENT_GUID_SIZE 16
extern
__u8
cifs_client_guid
[
SMB2_CLIENT_GUID_SIZE
];
struct
smb2_negotiate_req
{
struct
smb2_negotiate_req
{
struct
smb2_hdr
hdr
;
struct
smb2_hdr
hdr
;
__le16
StructureSize
;
/* Must be 36 */
__le16
StructureSize
;
/* Must be 36 */
...
@@ -237,6 +252,7 @@ struct smb2_sess_setup_req {
...
@@ -237,6 +252,7 @@ struct smb2_sess_setup_req {
/* Currently defined SessionFlags */
/* Currently defined SessionFlags */
#define SMB2_SESSION_FLAG_IS_GUEST 0x0001
#define SMB2_SESSION_FLAG_IS_GUEST 0x0001
#define SMB2_SESSION_FLAG_IS_NULL 0x0002
#define SMB2_SESSION_FLAG_IS_NULL 0x0002
#define SMB2_SESSION_FLAG_ENCRYPT_DATA 0x0004
struct
smb2_sess_setup_rsp
{
struct
smb2_sess_setup_rsp
{
struct
smb2_hdr
hdr
;
struct
smb2_hdr
hdr
;
__le16
StructureSize
;
/* Must be 9 */
__le16
StructureSize
;
/* Must be 9 */
...
@@ -419,11 +435,15 @@ struct smb2_tree_disconnect_rsp {
...
@@ -419,11 +435,15 @@ struct smb2_tree_disconnect_rsp {
#define SMB2_CREATE_SD_BUFFER "SecD"
/* security descriptor */
#define SMB2_CREATE_SD_BUFFER "SecD"
/* security descriptor */
#define SMB2_CREATE_DURABLE_HANDLE_REQUEST "DHnQ"
#define SMB2_CREATE_DURABLE_HANDLE_REQUEST "DHnQ"
#define SMB2_CREATE_DURABLE_HANDLE_RECONNECT "DHnC"
#define SMB2_CREATE_DURABLE_HANDLE_RECONNECT "DHnC"
#define SMB2_CREATE_ALLOCATION_SIZE "A
l
Si"
#define SMB2_CREATE_ALLOCATION_SIZE "A
I
Si"
#define SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST "MxAc"
#define SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST "MxAc"
#define SMB2_CREATE_TIMEWARP_REQUEST "TWrp"
#define SMB2_CREATE_TIMEWARP_REQUEST "TWrp"
#define SMB2_CREATE_QUERY_ON_DISK_ID "QFid"
#define SMB2_CREATE_QUERY_ON_DISK_ID "QFid"
#define SMB2_CREATE_REQUEST_LEASE "RqLs"
#define SMB2_CREATE_REQUEST_LEASE "RqLs"
#define SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 "DH2Q"
#define SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 "DH2C"
#define SMB2_CREATE_APP_INSTANCE_ID 0x45BCA66AEFA7F74A9008FA462E144D74
#define SVHDX_OPEN_DEVICE_CONTEXT 0x83CE6F1AD851E0986E34401CC9BCFCE9
struct
smb2_create_req
{
struct
smb2_create_req
{
struct
smb2_hdr
hdr
;
struct
smb2_hdr
hdr
;
...
@@ -534,9 +554,16 @@ struct create_durable {
...
@@ -534,9 +554,16 @@ struct create_durable {
}
Data
;
}
Data
;
}
__packed
;
}
__packed
;
#define COPY_CHUNK_RES_KEY_SIZE 24
struct
resume_key_req
{
char
ResumeKey
[
COPY_CHUNK_RES_KEY_SIZE
];
__le32
ContextLength
;
/* MBZ */
char
Context
[
0
];
/* ignored, Windows sets to 4 bytes of zero */
}
__packed
;
/* this goes in the ioctl buffer when doing a copychunk request */
/* this goes in the ioctl buffer when doing a copychunk request */
struct
copychunk_ioctl
{
struct
copychunk_ioctl
{
char
SourceKey
[
24
];
char
SourceKey
[
COPY_CHUNK_RES_KEY_SIZE
];
__le32
ChunkCount
;
/* we are only sending 1 */
__le32
ChunkCount
;
/* we are only sending 1 */
__le32
Reserved
;
__le32
Reserved
;
/* array will only be one chunk long for us */
/* array will only be one chunk long for us */
...
@@ -546,13 +573,25 @@ struct copychunk_ioctl {
...
@@ -546,13 +573,25 @@ struct copychunk_ioctl {
__u32
Reserved2
;
__u32
Reserved2
;
}
__packed
;
}
__packed
;
/* Response and Request are the same format */
struct
copychunk_ioctl_rsp
{
struct
validate_negotiate_info
{
__le32
ChunksWritten
;
__le32
ChunkBytesWritten
;
__le32
TotalBytesWritten
;
}
__packed
;
struct
validate_negotiate_info_req
{
__le32
Capabilities
;
__le32
Capabilities
;
__u8
Guid
[
SMB2_CLIENT_GUID_SIZE
];
__u8
Guid
[
SMB2_CLIENT_GUID_SIZE
];
__le16
SecurityMode
;
__le16
SecurityMode
;
__le16
DialectCount
;
__le16
DialectCount
;
__le16
Dialect
[
1
];
__le16
Dialects
[
1
];
/* dialect (someday maybe list) client asked for */
}
__packed
;
struct
validate_negotiate_info_rsp
{
__le32
Capabilities
;
__u8
Guid
[
SMB2_CLIENT_GUID_SIZE
];
__le16
SecurityMode
;
__le16
Dialect
;
/* Dialect in use for the connection */
}
__packed
;
}
__packed
;
#define RSS_CAPABLE 0x00000001
#define RSS_CAPABLE 0x00000001
...
@@ -569,6 +608,10 @@ struct network_interface_info_ioctl_rsp {
...
@@ -569,6 +608,10 @@ struct network_interface_info_ioctl_rsp {
#define NO_FILE_ID 0xFFFFFFFFFFFFFFFFULL
/* general ioctls to srv not to file */
#define NO_FILE_ID 0xFFFFFFFFFFFFFFFFULL
/* general ioctls to srv not to file */
struct
compress_ioctl
{
__le16
CompressionState
;
/* See cifspdu.h for possible flag values */
}
__packed
;
struct
smb2_ioctl_req
{
struct
smb2_ioctl_req
{
struct
smb2_hdr
hdr
;
struct
smb2_hdr
hdr
;
__le16
StructureSize
;
/* Must be 57 */
__le16
StructureSize
;
/* Must be 57 */
...
@@ -584,7 +627,7 @@ struct smb2_ioctl_req {
...
@@ -584,7 +627,7 @@ struct smb2_ioctl_req {
__le32
MaxOutputResponse
;
__le32
MaxOutputResponse
;
__le32
Flags
;
__le32
Flags
;
__u32
Reserved2
;
__u32
Reserved2
;
char
Buffer
[
0
];
__u8
Buffer
[
0
];
}
__packed
;
}
__packed
;
struct
smb2_ioctl_rsp
{
struct
smb2_ioctl_rsp
{
...
@@ -870,14 +913,16 @@ struct smb2_lease_ack {
...
@@ -870,14 +913,16 @@ struct smb2_lease_ack {
/* File System Information Classes */
/* File System Information Classes */
#define FS_VOLUME_INFORMATION 1
/* Query */
#define FS_VOLUME_INFORMATION 1
/* Query */
#define FS_LABEL_INFORMATION 2
/*
Set
*/
#define FS_LABEL_INFORMATION 2
/*
Local only
*/
#define FS_SIZE_INFORMATION 3
/* Query */
#define FS_SIZE_INFORMATION 3
/* Query */
#define FS_DEVICE_INFORMATION 4
/* Query */
#define FS_DEVICE_INFORMATION 4
/* Query */
#define FS_ATTRIBUTE_INFORMATION 5
/* Query */
#define FS_ATTRIBUTE_INFORMATION 5
/* Query */
#define FS_CONTROL_INFORMATION 6
/* Query, Set */
#define FS_CONTROL_INFORMATION 6
/* Query, Set */
#define FS_FULL_SIZE_INFORMATION 7
/* Query */
#define FS_FULL_SIZE_INFORMATION 7
/* Query */
#define FS_OBJECT_ID_INFORMATION 8
/* Query, Set */
#define FS_OBJECT_ID_INFORMATION 8
/* Query, Set */
#define FS_DRIVER_PATH_INFORMATION 9
/* Query */
#define FS_DRIVER_PATH_INFORMATION 9
/* Local only */
#define FS_VOLUME_FLAGS_INFORMATION 10
/* Local only */
#define FS_SECTOR_SIZE_INFORMATION 11
/* SMB3 or later. Query */
struct
smb2_fs_full_size_info
{
struct
smb2_fs_full_size_info
{
__le64
TotalAllocationUnits
;
__le64
TotalAllocationUnits
;
...
@@ -887,6 +932,22 @@ struct smb2_fs_full_size_info {
...
@@ -887,6 +932,22 @@ struct smb2_fs_full_size_info {
__le32
BytesPerSector
;
__le32
BytesPerSector
;
}
__packed
;
}
__packed
;
#define SSINFO_FLAGS_ALIGNED_DEVICE 0x00000001
#define SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE 0x00000002
#define SSINFO_FLAGS_NO_SEEK_PENALTY 0x00000004
#define SSINFO_FLAGS_TRIM_ENABLED 0x00000008
/* sector size info struct */
struct
smb3_fs_ss_info
{
__le32
LogicalBytesPerSector
;
__le32
PhysicalBytesPerSectorForAtomicity
;
__le32
PhysicalBytesPerSectorForPerf
;
__le32
FileSystemEffectivePhysicalBytesPerSectorForAtomicity
;
__le32
Flags
;
__le32
ByteOffsetForSectorAlignment
;
__le32
ByteOffsetForPartitionAlignment
;
}
__packed
;
/* partial list of QUERY INFO levels */
/* partial list of QUERY INFO levels */
#define FILE_DIRECTORY_INFORMATION 1
#define FILE_DIRECTORY_INFORMATION 1
#define FILE_FULL_DIRECTORY_INFORMATION 2
#define FILE_FULL_DIRECTORY_INFORMATION 2
...
...
sources/centos70/smb2proto.h
View file @
9d798057
...
@@ -61,7 +61,7 @@ extern void move_smb2_info_to_cifs(FILE_ALL_INFO *dst,
...
@@ -61,7 +61,7 @@ extern void move_smb2_info_to_cifs(FILE_ALL_INFO *dst,
extern
int
smb2_query_path_info
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
extern
int
smb2_query_path_info
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
struct
cifs_sb_info
*
cifs_sb
,
struct
cifs_sb_info
*
cifs_sb
,
const
char
*
full_path
,
FILE_ALL_INFO
*
data
,
const
char
*
full_path
,
FILE_ALL_INFO
*
data
,
bool
*
adjust_tz
);
bool
*
adjust_tz
,
bool
*
symlink
);
extern
int
smb2_set_path_size
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
extern
int
smb2_set_path_size
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
const
char
*
full_path
,
__u64
size
,
const
char
*
full_path
,
__u64
size
,
struct
cifs_sb_info
*
cifs_sb
,
bool
set_alloc
);
struct
cifs_sb_info
*
cifs_sb
,
bool
set_alloc
);
...
@@ -143,12 +143,16 @@ extern int SMB2_set_eof(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -143,12 +143,16 @@ extern int SMB2_set_eof(const unsigned int xid, struct cifs_tcon *tcon,
extern
int
SMB2_set_info
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
extern
int
SMB2_set_info
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
u64
persistent_fid
,
u64
volatile_fid
,
u64
persistent_fid
,
u64
volatile_fid
,
FILE_BASIC_INFO
*
buf
);
FILE_BASIC_INFO
*
buf
);
extern
int
SMB2_set_compression
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
u64
persistent_fid
,
u64
volatile_fid
);
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_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
);
extern
int
SMB2_QFS_attr
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
u64
persistent_file_id
,
u64
volatile_file_id
,
int
lvl
);
extern
int
SMB2_lock
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
extern
int
SMB2_lock
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
const
__u64
persist_fid
,
const
__u64
volatile_fid
,
const
__u64
persist_fid
,
const
__u64
volatile_fid
,
const
__u32
pid
,
const
__u64
length
,
const
__u64
offset
,
const
__u32
pid
,
const
__u64
length
,
const
__u64
offset
,
...
@@ -159,5 +163,6 @@ extern int smb2_lockv(const unsigned int xid, struct cifs_tcon *tcon,
...
@@ -159,5 +163,6 @@ extern int smb2_lockv(const unsigned int xid, struct cifs_tcon *tcon,
struct
smb2_lock_element
*
buf
);
struct
smb2_lock_element
*
buf
);
extern
int
SMB2_lease_break
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
extern
int
SMB2_lease_break
(
const
unsigned
int
xid
,
struct
cifs_tcon
*
tcon
,
__u8
*
lease_key
,
const
__le32
lease_state
);
__u8
*
lease_key
,
const
__le32
lease_state
);
extern
int
smb3_validate_negotiate
(
const
unsigned
int
,
struct
cifs_tcon
*
);
#endif
/* _SMB2PROTO_H */
#endif
/* _SMB2PROTO_H */
sources/centos70/smb2transport.c
View file @
9d798057
...
@@ -466,7 +466,7 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
...
@@ -466,7 +466,7 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
static
inline
void
static
inline
void
smb2_seq_num_into_buf
(
struct
TCP_Server_Info
*
server
,
struct
smb2_hdr
*
hdr
)
smb2_seq_num_into_buf
(
struct
TCP_Server_Info
*
server
,
struct
smb2_hdr
*
hdr
)
{
{
hdr
->
MessageId
=
get_next_mid
(
server
);
hdr
->
MessageId
=
get_next_mid
64
(
server
);
}
}
static
struct
mid_q_entry
*
static
struct
mid_q_entry
*
...
@@ -516,13 +516,19 @@ smb2_get_mid_entry(struct cifs_ses *ses, struct smb2_hdr *buf,
...
@@ -516,13 +516,19 @@ smb2_get_mid_entry(struct cifs_ses *ses, struct smb2_hdr *buf,
return
-
EAGAIN
;
return
-
EAGAIN
;
}
}
if
(
ses
->
status
!=
CifsGood
)
{
if
(
ses
->
status
==
CifsNew
)
{
/* check if SMB2 session is bad because we are setting it up */
if
((
buf
->
Command
!=
SMB2_SESSION_SETUP
)
&&
if
((
buf
->
Command
!=
SMB2_SESSION_SETUP
)
&&
(
buf
->
Command
!=
SMB2_NEGOTIATE
))
(
buf
->
Command
!=
SMB2_NEGOTIATE
))
return
-
EAGAIN
;
return
-
EAGAIN
;
/* else ok - we are setting up session */
/* else ok - we are setting up session */
}
}
if
(
ses
->
status
==
CifsExiting
)
{
if
(
buf
->
Command
!=
SMB2_LOGOFF
)
return
-
EAGAIN
;
/* else ok - we are shutting down the session */
}
*
mid
=
smb2_mid_entry_alloc
(
buf
,
ses
->
server
);
*
mid
=
smb2_mid_entry_alloc
(
buf
,
ses
->
server
);
if
(
*
mid
==
NULL
)
if
(
*
mid
==
NULL
)
return
-
ENOMEM
;
return
-
ENOMEM
;
...
...
sources/centos70/smbfsctl.h
View file @
9d798057
...
@@ -90,16 +90,30 @@
...
@@ -90,16 +90,30 @@
#define FSCTL_LMR_REQUEST_RESILIENCY 0x001401D4
/* BB add struct */
#define FSCTL_LMR_REQUEST_RESILIENCY 0x001401D4
/* BB add struct */
#define FSCTL_LMR_GET_LINK_TRACK_INF 0x001400E8
/* BB add struct */
#define FSCTL_LMR_GET_LINK_TRACK_INF 0x001400E8
/* BB add struct */
#define FSCTL_LMR_SET_LINK_TRACK_INF 0x001400EC
/* BB add struct */
#define FSCTL_LMR_SET_LINK_TRACK_INF 0x001400EC
/* BB add struct */
#define FSCTL_VALIDATE_NEGOTIATE_INFO 0x00140204
/* BB add struct */
#define FSCTL_VALIDATE_NEGOTIATE_INFO 0x00140204
/* Perform server-side data movement */
/* Perform server-side data movement */
#define FSCTL_SRV_COPYCHUNK 0x001440F2
#define FSCTL_SRV_COPYCHUNK 0x001440F2
#define FSCTL_SRV_COPYCHUNK_WRITE 0x001480F2
#define FSCTL_SRV_COPYCHUNK_WRITE 0x001480F2
#define FSCTL_QUERY_NETWORK_INTERFACE_INFO 0x001401FC
/* BB add struct */
#define FSCTL_QUERY_NETWORK_INTERFACE_INFO 0x001401FC
/* BB add struct */
#define FSCTL_SRV_READ_HASH 0x001441BB
/* BB add struct */
#define FSCTL_SRV_READ_HASH 0x001441BB
/* BB add struct */
/* See FSCC 2.1.2.5 */
#define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003
#define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003
#define IO_REPARSE_TAG_HSM 0xC0000004
#define IO_REPARSE_TAG_HSM 0xC0000004
#define IO_REPARSE_TAG_SIS 0x80000007
#define IO_REPARSE_TAG_SIS 0x80000007
#define IO_REPARSE_TAG_HSM2 0x80000006
#define IO_REPARSE_TAG_DRIVER_EXTENDER 0x80000005
/* Used by the DFS filter. See MS-DFSC */
#define IO_REPARSE_TAG_DFS 0x8000000A
/* Used by the DFS filter See MS-DFSC */
#define IO_REPARSE_TAG_DFSR 0x80000012
#define IO_REPARSE_TAG_FILTER_MANAGER 0x8000000B
/* See section MS-FSCC 2.1.2.4 */
#define IO_REPARSE_TAG_SYMLINK 0xA000000C
#define IO_REPARSE_TAG_DEDUP 0x80000013
#define IO_REPARSE_APPXSTREAM 0xC0000014
/* NFS symlinks, Win 8/SMB3 and later */
#define IO_REPARSE_TAG_NFS 0x80000014
/* fsctl flags */
/* fsctl flags */
/* If Flags is set to this value, the request is an FSCTL not ioctl request */
/* If Flags is set to this value, the request is an FSCTL not ioctl request */
...
...
sources/centos70/transport.c
View file @
9d798057
...
@@ -58,7 +58,7 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
...
@@ -58,7 +58,7 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
return
temp
;
return
temp
;
else
{
else
{
memset
(
temp
,
0
,
sizeof
(
struct
mid_q_entry
));
memset
(
temp
,
0
,
sizeof
(
struct
mid_q_entry
));
temp
->
mid
=
smb_buffer
->
Mid
;
/* always LE */
temp
->
mid
=
get_mid
(
smb_buffer
);
temp
->
pid
=
current
->
pid
;
temp
->
pid
=
current
->
pid
;
temp
->
command
=
cpu_to_le16
(
smb_buffer
->
Command
);
temp
->
command
=
cpu_to_le16
(
smb_buffer
->
Command
);
cifs_dbg
(
FYI
,
"For smb_command %d
\n
"
,
smb_buffer
->
Command
);
cifs_dbg
(
FYI
,
"For smb_command %d
\n
"
,
smb_buffer
->
Command
);
...
@@ -439,8 +439,13 @@ static int
...
@@ -439,8 +439,13 @@ static int
wait_for_free_request
(
struct
TCP_Server_Info
*
server
,
const
int
timeout
,
wait_for_free_request
(
struct
TCP_Server_Info
*
server
,
const
int
timeout
,
const
int
optype
)
const
int
optype
)
{
{
return
wait_for_free_credits
(
server
,
timeout
,
int
*
val
;
server
->
ops
->
get_credits_field
(
server
,
optype
));
val
=
server
->
ops
->
get_credits_field
(
server
,
optype
);
/* Since an echo is already inflight, no need to wait to send another */
if
(
*
val
<=
0
&&
optype
==
CIFS_ECHO_OP
)
return
-
EAGAIN
;
return
wait_for_free_credits
(
server
,
timeout
,
val
);
}
}
static
int
allocate_mid
(
struct
cifs_ses
*
ses
,
struct
smb_hdr
*
in_buf
,
static
int
allocate_mid
(
struct
cifs_ses
*
ses
,
struct
smb_hdr
*
in_buf
,
...
@@ -455,13 +460,20 @@ static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf,
...
@@ -455,13 +460,20 @@ static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf,
return
-
EAGAIN
;
return
-
EAGAIN
;
}
}
if
(
ses
->
status
!=
CifsGood
)
{
if
(
ses
->
status
==
CifsNew
)
{
/* check if SMB session is bad because we are setting it up */
if
((
in_buf
->
Command
!=
SMB_COM_SESSION_SETUP_ANDX
)
&&
if
((
in_buf
->
Command
!=
SMB_COM_SESSION_SETUP_ANDX
)
&&
(
in_buf
->
Command
!=
SMB_COM_NEGOTIATE
))
(
in_buf
->
Command
!=
SMB_COM_NEGOTIATE
))
return
-
EAGAIN
;
return
-
EAGAIN
;
/* else ok - we are setting up session */
/* else ok - we are setting up session */
}
}
if
(
ses
->
status
==
CifsExiting
)
{
/* check if SMB session is bad because we are setting it up */
if
(
in_buf
->
Command
!=
SMB_COM_LOGOFF_ANDX
)
return
-
EAGAIN
;
/* else ok - we are shutting down session */
}
*
ppmidQ
=
AllocMidQEntry
(
in_buf
,
ses
->
server
);
*
ppmidQ
=
AllocMidQEntry
(
in_buf
,
ses
->
server
);
if
(
*
ppmidQ
==
NULL
)
if
(
*
ppmidQ
==
NULL
)
return
-
ENOMEM
;
return
-
ENOMEM
;
...
...
sources/centos70/xattr.c
View file @
9d798057
...
@@ -82,9 +82,11 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name)
...
@@ -82,9 +82,11 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name)
goto
remove_ea_exit
;
goto
remove_ea_exit
;
ea_name
+=
XATTR_USER_PREFIX_LEN
;
/* skip past user. prefix */
ea_name
+=
XATTR_USER_PREFIX_LEN
;
/* skip past user. prefix */
rc
=
CIFSSMBSetEA
(
xid
,
pTcon
,
full_path
,
ea_name
,
NULL
,
if
(
pTcon
->
ses
->
server
->
ops
->
set_EA
)
(
__u16
)
0
,
cifs_sb
->
local_nls
,
rc
=
pTcon
->
ses
->
server
->
ops
->
set_EA
(
xid
,
pTcon
,
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MAP_SPECIAL_CHR
);
full_path
,
ea_name
,
NULL
,
(
__u16
)
0
,
cifs_sb
->
local_nls
,
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MAP_SPECIAL_CHR
);
}
}
remove_ea_exit:
remove_ea_exit:
kfree
(
full_path
);
kfree
(
full_path
);
...
@@ -149,18 +151,22 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
...
@@ -149,18 +151,22 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
cifs_dbg
(
FYI
,
"attempt to set cifs inode metadata
\n
"
);
cifs_dbg
(
FYI
,
"attempt to set cifs inode metadata
\n
"
);
ea_name
+=
XATTR_USER_PREFIX_LEN
;
/* skip past user. prefix */
ea_name
+=
XATTR_USER_PREFIX_LEN
;
/* skip past user. prefix */
rc
=
CIFSSMBSetEA
(
xid
,
pTcon
,
full_path
,
ea_name
,
ea_value
,
if
(
pTcon
->
ses
->
server
->
ops
->
set_EA
)
(
__u16
)
value_size
,
cifs_sb
->
local_nls
,
rc
=
pTcon
->
ses
->
server
->
ops
->
set_EA
(
xid
,
pTcon
,
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MAP_SPECIAL_CHR
);
full_path
,
ea_name
,
ea_value
,
(
__u16
)
value_size
,
cifs_sb
->
local_nls
,
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MAP_SPECIAL_CHR
);
}
else
if
(
strncmp
(
ea_name
,
XATTR_OS2_PREFIX
,
XATTR_OS2_PREFIX_LEN
)
}
else
if
(
strncmp
(
ea_name
,
XATTR_OS2_PREFIX
,
XATTR_OS2_PREFIX_LEN
)
==
0
)
{
==
0
)
{
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NO_XATTR
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NO_XATTR
)
goto
set_ea_exit
;
goto
set_ea_exit
;
ea_name
+=
XATTR_OS2_PREFIX_LEN
;
/* skip past os2. prefix */
ea_name
+=
XATTR_OS2_PREFIX_LEN
;
/* skip past os2. prefix */
rc
=
CIFSSMBSetEA
(
xid
,
pTcon
,
full_path
,
ea_name
,
ea_value
,
if
(
pTcon
->
ses
->
server
->
ops
->
set_EA
)
(
__u16
)
value_size
,
cifs_sb
->
local_nls
,
rc
=
pTcon
->
ses
->
server
->
ops
->
set_EA
(
xid
,
pTcon
,
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MAP_SPECIAL_CHR
);
full_path
,
ea_name
,
ea_value
,
(
__u16
)
value_size
,
cifs_sb
->
local_nls
,
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MAP_SPECIAL_CHR
);
}
else
if
(
strncmp
(
ea_name
,
CIFS_XATTR_CIFS_ACL
,
}
else
if
(
strncmp
(
ea_name
,
CIFS_XATTR_CIFS_ACL
,
strlen
(
CIFS_XATTR_CIFS_ACL
))
==
0
)
{
strlen
(
CIFS_XATTR_CIFS_ACL
))
==
0
)
{
#ifdef CONFIG_CIFS_ACL
#ifdef CONFIG_CIFS_ACL
...
@@ -170,8 +176,12 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
...
@@ -170,8 +176,12 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
rc
=
-
ENOMEM
;
rc
=
-
ENOMEM
;
}
else
{
}
else
{
memcpy
(
pacl
,
ea_value
,
value_size
);
memcpy
(
pacl
,
ea_value
,
value_size
);
rc
=
set_cifs_acl
(
pacl
,
value_size
,
if
(
pTcon
->
ses
->
server
->
ops
->
set_acl
)
direntry
->
d_inode
,
full_path
,
CIFS_ACL_DACL
);
rc
=
pTcon
->
ses
->
server
->
ops
->
set_acl
(
pacl
,
value_size
,
direntry
->
d_inode
,
full_path
,
CIFS_ACL_DACL
);
else
rc
=
-
EOPNOTSUPP
;
if
(
rc
==
0
)
/* force revalidate of the inode */
if
(
rc
==
0
)
/* force revalidate of the inode */
CIFS_I
(
direntry
->
d_inode
)
->
time
=
0
;
CIFS_I
(
direntry
->
d_inode
)
->
time
=
0
;
kfree
(
pacl
);
kfree
(
pacl
);
...
@@ -272,17 +282,21 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
...
@@ -272,17 +282,21 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
/* revalidate/getattr then populate from inode */
/* revalidate/getattr then populate from inode */
}
/* BB add else when above is implemented */
}
/* BB add else when above is implemented */
ea_name
+=
XATTR_USER_PREFIX_LEN
;
/* skip past user. prefix */
ea_name
+=
XATTR_USER_PREFIX_LEN
;
/* skip past user. prefix */
rc
=
CIFSSMBQAllEAs
(
xid
,
pTcon
,
full_path
,
ea_name
,
ea_value
,
if
(
pTcon
->
ses
->
server
->
ops
->
query_all_EAs
)
buf_size
,
cifs_sb
->
local_nls
,
rc
=
pTcon
->
ses
->
server
->
ops
->
query_all_EAs
(
xid
,
pTcon
,
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MAP_SPECIAL_CHR
);
full_path
,
ea_name
,
ea_value
,
buf_size
,
cifs_sb
->
local_nls
,
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MAP_SPECIAL_CHR
);
}
else
if
(
strncmp
(
ea_name
,
XATTR_OS2_PREFIX
,
XATTR_OS2_PREFIX_LEN
)
==
0
)
{
}
else
if
(
strncmp
(
ea_name
,
XATTR_OS2_PREFIX
,
XATTR_OS2_PREFIX_LEN
)
==
0
)
{
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NO_XATTR
)
if
(
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_NO_XATTR
)
goto
get_ea_exit
;
goto
get_ea_exit
;
ea_name
+=
XATTR_OS2_PREFIX_LEN
;
/* skip past os2. prefix */
ea_name
+=
XATTR_OS2_PREFIX_LEN
;
/* skip past os2. prefix */
rc
=
CIFSSMBQAllEAs
(
xid
,
pTcon
,
full_path
,
ea_name
,
ea_value
,
if
(
pTcon
->
ses
->
server
->
ops
->
query_all_EAs
)
buf_size
,
cifs_sb
->
local_nls
,
rc
=
pTcon
->
ses
->
server
->
ops
->
query_all_EAs
(
xid
,
pTcon
,
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MAP_SPECIAL_CHR
);
full_path
,
ea_name
,
ea_value
,
buf_size
,
cifs_sb
->
local_nls
,
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MAP_SPECIAL_CHR
);
}
else
if
(
strncmp
(
ea_name
,
POSIX_ACL_XATTR_ACCESS
,
}
else
if
(
strncmp
(
ea_name
,
POSIX_ACL_XATTR_ACCESS
,
strlen
(
POSIX_ACL_XATTR_ACCESS
))
==
0
)
{
strlen
(
POSIX_ACL_XATTR_ACCESS
))
==
0
)
{
#ifdef CONFIG_CIFS_POSIX
#ifdef CONFIG_CIFS_POSIX
...
@@ -313,8 +327,11 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
...
@@ -313,8 +327,11 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
u32
acllen
;
u32
acllen
;
struct
cifs_ntsd
*
pacl
;
struct
cifs_ntsd
*
pacl
;
pacl
=
get_cifs_acl
(
cifs_sb
,
direntry
->
d_inode
,
if
(
pTcon
->
ses
->
server
->
ops
->
get_acl
==
NULL
)
full_path
,
&
acllen
);
goto
get_ea_exit
;
/* rc already EOPNOTSUPP */
pacl
=
pTcon
->
ses
->
server
->
ops
->
get_acl
(
cifs_sb
,
direntry
->
d_inode
,
full_path
,
&
acllen
);
if
(
IS_ERR
(
pacl
))
{
if
(
IS_ERR
(
pacl
))
{
rc
=
PTR_ERR
(
pacl
);
rc
=
PTR_ERR
(
pacl
);
cifs_dbg
(
VFS
,
"%s: error %zd getting sec desc
\n
"
,
cifs_dbg
(
VFS
,
"%s: error %zd getting sec desc
\n
"
,
...
@@ -400,11 +417,12 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
...
@@ -400,11 +417,12 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
/* if proc/fs/cifs/streamstoxattr is set then
/* if proc/fs/cifs/streamstoxattr is set then
search server for EAs or streams to
search server for EAs or streams to
returns as xattrs */
returns as xattrs */
rc
=
CIFSSMBQAllEAs
(
xid
,
pTcon
,
full_path
,
NULL
,
data
,
buf_size
,
cifs_sb
->
local_nls
,
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MAP_SPECIAL_CHR
);
if
(
pTcon
->
ses
->
server
->
ops
->
query_all_EAs
)
rc
=
pTcon
->
ses
->
server
->
ops
->
query_all_EAs
(
xid
,
pTcon
,
full_path
,
NULL
,
data
,
buf_size
,
cifs_sb
->
local_nls
,
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MAP_SPECIAL_CHR
);
list_ea_exit:
list_ea_exit:
kfree
(
full_path
);
kfree
(
full_path
);
free_xid
(
xid
);
free_xid
(
xid
);
...
...
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