aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2005-09-01 00:50:37 -0400
committerSteve French <sfrench@us.ibm.com>2005-09-01 00:50:37 -0400
commitbfa0d75a1eee59f0577e3c1697ff570b77581a35 (patch)
treec5399d95379f71903c4f3e82160bd7b4d36bb42d /fs/cifs
parent1c9551878c4629ca78dfe12ed23b9dc8d97770cc (diff)
[CIFS] Add support for legacy servers part 5
Handle small negotiated read sizes (under 4K) and finish up read and write support. Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/cifsproto.h3
-rw-r--r--fs/cifs/cifssmb.c99
-rw-r--r--fs/cifs/file.c58
-rw-r--r--fs/cifs/inode.c7
-rw-r--r--fs/cifs/readdir.c9
5 files changed, 39 insertions, 137 deletions
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 656b78ddf674..6943f7c6de08 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -226,9 +226,6 @@ extern int SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
226extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, 226extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
227 const int smb_file_id); 227 const int smb_file_id);
228 228
229extern int SMBLegacyRead(const int xid, struct cifsTconInfo *tcon,
230 const int netfid, unsigned int count,
231 const __u64 lseek, unsigned int *nbytes, char **buf);
232extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, 229extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
233 const int netfid, unsigned int count, 230 const int netfid, unsigned int count,
234 const __u64 lseek, unsigned int *nbytes, char **buf); 231 const __u64 lseek, unsigned int *nbytes, char **buf);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 74733851cfad..b8830118f09a 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -923,81 +923,6 @@ openRetry:
923 return rc; 923 return rc;
924} 924}
925 925
926int
927SMBLegacyRead(const int xid, struct cifsTconInfo *tcon,
928 const int netfid, unsigned int count,
929 const __u64 lseek, unsigned int *nbytes, char **buf)
930{
931 int rc = -EACCES;
932 READX_REQ *pSMB = NULL;
933 READ_RSP *pSMBr = NULL;
934 char *pReadData = NULL;
935 int bytes_returned;
936
937 cFYI(1,("Legacy read %d bytes fid %d",count,netfid));
938
939 /* field is shorter in legacy read, only 16 bits */
940 if(count > 2048)
941 count = 2048; /* BB FIXME make this configurable */
942
943 if(lseek > 0xFFFFFFFF)
944 return -EIO; /* can not read that far into file on old server */
945
946 *nbytes = 0;
947 rc = smb_init(SMB_COM_READ_ANDX, 10, tcon, (void **) &pSMB,
948 (void **) &pSMBr);
949 if (rc)
950 return rc;
951
952 /* tcon and ses pointer are checked in smb_init */
953 if (tcon->ses->server == NULL)
954 return -ECONNABORTED;
955
956 pSMB->AndXCommand = 0xFF; /* none */
957 pSMB->Fid = netfid;
958 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
959 pSMB->Remaining = 0;
960 pSMB->MaxCount = cpu_to_le16(count);
961 pSMB->Reserved = 0; /* Must Be Zero */
962 pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */
963
964 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
965 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
966 cifs_stats_inc(&tcon->num_reads);
967 if (rc) {
968 cERROR(1, ("Send error in legacy read = %d", rc));
969 } else {
970 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
971 data_length = data_length << 16;
972 data_length += le16_to_cpu(pSMBr->DataLength);
973 *nbytes = data_length;
974
975 /*check that DataLength would not go beyond end of SMB */
976 if ((data_length > CIFSMaxBufSize) || (data_length > count)) {
977 cFYI(1,("bad length %d for count %d",data_length,count));
978 rc = -EIO;
979 *nbytes = 0;
980 } else {
981 pReadData = (char *) (&pSMBr->hdr.Protocol) +
982 le16_to_cpu(pSMBr->DataOffset);
983/* if(rc = copy_to_user(buf, pReadData, data_length)) {
984 cERROR(1,("Faulting on read rc = %d",rc));
985 rc = -EFAULT;
986 }*/ /* can not use copy_to_user when using page cache*/
987 if(*buf)
988 memcpy(*buf,pReadData,data_length);
989 }
990 }
991 if(*buf)
992 cifs_buf_release(pSMB);
993 else
994 *buf = (char *)pSMB;
995
996 /* Note: On -EAGAIN error only caller can retry on handle based calls
997 since file handle passed in no longer valid */
998 return rc;
999}
1000
1001/* If no buffer passed in, then caller wants to do the copy 926/* If no buffer passed in, then caller wants to do the copy
1002 as in the case of readpages so the SMB buffer must be 927 as in the case of readpages so the SMB buffer must be
1003 freed by the caller */ 928 freed by the caller */
@@ -1012,11 +937,16 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
1012 READ_RSP *pSMBr = NULL; 937 READ_RSP *pSMBr = NULL;
1013 char *pReadData = NULL; 938 char *pReadData = NULL;
1014 int bytes_returned; 939 int bytes_returned;
940 int wct;
1015 941
1016 cFYI(1,("Reading %d bytes on fid %d",count,netfid)); 942 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
943 if(tcon->ses->capabilities & CAP_LARGE_FILES)
944 wct = 12;
945 else
946 wct = 10; /* old style read */
1017 947
1018 *nbytes = 0; 948 *nbytes = 0;
1019 rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB, 949 rc = smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB,
1020 (void **) &pSMBr); 950 (void **) &pSMBr);
1021 if (rc) 951 if (rc)
1022 return rc; 952 return rc;
@@ -1028,12 +958,23 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
1028 pSMB->AndXCommand = 0xFF; /* none */ 958 pSMB->AndXCommand = 0xFF; /* none */
1029 pSMB->Fid = netfid; 959 pSMB->Fid = netfid;
1030 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF); 960 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1031 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32); 961 if(wct == 12)
962 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
963 else if((lseek >> 32) > 0) /* can not handle this big offset for old */
964 return -EIO;
965
1032 pSMB->Remaining = 0; 966 pSMB->Remaining = 0;
1033 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF); 967 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1034 pSMB->MaxCountHigh = cpu_to_le32(count >> 16); 968 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1035 pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */ 969 if(wct == 12)
1036 970 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
971 else {
972 /* old style read */
973 struct smb_com_readx_req * pSMBW =
974 (struct smb_com_readx_req *)pSMB;
975 pSMBW->ByteCount = 0;
976 }
977
1037 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 978 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1038 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 979 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1039 cifs_stats_inc(&tcon->num_reads); 980 cifs_stats_inc(&tcon->num_reads);
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index b6c303f6373f..5ecda554f913 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1183,16 +1183,11 @@ 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;
1187 1186
1188 xid = GetXid(); 1187 xid = GetXid();
1189 cifs_sb = CIFS_SB(file->f_dentry->d_sb); 1188 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1190 pTcon = cifs_sb->tcon; 1189 pTcon = cifs_sb->tcon;
1191 1190
1192 if(pTcon->ses)
1193 if((pTcon->ses->capabilities & CAP_LARGE_FILES) == 0)
1194 use_old_read = TRUE;
1195
1196 if (file->private_data == NULL) { 1191 if (file->private_data == NULL) {
1197 FreeXid(xid); 1192 FreeXid(xid);
1198 return -EBADF; 1193 return -EBADF;
@@ -1217,22 +1212,10 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
1217 if (rc != 0) 1212 if (rc != 0)
1218 break; 1213 break;
1219 } 1214 }
1220 if(use_old_read) 1215 rc = CIFSSMBRead(xid, pTcon,
1221 rc = SMBLegacyRead(xid, pTcon,
1222 open_file->netfid,
1223 current_read_size, *poffset,
1224 &bytes_read, &smb_read_data);
1225 else {
1226 rc = CIFSSMBRead(xid, pTcon,
1227 open_file->netfid, 1216 open_file->netfid,
1228 current_read_size, *poffset, 1217 current_read_size, *poffset,
1229 &bytes_read, &smb_read_data); 1218 &bytes_read, &smb_read_data);
1230 if(rc == -EINVAL) {
1231 use_old_read = TRUE;
1232 rc = -EAGAIN;
1233 continue;
1234 }
1235 }
1236 pSMBr = (struct smb_com_read_rsp *)smb_read_data; 1219 pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1237 if (copy_to_user(current_offset, 1220 if (copy_to_user(current_offset,
1238 smb_read_data + 4 /* RFC1001 hdr */ 1221 smb_read_data + 4 /* RFC1001 hdr */
@@ -1276,7 +1259,6 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1276 int xid; 1259 int xid;
1277 char *current_offset; 1260 char *current_offset;
1278 struct cifsFileInfo *open_file; 1261 struct cifsFileInfo *open_file;
1279 int use_old_read = FALSE;
1280 1262
1281 xid = GetXid(); 1263 xid = GetXid();
1282 cifs_sb = CIFS_SB(file->f_dentry->d_sb); 1264 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
@@ -1287,9 +1269,6 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1287 return -EBADF; 1269 return -EBADF;
1288 } 1270 }
1289 open_file = (struct cifsFileInfo *)file->private_data; 1271 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;
1293 1272
1294 if ((file->f_flags & O_ACCMODE) == O_WRONLY) 1273 if ((file->f_flags & O_ACCMODE) == O_WRONLY)
1295 cFYI(1, ("attempting read on write only file instance")); 1274 cFYI(1, ("attempting read on write only file instance"));
@@ -1308,24 +1287,10 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1308 if (rc != 0) 1287 if (rc != 0)
1309 break; 1288 break;
1310 } 1289 }
1311 if(use_old_read) 1290 rc = CIFSSMBRead(xid, pTcon,
1312 rc = SMBLegacyRead(xid, pTcon,
1313 open_file->netfid,
1314 current_read_size, *poffset,
1315 &bytes_read, &current_offset);
1316 else {
1317 rc = CIFSSMBRead(xid, pTcon,
1318 open_file->netfid, 1291 open_file->netfid,
1319 current_read_size, *poffset, 1292 current_read_size, *poffset,
1320 &bytes_read, &current_offset); 1293 &bytes_read, &current_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 }
1328 }
1329 } 1294 }
1330 if (rc || (bytes_read == 0)) { 1295 if (rc || (bytes_read == 0)) {
1331 if (total_read) { 1296 if (total_read) {
@@ -1423,7 +1388,6 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
1423 struct smb_com_read_rsp *pSMBr; 1388 struct smb_com_read_rsp *pSMBr;
1424 struct pagevec lru_pvec; 1389 struct pagevec lru_pvec;
1425 struct cifsFileInfo *open_file; 1390 struct cifsFileInfo *open_file;
1426 int use_old_read = FALSE;
1427 1391
1428 xid = GetXid(); 1392 xid = GetXid();
1429 if (file->private_data == NULL) { 1393 if (file->private_data == NULL) {
@@ -1433,9 +1397,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
1433 open_file = (struct cifsFileInfo *)file->private_data; 1397 open_file = (struct cifsFileInfo *)file->private_data;
1434 cifs_sb = CIFS_SB(file->f_dentry->d_sb); 1398 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1435 pTcon = cifs_sb->tcon; 1399 pTcon = cifs_sb->tcon;
1436 if(pTcon->ses) 1400
1437 if((pTcon->ses->capabilities & CAP_LARGE_FILES) == 0)
1438 use_old_read = TRUE;
1439 pagevec_init(&lru_pvec, 0); 1401 pagevec_init(&lru_pvec, 0);
1440 1402
1441 for (i = 0; i < num_pages; ) { 1403 for (i = 0; i < num_pages; ) {
@@ -1481,22 +1443,10 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
1481 break; 1443 break;
1482 } 1444 }
1483 1445
1484 if(use_old_read) 1446 rc = CIFSSMBRead(xid, pTcon,
1485 rc = SMBLegacyRead(xid, pTcon,
1486 open_file->netfid,
1487 read_size, offset,
1488 &bytes_read, &smb_read_data);
1489 else {
1490 rc = CIFSSMBRead(xid, pTcon,
1491 open_file->netfid, 1447 open_file->netfid,
1492 read_size, offset, 1448 read_size, offset,
1493 &bytes_read, &smb_read_data); 1449 &bytes_read, &smb_read_data);
1494 if(rc == -EINVAL) {
1495 use_old_read = TRUE;
1496 rc = -EAGAIN;
1497 continue;
1498 }
1499 }
1500 1450
1501 /* BB more RC checks ? */ 1451 /* BB more RC checks ? */
1502 if (rc== -EAGAIN) { 1452 if (rc== -EAGAIN) {
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 0485c6d6ecd5..0fbe02ebc033 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -169,6 +169,10 @@ int cifs_get_inode_info_unix(struct inode **pinode,
169 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) 169 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
170 inode->i_fop->lock = NULL; 170 inode->i_fop->lock = NULL;
171 inode->i_data.a_ops = &cifs_addr_ops; 171 inode->i_data.a_ops = &cifs_addr_ops;
172 /* check if server can support readpages */
173 if(pTcon->ses->server->maxBuf <
174 4096 + MAX_CIFS_HDR_SIZE)
175 inode->i_data.a_ops->readpages = NULL;
172 } else if (S_ISDIR(inode->i_mode)) { 176 } else if (S_ISDIR(inode->i_mode)) {
173 cFYI(1, (" Directory inode")); 177 cFYI(1, (" Directory inode"));
174 inode->i_op = &cifs_dir_inode_ops; 178 inode->i_op = &cifs_dir_inode_ops;
@@ -384,6 +388,9 @@ int cifs_get_inode_info(struct inode **pinode,
384 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) 388 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
385 inode->i_fop->lock = NULL; 389 inode->i_fop->lock = NULL;
386 inode->i_data.a_ops = &cifs_addr_ops; 390 inode->i_data.a_ops = &cifs_addr_ops;
391 if(pTcon->ses->server->maxBuf <
392 4096 + MAX_CIFS_HDR_SIZE)
393 inode->i_data.a_ops->readpages = NULL;
387 } else if (S_ISDIR(inode->i_mode)) { 394 } else if (S_ISDIR(inode->i_mode)) {
388 cFYI(1, (" Directory inode ")); 395 cFYI(1, (" Directory inode "));
389 inode->i_op = &cifs_dir_inode_ops; 396 inode->i_op = &cifs_dir_inode_ops;
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 9780f4ee7f12..a1e8dc901de4 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -200,7 +200,10 @@ static void fill_in_inode(struct inode *tmp_inode,
200 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) 200 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
201 tmp_inode->i_fop->lock = NULL; 201 tmp_inode->i_fop->lock = NULL;
202 tmp_inode->i_data.a_ops = &cifs_addr_ops; 202 tmp_inode->i_data.a_ops = &cifs_addr_ops;
203 203 if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
204 (cifs_sb->tcon->ses->server->maxBuf <
205 4096 + MAX_CIFS_HDR_SIZE))
206 tmp_inode->i_data.a_ops->readpages = NULL;
204 if(isNewInode) 207 if(isNewInode)
205 return; /* No sense invalidating pages for new inode 208 return; /* No sense invalidating pages for new inode
206 since have not started caching readahead file 209 since have not started caching readahead file
@@ -306,6 +309,10 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
306 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) 309 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
307 tmp_inode->i_fop->lock = NULL; 310 tmp_inode->i_fop->lock = NULL;
308 tmp_inode->i_data.a_ops = &cifs_addr_ops; 311 tmp_inode->i_data.a_ops = &cifs_addr_ops;
312 if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
313 (cifs_sb->tcon->ses->server->maxBuf <
314 4096 + MAX_CIFS_HDR_SIZE))
315 tmp_inode->i_data.a_ops->readpages = NULL;
309 316
310 if(isNewInode) 317 if(isNewInode)
311 return; /* No sense invalidating pages for new inode since we 318 return; /* No sense invalidating pages for new inode since we