aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/cifssmb.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r--fs/cifs/cifssmb.c99
1 files changed, 20 insertions, 79 deletions
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);