Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 12055
b: refs/heads/master
c: 3e84469
h: refs/heads/master
i:
  12053: 173c14c
  12051: 481a0a4
  12047: e52be85
v: v3
  • Loading branch information
Steve French committed Oct 3, 2005
1 parent b5204c5 commit 215c1dc
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 73 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 70ca734a14366b634224a1e4586d43b36b65ab67
refs/heads/master: 3e84469d0101456caceffc6b22218a49017fcd3f
5 changes: 2 additions & 3 deletions trunk/fs/cifs/cifsproto.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
struct smb_hdr * /* out */ ,
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,
struct kvec *, int /* nvec */,
int * /* bytes 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);
Expand Down Expand Up @@ -241,7 +240,7 @@ extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
const int netfid, const unsigned int count,
const __u64 offset, unsigned int *nbytes,
const char *buf,const int long_op);
struct kvec *iov, const int nvec, const int long_op);
extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName, __u64 * inode_number,
const struct nls_table *nls_codepage,
Expand Down
41 changes: 17 additions & 24 deletions trunk/fs/cifs/cifssmb.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon
, nls_codepage);
up(&tcon->ses->sesSem);
/* BB FIXME add code to check if wsize needs
update due to negotiated smb buffer size
shrinking */
if(rc == 0)
atomic_inc(&tconInfoReconnectCount);

Expand Down Expand Up @@ -220,6 +223,9 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
rc = CIFSTCon(0, tcon->ses, tcon->treeName,
tcon, nls_codepage);
up(&tcon->ses->sesSem);
/* BB FIXME add code to check if wsize needs
update due to negotiated smb buffer size
shrinking */
if(rc == 0)
atomic_inc(&tconInfoReconnectCount);

Expand Down Expand Up @@ -1128,15 +1134,13 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
int
CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
const int netfid, const unsigned int count,
const __u64 offset, unsigned int *nbytes, const char *buf,
const int long_op)
const __u64 offset, unsigned int *nbytes, struct kvec *iov,
int n_vec, const int long_op)
{
int rc = -EACCES;
WRITE_REQ *pSMB = NULL;
int bytes_returned;
int smb_hdr_len;
__u32 bytes_sent;
__u16 byte_count;

cFYI(1,("write2 at %lld %d bytes",offset,count)); /* BB removeme BB */
rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB);
Expand All @@ -1154,31 +1158,20 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
pSMB->WriteMode = 0;
pSMB->Remaining = 0;

/* 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)
bytes_sent = count;
pSMB->DataOffset =
cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);

byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
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->hdr.smb_buf_length += count+1;
pSMB->ByteCount = cpu_to_le16(count + 1);

iov[0].iov_base = pSMB;
iov[0].iov_len = smb_hdr_len + 4;

rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB, smb_hdr_len,
buf, bytes_sent, &bytes_returned, long_op);
rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &bytes_returned,
long_op);
cifs_stats_inc(&tcon->num_writes);
if (rc) {
cFYI(1, ("Send error in write = %d", rc));
Expand Down
4 changes: 4 additions & 0 deletions trunk/fs/cifs/connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -1891,6 +1891,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
}
}
}
if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
cifs_sb->wsize = min(cifs_sb->wsize,
(tcon->ses->server->maxBuf -
MAX_CIFS_HDR_SIZE));
}

/* volume_info.password is freed above when existing session found
Expand Down
16 changes: 11 additions & 5 deletions trunk/fs/cifs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -849,13 +849,19 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
/* BB FIXME We can not sign across two buffers yet */
if((experimEnabled) && ((pTcon->ses->server->secMode &
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) == 0)) {
struct kvec iov[2];
unsigned int len;

len = min(cifs_sb->wsize,
write_size - total_written);
/* iov[0] is reserved for smb header */
iov[1].iov_base = (char *)write_data +
total_written;
iov[1].iov_len = len;
rc = CIFSSMBWrite2(xid, pTcon,
open_file->netfid,
min_t(const int, cifs_sb->wsize,
write_size - total_written),
open_file->netfid, len,
*poffset, &bytes_written,
write_data + total_written,
long_op);
iov, 1, long_op);
} else
/* BB FIXME fixup indentation of line below */
#endif
Expand Down
95 changes: 55 additions & 40 deletions trunk/fs/cifs/transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,16 +147,19 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
Flags2 is converted in SendReceive */

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", smb_buf_length));
dump_smb(smb_buffer, len);

