diff options
author | Steve French <sfrench@us.ibm.com> | 2005-08-30 23:58:07 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2005-08-30 23:58:07 -0400 |
commit | 1c9551878c4629ca78dfe12ed23b9dc8d97770cc (patch) | |
tree | 4d9df5ad22d88dd0f62ab9f44d761f1df6a77d55 /fs/cifs | |
parent | cb8be64084e6294fcb9e558188fe104050b94f0b (diff) |
[CIFS] Add support for legacy servers part 4
Fix WriteX support for old servers which do not support large
files.
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/cifssmb.c | 27 | ||||
-rw-r--r-- | fs/cifs/connect.c | 2 | ||||
-rw-r--r-- | fs/cifs/file.c | 66 |
3 files changed, 72 insertions, 23 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index c8ae3ef422ba..74733851cfad 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -1082,12 +1082,20 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, | |||
1082 | int rc = -EACCES; | 1082 | int rc = -EACCES; |
1083 | WRITE_REQ *pSMB = NULL; | 1083 | WRITE_REQ *pSMB = NULL; |
1084 | WRITE_RSP *pSMBr = NULL; | 1084 | WRITE_RSP *pSMBr = NULL; |
1085 | int bytes_returned; | 1085 | int bytes_returned, wct; |
1086 | __u32 bytes_sent; | 1086 | __u32 bytes_sent; |
1087 | __u16 byte_count; | 1087 | __u16 byte_count; |
1088 | 1088 | ||
1089 | /* cFYI(1,("write at %lld %d bytes",offset,count));*/ | 1089 | /* cFYI(1,("write at %lld %d bytes",offset,count));*/ |
1090 | rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB, | 1090 | if(tcon->ses == NULL) |
1091 | return -ECONNABORTED; | ||
1092 | |||
1093 | if(tcon->ses->capabilities & CAP_LARGE_FILES) | ||
1094 | wct = 14; | ||
1095 | else | ||
1096 | wct = 12; | ||
1097 | |||
1098 | rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB, | ||
1091 | (void **) &pSMBr); | 1099 | (void **) &pSMBr); |
1092 | if (rc) | 1100 | if (rc) |
1093 | return rc; | 1101 | return rc; |
@@ -1098,7 +1106,11 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, | |||
1098 | pSMB->AndXCommand = 0xFF; /* none */ | 1106 | pSMB->AndXCommand = 0xFF; /* none */ |
1099 | pSMB->Fid = netfid; | 1107 | pSMB->Fid = netfid; |
1100 | pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); | 1108 | pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); |
1101 | pSMB->OffsetHigh = cpu_to_le32(offset >> 32); | 1109 | if(wct == 14) |
1110 | pSMB->OffsetHigh = cpu_to_le32(offset >> 32); | ||
1111 | else if((offset >> 32) > 0) /* can not handle this big offset for old */ | ||
1112 | return -EIO; | ||
1113 | |||
1102 | pSMB->Reserved = 0xFFFFFFFF; | 1114 | pSMB->Reserved = 0xFFFFFFFF; |
1103 | pSMB->WriteMode = 0; | 1115 | pSMB->WriteMode = 0; |
1104 | pSMB->Remaining = 0; | 1116 | pSMB->Remaining = 0; |
@@ -1135,7 +1147,14 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, | |||
1135 | pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF); | 1147 | pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF); |
1136 | pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16); | 1148 | pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16); |
1137 | pSMB->hdr.smb_buf_length += bytes_sent+1; | 1149 | pSMB->hdr.smb_buf_length += bytes_sent+1; |
1138 | pSMB->ByteCount = cpu_to_le16(byte_count); | 1150 | |
1151 | if(wct == 14) | ||
1152 | pSMB->ByteCount = cpu_to_le16(byte_count); | ||
1153 | else { /* old style write has byte count 4 bytes earlier */ | ||
1154 | struct smb_com_writex_req * pSMBW = | ||
1155 | (struct smb_com_writex_req *)pSMB; | ||
1156 | pSMBW->ByteCount = cpu_to_le16(byte_count); | ||
1157 | } | ||
1139 | 1158 | ||
1140 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1159 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
1141 | (struct smb_hdr *) pSMBr, &bytes_returned, long_op); | 1160 | (struct smb_hdr *) pSMBr, &bytes_returned, long_op); |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index f784b70abfeb..196976049c00 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -1079,7 +1079,7 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
1079 | } else if (strnicmp(data, "brl", 3) == 0) { | 1079 | } else if (strnicmp(data, "brl", 3) == 0) { |
1080 | vol->nobrl = 0; | 1080 | vol->nobrl = 0; |
1081 | } else if ((strnicmp(data, "nobrl", 5) == 0) || | 1081 | } else if ((strnicmp(data, "nobrl", 5) == 0) || |
1082 | (strnicmp(data, "nolock", 6)) { | 1082 | (strnicmp(data, "nolock", 6) == 0)) { |
1083 | vol->nobrl = 1; | 1083 | vol->nobrl = 1; |
1084 | /* turn off mandatory locking in mode | 1084 | /* turn off mandatory locking in mode |
1085 | if remote locking is turned off since the | 1085 | if remote locking is turned off since the |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index ef455dda0473..b6c303f6373f 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -1183,11 +1183,16 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, | |||
1183 | char *smb_read_data; | 1183 | char *smb_read_data; |
1184 | char __user *current_offset; | 1184 | char __user *current_offset; |
1185 | struct smb_com_read_rsp *pSMBr; | 1185 | struct smb_com_read_rsp *pSMBr; |
1186 | int use_old_read = FALSE; | ||
1186 | 1187 | ||
1187 | xid = GetXid(); | 1188 | xid = GetXid(); |
1188 | cifs_sb = CIFS_SB(file->f_dentry->d_sb); | 1189 | cifs_sb = CIFS_SB(file->f_dentry->d_sb); |
1189 | pTcon = cifs_sb->tcon; | 1190 | pTcon = cifs_sb->tcon; |
1190 | 1191 | ||
1192 | if(pTcon->ses) | ||
1193 | if((pTcon->ses->capabilities & CAP_LARGE_FILES) == 0) | ||
1194 | use_old_read = TRUE; | ||
1195 | |||
1191 | if (file->private_data == NULL) { | 1196 | if (file->private_data == NULL) { |
1192 | FreeXid(xid); | 1197 | FreeXid(xid); |
1193 | return -EBADF; | 1198 | return -EBADF; |
@@ -1212,16 +1217,21 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, | |||
1212 | if (rc != 0) | 1217 | if (rc != 0) |
1213 | break; | 1218 | break; |
1214 | } | 1219 | } |
1215 | 1220 | if(use_old_read) | |
1216 | rc = CIFSSMBRead(xid, pTcon, | ||
1217 | open_file->netfid, | ||
1218 | current_read_size, *poffset, | ||
1219 | &bytes_read, &smb_read_data); | ||
1220 | if(rc == -EINVAL) { | ||
1221 | rc = SMBLegacyRead(xid, pTcon, | 1221 | rc = SMBLegacyRead(xid, pTcon, |
1222 | open_file->netfid, | 1222 | open_file->netfid, |
1223 | current_read_size, *poffset, | 1223 | current_read_size, *poffset, |
1224 | &bytes_read, &smb_read_data); | 1224 | &bytes_read, &smb_read_data); |
1225 | else { | ||
1226 | rc = CIFSSMBRead(xid, pTcon, | ||
1227 | open_file->netfid, | ||
1228 | current_read_size, *poffset, | ||
1229 | &bytes_read, &smb_read_data); | ||
1230 | if(rc == -EINVAL) { | ||
1231 | use_old_read = TRUE; | ||
1232 | rc = -EAGAIN; | ||
1233 | continue; | ||
1234 | } | ||
1225 | } | 1235 | } |
1226 | pSMBr = (struct smb_com_read_rsp *)smb_read_data; | 1236 | pSMBr = (struct smb_com_read_rsp *)smb_read_data; |
1227 | if (copy_to_user(current_offset, | 1237 | if (copy_to_user(current_offset, |
@@ -1266,6 +1276,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, | |||
1266 | int xid; | 1276 | int xid; |
1267 | char *current_offset; | 1277 | char *current_offset; |
1268 | struct cifsFileInfo *open_file; | 1278 | struct cifsFileInfo *open_file; |
1279 | int use_old_read = FALSE; | ||
1269 | 1280 | ||
1270 | xid = GetXid(); | 1281 | xid = GetXid(); |
1271 | cifs_sb = CIFS_SB(file->f_dentry->d_sb); | 1282 | cifs_sb = CIFS_SB(file->f_dentry->d_sb); |
@@ -1276,6 +1287,9 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, | |||
1276 | return -EBADF; | 1287 | return -EBADF; |
1277 | } | 1288 | } |
1278 | open_file = (struct cifsFileInfo *)file->private_data; | 1289 | open_file = (struct cifsFileInfo *)file->private_data; |
1290 | if(pTcon->ses) | ||
1291 | if((pTcon->ses->capabilities & CAP_LARGE_FILES) == 0) | ||
1292 | use_old_read = TRUE; | ||
1279 | 1293 | ||
1280 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) | 1294 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) |
1281 | cFYI(1, ("attempting read on write only file instance")); | 1295 | cFYI(1, ("attempting read on write only file instance")); |
@@ -1294,16 +1308,23 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, | |||
1294 | if (rc != 0) | 1308 | if (rc != 0) |
1295 | break; | 1309 | break; |
1296 | } | 1310 | } |
1297 | 1311 | if(use_old_read) | |
1298 | rc = CIFSSMBRead(xid, pTcon, | ||
1299 | open_file->netfid, | ||
1300 | current_read_size, *poffset, | ||
1301 | &bytes_read, ¤t_offset); | ||
1302 | if(rc == -EINVAL) { | ||
1303 | rc = SMBLegacyRead(xid, pTcon, | 1312 | rc = SMBLegacyRead(xid, pTcon, |
1313 | open_file->netfid, | ||
1314 | current_read_size, *poffset, | ||
1315 | &bytes_read, ¤t_offset); | ||
1316 | else { | ||
1317 | rc = CIFSSMBRead(xid, pTcon, | ||
1304 | open_file->netfid, | 1318 | open_file->netfid, |
1305 | current_read_size, *poffset, | 1319 | current_read_size, *poffset, |
1306 | &bytes_read, ¤t_offset); | 1320 | &bytes_read, ¤t_offset); |
1321 | /* check if server disavows support for | ||
1322 | 64 bit offsets */ | ||
1323 | if(rc == -EINVAL) { | ||
1324 | rc = -EAGAIN; | ||
1325 | use_old_read = TRUE; | ||
1326 | continue; | ||
1327 | } | ||
1307 | } | 1328 | } |
1308 | } | 1329 | } |
1309 | if (rc || (bytes_read == 0)) { | 1330 | if (rc || (bytes_read == 0)) { |
@@ -1402,6 +1423,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
1402 | struct smb_com_read_rsp *pSMBr; | 1423 | struct smb_com_read_rsp *pSMBr; |
1403 | struct pagevec lru_pvec; | 1424 | struct pagevec lru_pvec; |
1404 | struct cifsFileInfo *open_file; | 1425 | struct cifsFileInfo *open_file; |
1426 | int use_old_read = FALSE; | ||
1405 | 1427 | ||
1406 | xid = GetXid(); | 1428 | xid = GetXid(); |
1407 | if (file->private_data == NULL) { | 1429 | if (file->private_data == NULL) { |
@@ -1411,7 +1433,9 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
1411 | open_file = (struct cifsFileInfo *)file->private_data; | 1433 | open_file = (struct cifsFileInfo *)file->private_data; |
1412 | cifs_sb = CIFS_SB(file->f_dentry->d_sb); | 1434 | cifs_sb = CIFS_SB(file->f_dentry->d_sb); |
1413 | pTcon = cifs_sb->tcon; | 1435 | pTcon = cifs_sb->tcon; |
1414 | 1436 | if(pTcon->ses) | |
1437 | if((pTcon->ses->capabilities & CAP_LARGE_FILES) == 0) | ||
1438 | use_old_read = TRUE; | ||
1415 | pagevec_init(&lru_pvec, 0); | 1439 | pagevec_init(&lru_pvec, 0); |
1416 | 1440 | ||
1417 | for (i = 0; i < num_pages; ) { | 1441 | for (i = 0; i < num_pages; ) { |
@@ -1457,15 +1481,21 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
1457 | break; | 1481 | break; |
1458 | } | 1482 | } |
1459 | 1483 | ||
1460 | rc = CIFSSMBRead(xid, pTcon, | 1484 | if(use_old_read) |
1461 | open_file->netfid, | ||
1462 | read_size, offset, | ||
1463 | &bytes_read, &smb_read_data); | ||
1464 | if (rc == -EINVAL) { | ||
1465 | rc = SMBLegacyRead(xid, pTcon, | 1485 | rc = SMBLegacyRead(xid, pTcon, |
1466 | open_file->netfid, | 1486 | open_file->netfid, |
1467 | read_size, offset, | 1487 | read_size, offset, |
1468 | &bytes_read, &smb_read_data); | 1488 | &bytes_read, &smb_read_data); |
1489 | else { | ||
1490 | rc = CIFSSMBRead(xid, pTcon, | ||
1491 | open_file->netfid, | ||
1492 | read_size, offset, | ||
1493 | &bytes_read, &smb_read_data); | ||
1494 | if(rc == -EINVAL) { | ||
1495 | use_old_read = TRUE; | ||
1496 | rc = -EAGAIN; | ||
1497 | continue; | ||
1498 | } | ||
1469 | } | 1499 | } |
1470 | 1500 | ||
1471 | /* BB more RC checks ? */ | 1501 | /* BB more RC checks ? */ |