Skip to content

Commit

Permalink
[CIFS] CIFS writepage improvements - eliminate double copy
Browse files Browse the repository at this point in the history
Signed-off-by: Steve French (sfrench@us.ibm.com)
  • Loading branch information
Steve French committed Jun 13, 2005
1 parent 2830077 commit d6e04ae
Show file tree
Hide file tree
Showing 4 changed files with 231 additions and 76 deletions.
6 changes: 5 additions & 1 deletion fs/cifs/cifsproto.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
struct smb_hdr * /* input */ ,
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,
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);
extern int is_valid_oplock_break(struct smb_hdr *smb);
Expand Down Expand Up @@ -222,7 +226,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 __user *buf,const int long_op);
const char *buf,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
57 changes: 36 additions & 21 deletions fs/cifs/cifssmb.c
Original file line number Diff line number Diff line change
Expand Up @@ -951,56 +951,69 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
}

#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 __u64 offset, unsigned int *nbytes, const char __user *buf,
const __u64 offset, unsigned int *nbytes, const char *buf,
const int long_op)
{
int rc = -EACCES;
WRITE_REQ *pSMB = NULL;
WRITE_RSP *pSMBr = NULL;
/*int bytes_returned;*/
unsigned bytes_sent;
int bytes_returned;
int smb_hdr_len;
__u32 bytes_sent;
__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);

if (rc)
return rc;

pSMBr = (WRITE_RSP *)pSMB; /* BB removeme BB */

/* tcon and ses pointer are checked in smb_init */
if (tcon->ses->server == NULL)
return -ECONNABORTED;

pSMB->AndXCommand = 0xFF; /* none */
pSMB->AndXCommand = 0xFF; /* none */
pSMB->Fid = netfid;
pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
pSMB->Reserved = 0xFFFFFFFF;
pSMB->WriteMode = 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)
bytes_sent = count;
pSMB->DataLengthHigh = 0;
pSMB->DataOffset =
cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);

byte_count = bytes_sent + 1 /* pad */ ;
pSMB->DataLengthLow = cpu_to_le16(bytes_sent);
pSMB->DataLengthHigh = 0;
pSMB->hdr.smb_buf_length += byte_count;
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);
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);

/* rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, buf, buflen, &bytes_returned, long_op); */ /* BB fixme BB */
rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB, smb_hdr_len,
buf, bytes_sent, &bytes_returned, long_op);
if (rc) {
cFYI(1, ("Send error in write2 (large write) = %d", rc));
cFYI(1, ("Send error in write = %d", rc));
*nbytes = 0;
} else
*nbytes = le16_to_cpu(pSMBr->Count);
} else {
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);

Expand All @@ -1009,6 +1022,8 @@ int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,

return rc;
}


#endif /* CIFS_EXPERIMENTAL */

int
Expand Down
21 changes: 17 additions & 4 deletions fs/cifs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -791,9 +791,8 @@ static ssize_t cifs_write(struct file *file, const char *write_data,

pTcon = cifs_sb->tcon;

/* cFYI(1,
(" write %d bytes to offset %lld of %s", write_size,
*poffset, file->f_dentry->d_name.name)); */
cFYI(1,(" write %d bytes to offset %lld of %s", write_size,
*poffset, file->f_dentry->d_name.name)); /* BB removeme BB */

if (file->private_data == NULL)
return -EBADF;
Expand Down Expand Up @@ -846,7 +845,21 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
if (rc != 0)
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,
open_file->netfid,
min_t(const int, cifs_sb->wsize,
Expand Down
Loading

0 comments on commit d6e04ae

Please sign in to comment.