diff options
-rw-r--r-- | fs/cifs/cifspdu.h | 73 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 8 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 215 | ||||
-rw-r--r-- | fs/cifs/dir.c | 7 | ||||
-rw-r--r-- | fs/cifs/file.c | 29 |
5 files changed, 330 insertions, 2 deletions
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 026c88f486a2..cf466595b0d4 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
@@ -40,6 +40,7 @@ | |||
40 | #define SMB_COM_SETATTR 0x09 /* trivial response */ | 40 | #define SMB_COM_SETATTR 0x09 /* trivial response */ |
41 | #define SMB_COM_LOCKING_ANDX 0x24 /* trivial response */ | 41 | #define SMB_COM_LOCKING_ANDX 0x24 /* trivial response */ |
42 | #define SMB_COM_COPY 0x29 /* trivial rsp, fail filename ignrd*/ | 42 | #define SMB_COM_COPY 0x29 /* trivial rsp, fail filename ignrd*/ |
43 | #define SMB_COM_OPEN_ANDX 0x2D /* Legacy open for old servers */ | ||
43 | #define SMB_COM_READ_ANDX 0x2E | 44 | #define SMB_COM_READ_ANDX 0x2E |
44 | #define SMB_COM_WRITE_ANDX 0x2F | 45 | #define SMB_COM_WRITE_ANDX 0x2F |
45 | #define SMB_COM_TRANSACTION2 0x32 | 46 | #define SMB_COM_TRANSACTION2 0x32 |
@@ -625,6 +626,7 @@ typedef struct smb_com_findclose_req { | |||
625 | } FINDCLOSE_REQ; | 626 | } FINDCLOSE_REQ; |
626 | 627 | ||
627 | /* OpenFlags */ | 628 | /* OpenFlags */ |
629 | #define REQ_MORE_INFO 0x00000001 /* legacy (OPEN_AND_X) only */ | ||
628 | #define REQ_OPLOCK 0x00000002 | 630 | #define REQ_OPLOCK 0x00000002 |
629 | #define REQ_BATCHOPLOCK 0x00000004 | 631 | #define REQ_BATCHOPLOCK 0x00000004 |
630 | #define REQ_OPENDIRONLY 0x00000008 | 632 | #define REQ_OPENDIRONLY 0x00000008 |
@@ -680,6 +682,62 @@ typedef struct smb_com_open_rsp { | |||
680 | __u16 ByteCount; /* bct = 0 */ | 682 | __u16 ByteCount; /* bct = 0 */ |
681 | } OPEN_RSP; | 683 | } OPEN_RSP; |
682 | 684 | ||
685 | /* format of legacy open request */ | ||
686 | typedef struct smb_com_openx_req { | ||
687 | struct smb_hdr hdr; /* wct = 15 */ | ||
688 | __u8 AndXCommand; | ||
689 | __u8 AndXReserved; | ||
690 | __le16 AndXOffset; | ||
691 | __le16 OpenFlags; | ||
692 | __le16 Mode; | ||
693 | __le16 Sattr; /* search attributes */ | ||
694 | __le16 FileAttributes; /* dos attrs */ | ||
695 | __le32 CreateTime; /* os2 format */ | ||
696 | __le16 OpenFunction; | ||
697 | __le32 EndOfFile; | ||
698 | __le32 Timeout; | ||
699 | __le32 Reserved; | ||
700 | __u16 ByteCount; /* file name follows */ | ||
701 | char fileName[1]; | ||
702 | } OPENX_REQ; | ||
703 | |||
704 | typedef struct smb_com_openx_rsp { | ||
705 | struct smb_hdr hdr; /* wct = 15 */ | ||
706 | __u8 AndXCommand; | ||
707 | __u8 AndXReserved; | ||
708 | __le16 AndXOffset; | ||
709 | __u16 Fid; | ||
710 | __le16 FileAttributes; | ||
711 | __le32 LastWriteTime; /* os2 format */ | ||
712 | __le32 EndOfFile; | ||
713 | __le16 Access; | ||
714 | __le16 FileType; | ||
715 | __le16 IPCState; | ||
716 | __le16 Action; | ||
717 | __u32 FileId; | ||
718 | __u16 Reserved; | ||
719 | __u16 ByteCount; | ||
720 | } OPENX_RSP; | ||
721 | |||
722 | /* Legacy write request for older servers */ | ||
723 | typedef struct smb_com_writex_req { | ||
724 | struct smb_hdr hdr; /* wct = 12 */ | ||
725 | __u8 AndXCommand; | ||
726 | __u8 AndXReserved; | ||
727 | __le16 AndXOffset; | ||
728 | __u16 Fid; | ||
729 | __le32 OffsetLow; | ||
730 | __u32 Reserved; /* Timeout */ | ||
731 | __le16 WriteMode; /* 1 = write through */ | ||
732 | __le16 Remaining; | ||
733 | __le16 Reserved2; | ||
734 | __le16 DataLengthLow; | ||
735 | __le16 DataOffset; | ||
736 | __le16 ByteCount; | ||
737 | __u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */ | ||
738 | char Data[0]; | ||
739 | } WRITEX_REQ; | ||
740 | |||
683 | typedef struct smb_com_write_req { | 741 | typedef struct smb_com_write_req { |
684 | struct smb_hdr hdr; /* wct = 14 */ | 742 | struct smb_hdr hdr; /* wct = 14 */ |
685 | __u8 AndXCommand; | 743 | __u8 AndXCommand; |
@@ -711,6 +769,21 @@ typedef struct smb_com_write_rsp { | |||
711 | __u16 ByteCount; | 769 | __u16 ByteCount; |
712 | } WRITE_RSP; | 770 | } WRITE_RSP; |
713 | 771 | ||
772 | /* legacy read request for older servers */ | ||
773 | typedef struct smb_com_readx_req { | ||
774 | struct smb_hdr hdr; /* wct = 10 */ | ||
775 | __u8 AndXCommand; | ||
776 | __u8 AndXReserved; | ||
777 | __le16 AndXOffset; | ||
778 | __u16 Fid; | ||
779 | __le32 OffsetLow; | ||
780 | __le16 MaxCount; | ||
781 | __le16 MinCount; /* obsolete */ | ||
782 | __le32 Reserved; | ||
783 | __le16 Remaining; | ||
784 | __le16 ByteCount; | ||
785 | } READX_REQ; | ||
786 | |||
714 | typedef struct smb_com_read_req { | 787 | typedef struct smb_com_read_req { |
715 | struct smb_hdr hdr; /* wct = 12 */ | 788 | struct smb_hdr hdr; /* wct = 12 */ |
716 | __u8 AndXCommand; | 789 | __u8 AndXCommand; |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 28b1ebbd3801..c411f2e001aa 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -218,9 +218,17 @@ extern int CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, | |||
218 | const int access_flags, const int omode, | 218 | const int access_flags, const int omode, |
219 | __u16 * netfid, int *pOplock, FILE_ALL_INFO *, | 219 | __u16 * netfid, int *pOplock, FILE_ALL_INFO *, |
220 | const struct nls_table *nls_codepage, int remap); | 220 | const struct nls_table *nls_codepage, int remap); |
221 | extern int SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon, | ||
222 | const char *fileName, const int disposition, | ||
223 | const int access_flags, const int omode, | ||
224 | __u16 * netfid, int *pOplock, FILE_ALL_INFO *, | ||
225 | const struct nls_table *nls_codepage, int remap); | ||
221 | extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, | 226 | extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, |
222 | const int smb_file_id); | 227 | const int smb_file_id); |
223 | 228 | ||
229 | extern int SMBLegacyRead(const int xid, struct cifsTconInfo *tcon, | ||
230 | const int netfid, unsigned int count, | ||
231 | const __u64 lseek, unsigned int *nbytes, char **buf); | ||
224 | extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, | 232 | extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, |
225 | const int netfid, unsigned int count, | 233 | const int netfid, unsigned int count, |
226 | const __u64 lseek, unsigned int *nbytes, char **buf); | 234 | const __u64 lseek, unsigned int *nbytes, char **buf); |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 67a6240ff2ba..c8ae3ef422ba 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -680,6 +680,146 @@ MkDirRetry: | |||
680 | return rc; | 680 | return rc; |
681 | } | 681 | } |
682 | 682 | ||
683 | static __u16 convert_disposition(int disposition) | ||
684 | { | ||
685 | __u16 ofun = 0; | ||
686 | |||
687 | switch (disposition) { | ||
688 | case FILE_SUPERSEDE: | ||
689 | ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC; | ||
690 | break; | ||
691 | case FILE_OPEN: | ||
692 | ofun = SMBOPEN_OAPPEND; | ||
693 | break; | ||
694 | case FILE_CREATE: | ||
695 | ofun = SMBOPEN_OCREATE; | ||
696 | break; | ||
697 | case FILE_OPEN_IF: | ||
698 | ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND; | ||
699 | break; | ||
700 | case FILE_OVERWRITE: | ||
701 | ofun = SMBOPEN_OTRUNC; | ||
702 | break; | ||
703 | case FILE_OVERWRITE_IF: | ||
704 | ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC; | ||
705 | break; | ||
706 | default: | ||
707 | cFYI(1,("unknown disposition %d",disposition)); | ||
708 | ofun = SMBOPEN_OAPPEND; /* regular open */ | ||
709 | } | ||
710 | return ofun; | ||
711 | } | ||
712 | |||
713 | int | ||
714 | SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon, | ||
715 | const char *fileName, const int openDisposition, | ||
716 | const int access_flags, const int create_options, __u16 * netfid, | ||
717 | int *pOplock, FILE_ALL_INFO * pfile_info, | ||
718 | const struct nls_table *nls_codepage, int remap) | ||
719 | { | ||
720 | int rc = -EACCES; | ||
721 | OPENX_REQ *pSMB = NULL; | ||
722 | OPENX_RSP *pSMBr = NULL; | ||
723 | int bytes_returned; | ||
724 | int name_len; | ||
725 | __u16 count; | ||
726 | |||
727 | OldOpenRetry: | ||
728 | rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB, | ||
729 | (void **) &pSMBr); | ||
730 | if (rc) | ||
731 | return rc; | ||
732 | |||
733 | pSMB->AndXCommand = 0xFF; /* none */ | ||
734 | |||
735 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | ||
736 | count = 1; /* account for one byte pad to word boundary */ | ||
737 | name_len = | ||
738 | cifsConvertToUCS((__le16 *) (pSMB->fileName + 1), | ||
739 | fileName, PATH_MAX, nls_codepage, remap); | ||
740 | name_len++; /* trailing null */ | ||
741 | name_len *= 2; | ||
742 | } else { /* BB improve check for buffer overruns BB */ | ||
743 | count = 0; /* no pad */ | ||
744 | name_len = strnlen(fileName, PATH_MAX); | ||
745 | name_len++; /* trailing null */ | ||
746 | strncpy(pSMB->fileName, fileName, name_len); | ||
747 | } | ||
748 | if (*pOplock & REQ_OPLOCK) | ||
749 | pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK); | ||
750 | else if (*pOplock & REQ_BATCHOPLOCK) { | ||
751 | pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK); | ||
752 | } | ||
753 | pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO); | ||
754 | /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */ | ||
755 | /* 0 = read | ||
756 | 1 = write | ||
757 | 2 = rw | ||
758 | 3 = execute | ||
759 | */ | ||
760 | pSMB->Mode = cpu_to_le16(2); | ||
761 | pSMB->Mode |= cpu_to_le16(0x40); /* deny none */ | ||
762 | /* set file as system file if special file such | ||
763 | as fifo and server expecting SFU style and | ||
764 | no Unix extensions */ | ||
765 | |||
766 | if(create_options & CREATE_OPTION_SPECIAL) | ||
767 | pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM); | ||
768 | else | ||
769 | pSMB->FileAttributes = cpu_to_le16(ATTR_NORMAL); | ||
770 | |||
771 | /* if ((omode & S_IWUGO) == 0) | ||
772 | pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/ | ||
773 | /* Above line causes problems due to vfs splitting create into two | ||
774 | pieces - need to set mode after file created not while it is | ||
775 | being created */ | ||
776 | |||
777 | /* BB FIXME BB */ | ||
778 | /* pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); */ | ||
779 | /* BB FIXME END BB */ | ||
780 | pSMB->OpenFunction = convert_disposition(openDisposition); | ||
781 | count += name_len; | ||
782 | pSMB->hdr.smb_buf_length += count; | ||
783 | |||
784 | pSMB->ByteCount = cpu_to_le16(count); | ||
785 | /* long_op set to 1 to allow for oplock break timeouts */ | ||
786 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | ||
787 | (struct smb_hdr *) pSMBr, &bytes_returned, 1); | ||
788 | cifs_stats_inc(&tcon->num_opens); | ||
789 | if (rc) { | ||
790 | cFYI(1, ("Error in Open = %d", rc)); | ||
791 | } else { | ||
792 | /* BB verify if wct == 15 */ | ||
793 | |||
794 | /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */ | ||
795 | |||
796 | *netfid = pSMBr->Fid; /* cifs fid stays in le */ | ||
797 | /* Let caller know file was created so we can set the mode. */ | ||
798 | /* Do we care about the CreateAction in any other cases? */ | ||
799 | /* BB FIXME BB */ | ||
800 | /* if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction) | ||
801 | *pOplock |= CIFS_CREATE_ACTION; */ | ||
802 | /* BB FIXME END */ | ||
803 | |||
804 | if(pfile_info) { | ||
805 | pfile_info->CreationTime = 0; /* BB convert CreateTime*/ | ||
806 | pfile_info->LastAccessTime = 0; /* BB fixme */ | ||
807 | pfile_info->LastWriteTime = 0; /* BB fixme */ | ||
808 | pfile_info->ChangeTime = 0; /* BB fixme */ | ||
809 | pfile_info->Attributes = pSMBr->FileAttributes; | ||
810 | /* the file_info buf is endian converted by caller */ | ||
811 | pfile_info->AllocationSize = pSMBr->EndOfFile; | ||
812 | pfile_info->EndOfFile = pSMBr->EndOfFile; | ||
813 | pfile_info->NumberOfLinks = cpu_to_le32(1); | ||
814 | } | ||
815 | } | ||
816 | |||
817 | cifs_buf_release(pSMB); | ||
818 | if (rc == -EAGAIN) | ||
819 | goto OldOpenRetry; | ||
820 | return rc; | ||
821 | } | ||
822 | |||
683 | int | 823 | int |
684 | CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, | 824 | CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, |
685 | const char *fileName, const int openDisposition, | 825 | const char *fileName, const int openDisposition, |
@@ -783,6 +923,81 @@ openRetry: | |||
783 | return rc; | 923 | return rc; |
784 | } | 924 | } |
785 | 925 | ||
926 | int | ||
927 | SMBLegacyRead(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 | |||
786 | /* If no buffer passed in, then caller wants to do the copy | 1001 | /* If no buffer passed in, then caller wants to do the copy |
787 | as in the case of readpages so the SMB buffer must be | 1002 | as in the case of readpages so the SMB buffer must be |
788 | freed by the caller */ | 1003 | freed by the caller */ |
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 5311c50734b0..248ddebd67f4 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -184,6 +184,13 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
184 | desiredAccess, CREATE_NOT_DIR, | 184 | desiredAccess, CREATE_NOT_DIR, |
185 | &fileHandle, &oplock, buf, cifs_sb->local_nls, | 185 | &fileHandle, &oplock, buf, cifs_sb->local_nls, |
186 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 186 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
187 | if(rc == -EIO) { | ||
188 | /* old server, retry the open legacy style */ | ||
189 | rc = SMBLegacyOpen(xid, pTcon, full_path, disposition, | ||
190 | desiredAccess, CREATE_NOT_DIR, | ||
191 | &fileHandle, &oplock, buf, cifs_sb->local_nls, | ||
192 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
193 | } | ||
187 | if (rc) { | 194 | if (rc) { |
188 | cFYI(1, ("cifs_create returned 0x%x ", rc)); | 195 | cFYI(1, ("cifs_create returned 0x%x ", rc)); |
189 | } else { | 196 | } else { |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 5857d12611e6..8ae962e7c93f 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -256,6 +256,13 @@ int cifs_open(struct inode *inode, struct file *file) | |||
256 | CREATE_NOT_DIR, &netfid, &oplock, buf, | 256 | CREATE_NOT_DIR, &netfid, &oplock, buf, |
257 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags | 257 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags |
258 | & CIFS_MOUNT_MAP_SPECIAL_CHR); | 258 | & CIFS_MOUNT_MAP_SPECIAL_CHR); |
259 | if (rc == -EIO) { | ||
260 | /* Old server, try legacy style OpenX */ | ||
261 | rc = SMBLegacyOpen(xid, pTcon, full_path, disposition, | ||
262 | desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf, | ||
263 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags | ||
264 | & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
265 | } | ||
259 | if (rc) { | 266 | if (rc) { |
260 | cFYI(1, ("cifs_open returned 0x%x ", rc)); | 267 | cFYI(1, ("cifs_open returned 0x%x ", rc)); |
261 | goto out; | 268 | goto out; |
@@ -1210,7 +1217,12 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, | |||
1210 | open_file->netfid, | 1217 | open_file->netfid, |
1211 | current_read_size, *poffset, | 1218 | current_read_size, *poffset, |
1212 | &bytes_read, &smb_read_data); | 1219 | &bytes_read, &smb_read_data); |
1213 | 1220 | if(rc == -EINVAL) { | |
1221 | rc = SMBLegacyRead(xid, pTcon, | ||
1222 | open_file->netfid, | ||
1223 | current_read_size, *poffset, | ||
1224 | &bytes_read, &smb_read_data); | ||
1225 | } | ||
1214 | pSMBr = (struct smb_com_read_rsp *)smb_read_data; | 1226 | pSMBr = (struct smb_com_read_rsp *)smb_read_data; |
1215 | if (copy_to_user(current_offset, | 1227 | if (copy_to_user(current_offset, |
1216 | smb_read_data + 4 /* RFC1001 hdr */ | 1228 | smb_read_data + 4 /* RFC1001 hdr */ |
@@ -1287,6 +1299,12 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, | |||
1287 | open_file->netfid, | 1299 | open_file->netfid, |
1288 | current_read_size, *poffset, | 1300 | current_read_size, *poffset, |
1289 | &bytes_read, ¤t_offset); | 1301 | &bytes_read, ¤t_offset); |
1302 | if(rc == -EINVAL) { | ||
1303 | rc = SMBLegacyRead(xid, pTcon, | ||
1304 | open_file->netfid, | ||
1305 | current_read_size, *poffset, | ||
1306 | &bytes_read, ¤t_offset); | ||
1307 | } | ||
1290 | } | 1308 | } |
1291 | if (rc || (bytes_read == 0)) { | 1309 | if (rc || (bytes_read == 0)) { |
1292 | if (total_read) { | 1310 | if (total_read) { |
@@ -1443,7 +1461,14 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
1443 | open_file->netfid, | 1461 | open_file->netfid, |
1444 | read_size, offset, | 1462 | read_size, offset, |
1445 | &bytes_read, &smb_read_data); | 1463 | &bytes_read, &smb_read_data); |
1446 | /* BB need to check return code here */ | 1464 | if (rc == -EINVAL) { |
1465 | rc = SMBLegacyRead(xid, pTcon, | ||
1466 | open_file->netfid, | ||
1467 | read_size, offset, | ||
1468 | &bytes_read, &smb_read_data); | ||
1469 | } | ||
1470 | |||
1471 | /* BB more RC checks ? */ | ||
1447 | if (rc== -EAGAIN) { | 1472 | if (rc== -EAGAIN) { |
1448 | if (smb_read_data) { | 1473 | if (smb_read_data) { |
1449 | cifs_buf_release(smb_read_data); | 1474 | cifs_buf_release(smb_read_data); |