Skip to content

Commit

Permalink
cifs: cork the socket before a send and uncork it afterward
Browse files Browse the repository at this point in the history
We want to send SMBs as "atomically" as possible. Prior to sending any
data on the socket, cork it to make sure that no non-full frames go
out. Afterward, uncork it to make sure all of the data gets pushed out
to the wire.

Note that this more or less renders the socket=TCP_NODELAY mount option
obsolete. When TCP_CORK and TCP_NODELAY are used on the same socket,
TCP_NODELAY is essentially ignored.

Acked-by: Pavel Shilovsky <pshilovsky@samba.org>
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <smfrench@gmail.com>
  • Loading branch information
jtlayton authored and smfrench committed Sep 25, 2012
1 parent 6f49f46 commit b8eed28
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 0 deletions.
4 changes: 4 additions & 0 deletions fs/cifs/connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -1680,6 +1680,10 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
if (string == NULL)
goto out_nomem;

/*
* FIXME: since we now cork/uncork the socket while
* sending, should we deprecate this option?
*/
if (strnicmp(string, "TCP_NODELAY", 11) == 0)
vol->sockopt_tcp_nodelay = 1;
break;
Expand Down
12 changes: 12 additions & 0 deletions fs/cifs/transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <linux/net.h>
#include <linux/delay.h>
#include <linux/freezer.h>
#include <linux/tcp.h>
#include <asm/uaccess.h>
#include <asm/processor.h>
#include <linux/mempool.h>
Expand Down Expand Up @@ -247,12 +248,23 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
int n_vec = rqst->rq_nvec;
unsigned int smb_buf_length = get_rfc1002_length(iov[0].iov_base);
size_t total_len;
struct socket *ssocket = server->ssocket;
int val = 1;

cFYI(1, "Sending smb: smb_len=%u", smb_buf_length);
dump_smb(iov[0].iov_base, iov[0].iov_len);

/* cork the socket */
kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK,
(char *)&val, sizeof(val));

rc = smb_send_kvec(server, iov, n_vec, &total_len);

/* uncork it */
val = 0;
kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK,
(char *)&val, sizeof(val));

if ((total_len > 0) && (total_len != smb_buf_length + 4)) {
cFYI(1, "partial send (wanted=%u sent=%zu): terminating "
"session", smb_buf_length + 4, total_len);
Expand Down

0 comments on commit b8eed28

Please sign in to comment.