diff options
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r-- | fs/cifs/cifssmb.c | 659 |
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 | ||
689 | static __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 | |||
719 | int | ||
720 | SMBLegacyOpen(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 | |||
733 | OldOpenRetry: | ||
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 | |||
697 | int | 833 | int |
698 | CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, | 834 | CIFSSMBOpen(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 |
954 | int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, | 1134 | int |
1135 | CIFSSMBWrite2(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 | ||
1014 | int | 1212 | int |
@@ -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 | } |
1777 | qreparse_out: | 1971 | qreparse_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 */ | ||
2363 | int 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)); | ||
2375 | QInfRetry: | ||
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 | |||
2168 | int | 2422 | int |
2169 | CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, | 2423 | CIFSSMBQPathInfo(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 */ | ||
3231 | int | ||
3232 | SMBOldQFSInfo(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")); | ||
3243 | oldQFSInfoRetry: | ||
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 | |||
2971 | int | 3316 | int |
2972 | CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData) | 3317 | CIFSSMBQFSInfo(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 | ||
3602 | int | ||
3603 | CIFSSMBSetFSUnixInfo(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")); | ||
3613 | SETFSUnixRetry: | ||
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 | ||
3261 | int | 3674 | int |
3262 | CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, | 3675 | CIFSSMBQFSPosixInfo(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 | ||
3841 | int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, | 4254 | int 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; |