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
d6e04ae6
Commit
d6e04ae6
authored
Jun 13, 2005
by
Steve French
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[CIFS] CIFS writepage improvements - eliminate double copy
Signed-off-by: Steve French (sfrench@us.ibm.com)
parent
2830077f
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
231 additions
and
76 deletions
+231
-76
fs/cifs/cifsproto.h
fs/cifs/cifsproto.h
+5
-1
fs/cifs/cifssmb.c
fs/cifs/cifssmb.c
+36
-21
fs/cifs/file.c
fs/cifs/file.c
+17
-4
fs/cifs/transport.c
fs/cifs/transport.c
+173
-50
No files found.
fs/cifs/cifsproto.h
View file @
d6e04ae6
...
@@ -47,6 +47,10 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
...
@@ -47,6 +47,10 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
struct
smb_hdr
*
/* input */
,
struct
smb_hdr
*
/* input */
,
struct
smb_hdr
*
/* out */
,
struct
smb_hdr
*
/* out */
,
int
*
/* bytes returned */
,
const
int
long_op
);
int
*
/* bytes returned */
,
const
int
long_op
);
extern
int
SendReceive2
(
const
unsigned
int
/* xid */
,
struct
cifsSesInfo
*
,
struct
smb_hdr
*
/* input */
,
int
hdr_len
,
const
char
*
/* SMB data to send */
,
int
data_len
,
int
*
/* bytes returned */
,
const
int
long_op
);
extern
int
checkSMBhdr
(
struct
smb_hdr
*
smb
,
__u16
mid
);
extern
int
checkSMBhdr
(
struct
smb_hdr
*
smb
,
__u16
mid
);
extern
int
checkSMB
(
struct
smb_hdr
*
smb
,
__u16
mid
,
int
length
);
extern
int
checkSMB
(
struct
smb_hdr
*
smb
,
__u16
mid
,
int
length
);
extern
int
is_valid_oplock_break
(
struct
smb_hdr
*
smb
);
extern
int
is_valid_oplock_break
(
struct
smb_hdr
*
smb
);
...
@@ -222,7 +226,7 @@ extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
...
@@ -222,7 +226,7 @@ extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
extern
int
CIFSSMBWrite2
(
const
int
xid
,
struct
cifsTconInfo
*
tcon
,
extern
int
CIFSSMBWrite2
(
const
int
xid
,
struct
cifsTconInfo
*
tcon
,
const
int
netfid
,
const
unsigned
int
count
,
const
int
netfid
,
const
unsigned
int
count
,
const
__u64
offset
,
unsigned
int
*
nbytes
,
const
__u64
offset
,
unsigned
int
*
nbytes
,
const
char
__user
*
buf
,
const
int
long_op
);
const
char
*
buf
,
const
int
long_op
);
extern
int
CIFSGetSrvInodeNumber
(
const
int
xid
,
struct
cifsTconInfo
*
tcon
,
extern
int
CIFSGetSrvInodeNumber
(
const
int
xid
,
struct
cifsTconInfo
*
tcon
,
const
unsigned
char
*
searchName
,
__u64
*
inode_number
,
const
unsigned
char
*
searchName
,
__u64
*
inode_number
,
const
struct
nls_table
*
nls_codepage
,
const
struct
nls_table
*
nls_codepage
,
...
...
fs/cifs/cifssmb.c
View file @
d6e04ae6
...
@@ -951,56 +951,69 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
...
@@ -951,56 +951,69 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
}
}
#ifdef CONFIG_CIFS_EXPERIMENTAL
#ifdef CONFIG_CIFS_EXPERIMENTAL
int
CIFSSMBWrite2
(
const
int
xid
,
struct
cifsTconInfo
*
tcon
,
int
CIFSSMBWrite2
(
const
int
xid
,
struct
cifsTconInfo
*
tcon
,
const
int
netfid
,
const
unsigned
int
count
,
const
int
netfid
,
const
unsigned
int
count
,
const
__u64
offset
,
unsigned
int
*
nbytes
,
const
char
__user
*
buf
,
const
__u64
offset
,
unsigned
int
*
nbytes
,
const
char
*
buf
,
const
int
long_op
)
const
int
long_op
)
{
{
int
rc
=
-
EACCES
;
int
rc
=
-
EACCES
;
WRITE_REQ
*
pSMB
=
NULL
;
WRITE_REQ
*
pSMB
=
NULL
;
WRITE_RSP
*
pSMBr
=
NULL
;
int
bytes_returned
;
/*int bytes_returned;*/
int
smb_hdr_len
;
unsigned
bytes_sent
;
__u32
bytes_sent
;
__u16
byte_count
;
__u16
byte_count
;
cERROR
(
1
,(
"write2 at %lld %d bytes"
,
offset
,
count
));
/* BB removeme BB */
rc
=
small_smb_init
(
SMB_COM_WRITE_ANDX
,
14
,
tcon
,
(
void
**
)
&
pSMB
);
rc
=
small_smb_init
(
SMB_COM_WRITE_ANDX
,
14
,
tcon
,
(
void
**
)
&
pSMB
);
if
(
rc
)
if
(
rc
)
return
rc
;
return
rc
;
pSMBr
=
(
WRITE_RSP
*
)
pSMB
;
/* BB removeme BB */
/* tcon and ses pointer are checked in smb_init */
/* tcon and ses pointer are checked in smb_init */
if
(
tcon
->
ses
->
server
==
NULL
)
if
(
tcon
->
ses
->
server
==
NULL
)
return
-
ECONNABORTED
;
return
-
ECONNABORTED
;
pSMB
->
AndXCommand
=
0xFF
;
/* none */
pSMB
->
AndXCommand
=
0xFF
;
/* none */
pSMB
->
Fid
=
netfid
;
pSMB
->
Fid
=
netfid
;
pSMB
->
OffsetLow
=
cpu_to_le32
(
offset
&
0xFFFFFFFF
);
pSMB
->
OffsetLow
=
cpu_to_le32
(
offset
&
0xFFFFFFFF
);
pSMB
->
OffsetHigh
=
cpu_to_le32
(
offset
>>
32
);
pSMB
->
OffsetHigh
=
cpu_to_le32
(
offset
>>
32
);
pSMB
->
Reserved
=
0xFFFFFFFF
;
pSMB
->
Reserved
=
0xFFFFFFFF
;
pSMB
->
WriteMode
=
0
;
pSMB
->
WriteMode
=
0
;
pSMB
->
Remaining
=
0
;
pSMB
->
Remaining
=
0
;
bytes_sent
=
(
tcon
->
ses
->
server
->
maxBuf
-
MAX_CIFS_HDR_SIZE
)
&
~
0xFF
;
/* Can increase buffer size if buffer is big enough in some cases - ie
can send more if LARGE_WRITE_X capability returned by the server and if
our buffer is big enough or if we convert to iovecs on socket writes
and eliminate the copy to the CIFS buffer */
if
(
tcon
->
ses
->
capabilities
&
CAP_LARGE_WRITE_X
)
{
bytes_sent
=
min_t
(
const
unsigned
int
,
CIFSMaxBufSize
,
count
);
}
else
{
bytes_sent
=
(
tcon
->
ses
->
server
->
maxBuf
-
MAX_CIFS_HDR_SIZE
)
&
~
0xFF
;
}
if
(
bytes_sent
>
count
)
if
(
bytes_sent
>
count
)
bytes_sent
=
count
;
bytes_sent
=
count
;
pSMB
->
DataLengthHigh
=
0
;
pSMB
->
DataOffset
=
pSMB
->
DataOffset
=
cpu_to_le16
(
offsetof
(
struct
smb_com_write_req
,
Data
)
-
4
);
cpu_to_le16
(
offsetof
(
struct
smb_com_write_req
,
Data
)
-
4
);
byte_count
=
bytes_sent
+
1
/* pad */
;
byte_count
=
bytes_sent
+
1
/* pad */
;
/* BB fix this for sends > 64K */
pSMB
->
DataLengthLow
=
cpu_to_le16
(
bytes_sent
);
pSMB
->
DataLengthLow
=
cpu_to_le16
(
bytes_sent
&
0xFFFF
);
pSMB
->
DataLengthHigh
=
0
;
pSMB
->
DataLengthHigh
=
cpu_to_le16
(
bytes_sent
>>
16
);
pSMB
->
hdr
.
smb_buf_length
+=
byte_count
;
smb_hdr_len
=
pSMB
->
hdr
.
smb_buf_length
+
1
;
/* hdr + 1 byte pad */
pSMB
->
hdr
.
smb_buf_length
+=
bytes_sent
+
1
;
pSMB
->
ByteCount
=
cpu_to_le16
(
byte_count
);
pSMB
->
ByteCount
=
cpu_to_le16
(
byte_count
);
/* rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB
,
rc
=
SendReceive2
(
xid
,
tcon
->
ses
,
(
struct
smb_hdr
*
)
pSMB
,
smb_hdr_len
,
(struct smb_hdr *) pSMBr, buf, buflen, &bytes_returned, long_op); */
/* BB fixme BB */
buf
,
bytes_sent
,
&
bytes_returned
,
long_op
);
if
(
rc
)
{
if
(
rc
)
{
cFYI
(
1
,
(
"Send error in write
2 (large write)
= %d"
,
rc
));
cFYI
(
1
,
(
"Send error in write = %d"
,
rc
));
*
nbytes
=
0
;
*
nbytes
=
0
;
}
else
}
else
{
*
nbytes
=
le16_to_cpu
(
pSMBr
->
Count
);
WRITE_RSP
*
pSMBr
=
(
WRITE_RSP
*
)
pSMB
;
*
nbytes
=
le16_to_cpu
(
pSMBr
->
CountHigh
);
*
nbytes
=
(
*
nbytes
)
<<
16
;
*
nbytes
+=
le16_to_cpu
(
pSMBr
->
Count
);
}
cifs_small_buf_release
(
pSMB
);
cifs_small_buf_release
(
pSMB
);
...
@@ -1009,6 +1022,8 @@ int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
...
@@ -1009,6 +1022,8 @@ int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
return
rc
;
return
rc
;
}
}
#endif
/* CIFS_EXPERIMENTAL */
#endif
/* CIFS_EXPERIMENTAL */
int
int
...
...
fs/cifs/file.c
View file @
d6e04ae6
...
@@ -791,9 +791,8 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
...
@@ -791,9 +791,8 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
pTcon
=
cifs_sb
->
tcon
;
pTcon
=
cifs_sb
->
tcon
;
/* cFYI(1,
cFYI
(
1
,(
" write %d bytes to offset %lld of %s"
,
write_size
,
(" write %d bytes to offset %lld of %s", write_size,
*
poffset
,
file
->
f_dentry
->
d_name
.
name
));
/* BB removeme BB */
*poffset, file->f_dentry->d_name.name)); */
if
(
file
->
private_data
==
NULL
)
if
(
file
->
private_data
==
NULL
)
return
-
EBADF
;
return
-
EBADF
;
...
@@ -846,7 +845,21 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
...
@@ -846,7 +845,21 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
if
(
rc
!=
0
)
if
(
rc
!=
0
)
break
;
break
;
}
}
#ifdef CIFS_EXPERIMENTAL
/* BB FIXME We can not sign across two buffers yet */
cERROR
(
1
,(
"checking signing"
));
/* BB removeme BB */
if
(
pTcon
->
ses
->
server
->
secMode
&
(
SECMODE_SIGN_REQUIRED
|
SECMODE_SIGN_ENABLED
)
==
0
)
rc
=
CIFSSMBWrite2
(
xid
,
pTcon
,
open_file
->
netfid
,
min_t
(
const
int
,
cifs_sb
->
wsize
,
write_size
-
total_written
),
*
poffset
,
&
bytes_written
,
write_data
+
total_written
,
long_op
);
}
else
/* BB FIXME fixup indentation of line below */
#endif
rc
=
CIFSSMBWrite
(
xid
,
pTcon
,
rc
=
CIFSSMBWrite
(
xid
,
pTcon
,
open_file
->
netfid
,
open_file
->
netfid
,
min_t
(
const
int
,
cifs_sb
->
wsize
,
min_t
(
const
int
,
cifs_sb
->
wsize
,
...
...
fs/cifs/transport.c
View file @
d6e04ae6
...
@@ -49,7 +49,8 @@ AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
...
@@ -49,7 +49,8 @@ AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
return
NULL
;
return
NULL
;
}
}
temp
=
(
struct
mid_q_entry
*
)
mempool_alloc
(
cifs_mid_poolp
,
SLAB_KERNEL
|
SLAB_NOFS
);
temp
=
(
struct
mid_q_entry
*
)
mempool_alloc
(
cifs_mid_poolp
,
SLAB_KERNEL
|
SLAB_NOFS
);
if
(
temp
==
NULL
)
if
(
temp
==
NULL
)
return
temp
;
return
temp
;
else
{
else
{
...
@@ -179,27 +180,24 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
...
@@ -179,27 +180,24 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
return
rc
;
return
rc
;
}
}
#ifdef CIFS_EXPERIMENTAL
#ifdef CONFIG_CIFS_EXPERIMENTAL
/* BB finish off this function, adding support for writing set of pages as iovec */
static
int
/* and also adding support for operations that need to parse the response smb */
smb_send2
(
struct
socket
*
ssocket
,
struct
smb_hdr
*
smb_buffer
,
unsigned
int
smb_hdr_length
,
const
char
*
data
,
unsigned
int
datalen
,
int
struct
sockaddr
*
sin
)
smb_sendv
(
struct
socket
*
ssocket
,
struct
smb_hdr
*
smb_buffer
,
unsigned
int
smb_buf_length
,
struct
kvec
*
write_vector
/* page list */
,
struct
sockaddr
*
sin
)
{
{
int
rc
=
0
;
int
rc
=
0
;
int
i
=
0
;
int
i
=
0
;
struct
msghdr
smb_msg
;
struct
msghdr
smb_msg
;
number_of_pages
+=
1
;
/* account for SMB header */
struct
kvec
iov
[
2
];
struct
kvec
*
piov
=
kmalloc
(
number_of_pages
*
sizeof
(
struct
kvec
));
unsigned
len
=
smb_hdr_length
+
4
;
unsigned
len
=
smb_buf_length
+
4
;
if
(
ssocket
==
NULL
)
if
(
ssocket
==
NULL
)
return
-
ENOTSOCK
;
/* BB eventually add reconnect code here */
return
-
ENOTSOCK
;
/* BB eventually add reconnect code here */
iov
.
iov_base
=
smb_buffer
;
iov
[
0
].
iov_base
=
smb_buffer
;
iov
.
iov_len
=
len
;
iov
[
0
].
iov_len
=
len
;
iov
[
1
].
iov_base
=
data
;
iov
[
2
].
iov_len
=
datalen
;
smb_msg
.
msg_name
=
sin
;
smb_msg
.
msg_name
=
sin
;
smb_msg
.
msg_namelen
=
sizeof
(
struct
sockaddr
);
smb_msg
.
msg_namelen
=
sizeof
(
struct
sockaddr
);
smb_msg
.
msg_control
=
NULL
;
smb_msg
.
msg_control
=
NULL
;
...
@@ -212,12 +210,11 @@ smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer,
...
@@ -212,12 +210,11 @@ smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer,
Flags2 is converted in SendReceive */
Flags2 is converted in SendReceive */
smb_buffer
->
smb_buf_length
=
cpu_to_be32
(
smb_buffer
->
smb_buf_length
);
smb_buffer
->
smb_buf_length
=
cpu_to_be32
(
smb_buffer
->
smb_buf_length
);
cFYI
(
1
,
(
"Sending smb of length %d "
,
smb_buf_length
));
cFYI
(
1
,
(
"Sending smb of length %d "
,
len
+
datalen
));
dump_smb
(
smb_buffer
,
len
);
dump_smb
(
smb_buffer
,
len
);
while
(
len
>
0
)
{
while
(
len
+
datalen
>
0
)
{
rc
=
kernel_sendmsg
(
ssocket
,
&
smb_msg
,
&
iov
,
number_of_pages
,
rc
=
kernel_sendmsg
(
ssocket
,
&
smb_msg
,
iov
,
2
,
len
);
len
);
if
((
rc
==
-
ENOSPC
)
||
(
rc
==
-
EAGAIN
))
{
if
((
rc
==
-
ENOSPC
)
||
(
rc
==
-
EAGAIN
))
{
i
++
;
i
++
;
if
(
i
>
60
)
{
if
(
i
>
60
)
{
...
@@ -232,9 +229,22 @@ smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer,
...
@@ -232,9 +229,22 @@ smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer,
}
}
if
(
rc
<
0
)
if
(
rc
<
0
)
break
;
break
;
iov
.
iov_base
+=
rc
;
if
(
iov
[
0
].
iov_len
>
0
)
{
iov
.
iov_len
-=
rc
;
if
(
rc
>=
len
)
{
len
-=
rc
;
iov
[
0
].
iov_len
=
0
;
rc
-=
len
;
}
else
{
/* some of hdr was not sent */
len
-=
rc
;
iov
[
0
].
iov_len
-=
rc
;
iov
[
0
].
iov_base
+=
rc
;
continue
;
}
}
if
((
iov
[
0
].
iov_len
==
0
)
&&
(
rc
>
0
)){
iov
[
1
].
iov_base
+=
rc
;
iov
[
1
].
iov_len
-=
rc
;
datalen
-=
rc
;
}
}
}
if
(
rc
<
0
)
{
if
(
rc
<
0
)
{
...
@@ -246,14 +256,15 @@ smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer,
...
@@ -246,14 +256,15 @@ smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer,
return
rc
;
return
rc
;
}
}
int
int
CIFSSendRcv
(
const
unsigned
int
xid
,
struct
cifsSesInfo
*
ses
,
SendReceive2
(
const
unsigned
int
xid
,
struct
cifsSesInfo
*
ses
,
struct
smb_hdr
*
in_buf
,
struct
kvec
*
write_vector
/* page list */
,
int
*
pbytes_returned
,
const
int
long_op
)
struct
smb_hdr
*
in_buf
,
int
hdrlen
,
const
char
*
data
,
int
datalen
,
int
*
pbytes_returned
,
const
int
long_op
)
{
{
int
rc
=
0
;
int
rc
=
0
;
unsigned
long
timeout
=
15
*
HZ
;
unsigned
int
receive_len
;
struct
mid_q_entry
*
midQ
=
NULL
;
unsigned
long
timeout
;
struct
mid_q_entry
*
midQ
;
if
(
ses
==
NULL
)
{
if
(
ses
==
NULL
)
{
cERROR
(
1
,(
"Null smb session"
));
cERROR
(
1
,(
"Null smb session"
));
...
@@ -263,14 +274,8 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
...
@@ -263,14 +274,8 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
cERROR
(
1
,(
"Null tcp session"
));
cERROR
(
1
,(
"Null tcp session"
));
return
-
EIO
;
return
-
EIO
;
}
}
if
(
pbytes_returned
==
NULL
)
return
-
EIO
;
else
*
pbytes_returned
=
0
;
if
(
ses
->
server
->
tcpStatus
==
CifsExiting
)
if
(
ses
->
server
->
tcpStatus
==
CIFS_EXITING
)
return
-
ENOENT
;
return
-
ENOENT
;
/* Ensure that we do not send more than 50 overlapping requests
/* Ensure that we do not send more than 50 overlapping requests
...
@@ -282,7 +287,8 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
...
@@ -282,7 +287,8 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
}
else
{
}
else
{
spin_lock
(
&
GlobalMid_Lock
);
spin_lock
(
&
GlobalMid_Lock
);
while
(
1
)
{
while
(
1
)
{
if
(
atomic_read
(
&
ses
->
server
->
inFlight
)
>=
cifs_max_pending
){
if
(
atomic_read
(
&
ses
->
server
->
inFlight
)
>=
cifs_max_pending
){
spin_unlock
(
&
GlobalMid_Lock
);
spin_unlock
(
&
GlobalMid_Lock
);
wait_event
(
ses
->
server
->
request_q
,
wait_event
(
ses
->
server
->
request_q
,
atomic_read
(
&
ses
->
server
->
inFlight
)
atomic_read
(
&
ses
->
server
->
inFlight
)
...
@@ -314,17 +320,17 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
...
@@ -314,17 +320,17 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
if
(
ses
->
server
->
tcpStatus
==
CifsExiting
)
{
if
(
ses
->
server
->
tcpStatus
==
CifsExiting
)
{
rc
=
-
ENOENT
;
rc
=
-
ENOENT
;
goto
cifs_out_label
;
goto
out_unlock2
;
}
else
if
(
ses
->
server
->
tcpStatus
==
CifsNeedReconnect
)
{
}
else
if
(
ses
->
server
->
tcpStatus
==
CifsNeedReconnect
)
{
cFYI
(
1
,(
"tcp session dead - return to caller to retry"
));
cFYI
(
1
,(
"tcp session dead - return to caller to retry"
));
rc
=
-
EAGAIN
;
rc
=
-
EAGAIN
;
goto
cifs_out_label
;
goto
out_unlock2
;
}
else
if
(
ses
->
status
!=
CifsGood
)
{
}
else
if
(
ses
->
status
!=
CifsGood
)
{
/* check if SMB session is bad because we are setting it up */
/* 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
))
{
rc
=
-
EAGAIN
;
rc
=
-
EAGAIN
;
goto
cifs_out_label
;
goto
out_unlock2
;
}
/* else ok - we are setting up session */
}
/* else ok - we are setting up session */
}
}
midQ
=
AllocMidQEntry
(
in_buf
,
ses
);
midQ
=
AllocMidQEntry
(
in_buf
,
ses
);
...
@@ -352,13 +358,12 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
...
@@ -352,13 +358,12 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
return
-
EIO
;
return
-
EIO
;
}
}
/* BB can we sign efficiently in this path?
*/
/* BB FIXME
*/
rc
=
cifs_sign_smb
(
in_buf
,
ses
->
server
,
&
midQ
->
sequence_number
);
/* rc = cifs_sign_smb2(in_buf, data, ses->server, &midQ->sequence_number); */
midQ
->
midState
=
MID_REQUEST_SUBMITTED
;
midQ
->
midState
=
MID_REQUEST_SUBMITTED
;
/* rc = smb_sendv(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
rc
=
smb_send2
(
ses
->
server
->
ssocket
,
in_buf
,
hdrlen
,
data
,
datalen
,
piovec,
(
struct
sockaddr
*
)
&
(
ses
->
server
->
addr
.
sockAddr
));
(struct sockaddr *) &(ses->server->addr.sockAddr));*/
if
(
rc
<
0
)
{
if
(
rc
<
0
)
{
DeleteMidQEntry
(
midQ
);
DeleteMidQEntry
(
midQ
);
up
(
&
ses
->
server
->
tcpSem
);
up
(
&
ses
->
server
->
tcpSem
);
...
@@ -370,19 +375,137 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
...
@@ -370,19 +375,137 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
return
rc
;
return
rc
;
}
else
}
else
up
(
&
ses
->
server
->
tcpSem
);
up
(
&
ses
->
server
->
tcpSem
);
cifs_out_label:
if
(
long_op
==
-
1
)
if
(
midQ
)
goto
cifs_no_response_exit2
;
DeleteMidQEntry
(
midQ
);
else
if
(
long_op
==
2
)
/* writes past end of file can take loong time */
timeout
=
300
*
HZ
;
else
if
(
long_op
==
1
)
timeout
=
45
*
HZ
;
/* should be greater than
servers oplock break timeout (about 43 seconds) */
else
if
(
long_op
>
2
)
{
timeout
=
MAX_SCHEDULE_TIMEOUT
;
}
else
timeout
=
15
*
HZ
;
/* wait for 15 seconds or until woken up due to response arriving or
due to last connection to this server being unmounted */
if
(
signal_pending
(
current
))
{
/* if signal pending do not hold up user for full smb timeout
but we still give response a change to complete */
timeout
=
2
*
HZ
;
}
/* No user interrupts in wait - wreaks havoc with performance */
if
(
timeout
!=
MAX_SCHEDULE_TIMEOUT
)
{
timeout
+=
jiffies
;
wait_event
(
ses
->
server
->
response_q
,
(
!
(
midQ
->
midState
&
MID_REQUEST_SUBMITTED
))
||
time_after
(
jiffies
,
timeout
)
||
((
ses
->
server
->
tcpStatus
!=
CifsGood
)
&&
(
ses
->
server
->
tcpStatus
!=
CifsNew
)));
}
else
{
wait_event
(
ses
->
server
->
response_q
,
(
!
(
midQ
->
midState
&
MID_REQUEST_SUBMITTED
))
||
((
ses
->
server
->
tcpStatus
!=
CifsGood
)
&&
(
ses
->
server
->
tcpStatus
!=
CifsNew
)));
}
spin_lock
(
&
GlobalMid_Lock
);
if
(
midQ
->
resp_buf
)
{
spin_unlock
(
&
GlobalMid_Lock
);
receive_len
=
be32_to_cpu
(
*
(
__be32
*
)
midQ
->
resp_buf
);
}
else
{
cERROR
(
1
,(
"No response buffer"
));
if
(
midQ
->
midState
==
MID_REQUEST_SUBMITTED
)
{
if
(
ses
->
server
->
tcpStatus
==
CifsExiting
)
rc
=
-
EHOSTDOWN
;
else
{
ses
->
server
->
tcpStatus
=
CifsNeedReconnect
;
midQ
->
midState
=
MID_RETRY_NEEDED
;
}
}
if
(
rc
!=
-
EHOSTDOWN
)
{
if
(
midQ
->
midState
==
MID_RETRY_NEEDED
)
{
rc
=
-
EAGAIN
;
cFYI
(
1
,(
"marking request for retry"
));
}
else
{
rc
=
-
EIO
;
}
}
spin_unlock
(
&
GlobalMid_Lock
);
DeleteMidQEntry
(
midQ
);
/* If not lock req, update # of requests on wire to server */
if
(
long_op
<
3
)
{
atomic_dec
(
&
ses
->
server
->
inFlight
);
wake_up
(
&
ses
->
server
->
request_q
);
}
return
rc
;
}
if
(
receive_len
>
CIFSMaxBufSize
+
MAX_CIFS_HDR_SIZE
)
{
cERROR
(
1
,
(
"Frame too large received. Length: %d Xid: %d"
,
receive_len
,
xid
));
rc
=
-
EIO
;
}
else
{
/* rcvd frame is ok */
if
(
midQ
->
resp_buf
&&
(
midQ
->
midState
==
MID_RESPONSE_RECEIVED
))
{
in_buf
->
smb_buf_length
=
receive_len
;
/* BB verify that length would not overrun small buf */
memcpy
((
char
*
)
in_buf
+
4
,
(
char
*
)
midQ
->
resp_buf
+
4
,
receive_len
);
dump_smb
(
in_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
,
ses
->
server
->
mac_signing_key
,
midQ
->
sequence_number
+
1
);
if
(
rc
)
{
cERROR
(
1
,(
"Unexpected SMB signature"
));
/* BB FIXME add code to kill session */
}
}
*
pbytes_returned
=
in_buf
->
smb_buf_length
;
/* BB special case reconnect tid and uid here? */
rc
=
map_smb_to_linux_error
(
in_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
(
in_buf
));
}
else
{
rc
=
-
EIO
;
cFYI
(
1
,(
"Bad MID state? "
));
}
}
cifs_no_response_exit2:
DeleteMidQEntry
(
midQ
);
if
(
long_op
<
3
)
{
if
(
long_op
<
3
)
{
atomic_dec
(
&
ses
->
server
->
inFlight
);
atomic_dec
(
&
ses
->
server
->
inFlight
);
wake_up
(
&
ses
->
server
->
request_q
);
wake_up
(
&
ses
->
server
->
request_q
);
}
}
return
rc
;
return
rc
;
}
out_unlock2:
up
(
&
ses
->
server
->
tcpSem
);
/* If not lock req, update # of requests on wire to server */
if
(
long_op
<
3
)
{
atomic_dec
(
&
ses
->
server
->
inFlight
);
wake_up
(
&
ses
->
server
->
request_q
);
}
return
rc
;
}
#endif
/* CIFS_EXPERIMENTAL */
#endif
/* CIFS_EXPERIMENTAL */
int
int
...
...
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