diff options
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/cifssmb.c | 29 |
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; |