Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
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 @@ CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
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