while (len > 0) {
rc = kernel_sendmsg(ssocket, &smb_msg, &iov, 1, len);
if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
i++;
if(i > 60) {
/* smaller timeout here than send2 since smaller size */
/* Although it may not be required, this also is smaller
oplock break time */
if(i > 30) {
cERROR(1,
("sends on sock %p stuck for 30 seconds",
("sends on sock %p stuck for 15 seconds",
ssocket));
rc = -EAGAIN;
break;
Expand All @@ -172,7 +175,7 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
}

if (rc < 0) {
cERROR(1,("Error %d sending data on socket to server.", rc));
cERROR(1,("Error %d sending data on socket to server", rc));
} else {
rc = 0;
}
Expand All @@ -182,22 +185,20 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,

#ifdef CONFIG_CIFS_EXPERIMENTAL
static int
smb_send2(struct socket *ssocket, struct smb_hdr *smb_buffer,
unsigned int smb_hdr_length, const char * data, unsigned int datalen,
struct sockaddr *sin)
smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
struct sockaddr *sin)
{
int rc = 0;
int i = 0;
struct msghdr smb_msg;
struct kvec iov[2];
unsigned len = smb_hdr_length + 4;
struct smb_hdr *smb_buffer = iov[0].iov_base;
unsigned int len = iov[0].iov_len;
unsigned int total_len;
int first_vec = 0;

if(ssocket == NULL)
return -ENOTSOCK; /* BB eventually add reconnect code here */
iov[0].iov_base = smb_buffer;
iov[0].iov_len = len;
iov[1].iov_base = data;
iov[1].iov_len = datalen;

smb_msg.msg_name = sin;
smb_msg.msg_namelen = sizeof (struct sockaddr);
smb_msg.msg_control = NULL;
Expand All @@ -209,18 +210,23 @@ smb_send2(struct socket *ssocket, struct smb_hdr *smb_buffer,
cifssmb.c and RFC1001 len is converted to bigendian in smb_send
Flags2 is converted in SendReceive */


total_len = 0;
for (i = 0; i < n_vec; i++)
total_len += iov[i].iov_len;

smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
cFYI(1, ("Sending smb: hdrlen %d datalen %d",
smb_hdr_length,datalen));
cFYI(1, ("Sending smb: total_len %d", total_len));
dump_smb(smb_buffer, len);

while (len + datalen > 0) {
rc = kernel_sendmsg(ssocket, &smb_msg, iov, 2, len);
while (total_len) {
rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
n_vec - first_vec, total_len);
if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
i++;
if(i > 60) {
if(i > 40) {
cERROR(1,
("sends on sock %p stuck for 30 seconds",
("sends on sock %p stuck for 20 seconds",
ssocket));
rc = -EAGAIN;
break;
Expand All @@ -230,43 +236,52 @@ smb_send2(struct socket *ssocket, struct smb_hdr *smb_buffer,
}
if (rc < 0)
break;
if(iov[0].iov_len > 0) {
if(rc >= len) {
iov[0].iov_len = 0;
rc -= len;
len = 0;
} else { /* some of hdr was not sent */
len -= rc;
iov[0].iov_len -= rc;
iov[0].iov_base += rc;
continue;
}

if (rc >= total_len) {
WARN_ON(rc > total_len);
break;
}
if(rc == 0) {
/* should never happen, letting socket clear before
retrying is our only obvious option here */
cERROR(1,("tcp sent no data");
msleep(500);
continue;
}
if((iov[0].iov_len == 0) && (rc > 0)){
iov[1].iov_base += rc;
iov[1].iov_len -= rc;
datalen -= rc;
total_len -= rc;
for (i = first_vec; i < n_vec; i++) {
if (iov[i].iov_len) {
if (rc > iov[i].iov_len) {
rc -= iov[i].iov_len;
iov[i].iov_len = 0;
} else {
iov[i].iov_base += rc;
iov[i].iov_len -= rc;
first_vec = i;
break;
}
}
}
}

if (rc < 0) {
cERROR(1,("Error %d sending data on socket to server.", rc));
} else {
cERROR(1,("Error %d sending data on socket to server", rc));
} else
rc = 0;
}

return rc;
}

int
SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
struct smb_hdr *in_buf, int hdrlen, const char * data,
int datalen, int *pbytes_returned, const int long_op)
struct kvec *iov, int n_vec, int *pbytes_returned,
const int long_op)
{
int rc = 0;
unsigned int receive_len;
unsigned long timeout;
struct mid_q_entry *midQ;
struct smb_hdr *in_buf = iov[0].iov_base;

if (ses == NULL) {
cERROR(1,("Null smb session"));
Expand Down Expand Up @@ -364,7 +379,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
/* rc = cifs_sign_smb2(in_buf, data, ses->server, &midQ->sequence_number); */

midQ->midState = MID_REQUEST_SUBMITTED;
rc = smb_send2(ses->server->ssocket, in_buf, hdrlen, data, datalen,
rc = smb_send2(ses->server->ssocket, iov, n_vec,
(struct sockaddr *) &(ses->server->addr.sockAddr));
if(rc < 0) {
DeleteMidQEntry(midQ);
Expand Down

0 comments on commit 215c1dc

Please sign in to comment.