diff options
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r-- | fs/cifs/cifssmb.c | 57 |
1 files changed, 36 insertions, 21 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 3c628bf667a5..b4f7b9859e3b 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -951,56 +951,69 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, | |||
951 | } | 951 | } |
952 | 952 | ||
953 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 953 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
954 | int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, | 954 | int |
955 | CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, | ||
955 | const int netfid, const unsigned int count, | 956 | const int netfid, const unsigned int count, |
956 | const __u64 offset, unsigned int *nbytes, const char __user *buf, | 957 | const __u64 offset, unsigned int *nbytes, const char *buf, |
957 | const int long_op) | 958 | const int long_op) |
958 | { | 959 | { |
959 | int rc = -EACCES; | 960 | int rc = -EACCES; |
960 | WRITE_REQ *pSMB = NULL; | 961 | WRITE_REQ *pSMB = NULL; |
961 | WRITE_RSP *pSMBr = NULL; | 962 | int bytes_returned; |
962 | /*int bytes_returned;*/ | 963 | int smb_hdr_len; |
963 | unsigned bytes_sent; | 964 | __u32 bytes_sent; |
964 | __u16 byte_count; | 965 | __u16 byte_count; |
965 | 966 | ||
967 | cERROR(1,("write2 at %lld %d bytes",offset,count)); /* BB removeme BB */ | ||
966 | rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB); | 968 | rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB); |
967 | |||
968 | if (rc) | 969 | if (rc) |
969 | return rc; | 970 | return rc; |
970 | |||
971 | pSMBr = (WRITE_RSP *)pSMB; /* BB removeme BB */ | ||
972 | |||
973 | /* tcon and ses pointer are checked in smb_init */ | 971 | /* tcon and ses pointer are checked in smb_init */ |
974 | if (tcon->ses->server == NULL) | 972 | if (tcon->ses->server == NULL) |
975 | return -ECONNABORTED; | 973 | return -ECONNABORTED; |
976 | 974 | ||
977 | pSMB->AndXCommand = 0xFF; /* none */ | 975 | pSMB->AndXCommand = 0xFF; /* none */ |
978 | pSMB->Fid = netfid; | 976 | pSMB->Fid = netfid; |
979 | pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); | 977 | pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); |
980 | pSMB->OffsetHigh = cpu_to_le32(offset >> 32); | 978 | pSMB->OffsetHigh = cpu_to_le32(offset >> 32); |
981 | pSMB->Reserved = 0xFFFFFFFF; | 979 | pSMB->Reserved = 0xFFFFFFFF; |
982 | pSMB->WriteMode = 0; | 980 | pSMB->WriteMode = 0; |
983 | pSMB->Remaining = 0; | 981 | pSMB->Remaining = 0; |
984 | bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF; | 982 | |
983 | /* Can increase buffer size if buffer is big enough in some cases - ie | ||
984 | can send more if LARGE_WRITE_X capability returned by the server and if | ||
985 | our buffer is big enough or if we convert to iovecs on socket writes | ||
986 | and eliminate the copy to the CIFS buffer */ | ||
987 | if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) { | ||
988 | bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count); | ||
989 | } else { | ||
990 | bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) | ||
991 | & ~0xFF; | ||
992 | } | ||
993 | |||
985 | if (bytes_sent > count) | 994 | if (bytes_sent > count) |
986 | bytes_sent = count; | 995 | bytes_sent = count; |
987 | pSMB->DataLengthHigh = 0; | ||
988 | pSMB->DataOffset = | 996 | pSMB->DataOffset = |
989 | cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4); | 997 | cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4); |
990 | 998 | ||
991 | byte_count = bytes_sent + 1 /* pad */ ; | 999 | byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */ |
992 | pSMB->DataLengthLow = cpu_to_le16(bytes_sent); | 1000 | pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF); |
993 | pSMB->DataLengthHigh = 0; | 1001 | pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16); |
994 | pSMB->hdr.smb_buf_length += byte_count; | 1002 | smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */ |
1003 | pSMB->hdr.smb_buf_length += bytes_sent+1; | ||
995 | pSMB->ByteCount = cpu_to_le16(byte_count); | 1004 | pSMB->ByteCount = cpu_to_le16(byte_count); |
996 | 1005 | ||
997 | /* rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1006 | rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB, smb_hdr_len, |
998 | (struct smb_hdr *) pSMBr, buf, buflen, &bytes_returned, long_op); */ /* BB fixme BB */ | 1007 | buf, bytes_sent, &bytes_returned, long_op); |
999 | if (rc) { | 1008 | if (rc) { |
1000 | cFYI(1, ("Send error in write2 (large write) = %d", rc)); | 1009 | cFYI(1, ("Send error in write = %d", rc)); |
1001 | *nbytes = 0; | 1010 | *nbytes = 0; |
1002 | } else | 1011 | } else { |
1003 | *nbytes = le16_to_cpu(pSMBr->Count); | 1012 | WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB; |
1013 | *nbytes = le16_to_cpu(pSMBr->CountHigh); | ||
1014 | *nbytes = (*nbytes) << 16; | ||
1015 | *nbytes += le16_to_cpu(pSMBr->Count); | ||
1016 | } | ||
1004 | 1017 | ||
1005 | cifs_small_buf_release(pSMB); | 1018 | cifs_small_buf_release(pSMB); |
1006 | 1019 | ||
@@ -1009,6 +1022,8 @@ int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, | |||
1009 | 1022 | ||
1010 | return rc; | 1023 | return rc; |
1011 | } | 1024 | } |
1025 | |||
1026 | |||
1012 | #endif /* CIFS_EXPERIMENTAL */ | 1027 | #endif /* CIFS_EXPERIMENTAL */ |
1013 | 1028 | ||
1014 | int | 1029 | int |