Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
Commits
ec637e3f
Commit
ec637e3f
authored
Dec 12, 2005
by
Steve French
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[CIFS] Avoid extra large buffer allocation (and memcpy) in cifs_readpages
Signed-off-by:
Steve French
<
sfrench@us.ibm.com
>
parent
c89a86bb
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
156 additions
and
108 deletions
+156
-108
fs/cifs/cifs_debug.c
fs/cifs/cifs_debug.c
+19
-20
fs/cifs/cifsfs.c
fs/cifs/cifsfs.c
+3
-2
fs/cifs/cifsglob.h
fs/cifs/cifsglob.h
+7
-1
fs/cifs/cifspdu.h
fs/cifs/cifspdu.h
+5
-1
fs/cifs/cifsproto.h
fs/cifs/cifsproto.h
+8
-6
fs/cifs/cifssmb.c
fs/cifs/cifssmb.c
+58
-35
fs/cifs/connect.c
fs/cifs/connect.c
+1
-1
fs/cifs/file.c
fs/cifs/file.c
+32
-20
fs/cifs/inode.c
fs/cifs/inode.c
+3
-2
fs/cifs/misc.c
fs/cifs/misc.c
+1
-1
fs/cifs/transport.c
fs/cifs/transport.c
+19
-19
No files found.
fs/cifs/cifs_debug.c
View file @
ec637e3f
...
...
@@ -401,8 +401,8 @@ static read_proc_t ntlmv2_enabled_read;
static
write_proc_t
ntlmv2_enabled_write
;
static
read_proc_t
packet_signing_enabled_read
;
static
write_proc_t
packet_signing_enabled_write
;
static
read_proc_t
quota
Enabled_read
;
static
write_proc_t
quota
Enabled_write
;
static
read_proc_t
experim
Enabled_read
;
static
write_proc_t
experim
Enabled_write
;
static
read_proc_t
linuxExtensionsEnabled_read
;
static
write_proc_t
linuxExtensionsEnabled_write
;
...
...
@@ -442,9 +442,9 @@ cifs_proc_init(void)
pde
->
write_proc
=
oplockEnabled_write
;
pde
=
create_proc_read_entry
(
"Experimental"
,
0
,
proc_fs_cifs
,
quota
Enabled_read
,
NULL
);
experim
Enabled_read
,
NULL
);
if
(
pde
)
pde
->
write_proc
=
quota
Enabled_write
;
pde
->
write_proc
=
experim
Enabled_write
;
pde
=
create_proc_read_entry
(
"LinuxExtensionsEnabled"
,
0
,
proc_fs_cifs
,
linuxExtensionsEnabled_read
,
NULL
);
...
...
@@ -586,14 +586,13 @@ oplockEnabled_write(struct file *file, const char __user *buffer,
}
static
int
quota
Enabled_read
(
char
*
page
,
char
**
start
,
off_t
off
,
experim
Enabled_read
(
char
*
page
,
char
**
start
,
off_t
off
,
int
count
,
int
*
eof
,
void
*
data
)
{
int
len
;
len
=
sprintf
(
page
,
"%d
\n
"
,
experimEnabled
);
/* could also check if quotas are enabled in kernel
as a whole first */
len
-=
off
;
*
start
=
page
+
off
;
...
...
@@ -608,21 +607,23 @@ quotaEnabled_read(char *page, char **start, off_t off,
return
len
;
}
static
int
quota
Enabled_write
(
struct
file
*
file
,
const
char
__user
*
buffer
,
experim
Enabled_write
(
struct
file
*
file
,
const
char
__user
*
buffer
,
unsigned
long
count
,
void
*
data
)
{
char
c
;
int
rc
;
char
c
;
int
rc
;
rc
=
get_user
(
c
,
buffer
);
if
(
rc
)
return
rc
;
if
(
c
==
'0'
||
c
==
'n'
||
c
==
'N'
)
experimEnabled
=
0
;
else
if
(
c
==
'1'
||
c
==
'y'
||
c
==
'Y'
)
experimEnabled
=
1
;
rc
=
get_user
(
c
,
buffer
);
if
(
rc
)
return
rc
;
if
(
c
==
'0'
||
c
==
'n'
||
c
==
'N'
)
experimEnabled
=
0
;
else
if
(
c
==
'1'
||
c
==
'y'
||
c
==
'Y'
)
experimEnabled
=
1
;
else
if
(
c
==
'2'
)
experimEnabled
=
2
;
return
count
;
return
count
;
}
static
int
...
...
@@ -632,8 +633,6 @@ linuxExtensionsEnabled_read(char *page, char **start, off_t off,
int
len
;
len
=
sprintf
(
page
,
"%d
\n
"
,
linuxExtEnabled
);
/* could also check if quotas are enabled in kernel
as a whole first */
len
-=
off
;
*
start
=
page
+
off
;
...
...
fs/cifs/cifsfs.c
View file @
ec637e3f
...
...
@@ -733,7 +733,7 @@ cifs_init_request_bufs(void)
kmem_cache_destroy
(
cifs_req_cachep
);
return
-
ENOMEM
;
}
/*
256 (MAX_CIFS_HD
R_SIZE bytes is enough for most SMB responses and
/*
MAX_CIFS_SMALL_BUFFE
R_SIZE bytes is enough for most SMB responses and
almost all handle based requests (but not write response, nor is it
sufficient for path based requests). A smaller size would have
been more efficient (compacting multiple slab items on one 4k page)
...
...
@@ -742,7 +742,8 @@ cifs_init_request_bufs(void)
efficient to alloc 1 per page off the slab compared to 17K (5page)
alloc of large cifs buffers even when page debugging is on */
cifs_sm_req_cachep
=
kmem_cache_create
(
"cifs_small_rq"
,
MAX_CIFS_HDR_SIZE
,
0
,
SLAB_HWCACHE_ALIGN
,
NULL
,
NULL
);
MAX_CIFS_SMALL_BUFFER_SIZE
,
0
,
SLAB_HWCACHE_ALIGN
,
NULL
,
NULL
);
if
(
cifs_sm_req_cachep
==
NULL
)
{
mempool_destroy
(
cifs_req_poolp
);
kmem_cache_destroy
(
cifs_req_cachep
);
...
...
fs/cifs/cifsglob.h
View file @
ec637e3f
...
...
@@ -285,6 +285,7 @@ struct cifs_search_info {
unsigned
endOfSearch
:
1
;
unsigned
emptyDir
:
1
;
unsigned
unicode
:
1
;
unsigned
smallBuf
:
1
;
/* so we know which buf_release function to call */
};
struct
cifsFileInfo
{
...
...
@@ -420,7 +421,12 @@ struct dir_notify_req {
#define MID_RESPONSE_RECEIVED 4
#define MID_RETRY_NEEDED 8
/* session closed while this request out */
#define MID_NO_RESP_NEEDED 0x10
#define MID_SMALL_BUFFER 0x20
/* 112 byte response buffer instead of 4K */
/* Types of response buffer returned from SendReceive2 */
#define CIFS_NO_BUFFER 0
/* Response buffer not returned */
#define CIFS_SMALL_BUFFER 1
#define CIFS_LARGE_BUFFER 2
#define CIFS_IOVEC 4
/* array of response buffers */
/*
*****************************************************************
...
...
fs/cifs/cifspdu.h
View file @
ec637e3f
...
...
@@ -80,7 +80,11 @@
#define NT_TRANSACT_GET_USER_QUOTA 0x07
#define NT_TRANSACT_SET_USER_QUOTA 0x08
#define MAX_CIFS_HDR_SIZE 256
/* is future chained NTCreateXReadX bigger? */
#define MAX_CIFS_SMALL_BUFFER_SIZE 448
/* big enough for most */
/* future chained NTCreateXReadX bigger, but for time being NTCreateX biggest */
/* among the requests (NTCreateX response is bigger with wct of 34) */
#define MAX_CIFS_HDR_SIZE 0x58
/* 4 len + 32 hdr + (2*24 wct) + 2 bct + 2 pad */
#define CIFS_SMALL_PATH 120
/* allows for (448-88)/3 */
/* internal cifs vfs structures */
/*****************************************************************
...
...
fs/cifs/cifsproto.h
View file @
ec637e3f
...
...
@@ -49,7 +49,7 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
int
*
/* bytes returned */
,
const
int
long_op
);
extern
int
SendReceive2
(
const
unsigned
int
/* xid */
,
struct
cifsSesInfo
*
,
struct
kvec
*
,
int
/* nvec to send */
,
int
*
/*
bytes
returned */
,
const
int
long_op
);
int
*
/*
type of buf
returned */
,
const
int
long_op
);
extern
int
checkSMBhdr
(
struct
smb_hdr
*
smb
,
__u16
mid
);
extern
int
checkSMB
(
struct
smb_hdr
*
smb
,
__u16
mid
,
int
length
);
extern
int
is_valid_oplock_break
(
struct
smb_hdr
*
smb
);
...
...
@@ -93,11 +93,12 @@ extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
const
struct
nls_table
*
);
extern
int
CIFSFindFirst
(
const
int
xid
,
struct
cifsTconInfo
*
tcon
,
const
char
*
searchName
,
const
struct
nls_table
*
nls_codepage
,
__u16
*
searchHandle
,
struct
cifs_search_info
*
psrch_inf
,
int
map
,
const
char
dirsep
);
const
char
*
searchName
,
const
struct
nls_table
*
nls_codepage
,
__u16
*
searchHandle
,
struct
cifs_search_info
*
psrch_inf
,
int
map
,
const
char
dirsep
);
extern
int
CIFSFindNext
(
const
int
xid
,
struct
cifsTconInfo
*
tcon
,
__u16
searchHandle
,
struct
cifs_search_info
*
psrch_inf
);
__u16
searchHandle
,
struct
cifs_search_info
*
psrch_inf
);
extern
int
CIFSFindClose
(
const
int
,
struct
cifsTconInfo
*
tcon
,
const
__u16
search_handle
);
...
...
@@ -230,8 +231,9 @@ extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
const
int
smb_file_id
);
extern
int
CIFSSMBRead
(
const
int
xid
,
struct
cifsTconInfo
*
tcon
,
const
int
netfid
,
unsigned
int
count
,
const
__u64
lseek
,
unsigned
int
*
nbytes
,
char
**
buf
);
const
int
netfid
,
unsigned
int
count
,
const
__u64
lseek
,
unsigned
int
*
nbytes
,
char
**
buf
,
int
*
return_buf_type
);
extern
int
CIFSSMBWrite
(
const
int
xid
,
struct
cifsTconInfo
*
tcon
,
const
int
netfid
,
const
unsigned
int
count
,
const
__u64
lseek
,
unsigned
int
*
nbytes
,
...
...
fs/cifs/cifssmb.c
View file @
ec637e3f
...
...
@@ -958,21 +958,19 @@ openRetry:
return
rc
;
}
/* If no buffer passed in, then caller wants to do the copy
as in the case of readpages so the SMB buffer must be
freed by the caller */
int
CIFSSMBRead
(
const
int
xid
,
struct
cifsTconInfo
*
tcon
,
const
int
netfid
,
const
unsigned
int
count
,
const
__u64
lseek
,
unsigned
int
*
nbytes
,
char
**
buf
)
const
int
netfid
,
const
unsigned
int
count
,
const
__u64
lseek
,
unsigned
int
*
nbytes
,
char
**
buf
,
int
*
pbuf_type
)
{
int
rc
=
-
EACCES
;
READ_REQ
*
pSMB
=
NULL
;
READ_RSP
*
pSMBr
=
NULL
;
char
*
pReadData
=
NULL
;
int
bytes_returned
;
int
wct
;
int
resp_buf_type
=
0
;
struct
kvec
iov
[
1
];
cFYI
(
1
,(
"Reading %d bytes on fid %d"
,
count
,
netfid
));
if
(
tcon
->
ses
->
capabilities
&
CAP_LARGE_FILES
)
...
...
@@ -981,8 +979,7 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
wct
=
10
;
/* old style read */
*
nbytes
=
0
;
rc
=
smb_init
(
SMB_COM_READ_ANDX
,
wct
,
tcon
,
(
void
**
)
&
pSMB
,
(
void
**
)
&
pSMBr
);
rc
=
small_smb_init
(
SMB_COM_READ_ANDX
,
wct
,
tcon
,
(
void
**
)
&
pSMB
);
if
(
rc
)
return
rc
;
...
...
@@ -990,13 +987,13 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
if
(
tcon
->
ses
->
server
==
NULL
)
return
-
ECONNABORTED
;
pSMB
->
AndXCommand
=
0xFF
;
/* none */
pSMB
->
AndXCommand
=
0xFF
;
/* none */
pSMB
->
Fid
=
netfid
;
pSMB
->
OffsetLow
=
cpu_to_le32
(
lseek
&
0xFFFFFFFF
);
if
(
wct
==
12
)
pSMB
->
OffsetHigh
=
cpu_to_le32
(
lseek
>>
32
);
else
if
((
lseek
>>
32
)
>
0
)
/* can not handle this big offset for old */
return
-
EIO
;
else
if
((
lseek
>>
32
)
>
0
)
/* can not handle this big offset for old */
return
-
EIO
;
pSMB
->
Remaining
=
0
;
pSMB
->
MaxCount
=
cpu_to_le16
(
count
&
0xFFFF
);
...
...
@@ -1005,14 +1002,18 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
pSMB
->
ByteCount
=
0
;
/* no need to do le conversion since 0 */
else
{
/* old style read */
struct
smb_com_readx_req
*
pSMBW
=
struct
smb_com_readx_req
*
pSMBW
=
(
struct
smb_com_readx_req
*
)
pSMB
;
pSMBW
->
ByteCount
=
0
;
pSMBW
->
ByteCount
=
0
;
}
rc
=
SendReceive
(
xid
,
tcon
->
ses
,
(
struct
smb_hdr
*
)
pSMB
,
(
struct
smb_hdr
*
)
pSMBr
,
&
bytes_returned
,
0
);
iov
[
0
].
iov_base
=
(
char
*
)
pSMB
;
iov
[
0
].
iov_len
=
pSMB
->
hdr
.
smb_buf_length
+
4
;
rc
=
SendReceive2
(
xid
,
tcon
->
ses
,
iov
,
1
/* num iovecs */
,
&
resp_buf_type
,
0
);
cifs_stats_inc
(
&
tcon
->
num_reads
);
pSMBr
=
(
READ_RSP
*
)
iov
[
0
].
iov_base
;
if
(
rc
)
{
cERROR
(
1
,
(
"Send error in read = %d"
,
rc
));
}
else
{
...
...
@@ -1022,33 +1023,43 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
*
nbytes
=
data_length
;
/*check that DataLength would not go beyond end of SMB */
if
((
data_length
>
CIFSMaxBufSize
)
if
((
data_length
>
CIFSMaxBufSize
)
||
(
data_length
>
count
))
{
cFYI
(
1
,(
"bad length %d for count %d"
,
data_length
,
count
));
rc
=
-
EIO
;
*
nbytes
=
0
;
}
else
{
pReadData
=
(
char
*
)
(
&
pSMBr
->
hdr
.
Protocol
)
+
pReadData
=
(
char
*
)
(
&
pSMBr
->
hdr
.
Protocol
)
+
le16_to_cpu
(
pSMBr
->
DataOffset
);
/*
if(rc = copy_to_user(buf, pReadData, data_length)) {
cERROR(1,("Faulting on read rc = %d",rc));
rc = -EFAULT;
}*/
/* can not use copy_to_user when using page cache*/
/*
if(rc = copy_to_user(buf, pReadData, data_length)) {
cERROR(1,("Faulting on read rc = %d",rc));
rc = -EFAULT;
}*/
/* can not use copy_to_user when using page cache*/
if
(
*
buf
)
memcpy
(
*
buf
,
pReadData
,
data_length
);
memcpy
(
*
buf
,
pReadData
,
data_length
);
}
}
if
(
*
buf
)
cifs_buf_release
(
pSMB
);
else
*
buf
=
(
char
*
)
pSMB
;
/* Note: On -EAGAIN error only caller can retry on handle based calls
cifs_small_buf_release
(
pSMB
);
if
(
*
buf
)
{
if
(
resp_buf_type
==
CIFS_SMALL_BUFFER
)
cifs_small_buf_release
(
iov
[
0
].
iov_base
);
else
if
(
resp_buf_type
==
CIFS_LARGE_BUFFER
)
cifs_buf_release
(
iov
[
0
].
iov_base
);
}
else
/* return buffer to caller to free */
/* BB FIXME how do we tell caller if it is not a large buffer */
{
*
buf
=
iov
[
0
].
iov_base
;
if
(
resp_buf_type
==
CIFS_SMALL_BUFFER
)
*
pbuf_type
=
CIFS_SMALL_BUFFER
;
else
if
(
resp_buf_type
==
CIFS_LARGE_BUFFER
)
*
pbuf_type
=
CIFS_LARGE_BUFFER
;
}
/* Note: On -EAGAIN error only caller can retry on handle based calls
since file handle passed in no longer valid */
return
rc
;
}
int
CIFSSMBWrite
(
const
int
xid
,
struct
cifsTconInfo
*
tcon
,
const
int
netfid
,
const
unsigned
int
count
,
...
...
@@ -1163,10 +1174,10 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
{
int
rc
=
-
EACCES
;
WRITE_REQ
*
pSMB
=
NULL
;
int
bytes_returned
,
wct
;
int
wct
;
int
smb_hdr_len
;
int
resp_buf_type
=
0
;
/* BB removeme BB */
cFYI
(
1
,(
"write2 at %lld %d bytes"
,
(
long
long
)
offset
,
count
));
if
(
tcon
->
ses
->
capabilities
&
CAP_LARGE_FILES
)
...
...
@@ -1209,22 +1220,34 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
pSMBW
->
ByteCount
=
cpu_to_le16
(
count
+
5
);
}
iov
[
0
].
iov_base
=
pSMB
;
iov
[
0
].
iov_len
=
smb_hdr_len
+
4
;
if
(
wct
==
14
)
iov
[
0
].
iov_len
=
smb_hdr_len
+
4
;
else
/* wct == 12 pad bigger by four bytes */
iov
[
0
].
iov_len
=
smb_hdr_len
+
8
;
rc
=
SendReceive2
(
xid
,
tcon
->
ses
,
iov
,
n_vec
+
1
,
&
bytes_returned
,
rc
=
SendReceive2
(
xid
,
tcon
->
ses
,
iov
,
n_vec
+
1
,
&
resp_buf_type
,
long_op
);
cifs_stats_inc
(
&
tcon
->
num_writes
);
if
(
rc
)
{
cFYI
(
1
,
(
"Send error Write2 = %d"
,
rc
));
*
nbytes
=
0
;
}
else
if
(
resp_buf_type
==
0
)
{
/* presumably this can not happen, but best to be safe */
rc
=
-
EIO
;
*
nbytes
=
0
;
}
else
{
WRITE_RSP
*
pSMBr
=
(
WRITE_RSP
*
)
pSMB
;
WRITE_RSP
*
pSMBr
=
(
WRITE_RSP
*
)
iov
[
0
].
iov_base
;
*
nbytes
=
le16_to_cpu
(
pSMBr
->
CountHigh
);
*
nbytes
=
(
*
nbytes
)
<<
16
;
*
nbytes
+=
le16_to_cpu
(
pSMBr
->
Count
);
}
cifs_small_buf_release
(
pSMB
);
if
(
resp_buf_type
==
CIFS_SMALL_BUFFER
)
cifs_small_buf_release
(
iov
[
0
].
iov_base
);
else
if
(
resp_buf_type
==
CIFS_LARGE_BUFFER
)
cifs_buf_release
(
iov
[
0
].
iov_base
);
/* Note: On -EAGAIN error only caller can retry on handle based calls
since file handle passed in no longer valid */
...
...
fs/cifs/connect.c
View file @
ec637e3f
...
...
@@ -514,7 +514,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
/* else length ok */
reconnect
=
0
;
if
(
pdu_length
>
MAX_CIFS_
HD
R_SIZE
-
4
)
{
if
(
pdu_length
>
MAX_CIFS_
SMALL_BUFFE
R_SIZE
-
4
)
{
isLargeBuf
=
TRUE
;
memcpy
(
bigbuf
,
smallbuf
,
4
);
smb_buffer
=
bigbuf
;
...
...
fs/cifs/file.c
View file @
ec637e3f
...
...
@@ -555,13 +555,13 @@ int cifs_closedir(struct inode *inode, struct file *file)
}
ptmp
=
pCFileStruct
->
srch_inf
.
ntwrk_buf_start
;
if
(
ptmp
)
{
/* BB removeme BB */
cFYI
(
1
,
(
"freeing smb buf in srch struct in closedir
"
));
cFYI
(
1
,
(
"closedir free smb buf in srch struct
"
));
pCFileStruct
->
srch_inf
.
ntwrk_buf_start
=
NULL
;
cifs_buf_release
(
ptmp
);
}
ptmp
=
pCFileStruct
->
search_resume_name
;
if
(
ptmp
)
{
/* BB removeme BB */
cFYI
(
1
,
(
"freeing resume name in closedir
"
));
cFYI
(
1
,
(
"closedir free resume name
"
));
pCFileStruct
->
search_resume_name
=
NULL
;
kfree
(
ptmp
);
}
...
...
@@ -871,8 +871,8 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
break
;
}
/* BB FIXME We can not sign across two buffers yet */
if
((
experimEnabled
)
&&
((
pTcon
->
ses
->
server
->
secMode
&
(
SECMODE_SIGN_REQUIRED
|
SECMODE_SIGN_ENABLED
))
==
0
)
)
{
if
((
pTcon
->
ses
->
server
->
secMode
&
(
SECMODE_SIGN_REQUIRED
|
SECMODE_SIGN_ENABLED
))
==
0
)
{
struct
kvec
iov
[
2
];
unsigned
int
len
;
...
...
@@ -1424,6 +1424,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
rc
=
-
EAGAIN
;
smb_read_data
=
NULL
;
while
(
rc
==
-
EAGAIN
)
{
int
buf_type
=
CIFS_NO_BUFFER
;
if
((
open_file
->
invalidHandle
)
&&
(
!
open_file
->
closePend
))
{
rc
=
cifs_reopen_file
(
file
->
f_dentry
->
d_inode
,
...
...
@@ -1432,20 +1433,22 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
break
;
}
rc
=
CIFSSMBRead
(
xid
,
pTcon
,
open_file
->
netfid
,
current_read_size
,
*
poffset
,
&
bytes_read
,
&
smb_read_data
);
open_file
->
netfid
,
current_read_size
,
*
poffset
,
&
bytes_read
,
&
smb_read_data
,
&
buf_type
);
pSMBr
=
(
struct
smb_com_read_rsp
*
)
smb_read_data
;
if
(
copy_to_user
(
current_offset
,
smb_read_data
+
4
/* RFC1001 hdr */
+
le16_to_cpu
(
pSMBr
->
DataOffset
),
bytes_read
))
{
rc
=
-
EFAULT
;
FreeXid
(
xid
);
return
rc
;
}
}
if
(
smb_read_data
)
{
cifs_buf_release
(
smb_read_data
);
if
(
buf_type
==
CIFS_SMALL_BUFFER
)
cifs_small_buf_release
(
smb_read_data
);
else
if
(
buf_type
==
CIFS_LARGE_BUFFER
)
cifs_buf_release
(
smb_read_data
);
smb_read_data
=
NULL
;
}
}
...
...
@@ -1478,6 +1481,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
int
xid
;
char
*
current_offset
;
struct
cifsFileInfo
*
open_file
;
int
buf_type
=
CIFS_NO_BUFFER
;
xid
=
GetXid
();
cifs_sb
=
CIFS_SB
(
file
->
f_dentry
->
d_sb
);
...
...
@@ -1514,9 +1518,10 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
break
;
}
rc
=
CIFSSMBRead
(
xid
,
pTcon
,
open_file
->
netfid
,
current_read_size
,
*
poffset
,
&
bytes_read
,
&
current_offset
);
open_file
->
netfid
,
current_read_size
,
*
poffset
,
&
bytes_read
,
&
current_offset
,
&
buf_type
);
}
if
(
rc
||
(
bytes_read
==
0
))
{
if
(
total_read
)
{
...
...
@@ -1614,6 +1619,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
struct
smb_com_read_rsp
*
pSMBr
;
struct
pagevec
lru_pvec
;
struct
cifsFileInfo
*
open_file
;
int
buf_type
=
CIFS_NO_BUFFER
;
xid
=
GetXid
();
if
(
file
->
private_data
==
NULL
)
{
...
...
@@ -1670,14 +1676,17 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
}
rc
=
CIFSSMBRead
(
xid
,
pTcon
,
open_file
->
netfid
,
read_size
,
offset
,
&
bytes_read
,
&
smb_read_data
);
open_file
->
netfid
,
read_size
,
offset
,
&
bytes_read
,
&
smb_read_data
,
&
buf_type
);
/* BB more RC checks ? */
if
(
rc
==
-
EAGAIN
)
{
if
(
smb_read_data
)
{
cifs_buf_release
(
smb_read_data
);
if
(
buf_type
==
CIFS_SMALL_BUFFER
)
cifs_small_buf_release
(
smb_read_data
);
else
if
(
buf_type
==
CIFS_LARGE_BUFFER
)
cifs_buf_release
(
smb_read_data
);
smb_read_data
=
NULL
;
}
}
...
...
@@ -1734,7 +1743,10 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
break
;
}
if
(
smb_read_data
)
{
cifs_buf_release
(
smb_read_data
);
if
(
buf_type
==
CIFS_SMALL_BUFFER
)
cifs_small_buf_release
(
smb_read_data
);
else
if
(
buf_type
==
CIFS_LARGE_BUFFER
)
cifs_buf_release
(
smb_read_data
);
smb_read_data
=
NULL
;
}
bytes_read
=
0
;
...
...
fs/cifs/inode.c
View file @
ec637e3f
...
...
@@ -229,11 +229,12 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
cifs_sb
->
mnt_cifs_flags
&
CIFS_MOUNT_MAP_SPECIAL_CHR
);
if
(
rc
==
0
)
{
int
buf_type
=
CIFS_NO_BUFFER
;
/* Read header */
rc
=
CIFSSMBRead
(
xid
,
pTcon
,
netfid
,
24
/* length */
,
0
/* offset */
,
&
bytes_read
,
&
pbuf
);
&
bytes_read
,
&
pbuf
,
&
buf_type
);
if
((
rc
==
0
)
&&
(
bytes_read
>=
8
))
{
if
(
memcmp
(
"IntxBLK"
,
pbuf
,
8
)
==
0
)
{
cFYI
(
1
,(
"Block device"
));
...
...
@@ -267,7 +268,7 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
}
else
{
inode
->
i_mode
|=
S_IFREG
;
/* then it is a file */
rc
=
-
EOPNOTSUPP
;
/* or some unknown SFU type */
}
}
CIFSSMBClose
(
xid
,
pTcon
,
netfid
);
}
return
rc
;
...
...
fs/cifs/misc.c
View file @
ec637e3f
...
...
@@ -299,7 +299,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
struct
cifsSesInfo
*
ses
;
char
*
temp
=
(
char
*
)
buffer
;
memset
(
temp
,
0
,
MAX_CIFS_HDR_SIZE
);
memset
(
temp
,
0
,
256
);
/* bigger than MAX_CIFS_HDR_SIZE */
buffer
->
smb_buf_length
=
(
2
*
word_count
)
+
sizeof
(
struct
smb_hdr
)
-
...
...
fs/cifs/transport.c
View file @
ec637e3f
...
...
@@ -298,7 +298,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
int
SendReceive2
(
const
unsigned
int
xid
,
struct
cifsSesInfo
*
ses
,
struct
kvec
*
iov
,
int
n_vec
,
int
*
pbytes_returned
,
struct
kvec
*
iov
,
int
n_vec
,
int
*
pRespBufType
/* ret */
,
const
int
long_op
)
{
int
rc
=
0
;
...
...
@@ -306,6 +306,8 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
unsigned
long
timeout
;
struct
mid_q_entry
*
midQ
;
struct
smb_hdr
*
in_buf
=
iov
[
0
].
iov_base
;
*
pRespBufType
=
CIFS_NO_BUFFER
;
/* no response buf yet */
if
(
ses
==
NULL
)
{
cERROR
(
1
,(
"Null smb session"
));
...
...
@@ -491,23 +493,20 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
if
(
midQ
->
resp_buf
&&
(
midQ
->
midState
==
MID_RESPONSE_RECEIVED
))
{
in_buf
->
smb_buf_length
=
receive_len
;
if
(
receive_len
>
500
)
{
/* use multiple buffers on way out */
}
else
{
memcpy
((
char
*
)
in_buf
+
4
,
(
char
*
)
midQ
->
resp_buf
+
4
,
receive_len
);
iov
[
0
].
iov_len
=
receive_len
+
4
;
iov
[
1
].
iov_len
=
0
;
}
iov
[
0
].
iov_base
=
(
char
*
)
midQ
->
resp_buf
;
if
(
midQ
->
largeBuf
)
*
pRespBufType
=
CIFS_LARGE_BUFFER
;
else
*
pRespBufType
=
CIFS_SMALL_BUFFER
;
iov
[
0
].
iov_len
=
receive_len
+
4
;
iov
[
1
].
iov_len
=
0
;
dump_smb
(
in
_buf
,
80
);
dump_smb
(
midQ
->
resp
_buf
,
80
);
/* convert the length into a more usable form */
if
((
receive_len
>
24
)
&&
(
ses
->
server
->
secMode
&
(
SECMODE_SIGN_REQUIRED
|
SECMODE_SIGN_ENABLED
)))
{
rc
=
cifs_verify_signature
(
in
_buf
,
rc
=
cifs_verify_signature
(
midQ
->
resp
_buf
,
ses
->
server
->
mac_signing_key
,
midQ
->
sequence_number
+
1
);
if
(
rc
)
{
...
...
@@ -516,18 +515,19 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
}
}
*
pbytes_returned
=
in_buf
->
smb_buf_length
;
/* BB special case reconnect tid and uid here? */
/* BB special case Errbadpassword and pwdexpired here */
rc
=
map_smb_to_linux_error
(
in
_buf
);
rc
=
map_smb_to_linux_error
(
midQ
->
resp
_buf
);
/* convert ByteCount if necessary */
if
(
receive_len
>=
sizeof
(
struct
smb_hdr
)
-
4
/* do not count RFC1001 header */
+
(
2
*
in_buf
->
WordCount
)
+
2
/* bcc */
)
BCC
(
in_buf
)
=
le16_to_cpu
(
BCC_LE
(
in_buf
));
(
2
*
midQ
->
resp_buf
->
WordCount
)
+
2
/* bcc */
)
BCC
(
midQ
->
resp_buf
)
=
le16_to_cpu
(
BCC_LE
(
midQ
->
resp_buf
));
midQ
->
resp_buf
=
NULL
;
/* mark it so will not be freed
by DeleteMidQEntry */
}
else
{
rc
=
-
EIO
;
cFYI
(
1
,(
"Bad MID state?"
));
...
...
@@ -793,7 +793,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
BCC
(
out_buf
)
=
le16_to_cpu
(
BCC_LE
(
out_buf
));
}
else
{
rc
=
-
EIO
;
cERROR
(
1
,(
"Bad MID state?
"
));
cERROR
(
1
,(
"Bad MID state?"
));
}
}
cifs_no_response_exit:
...
...
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