aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/cifssmb.c29
1 files changed, 22 insertions, 7 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 365949c14646..41996a240149 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1139,11 +1139,15 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1139{ 1139{
1140 int rc = -EACCES; 1140 int rc = -EACCES;
1141 WRITE_REQ *pSMB = NULL; 1141 WRITE_REQ *pSMB = NULL;
1142 int bytes_returned; 1142 int bytes_returned, wct;
1143 int smb_hdr_len; 1143 int smb_hdr_len;
1144 1144
1145 cFYI(1,("write2 at %lld %d bytes",offset,count)); /* BB removeme BB */ 1145 cFYI(1,("write2 at %lld %d bytes",offset,count)); /* BB removeme BB */
1146 rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB); 1146 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1147 wct = 14;
1148 else
1149 wct = 12;
1150 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1147 if (rc) 1151 if (rc)
1148 return rc; 1152 return rc;
1149 /* tcon and ses pointer are checked in smb_init */ 1153 /* tcon and ses pointer are checked in smb_init */
@@ -1153,7 +1157,10 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1153 pSMB->AndXCommand = 0xFF; /* none */ 1157 pSMB->AndXCommand = 0xFF; /* none */
1154 pSMB->Fid = netfid; 1158 pSMB->Fid = netfid;
1155 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); 1159 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1156 pSMB->OffsetHigh = cpu_to_le32(offset >> 32); 1160 if(wct == 14)
1161 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1162 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1163 return -EIO;
1157 pSMB->Reserved = 0xFFFFFFFF; 1164 pSMB->Reserved = 0xFFFFFFFF;
1158 pSMB->WriteMode = 0; 1165 pSMB->WriteMode = 0;
1159 pSMB->Remaining = 0; 1166 pSMB->Remaining = 0;
@@ -1164,9 +1171,17 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1164 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF); 1171 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1165 pSMB->DataLengthHigh = cpu_to_le16(count >> 16); 1172 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1166 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */ 1173 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1167 pSMB->hdr.smb_buf_length += count+1; 1174 if(wct == 14)
1168 pSMB->ByteCount = cpu_to_le16(count + 1); 1175 pSMB->hdr.smb_buf_length += count+1;
1169 1176 else /* wct == 12 */
1177 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1178 if(wct == 14)
1179 pSMB->ByteCount = cpu_to_le16(count + 1);
1180 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1181 struct smb_com_writex_req * pSMBW =
1182 (struct smb_com_writex_req *)pSMB;
1183 pSMBW->ByteCount = cpu_to_le16(count + 5);
1184 }
1170 iov[0].iov_base = pSMB; 1185 iov[0].iov_base = pSMB;
1171 iov[0].iov_len = smb_hdr_len + 4; 1186 iov[0].iov_len = smb_hdr_len + 4;
1172 1187
@@ -1174,7 +1189,7 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1174 long_op); 1189 long_op);
1175 cifs_stats_inc(&tcon->num_writes); 1190 cifs_stats_inc(&tcon->num_writes);
1176 if (rc) { 1191 if (rc) {
1177 cFYI(1, ("Send error in write = %d", rc)); 1192 cFYI(1, ("Send error Write2 = %d", rc));
1178 *nbytes = 0; 1193 *nbytes = 0;
1179 } else { 1194 } else {
1180 WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB; 1195 WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB;