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.c659
1 files changed, 548 insertions, 111 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 0db0b313d715..9312bfc56682 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -125,6 +125,9 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
125 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon 125 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon
126 , nls_codepage); 126 , nls_codepage);
127 up(&tcon->ses->sesSem); 127 up(&tcon->ses->sesSem);
128 /* BB FIXME add code to check if wsize needs
129 update due to negotiated smb buffer size
130 shrinking */
128 if(rc == 0) 131 if(rc == 0)
129 atomic_inc(&tconInfoReconnectCount); 132 atomic_inc(&tconInfoReconnectCount);
130 133
@@ -166,11 +169,9 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
166 169
167 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct); 170 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
168 171
169#ifdef CONFIG_CIFS_STATS 172 if(tcon != NULL)
170 if(tcon != NULL) { 173 cifs_stats_inc(&tcon->num_smbs_sent);
171 atomic_inc(&tcon->num_smbs_sent); 174
172 }
173#endif /* CONFIG_CIFS_STATS */
174 return rc; 175 return rc;
175} 176}
176 177
@@ -222,6 +223,9 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
222 rc = CIFSTCon(0, tcon->ses, tcon->treeName, 223 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
223 tcon, nls_codepage); 224 tcon, nls_codepage);
224 up(&tcon->ses->sesSem); 225 up(&tcon->ses->sesSem);
226 /* BB FIXME add code to check if wsize needs
227 update due to negotiated smb buffer size
228 shrinking */
225 if(rc == 0) 229 if(rc == 0)
226 atomic_inc(&tconInfoReconnectCount); 230 atomic_inc(&tconInfoReconnectCount);
227 231
@@ -269,11 +273,9 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
269 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon, 273 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
270 wct /*wct */ ); 274 wct /*wct */ );
271 275
272#ifdef CONFIG_CIFS_STATS 276 if(tcon != NULL)
273 if(tcon != NULL) { 277 cifs_stats_inc(&tcon->num_smbs_sent);
274 atomic_inc(&tcon->num_smbs_sent); 278
275 }
276#endif /* CONFIG_CIFS_STATS */
277 return rc; 279 return rc;
278} 280}
279 281
@@ -330,7 +332,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
330 (void **) &pSMB, (void **) &pSMBr); 332 (void **) &pSMB, (void **) &pSMBr);
331 if (rc) 333 if (rc)
332 return rc; 334 return rc;
333 335 pSMB->hdr.Mid = GetNextMid(server);
334 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; 336 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
335 if (extended_security) 337 if (extended_security)
336 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; 338 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
@@ -422,8 +424,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
422 } 424 }
423 425
424 } 426 }
425 if (pSMB) 427
426 cifs_buf_release(pSMB); 428 cifs_buf_release(pSMB);
427 return rc; 429 return rc;
428} 430}
429 431
@@ -518,6 +520,8 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
518 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */ 520 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
519 521
520 if(ses->server) { 522 if(ses->server) {
523 pSMB->hdr.Mid = GetNextMid(ses->server);
524
521 if(ses->server->secMode & 525 if(ses->server->secMode &
522 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) 526 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
523 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; 527 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
@@ -537,9 +541,8 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
537 rc = -ESHUTDOWN; 541 rc = -ESHUTDOWN;
538 } 542 }
539 } 543 }
540 if (pSMB)
541 cifs_small_buf_release(pSMB);
542 up(&ses->sesSem); 544 up(&ses->sesSem);
545 cifs_small_buf_release(pSMB);
543 546
544 /* if session dead then we do not need to do ulogoff, 547 /* if session dead then we do not need to do ulogoff,
545 since server closed smb session, no sense reporting 548 since server closed smb session, no sense reporting
@@ -583,14 +586,10 @@ DelFileRetry:
583 pSMB->ByteCount = cpu_to_le16(name_len + 1); 586 pSMB->ByteCount = cpu_to_le16(name_len + 1);
584 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 587 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
585 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 588 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
589 cifs_stats_inc(&tcon->num_deletes);
586 if (rc) { 590 if (rc) {
587 cFYI(1, ("Error in RMFile = %d", rc)); 591 cFYI(1, ("Error in RMFile = %d", rc));
588 } 592 }
589#ifdef CONFIG_CIFS_STATS
590 else {
591 atomic_inc(&tcon->num_deletes);
592 }
593#endif
594 593
595 cifs_buf_release(pSMB); 594 cifs_buf_release(pSMB);
596 if (rc == -EAGAIN) 595 if (rc == -EAGAIN)
@@ -632,14 +631,10 @@ RmDirRetry:
632 pSMB->ByteCount = cpu_to_le16(name_len + 1); 631 pSMB->ByteCount = cpu_to_le16(name_len + 1);
633 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 632 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
634 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 633 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
634 cifs_stats_inc(&tcon->num_rmdirs);
635 if (rc) { 635 if (rc) {
636 cFYI(1, ("Error in RMDir = %d", rc)); 636 cFYI(1, ("Error in RMDir = %d", rc));
637 } 637 }
638#ifdef CONFIG_CIFS_STATS
639 else {
640 atomic_inc(&tcon->num_rmdirs);
641 }
642#endif
643 638
644 cifs_buf_release(pSMB); 639 cifs_buf_release(pSMB);
645 if (rc == -EAGAIN) 640 if (rc == -EAGAIN)
@@ -680,20 +675,161 @@ MkDirRetry:
680 pSMB->ByteCount = cpu_to_le16(name_len + 1); 675 pSMB->ByteCount = cpu_to_le16(name_len + 1);
681 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 676 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
682 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 677 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
678 cifs_stats_inc(&tcon->num_mkdirs);
683 if (rc) { 679 if (rc) {
684 cFYI(1, ("Error in Mkdir = %d", rc)); 680 cFYI(1, ("Error in Mkdir = %d", rc));
685 } 681 }
686#ifdef CONFIG_CIFS_STATS 682
687 else {
688 atomic_inc(&tcon->num_mkdirs);
689 }
690#endif
691 cifs_buf_release(pSMB); 683 cifs_buf_release(pSMB);
692 if (rc == -EAGAIN) 684 if (rc == -EAGAIN)
693 goto MkDirRetry; 685 goto MkDirRetry;
694 return rc; 686 return rc;
695} 687}
696 688
689static __u16 convert_disposition(int disposition)
690{
691 __u16 ofun = 0;
692
693 switch (disposition) {
694 case FILE_SUPERSEDE:
695 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
696 break;
697 case FILE_OPEN:
698 ofun = SMBOPEN_OAPPEND;
699 break;
700 case FILE_CREATE:
701 ofun = SMBOPEN_OCREATE;
702 break;
703 case FILE_OPEN_IF:
704 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
705 break;
706 case FILE_OVERWRITE:
707 ofun = SMBOPEN_OTRUNC;
708 break;
709 case FILE_OVERWRITE_IF:
710 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
711 break;
712 default:
713 cFYI(1,("unknown disposition %d",disposition));
714 ofun = SMBOPEN_OAPPEND; /* regular open */
715 }
716 return ofun;
717}
718
719int
720SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
721 const char *fileName, const int openDisposition,
722 const int access_flags, const int create_options, __u16 * netfid,
723 int *pOplock, FILE_ALL_INFO * pfile_info,
724 const struct nls_table *nls_codepage, int remap)
725{
726 int rc = -EACCES;
727 OPENX_REQ *pSMB = NULL;
728 OPENX_RSP *pSMBr = NULL;
729 int bytes_returned;
730 int name_len;
731 __u16 count;
732
733OldOpenRetry:
734 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
735 (void **) &pSMBr);
736 if (rc)
737 return rc;
738
739 pSMB->AndXCommand = 0xFF; /* none */
740
741 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
742 count = 1; /* account for one byte pad to word boundary */
743 name_len =
744 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
745 fileName, PATH_MAX, nls_codepage, remap);
746 name_len++; /* trailing null */
747 name_len *= 2;
748 } else { /* BB improve check for buffer overruns BB */
749 count = 0; /* no pad */
750 name_len = strnlen(fileName, PATH_MAX);
751 name_len++; /* trailing null */
752 strncpy(pSMB->fileName, fileName, name_len);
753 }
754 if (*pOplock & REQ_OPLOCK)
755 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
756 else if (*pOplock & REQ_BATCHOPLOCK) {
757 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
758 }
759 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
760 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
761 /* 0 = read
762 1 = write
763 2 = rw
764 3 = execute
765 */
766 pSMB->Mode = cpu_to_le16(2);
767 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
768 /* set file as system file if special file such
769 as fifo and server expecting SFU style and
770 no Unix extensions */
771
772 if(create_options & CREATE_OPTION_SPECIAL)
773 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
774 else
775 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
776
777 /* if ((omode & S_IWUGO) == 0)
778 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
779 /* Above line causes problems due to vfs splitting create into two
780 pieces - need to set mode after file created not while it is
781 being created */
782
783 /* BB FIXME BB */
784/* pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); */
785 /* BB FIXME END BB */
786
787 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
788 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
789 count += name_len;
790 pSMB->hdr.smb_buf_length += count;
791
792 pSMB->ByteCount = cpu_to_le16(count);
793 /* long_op set to 1 to allow for oplock break timeouts */
794 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
795 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
796 cifs_stats_inc(&tcon->num_opens);
797 if (rc) {
798 cFYI(1, ("Error in Open = %d", rc));
799 } else {
800 /* BB verify if wct == 15 */
801
802/* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
803
804 *netfid = pSMBr->Fid; /* cifs fid stays in le */
805 /* Let caller know file was created so we can set the mode. */
806 /* Do we care about the CreateAction in any other cases? */
807 /* BB FIXME BB */
808/* if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
809 *pOplock |= CIFS_CREATE_ACTION; */
810 /* BB FIXME END */
811
812 if(pfile_info) {
813 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
814 pfile_info->LastAccessTime = 0; /* BB fixme */
815 pfile_info->LastWriteTime = 0; /* BB fixme */
816 pfile_info->ChangeTime = 0; /* BB fixme */
817 pfile_info->Attributes =
818 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
819 /* the file_info buf is endian converted by caller */
820 pfile_info->AllocationSize =
821 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
822 pfile_info->EndOfFile = pfile_info->AllocationSize;
823 pfile_info->NumberOfLinks = cpu_to_le32(1);
824 }
825 }
826
827 cifs_buf_release(pSMB);
828 if (rc == -EAGAIN)
829 goto OldOpenRetry;
830 return rc;
831}
832
697int 833int
698CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, 834CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
699 const char *fileName, const int openDisposition, 835 const char *fileName, const int openDisposition,
@@ -738,7 +874,13 @@ openRetry:
738 } 874 }
739 pSMB->DesiredAccess = cpu_to_le32(access_flags); 875 pSMB->DesiredAccess = cpu_to_le32(access_flags);
740 pSMB->AllocationSize = 0; 876 pSMB->AllocationSize = 0;
741 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL); 877 /* set file as system file if special file such
878 as fifo and server expecting SFU style and
879 no Unix extensions */
880 if(create_options & CREATE_OPTION_SPECIAL)
881 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
882 else
883 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
742 /* XP does not handle ATTR_POSIX_SEMANTICS */ 884 /* XP does not handle ATTR_POSIX_SEMANTICS */
743 /* but it helps speed up case sensitive checks for other 885 /* but it helps speed up case sensitive checks for other
744 servers such as Samba */ 886 servers such as Samba */
@@ -752,7 +894,7 @@ openRetry:
752 being created */ 894 being created */
753 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL); 895 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
754 pSMB->CreateDisposition = cpu_to_le32(openDisposition); 896 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
755 pSMB->CreateOptions = cpu_to_le32(create_options); 897 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
756 /* BB Expirement with various impersonation levels and verify */ 898 /* BB Expirement with various impersonation levels and verify */
757 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); 899 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
758 pSMB->SecurityFlags = 900 pSMB->SecurityFlags =
@@ -765,6 +907,7 @@ openRetry:
765 /* long_op set to 1 to allow for oplock break timeouts */ 907 /* long_op set to 1 to allow for oplock break timeouts */
766 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 908 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
767 (struct smb_hdr *) pSMBr, &bytes_returned, 1); 909 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
910 cifs_stats_inc(&tcon->num_opens);
768 if (rc) { 911 if (rc) {
769 cFYI(1, ("Error in Open = %d", rc)); 912 cFYI(1, ("Error in Open = %d", rc));
770 } else { 913 } else {
@@ -782,11 +925,8 @@ openRetry:
782 pfile_info->EndOfFile = pSMBr->EndOfFile; 925 pfile_info->EndOfFile = pSMBr->EndOfFile;
783 pfile_info->NumberOfLinks = cpu_to_le32(1); 926 pfile_info->NumberOfLinks = cpu_to_le32(1);
784 } 927 }
785
786#ifdef CONFIG_CIFS_STATS
787 atomic_inc(&tcon->num_opens);
788#endif
789 } 928 }
929
790 cifs_buf_release(pSMB); 930 cifs_buf_release(pSMB);
791 if (rc == -EAGAIN) 931 if (rc == -EAGAIN)
792 goto openRetry; 932 goto openRetry;
@@ -807,11 +947,16 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
807 READ_RSP *pSMBr = NULL; 947 READ_RSP *pSMBr = NULL;
808 char *pReadData = NULL; 948 char *pReadData = NULL;
809 int bytes_returned; 949 int bytes_returned;
950 int wct;
810 951
811 cFYI(1,("Reading %d bytes on fid %d",count,netfid)); 952 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
953 if(tcon->ses->capabilities & CAP_LARGE_FILES)
954 wct = 12;
955 else
956 wct = 10; /* old style read */
812 957
813 *nbytes = 0; 958 *nbytes = 0;
814 rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB, 959 rc = smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB,
815 (void **) &pSMBr); 960 (void **) &pSMBr);
816 if (rc) 961 if (rc)
817 return rc; 962 return rc;
@@ -823,14 +968,26 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
823 pSMB->AndXCommand = 0xFF; /* none */ 968 pSMB->AndXCommand = 0xFF; /* none */
824 pSMB->Fid = netfid; 969 pSMB->Fid = netfid;
825 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF); 970 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
826 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32); 971 if(wct == 12)
972 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
973 else if((lseek >> 32) > 0) /* can not handle this big offset for old */
974 return -EIO;
975
827 pSMB->Remaining = 0; 976 pSMB->Remaining = 0;
828 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF); 977 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
829 pSMB->MaxCountHigh = cpu_to_le32(count >> 16); 978 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
830 pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */ 979 if(wct == 12)
831 980 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
981 else {
982 /* old style read */
983 struct smb_com_readx_req * pSMBW =
984 (struct smb_com_readx_req *)pSMB;
985 pSMBW->ByteCount = 0;
986 }
987
832 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 988 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
833 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 989 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
990 cifs_stats_inc(&tcon->num_reads);
834 if (rc) { 991 if (rc) {
835 cERROR(1, ("Send error in read = %d", rc)); 992 cERROR(1, ("Send error in read = %d", rc));
836 } else { 993 } else {
@@ -876,12 +1033,20 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
876 int rc = -EACCES; 1033 int rc = -EACCES;
877 WRITE_REQ *pSMB = NULL; 1034 WRITE_REQ *pSMB = NULL;
878 WRITE_RSP *pSMBr = NULL; 1035 WRITE_RSP *pSMBr = NULL;
879 int bytes_returned; 1036 int bytes_returned, wct;
880 __u32 bytes_sent; 1037 __u32 bytes_sent;
881 __u16 byte_count; 1038 __u16 byte_count;
882 1039
883 /* cFYI(1,("write at %lld %d bytes",offset,count));*/ 1040 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
884 rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB, 1041 if(tcon->ses == NULL)
1042 return -ECONNABORTED;
1043
1044 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1045 wct = 14;
1046 else
1047 wct = 12;
1048
1049 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
885 (void **) &pSMBr); 1050 (void **) &pSMBr);
886 if (rc) 1051 if (rc)
887 return rc; 1052 return rc;
@@ -892,7 +1057,11 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
892 pSMB->AndXCommand = 0xFF; /* none */ 1057 pSMB->AndXCommand = 0xFF; /* none */
893 pSMB->Fid = netfid; 1058 pSMB->Fid = netfid;
894 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); 1059 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
895 pSMB->OffsetHigh = cpu_to_le32(offset >> 32); 1060 if(wct == 14)
1061 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1062 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1063 return -EIO;
1064
896 pSMB->Reserved = 0xFFFFFFFF; 1065 pSMB->Reserved = 0xFFFFFFFF;
897 pSMB->WriteMode = 0; 1066 pSMB->WriteMode = 0;
898 pSMB->Remaining = 0; 1067 pSMB->Remaining = 0;
@@ -911,7 +1080,7 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
911 if (bytes_sent > count) 1080 if (bytes_sent > count)
912 bytes_sent = count; 1081 bytes_sent = count;
913 pSMB->DataOffset = 1082 pSMB->DataOffset =
914 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4); 1083 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
915 if(buf) 1084 if(buf)
916 memcpy(pSMB->Data,buf,bytes_sent); 1085 memcpy(pSMB->Data,buf,bytes_sent);
917 else if(ubuf) { 1086 else if(ubuf) {
@@ -919,20 +1088,31 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
919 cifs_buf_release(pSMB); 1088 cifs_buf_release(pSMB);
920 return -EFAULT; 1089 return -EFAULT;
921 } 1090 }
922 } else { 1091 } else if (count != 0) {
923 /* No buffer */ 1092 /* No buffer */
924 cifs_buf_release(pSMB); 1093 cifs_buf_release(pSMB);
925 return -EINVAL; 1094 return -EINVAL;
1095 } /* else setting file size with write of zero bytes */
1096 if(wct == 14)
1097 byte_count = bytes_sent + 1; /* pad */
1098 else /* wct == 12 */ {
1099 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
926 } 1100 }
927
928 byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
929 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF); 1101 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
930 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16); 1102 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
931 pSMB->hdr.smb_buf_length += bytes_sent+1; 1103 pSMB->hdr.smb_buf_length += byte_count;
932 pSMB->ByteCount = cpu_to_le16(byte_count); 1104
1105 if(wct == 14)
1106 pSMB->ByteCount = cpu_to_le16(byte_count);
1107 else { /* old style write has byte count 4 bytes earlier so 4 bytes pad */
1108 struct smb_com_writex_req * pSMBW =
1109 (struct smb_com_writex_req *)pSMB;
1110 pSMBW->ByteCount = cpu_to_le16(byte_count);
1111 }
933 1112
934 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1113 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
935 (struct smb_hdr *) pSMBr, &bytes_returned, long_op); 1114 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1115 cifs_stats_inc(&tcon->num_writes);
936 if (rc) { 1116 if (rc) {
937 cFYI(1, ("Send error in write = %d", rc)); 1117 cFYI(1, ("Send error in write = %d", rc));
938 *nbytes = 0; 1118 *nbytes = 0;
@@ -951,56 +1131,72 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
951} 1131}
952 1132
953#ifdef CONFIG_CIFS_EXPERIMENTAL 1133#ifdef CONFIG_CIFS_EXPERIMENTAL
954int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, 1134int
1135CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
955 const int netfid, const unsigned int count, 1136 const int netfid, const unsigned int count,
956 const __u64 offset, unsigned int *nbytes, const char __user *buf, 1137 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
957 const int long_op) 1138 int n_vec, const int long_op)
958{ 1139{
959 int rc = -EACCES; 1140 int rc = -EACCES;
960 WRITE_REQ *pSMB = NULL; 1141 WRITE_REQ *pSMB = NULL;
961 WRITE_RSP *pSMBr = NULL; 1142 int bytes_returned, wct;
962 /*int bytes_returned;*/ 1143 int smb_hdr_len;
963 unsigned bytes_sent;
964 __u16 byte_count;
965 1144
966 rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB); 1145 cFYI(1,("write2 at %lld %d bytes",offset,count)); /* BB removeme BB */
967 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);
968 if (rc) 1151 if (rc)
969 return rc; 1152 return rc;
970
971 pSMBr = (WRITE_RSP *)pSMB; /* BB removeme BB */
972
973 /* tcon and ses pointer are checked in smb_init */ 1153 /* tcon and ses pointer are checked in smb_init */
974 if (tcon->ses->server == NULL) 1154 if (tcon->ses->server == NULL)
975 return -ECONNABORTED; 1155 return -ECONNABORTED;
976 1156
977 pSMB->AndXCommand = 0xFF; /* none */ 1157 pSMB->AndXCommand = 0xFF; /* none */
978 pSMB->Fid = netfid; 1158 pSMB->Fid = netfid;
979 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); 1159 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
980 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;
981 pSMB->Reserved = 0xFFFFFFFF; 1164 pSMB->Reserved = 0xFFFFFFFF;
982 pSMB->WriteMode = 0; 1165 pSMB->WriteMode = 0;
983 pSMB->Remaining = 0; 1166 pSMB->Remaining = 0;
984 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF; 1167
985 if (bytes_sent > count)
986 bytes_sent = count;
987 pSMB->DataLengthHigh = 0;
988 pSMB->DataOffset = 1168 pSMB->DataOffset =
989 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4); 1169 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
990 1170
991 byte_count = bytes_sent + 1 /* pad */ ; 1171 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
992 pSMB->DataLengthLow = cpu_to_le16(bytes_sent); 1172 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
993 pSMB->DataLengthHigh = 0; 1173 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
994 pSMB->hdr.smb_buf_length += byte_count; 1174 if(wct == 14)
995 pSMB->ByteCount = cpu_to_le16(byte_count); 1175 pSMB->hdr.smb_buf_length += count+1;
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 }
1185 iov[0].iov_base = pSMB;
1186 iov[0].iov_len = smb_hdr_len + 4;
996 1187
997/* rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB, 1188 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &bytes_returned,
998 (struct smb_hdr *) pSMBr, buf, buflen, &bytes_returned, long_op); */ /* BB fixme BB */ 1189 long_op);
1190 cifs_stats_inc(&tcon->num_writes);
999 if (rc) { 1191 if (rc) {
1000 cFYI(1, ("Send error in write2 (large write) = %d", rc)); 1192 cFYI(1, ("Send error Write2 = %d", rc));
1001 *nbytes = 0; 1193 *nbytes = 0;
1002 } else 1194 } else {
1003 *nbytes = le16_to_cpu(pSMBr->Count); 1195 WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB;
1196 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1197 *nbytes = (*nbytes) << 16;
1198 *nbytes += le16_to_cpu(pSMBr->Count);
1199 }
1004 1200
1005 cifs_small_buf_release(pSMB); 1201 cifs_small_buf_release(pSMB);
1006 1202
@@ -1009,6 +1205,8 @@ int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1009 1205
1010 return rc; 1206 return rc;
1011} 1207}
1208
1209
1012#endif /* CIFS_EXPERIMENTAL */ 1210#endif /* CIFS_EXPERIMENTAL */
1013 1211
1014int 1212int
@@ -1065,7 +1263,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1065 1263
1066 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1264 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1067 (struct smb_hdr *) pSMBr, &bytes_returned, timeout); 1265 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1068 1266 cifs_stats_inc(&tcon->num_locks);
1069 if (rc) { 1267 if (rc) {
1070 cFYI(1, ("Send error in Lock = %d", rc)); 1268 cFYI(1, ("Send error in Lock = %d", rc));
1071 } 1269 }
@@ -1099,6 +1297,7 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1099 pSMB->ByteCount = 0; 1297 pSMB->ByteCount = 0;
1100 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1298 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1101 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1299 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1300 cifs_stats_inc(&tcon->num_closes);
1102 if (rc) { 1301 if (rc) {
1103 if(rc!=-EINTR) { 1302 if(rc!=-EINTR) {
1104 /* EINTR is expected when user ctl-c to kill app */ 1303 /* EINTR is expected when user ctl-c to kill app */
@@ -1171,16 +1370,11 @@ renameRetry:
1171 1370
1172 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1371 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1173 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1372 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1373 cifs_stats_inc(&tcon->num_renames);
1174 if (rc) { 1374 if (rc) {
1175 cFYI(1, ("Send error in rename = %d", rc)); 1375 cFYI(1, ("Send error in rename = %d", rc));
1176 } 1376 }
1177 1377
1178#ifdef CONFIG_CIFS_STATS
1179 else {
1180 atomic_inc(&tcon->num_renames);
1181 }
1182#endif
1183
1184 cifs_buf_release(pSMB); 1378 cifs_buf_release(pSMB);
1185 1379
1186 if (rc == -EAGAIN) 1380 if (rc == -EAGAIN)
@@ -1255,14 +1449,11 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1255 pSMB->ByteCount = cpu_to_le16(byte_count); 1449 pSMB->ByteCount = cpu_to_le16(byte_count);
1256 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB, 1450 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1257 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1451 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1452 cifs_stats_inc(&pTcon->num_t2renames);
1258 if (rc) { 1453 if (rc) {
1259 cFYI(1,("Send error in Rename (by file handle) = %d", rc)); 1454 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1260 } 1455 }
1261#ifdef CONFIG_CIFS_STATS 1456
1262 else {
1263 atomic_inc(&pTcon->num_t2renames);
1264 }
1265#endif
1266 cifs_buf_release(pSMB); 1457 cifs_buf_release(pSMB);
1267 1458
1268 /* Note: On -EAGAIN error only caller can retry on handle based calls 1459 /* Note: On -EAGAIN error only caller can retry on handle based calls
@@ -1416,6 +1607,7 @@ createSymLinkRetry:
1416 pSMB->ByteCount = cpu_to_le16(byte_count); 1607 pSMB->ByteCount = cpu_to_le16(byte_count);
1417 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1608 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1418 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1609 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1610 cifs_stats_inc(&tcon->num_symlinks);
1419 if (rc) { 1611 if (rc) {
1420 cFYI(1, 1612 cFYI(1,
1421 ("Send error in SetPathInfo (create symlink) = %d", 1613 ("Send error in SetPathInfo (create symlink) = %d",
@@ -1505,6 +1697,7 @@ createHardLinkRetry:
1505 pSMB->ByteCount = cpu_to_le16(byte_count); 1697 pSMB->ByteCount = cpu_to_le16(byte_count);
1506 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1698 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1507 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1699 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1700 cifs_stats_inc(&tcon->num_hardlinks);
1508 if (rc) { 1701 if (rc) {
1509 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc)); 1702 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
1510 } 1703 }
@@ -1575,6 +1768,7 @@ winCreateHardLinkRetry:
1575 1768
1576 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1769 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1577 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1770 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1771 cifs_stats_inc(&tcon->num_hardlinks);
1578 if (rc) { 1772 if (rc) {
1579 cFYI(1, ("Send error in hard link (NT rename) = %d", rc)); 1773 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
1580 } 1774 }
@@ -1775,8 +1969,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1775 } 1969 }
1776 } 1970 }
1777qreparse_out: 1971qreparse_out:
1778 if (pSMB) 1972 cifs_buf_release(pSMB);
1779 cifs_buf_release(pSMB);
1780 1973
1781 /* Note: On -EAGAIN error only caller can retry on handle based calls 1974 /* Note: On -EAGAIN error only caller can retry on handle based calls
1782 since file handle passed in no longer valid */ 1975 since file handle passed in no longer valid */
@@ -2165,6 +2358,67 @@ GetExtAttrOut:
2165 2358
2166#endif /* CONFIG_POSIX */ 2359#endif /* CONFIG_POSIX */
2167 2360
2361/* Legacy Query Path Information call for lookup to old servers such
2362 as Win9x/WinME */
2363int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
2364 const unsigned char *searchName,
2365 FILE_ALL_INFO * pFinfo,
2366 const struct nls_table *nls_codepage, int remap)
2367{
2368 QUERY_INFORMATION_REQ * pSMB;
2369 QUERY_INFORMATION_RSP * pSMBr;
2370 int rc = 0;
2371 int bytes_returned;
2372 int name_len;
2373
2374 cFYI(1, ("In SMBQPath path %s", searchName));
2375QInfRetry:
2376 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
2377 (void **) &pSMBr);
2378 if (rc)
2379 return rc;
2380
2381 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2382 name_len =
2383 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2384 PATH_MAX, nls_codepage, remap);
2385 name_len++; /* trailing null */
2386 name_len *= 2;
2387 } else {
2388 name_len = strnlen(searchName, PATH_MAX);
2389 name_len++; /* trailing null */
2390 strncpy(pSMB->FileName, searchName, name_len);
2391 }
2392 pSMB->BufferFormat = 0x04;
2393 name_len++; /* account for buffer type byte */
2394 pSMB->hdr.smb_buf_length += (__u16) name_len;
2395 pSMB->ByteCount = cpu_to_le16(name_len);
2396
2397 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2398 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2399 if (rc) {
2400 cFYI(1, ("Send error in QueryInfo = %d", rc));
2401 } else if (pFinfo) { /* decode response */
2402 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
2403 pFinfo->AllocationSize =
2404 cpu_to_le64(le32_to_cpu(pSMBr->size));
2405 pFinfo->EndOfFile = pFinfo->AllocationSize;
2406 pFinfo->Attributes =
2407 cpu_to_le32(le16_to_cpu(pSMBr->attr));
2408 } else
2409 rc = -EIO; /* bad buffer passed in */
2410
2411 cifs_buf_release(pSMB);
2412
2413 if (rc == -EAGAIN)
2414 goto QInfRetry;
2415
2416 return rc;
2417}
2418
2419
2420
2421
2168int 2422int
2169CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, 2423CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2170 const unsigned char *searchName, 2424 const unsigned char *searchName,
@@ -2396,7 +2650,7 @@ findUniqueRetry:
2396 if (rc) { 2650 if (rc) {
2397 cFYI(1, ("Send error in FindFileDirInfo = %d", rc)); 2651 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
2398 } else { /* decode response */ 2652 } else { /* decode response */
2399 2653 cifs_stats_inc(&tcon->num_ffirst);
2400 /* BB fill in */ 2654 /* BB fill in */
2401 } 2655 }
2402 2656
@@ -2414,7 +2668,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
2414 const char *searchName, 2668 const char *searchName,
2415 const struct nls_table *nls_codepage, 2669 const struct nls_table *nls_codepage,
2416 __u16 * pnetfid, 2670 __u16 * pnetfid,
2417 struct cifs_search_info * psrch_inf, int remap) 2671 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
2418{ 2672{
2419/* level 257 SMB_ */ 2673/* level 257 SMB_ */
2420 TRANSACTION2_FFIRST_REQ *pSMB = NULL; 2674 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
@@ -2441,7 +2695,7 @@ findFirstRetry:
2441 it got remapped to 0xF03A as if it were part of the 2695 it got remapped to 0xF03A as if it were part of the
2442 directory name instead of a wildcard */ 2696 directory name instead of a wildcard */
2443 name_len *= 2; 2697 name_len *= 2;
2444 pSMB->FileName[name_len] = '\\'; 2698 pSMB->FileName[name_len] = dirsep;
2445 pSMB->FileName[name_len+1] = 0; 2699 pSMB->FileName[name_len+1] = 0;
2446 pSMB->FileName[name_len+2] = '*'; 2700 pSMB->FileName[name_len+2] = '*';
2447 pSMB->FileName[name_len+3] = 0; 2701 pSMB->FileName[name_len+3] = 0;
@@ -2455,7 +2709,7 @@ findFirstRetry:
2455 if(name_len > buffersize-header) 2709 if(name_len > buffersize-header)
2456 free buffer exit; BB */ 2710 free buffer exit; BB */
2457 strncpy(pSMB->FileName, searchName, name_len); 2711 strncpy(pSMB->FileName, searchName, name_len);
2458 pSMB->FileName[name_len] = '\\'; 2712 pSMB->FileName[name_len] = dirsep;
2459 pSMB->FileName[name_len+1] = '*'; 2713 pSMB->FileName[name_len+1] = '*';
2460 pSMB->FileName[name_len+2] = 0; 2714 pSMB->FileName[name_len+2] = 0;
2461 name_len += 3; 2715 name_len += 3;
@@ -2496,6 +2750,7 @@ findFirstRetry:
2496 2750
2497 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 2751 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2498 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 2752 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2753 cifs_stats_inc(&tcon->num_ffirst);
2499 2754
2500 if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */ 2755 if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
2501 /* BB Add code to handle unsupported level rc */ 2756 /* BB Add code to handle unsupported level rc */
@@ -2617,7 +2872,7 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
2617 2872
2618 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 2873 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2619 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 2874 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2620 2875 cifs_stats_inc(&tcon->num_fnext);
2621 if (rc) { 2876 if (rc) {
2622 if (rc == -EBADF) { 2877 if (rc == -EBADF) {
2623 psrch_inf->endOfSearch = TRUE; 2878 psrch_inf->endOfSearch = TRUE;
@@ -2694,6 +2949,7 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle
2694 if (rc) { 2949 if (rc) {
2695 cERROR(1, ("Send error in FindClose = %d", rc)); 2950 cERROR(1, ("Send error in FindClose = %d", rc));
2696 } 2951 }
2952 cifs_stats_inc(&tcon->num_fclose);
2697 cifs_small_buf_release(pSMB); 2953 cifs_small_buf_release(pSMB);
2698 2954
2699 /* Since session is dead, search handle closed on server already */ 2955 /* Since session is dead, search handle closed on server already */
@@ -2827,7 +3083,10 @@ getDFSRetry:
2827 (void **) &pSMBr); 3083 (void **) &pSMBr);
2828 if (rc) 3084 if (rc)
2829 return rc; 3085 return rc;
2830 3086
3087 /* server pointer checked in called function,
3088 but should never be null here anyway */
3089 pSMB->hdr.Mid = GetNextMid(ses->server);
2831 pSMB->hdr.Tid = ses->ipc_tid; 3090 pSMB->hdr.Tid = ses->ipc_tid;
2832 pSMB->hdr.Uid = ses->Suid; 3091 pSMB->hdr.Uid = ses->Suid;
2833 if (ses->capabilities & CAP_STATUS32) { 3092 if (ses->capabilities & CAP_STATUS32) {
@@ -2968,6 +3227,92 @@ GetDFSRefExit:
2968 return rc; 3227 return rc;
2969} 3228}
2970 3229
3230/* Query File System Info such as free space to old servers such as Win 9x */
3231int
3232SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3233{
3234/* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
3235 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3236 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3237 FILE_SYSTEM_ALLOC_INFO *response_data;
3238 int rc = 0;
3239 int bytes_returned = 0;
3240 __u16 params, byte_count;
3241
3242 cFYI(1, ("OldQFSInfo"));
3243oldQFSInfoRetry:
3244 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3245 (void **) &pSMBr);
3246 if (rc)
3247 return rc;
3248 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3249 (void **) &pSMBr);
3250 if (rc)
3251 return rc;
3252
3253 params = 2; /* level */
3254 pSMB->TotalDataCount = 0;
3255 pSMB->MaxParameterCount = cpu_to_le16(2);
3256 pSMB->MaxDataCount = cpu_to_le16(1000);
3257 pSMB->MaxSetupCount = 0;
3258 pSMB->Reserved = 0;
3259 pSMB->Flags = 0;
3260 pSMB->Timeout = 0;
3261 pSMB->Reserved2 = 0;
3262 byte_count = params + 1 /* pad */ ;
3263 pSMB->TotalParameterCount = cpu_to_le16(params);
3264 pSMB->ParameterCount = pSMB->TotalParameterCount;
3265 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3266 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3267 pSMB->DataCount = 0;
3268 pSMB->DataOffset = 0;
3269 pSMB->SetupCount = 1;
3270 pSMB->Reserved3 = 0;
3271 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3272 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
3273 pSMB->hdr.smb_buf_length += byte_count;
3274 pSMB->ByteCount = cpu_to_le16(byte_count);
3275
3276 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3277 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3278 if (rc) {
3279 cFYI(1, ("Send error in QFSInfo = %d", rc));
3280 } else { /* decode response */
3281 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3282
3283 if (rc || (pSMBr->ByteCount < 18))
3284 rc = -EIO; /* bad smb */
3285 else {
3286 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3287 cFYI(1,("qfsinf resp BCC: %d Offset %d",
3288 pSMBr->ByteCount, data_offset));
3289
3290 response_data =
3291 (FILE_SYSTEM_ALLOC_INFO *)
3292 (((char *) &pSMBr->hdr.Protocol) + data_offset);
3293 FSData->f_bsize =
3294 le16_to_cpu(response_data->BytesPerSector) *
3295 le32_to_cpu(response_data->
3296 SectorsPerAllocationUnit);
3297 FSData->f_blocks =
3298 le32_to_cpu(response_data->TotalAllocationUnits);
3299 FSData->f_bfree = FSData->f_bavail =
3300 le32_to_cpu(response_data->FreeAllocationUnits);
3301 cFYI(1,
3302 ("Blocks: %lld Free: %lld Block size %ld",
3303 (unsigned long long)FSData->f_blocks,
3304 (unsigned long long)FSData->f_bfree,
3305 FSData->f_bsize));
3306 }
3307 }
3308 cifs_buf_release(pSMB);
3309
3310 if (rc == -EAGAIN)
3311 goto oldQFSInfoRetry;
3312
3313 return rc;
3314}
3315
2971int 3316int
2972CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData) 3317CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
2973{ 3318{
@@ -2989,7 +3334,7 @@ QFSInfoRetry:
2989 params = 2; /* level */ 3334 params = 2; /* level */
2990 pSMB->TotalDataCount = 0; 3335 pSMB->TotalDataCount = 0;
2991 pSMB->MaxParameterCount = cpu_to_le16(2); 3336 pSMB->MaxParameterCount = cpu_to_le16(2);
2992 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ 3337 pSMB->MaxDataCount = cpu_to_le16(1000);
2993 pSMB->MaxSetupCount = 0; 3338 pSMB->MaxSetupCount = 0;
2994 pSMB->Reserved = 0; 3339 pSMB->Reserved = 0;
2995 pSMB->Flags = 0; 3340 pSMB->Flags = 0;
@@ -3012,17 +3357,14 @@ QFSInfoRetry:
3012 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 3357 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3013 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 3358 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3014 if (rc) { 3359 if (rc) {
3015 cERROR(1, ("Send error in QFSInfo = %d", rc)); 3360 cFYI(1, ("Send error in QFSInfo = %d", rc));
3016 } else { /* decode response */ 3361 } else { /* decode response */
3017 rc = validate_t2((struct smb_t2_rsp *)pSMBr); 3362 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3018 3363
3019 if (rc || (pSMBr->ByteCount < 24)) /* BB alsO CHEck enough total bytes returned */ 3364 if (rc || (pSMBr->ByteCount < 24))
3020 rc = -EIO; /* bad smb */ 3365 rc = -EIO; /* bad smb */
3021 else { 3366 else {
3022 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); 3367 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3023 cFYI(1,
3024 ("Decoding qfsinfo response. BCC: %d Offset %d",
3025 pSMBr->ByteCount, data_offset));
3026 3368
3027 response_data = 3369 response_data =
3028 (FILE_SYSTEM_INFO 3370 (FILE_SYSTEM_INFO
@@ -3257,6 +3599,77 @@ QFSUnixRetry:
3257 return rc; 3599 return rc;
3258} 3600}
3259 3601
3602int
3603CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
3604{
3605/* level 0x200 SMB_SET_CIFS_UNIX_INFO */
3606 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
3607 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
3608 int rc = 0;
3609 int bytes_returned = 0;
3610 __u16 params, param_offset, offset, byte_count;
3611
3612 cFYI(1, ("In SETFSUnixInfo"));
3613SETFSUnixRetry:
3614 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3615 (void **) &pSMBr);
3616 if (rc)
3617 return rc;
3618
3619 params = 4; /* 2 bytes zero followed by info level. */
3620 pSMB->MaxSetupCount = 0;
3621 pSMB->Reserved = 0;
3622 pSMB->Flags = 0;
3623 pSMB->Timeout = 0;
3624 pSMB->Reserved2 = 0;
3625 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
3626 offset = param_offset + params;
3627
3628 pSMB->MaxParameterCount = cpu_to_le16(4);
3629 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3630 pSMB->SetupCount = 1;
3631 pSMB->Reserved3 = 0;
3632 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
3633 byte_count = 1 /* pad */ + params + 12;
3634
3635 pSMB->DataCount = cpu_to_le16(12);
3636 pSMB->ParameterCount = cpu_to_le16(params);
3637 pSMB->TotalDataCount = pSMB->DataCount;
3638 pSMB->TotalParameterCount = pSMB->ParameterCount;
3639 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3640 pSMB->DataOffset = cpu_to_le16(offset);
3641
3642 /* Params. */
3643 pSMB->FileNum = 0;
3644 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
3645
3646 /* Data. */
3647 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
3648 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
3649 pSMB->ClientUnixCap = cpu_to_le64(cap);
3650
3651 pSMB->hdr.smb_buf_length += byte_count;
3652 pSMB->ByteCount = cpu_to_le16(byte_count);
3653
3654 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3655 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3656 if (rc) {
3657 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
3658 } else { /* decode response */
3659 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3660 if (rc) {
3661 rc = -EIO; /* bad smb */
3662 }
3663 }
3664 cifs_buf_release(pSMB);
3665
3666 if (rc == -EAGAIN)
3667 goto SETFSUnixRetry;
3668
3669 return rc;
3670}
3671
3672
3260 3673
3261int 3674int
3262CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, 3675CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
@@ -3321,16 +3734,16 @@ QFSPosixRetry:
3321 le64_to_cpu(response_data->TotalBlocks); 3734 le64_to_cpu(response_data->TotalBlocks);
3322 FSData->f_bfree = 3735 FSData->f_bfree =
3323 le64_to_cpu(response_data->BlocksAvail); 3736 le64_to_cpu(response_data->BlocksAvail);
3324 if(response_data->UserBlocksAvail == -1) { 3737 if(response_data->UserBlocksAvail == cpu_to_le64(-1)) {
3325 FSData->f_bavail = FSData->f_bfree; 3738 FSData->f_bavail = FSData->f_bfree;
3326 } else { 3739 } else {
3327 FSData->f_bavail = 3740 FSData->f_bavail =
3328 le64_to_cpu(response_data->UserBlocksAvail); 3741 le64_to_cpu(response_data->UserBlocksAvail);
3329 } 3742 }
3330 if(response_data->TotalFileNodes != -1) 3743 if(response_data->TotalFileNodes != cpu_to_le64(-1))
3331 FSData->f_files = 3744 FSData->f_files =
3332 le64_to_cpu(response_data->TotalFileNodes); 3745 le64_to_cpu(response_data->TotalFileNodes);
3333 if(response_data->FreeFileNodes != -1) 3746 if(response_data->FreeFileNodes != cpu_to_le64(-1))
3334 FSData->f_ffree = 3747 FSData->f_ffree =
3335 le64_to_cpu(response_data->FreeFileNodes); 3748 le64_to_cpu(response_data->FreeFileNodes);
3336 } 3749 }
@@ -3376,7 +3789,7 @@ SetEOFRetry:
3376 PATH_MAX, nls_codepage, remap); 3789 PATH_MAX, nls_codepage, remap);
3377 name_len++; /* trailing null */ 3790 name_len++; /* trailing null */
3378 name_len *= 2; 3791 name_len *= 2;
3379 } else { /* BB improve the check for buffer overruns BB */ 3792 } else { /* BB improve the check for buffer overruns BB */
3380 name_len = strnlen(fileName, PATH_MAX); 3793 name_len = strnlen(fileName, PATH_MAX);
3381 name_len++; /* trailing null */ 3794 name_len++; /* trailing null */
3382 strncpy(pSMB->FileName, fileName, name_len); 3795 strncpy(pSMB->FileName, fileName, name_len);
@@ -3384,7 +3797,7 @@ SetEOFRetry:
3384 params = 6 + name_len; 3797 params = 6 + name_len;
3385 data_count = sizeof (struct file_end_of_file_info); 3798 data_count = sizeof (struct file_end_of_file_info);
3386 pSMB->MaxParameterCount = cpu_to_le16(2); 3799 pSMB->MaxParameterCount = cpu_to_le16(2);
3387 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */ 3800 pSMB->MaxDataCount = cpu_to_le16(4100);
3388 pSMB->MaxSetupCount = 0; 3801 pSMB->MaxSetupCount = 0;
3389 pSMB->Reserved = 0; 3802 pSMB->Reserved = 0;
3390 pSMB->Flags = 0; 3803 pSMB->Flags = 0;
@@ -3766,7 +4179,7 @@ setPermsRetry:
3766 PATH_MAX, nls_codepage, remap); 4179 PATH_MAX, nls_codepage, remap);
3767 name_len++; /* trailing null */ 4180 name_len++; /* trailing null */
3768 name_len *= 2; 4181 name_len *= 2;
3769 } else { /* BB improve the check for buffer overruns BB */ 4182 } else { /* BB improve the check for buffer overruns BB */
3770 name_len = strnlen(fileName, PATH_MAX); 4183 name_len = strnlen(fileName, PATH_MAX);
3771 name_len++; /* trailing null */ 4184 name_len++; /* trailing null */
3772 strncpy(pSMB->FileName, fileName, name_len); 4185 strncpy(pSMB->FileName, fileName, name_len);
@@ -3839,12 +4252,14 @@ setPermsRetry:
3839} 4252}
3840 4253
3841int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, 4254int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
3842 const int notify_subdirs, const __u16 netfid, 4255 const int notify_subdirs, const __u16 netfid,
3843 __u32 filter, const struct nls_table *nls_codepage) 4256 __u32 filter, struct file * pfile, int multishot,
4257 const struct nls_table *nls_codepage)
3844{ 4258{
3845 int rc = 0; 4259 int rc = 0;
3846 struct smb_com_transaction_change_notify_req * pSMB = NULL; 4260 struct smb_com_transaction_change_notify_req * pSMB = NULL;
3847 struct smb_com_transaction_change_notify_rsp * pSMBr = NULL; 4261 struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
4262 struct dir_notify_req *dnotify_req;
3848 int bytes_returned; 4263 int bytes_returned;
3849 4264
3850 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid)); 4265 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
@@ -3877,6 +4292,28 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
3877 (struct smb_hdr *) pSMBr, &bytes_returned, -1); 4292 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
3878 if (rc) { 4293 if (rc) {
3879 cFYI(1, ("Error in Notify = %d", rc)); 4294 cFYI(1, ("Error in Notify = %d", rc));
4295 } else {
4296 /* Add file to outstanding requests */
4297 /* BB change to kmem cache alloc */
4298 dnotify_req = (struct dir_notify_req *) kmalloc(
4299 sizeof(struct dir_notify_req),
4300 GFP_KERNEL);
4301 if(dnotify_req) {
4302 dnotify_req->Pid = pSMB->hdr.Pid;
4303 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
4304 dnotify_req->Mid = pSMB->hdr.Mid;
4305 dnotify_req->Tid = pSMB->hdr.Tid;
4306 dnotify_req->Uid = pSMB->hdr.Uid;
4307 dnotify_req->netfid = netfid;
4308 dnotify_req->pfile = pfile;
4309 dnotify_req->filter = filter;
4310 dnotify_req->multishot = multishot;
4311 spin_lock(&GlobalMid_Lock);
4312 list_add_tail(&dnotify_req->lhead,
4313 &GlobalDnotifyReqList);
4314 spin_unlock(&GlobalMid_Lock);
4315 } else
4316 rc = -ENOMEM;
3880 } 4317 }
3881 cifs_buf_release(pSMB); 4318 cifs_buf_release(pSMB);
3882 return rc; 4319 return rc;