diff options
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r-- | fs/cifs/cifssmb.c | 727 |
1 files changed, 595 insertions, 132 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 0db0b313d715..6867e556d37e 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -90,6 +90,18 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, | |||
90 | check for tcp and smb session status done differently | 90 | check for tcp and smb session status done differently |
91 | for those three - in the calling routine */ | 91 | for those three - in the calling routine */ |
92 | if(tcon) { | 92 | if(tcon) { |
93 | if(tcon->tidStatus == CifsExiting) { | ||
94 | /* only tree disconnect, open, and write, | ||
95 | (and ulogoff which does not have tcon) | ||
96 | are allowed as we start force umount */ | ||
97 | if((smb_command != SMB_COM_WRITE_ANDX) && | ||
98 | (smb_command != SMB_COM_OPEN_ANDX) && | ||
99 | (smb_command != SMB_COM_TREE_DISCONNECT)) { | ||
100 | cFYI(1,("can not send cmd %d while umounting", | ||
101 | smb_command)); | ||
102 | return -ENODEV; | ||
103 | } | ||
104 | } | ||
93 | if((tcon->ses) && (tcon->ses->status != CifsExiting) && | 105 | if((tcon->ses) && (tcon->ses->status != CifsExiting) && |
94 | (tcon->ses->server)){ | 106 | (tcon->ses->server)){ |
95 | struct nls_table *nls_codepage; | 107 | struct nls_table *nls_codepage; |
@@ -125,6 +137,9 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, | |||
125 | rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon | 137 | rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon |
126 | , nls_codepage); | 138 | , nls_codepage); |
127 | up(&tcon->ses->sesSem); | 139 | up(&tcon->ses->sesSem); |
140 | /* BB FIXME add code to check if wsize needs | ||
141 | update due to negotiated smb buffer size | ||
142 | shrinking */ | ||
128 | if(rc == 0) | 143 | if(rc == 0) |
129 | atomic_inc(&tconInfoReconnectCount); | 144 | atomic_inc(&tconInfoReconnectCount); |
130 | 145 | ||
@@ -166,11 +181,9 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, | |||
166 | 181 | ||
167 | header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct); | 182 | header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct); |
168 | 183 | ||
169 | #ifdef CONFIG_CIFS_STATS | 184 | if(tcon != NULL) |
170 | if(tcon != NULL) { | 185 | cifs_stats_inc(&tcon->num_smbs_sent); |
171 | atomic_inc(&tcon->num_smbs_sent); | 186 | |
172 | } | ||
173 | #endif /* CONFIG_CIFS_STATS */ | ||
174 | return rc; | 187 | return rc; |
175 | } | 188 | } |
176 | 189 | ||
@@ -186,6 +199,19 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, | |||
186 | check for tcp and smb session status done differently | 199 | check for tcp and smb session status done differently |
187 | for those three - in the calling routine */ | 200 | for those three - in the calling routine */ |
188 | if(tcon) { | 201 | if(tcon) { |
202 | if(tcon->tidStatus == CifsExiting) { | ||
203 | /* only tree disconnect, open, and write, | ||
204 | (and ulogoff which does not have tcon) | ||
205 | are allowed as we start force umount */ | ||
206 | if((smb_command != SMB_COM_WRITE_ANDX) && | ||
207 | (smb_command != SMB_COM_OPEN_ANDX) && | ||
208 | (smb_command != SMB_COM_TREE_DISCONNECT)) { | ||
209 | cFYI(1,("can not send cmd %d while umounting", | ||
210 | smb_command)); | ||
211 | return -ENODEV; | ||
212 | } | ||
213 | } | ||
214 | |||
189 | if((tcon->ses) && (tcon->ses->status != CifsExiting) && | 215 | if((tcon->ses) && (tcon->ses->status != CifsExiting) && |
190 | (tcon->ses->server)){ | 216 | (tcon->ses->server)){ |
191 | struct nls_table *nls_codepage; | 217 | struct nls_table *nls_codepage; |
@@ -222,6 +248,9 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, | |||
222 | rc = CIFSTCon(0, tcon->ses, tcon->treeName, | 248 | rc = CIFSTCon(0, tcon->ses, tcon->treeName, |
223 | tcon, nls_codepage); | 249 | tcon, nls_codepage); |
224 | up(&tcon->ses->sesSem); | 250 | up(&tcon->ses->sesSem); |
251 | /* BB FIXME add code to check if wsize needs | ||
252 | update due to negotiated smb buffer size | ||
253 | shrinking */ | ||
225 | if(rc == 0) | 254 | if(rc == 0) |
226 | atomic_inc(&tconInfoReconnectCount); | 255 | atomic_inc(&tconInfoReconnectCount); |
227 | 256 | ||
@@ -269,11 +298,9 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, | |||
269 | header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon, | 298 | header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon, |
270 | wct /*wct */ ); | 299 | wct /*wct */ ); |
271 | 300 | ||
272 | #ifdef CONFIG_CIFS_STATS | 301 | if(tcon != NULL) |
273 | if(tcon != NULL) { | 302 | cifs_stats_inc(&tcon->num_smbs_sent); |
274 | atomic_inc(&tcon->num_smbs_sent); | 303 | |
275 | } | ||
276 | #endif /* CONFIG_CIFS_STATS */ | ||
277 | return rc; | 304 | return rc; |
278 | } | 305 | } |
279 | 306 | ||
@@ -330,7 +357,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
330 | (void **) &pSMB, (void **) &pSMBr); | 357 | (void **) &pSMB, (void **) &pSMBr); |
331 | if (rc) | 358 | if (rc) |
332 | return rc; | 359 | return rc; |
333 | 360 | pSMB->hdr.Mid = GetNextMid(server); | |
334 | pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; | 361 | pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; |
335 | if (extended_security) | 362 | if (extended_security) |
336 | pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; | 363 | pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; |
@@ -422,8 +449,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
422 | } | 449 | } |
423 | 450 | ||
424 | } | 451 | } |
425 | if (pSMB) | 452 | |
426 | cifs_buf_release(pSMB); | 453 | cifs_buf_release(pSMB); |
427 | return rc; | 454 | return rc; |
428 | } | 455 | } |
429 | 456 | ||
@@ -518,6 +545,8 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) | |||
518 | smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */ | 545 | smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */ |
519 | 546 | ||
520 | if(ses->server) { | 547 | if(ses->server) { |
548 | pSMB->hdr.Mid = GetNextMid(ses->server); | ||
549 | |||
521 | if(ses->server->secMode & | 550 | if(ses->server->secMode & |
522 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) | 551 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) |
523 | pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; | 552 | pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; |
@@ -537,9 +566,8 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) | |||
537 | rc = -ESHUTDOWN; | 566 | rc = -ESHUTDOWN; |
538 | } | 567 | } |
539 | } | 568 | } |
540 | if (pSMB) | ||
541 | cifs_small_buf_release(pSMB); | ||
542 | up(&ses->sesSem); | 569 | up(&ses->sesSem); |
570 | cifs_small_buf_release(pSMB); | ||
543 | 571 | ||
544 | /* if session dead then we do not need to do ulogoff, | 572 | /* if session dead then we do not need to do ulogoff, |
545 | since server closed smb session, no sense reporting | 573 | since server closed smb session, no sense reporting |
@@ -583,14 +611,10 @@ DelFileRetry: | |||
583 | pSMB->ByteCount = cpu_to_le16(name_len + 1); | 611 | pSMB->ByteCount = cpu_to_le16(name_len + 1); |
584 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 612 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
585 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 613 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
614 | cifs_stats_inc(&tcon->num_deletes); | ||
586 | if (rc) { | 615 | if (rc) { |
587 | cFYI(1, ("Error in RMFile = %d", rc)); | 616 | cFYI(1, ("Error in RMFile = %d", rc)); |
588 | } | 617 | } |
589 | #ifdef CONFIG_CIFS_STATS | ||
590 | else { | ||
591 | atomic_inc(&tcon->num_deletes); | ||
592 | } | ||
593 | #endif | ||
594 | 618 | ||
595 | cifs_buf_release(pSMB); | 619 | cifs_buf_release(pSMB); |
596 | if (rc == -EAGAIN) | 620 | if (rc == -EAGAIN) |
@@ -632,14 +656,10 @@ RmDirRetry: | |||
632 | pSMB->ByteCount = cpu_to_le16(name_len + 1); | 656 | pSMB->ByteCount = cpu_to_le16(name_len + 1); |
633 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 657 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
634 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 658 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
659 | cifs_stats_inc(&tcon->num_rmdirs); | ||
635 | if (rc) { | 660 | if (rc) { |
636 | cFYI(1, ("Error in RMDir = %d", rc)); | 661 | cFYI(1, ("Error in RMDir = %d", rc)); |
637 | } | 662 | } |
638 | #ifdef CONFIG_CIFS_STATS | ||
639 | else { | ||
640 | atomic_inc(&tcon->num_rmdirs); | ||
641 | } | ||
642 | #endif | ||
643 | 663 | ||
644 | cifs_buf_release(pSMB); | 664 | cifs_buf_release(pSMB); |
645 | if (rc == -EAGAIN) | 665 | if (rc == -EAGAIN) |
@@ -680,20 +700,161 @@ MkDirRetry: | |||
680 | pSMB->ByteCount = cpu_to_le16(name_len + 1); | 700 | pSMB->ByteCount = cpu_to_le16(name_len + 1); |
681 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 701 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
682 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 702 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
703 | cifs_stats_inc(&tcon->num_mkdirs); | ||
683 | if (rc) { | 704 | if (rc) { |
684 | cFYI(1, ("Error in Mkdir = %d", rc)); | 705 | cFYI(1, ("Error in Mkdir = %d", rc)); |
685 | } | 706 | } |
686 | #ifdef CONFIG_CIFS_STATS | 707 | |
687 | else { | ||
688 | atomic_inc(&tcon->num_mkdirs); | ||
689 | } | ||
690 | #endif | ||
691 | cifs_buf_release(pSMB); | 708 | cifs_buf_release(pSMB); |
692 | if (rc == -EAGAIN) | 709 | if (rc == -EAGAIN) |
693 | goto MkDirRetry; | 710 | goto MkDirRetry; |
694 | return rc; | 711 | return rc; |
695 | } | 712 | } |
696 | 713 | ||
714 | static __u16 convert_disposition(int disposition) | ||
715 | { | ||
716 | __u16 ofun = 0; | ||
717 | |||
718 | switch (disposition) { | ||
719 | case FILE_SUPERSEDE: | ||
720 | ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC; | ||
721 | break; | ||
722 | case FILE_OPEN: | ||
723 | ofun = SMBOPEN_OAPPEND; | ||
724 | break; | ||
725 | case FILE_CREATE: | ||
726 | ofun = SMBOPEN_OCREATE; | ||
727 | break; | ||
728 | case FILE_OPEN_IF: | ||
729 | ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND; | ||
730 | break; | ||
731 | case FILE_OVERWRITE: | ||
732 | ofun = SMBOPEN_OTRUNC; | ||
733 | break; | ||
734 | case FILE_OVERWRITE_IF: | ||
735 | ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC; | ||
736 | break; | ||
737 | default: | ||
738 | cFYI(1,("unknown disposition %d",disposition)); | ||
739 | ofun = SMBOPEN_OAPPEND; /* regular open */ | ||
740 | } | ||
741 | return ofun; | ||
742 | } | ||
743 | |||
744 | int | ||
745 | SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon, | ||
746 | const char *fileName, const int openDisposition, | ||
747 | const int access_flags, const int create_options, __u16 * netfid, | ||
748 | int *pOplock, FILE_ALL_INFO * pfile_info, | ||
749 | const struct nls_table *nls_codepage, int remap) | ||
750 | { | ||
751 | int rc = -EACCES; | ||
752 | OPENX_REQ *pSMB = NULL; | ||
753 | OPENX_RSP *pSMBr = NULL; | ||
754 | int bytes_returned; | ||
755 | int name_len; | ||
756 | __u16 count; | ||
757 | |||
758 | OldOpenRetry: | ||
759 | rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB, | ||
760 | (void **) &pSMBr); | ||
761 | if (rc) | ||
762 | return rc; | ||
763 | |||
764 | pSMB->AndXCommand = 0xFF; /* none */ | ||
765 | |||
766 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | ||
767 | count = 1; /* account for one byte pad to word boundary */ | ||
768 | name_len = | ||
769 | cifsConvertToUCS((__le16 *) (pSMB->fileName + 1), | ||
770 | fileName, PATH_MAX, nls_codepage, remap); | ||
771 | name_len++; /* trailing null */ | ||
772 | name_len *= 2; | ||
773 | } else { /* BB improve check for buffer overruns BB */ | ||
774 | count = 0; /* no pad */ | ||
775 | name_len = strnlen(fileName, PATH_MAX); | ||
776 | name_len++; /* trailing null */ | ||
777 | strncpy(pSMB->fileName, fileName, name_len); | ||
778 | } | ||
779 | if (*pOplock & REQ_OPLOCK) | ||
780 | pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK); | ||
781 | else if (*pOplock & REQ_BATCHOPLOCK) { | ||
782 | pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK); | ||
783 | } | ||
784 | pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO); | ||
785 | /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */ | ||
786 | /* 0 = read | ||
787 | 1 = write | ||
788 | 2 = rw | ||
789 | 3 = execute | ||
790 | */ | ||
791 | pSMB->Mode = cpu_to_le16(2); | ||
792 | pSMB->Mode |= cpu_to_le16(0x40); /* deny none */ | ||
793 | /* set file as system file if special file such | ||
794 | as fifo and server expecting SFU style and | ||
795 | no Unix extensions */ | ||
796 | |||
797 | if(create_options & CREATE_OPTION_SPECIAL) | ||
798 | pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM); | ||
799 | else | ||
800 | pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */ | ||
801 | |||
802 | /* if ((omode & S_IWUGO) == 0) | ||
803 | pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/ | ||
804 | /* Above line causes problems due to vfs splitting create into two | ||
805 | pieces - need to set mode after file created not while it is | ||
806 | being created */ | ||
807 | |||
808 | /* BB FIXME BB */ | ||
809 | /* pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); */ | ||
810 | /* BB FIXME END BB */ | ||
811 | |||
812 | pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY); | ||
813 | pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition)); | ||
814 | count += name_len; | ||
815 | pSMB->hdr.smb_buf_length += count; | ||
816 | |||
817 | pSMB->ByteCount = cpu_to_le16(count); | ||
818 | /* long_op set to 1 to allow for oplock break timeouts */ | ||
819 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | ||
820 | (struct smb_hdr *) pSMBr, &bytes_returned, 1); | ||
821 | cifs_stats_inc(&tcon->num_opens); | ||
822 | if (rc) { | ||
823 | cFYI(1, ("Error in Open = %d", rc)); | ||
824 | } else { | ||
825 | /* BB verify if wct == 15 */ | ||
826 | |||
827 | /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */ | ||
828 | |||
829 | *netfid = pSMBr->Fid; /* cifs fid stays in le */ | ||
830 | /* Let caller know file was created so we can set the mode. */ | ||
831 | /* Do we care about the CreateAction in any other cases? */ | ||
832 | /* BB FIXME BB */ | ||
833 | /* if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction) | ||
834 | *pOplock |= CIFS_CREATE_ACTION; */ | ||
835 | /* BB FIXME END */ | ||
836 | |||
837 | if(pfile_info) { | ||
838 | pfile_info->CreationTime = 0; /* BB convert CreateTime*/ | ||
839 | pfile_info->LastAccessTime = 0; /* BB fixme */ | ||
840 | pfile_info->LastWriteTime = 0; /* BB fixme */ | ||
841 | pfile_info->ChangeTime = 0; /* BB fixme */ | ||
842 | pfile_info->Attributes = | ||
843 | cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes)); | ||
844 | /* the file_info buf is endian converted by caller */ | ||
845 | pfile_info->AllocationSize = | ||
846 | cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile)); | ||
847 | pfile_info->EndOfFile = pfile_info->AllocationSize; | ||
848 | pfile_info->NumberOfLinks = cpu_to_le32(1); | ||
849 | } | ||
850 | } | ||
851 | |||
852 | cifs_buf_release(pSMB); | ||
853 | if (rc == -EAGAIN) | ||
854 | goto OldOpenRetry; | ||
855 | return rc; | ||
856 | } | ||
857 | |||
697 | int | 858 | int |
698 | CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, | 859 | CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, |
699 | const char *fileName, const int openDisposition, | 860 | const char *fileName, const int openDisposition, |
@@ -738,7 +899,13 @@ openRetry: | |||
738 | } | 899 | } |
739 | pSMB->DesiredAccess = cpu_to_le32(access_flags); | 900 | pSMB->DesiredAccess = cpu_to_le32(access_flags); |
740 | pSMB->AllocationSize = 0; | 901 | pSMB->AllocationSize = 0; |
741 | pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL); | 902 | /* set file as system file if special file such |
903 | as fifo and server expecting SFU style and | ||
904 | no Unix extensions */ | ||
905 | if(create_options & CREATE_OPTION_SPECIAL) | ||
906 | pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM); | ||
907 | else | ||
908 | pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL); | ||
742 | /* XP does not handle ATTR_POSIX_SEMANTICS */ | 909 | /* XP does not handle ATTR_POSIX_SEMANTICS */ |
743 | /* but it helps speed up case sensitive checks for other | 910 | /* but it helps speed up case sensitive checks for other |
744 | servers such as Samba */ | 911 | servers such as Samba */ |
@@ -752,7 +919,7 @@ openRetry: | |||
752 | being created */ | 919 | being created */ |
753 | pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL); | 920 | pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL); |
754 | pSMB->CreateDisposition = cpu_to_le32(openDisposition); | 921 | pSMB->CreateDisposition = cpu_to_le32(openDisposition); |
755 | pSMB->CreateOptions = cpu_to_le32(create_options); | 922 | pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); |
756 | /* BB Expirement with various impersonation levels and verify */ | 923 | /* BB Expirement with various impersonation levels and verify */ |
757 | pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); | 924 | pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); |
758 | pSMB->SecurityFlags = | 925 | pSMB->SecurityFlags = |
@@ -765,6 +932,7 @@ openRetry: | |||
765 | /* long_op set to 1 to allow for oplock break timeouts */ | 932 | /* long_op set to 1 to allow for oplock break timeouts */ |
766 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 933 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
767 | (struct smb_hdr *) pSMBr, &bytes_returned, 1); | 934 | (struct smb_hdr *) pSMBr, &bytes_returned, 1); |
935 | cifs_stats_inc(&tcon->num_opens); | ||
768 | if (rc) { | 936 | if (rc) { |
769 | cFYI(1, ("Error in Open = %d", rc)); | 937 | cFYI(1, ("Error in Open = %d", rc)); |
770 | } else { | 938 | } else { |
@@ -782,11 +950,8 @@ openRetry: | |||
782 | pfile_info->EndOfFile = pSMBr->EndOfFile; | 950 | pfile_info->EndOfFile = pSMBr->EndOfFile; |
783 | pfile_info->NumberOfLinks = cpu_to_le32(1); | 951 | pfile_info->NumberOfLinks = cpu_to_le32(1); |
784 | } | 952 | } |
785 | |||
786 | #ifdef CONFIG_CIFS_STATS | ||
787 | atomic_inc(&tcon->num_opens); | ||
788 | #endif | ||
789 | } | 953 | } |
954 | |||
790 | cifs_buf_release(pSMB); | 955 | cifs_buf_release(pSMB); |
791 | if (rc == -EAGAIN) | 956 | if (rc == -EAGAIN) |
792 | goto openRetry; | 957 | goto openRetry; |
@@ -807,11 +972,16 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, | |||
807 | READ_RSP *pSMBr = NULL; | 972 | READ_RSP *pSMBr = NULL; |
808 | char *pReadData = NULL; | 973 | char *pReadData = NULL; |
809 | int bytes_returned; | 974 | int bytes_returned; |
975 | int wct; | ||
810 | 976 | ||
811 | cFYI(1,("Reading %d bytes on fid %d",count,netfid)); | 977 | cFYI(1,("Reading %d bytes on fid %d",count,netfid)); |
978 | if(tcon->ses->capabilities & CAP_LARGE_FILES) | ||
979 | wct = 12; | ||
980 | else | ||
981 | wct = 10; /* old style read */ | ||
812 | 982 | ||
813 | *nbytes = 0; | 983 | *nbytes = 0; |
814 | rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB, | 984 | rc = smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB, |
815 | (void **) &pSMBr); | 985 | (void **) &pSMBr); |
816 | if (rc) | 986 | if (rc) |
817 | return rc; | 987 | return rc; |
@@ -823,14 +993,26 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, | |||
823 | pSMB->AndXCommand = 0xFF; /* none */ | 993 | pSMB->AndXCommand = 0xFF; /* none */ |
824 | pSMB->Fid = netfid; | 994 | pSMB->Fid = netfid; |
825 | pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF); | 995 | pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF); |
826 | pSMB->OffsetHigh = cpu_to_le32(lseek >> 32); | 996 | if(wct == 12) |
997 | pSMB->OffsetHigh = cpu_to_le32(lseek >> 32); | ||
998 | else if((lseek >> 32) > 0) /* can not handle this big offset for old */ | ||
999 | return -EIO; | ||
1000 | |||
827 | pSMB->Remaining = 0; | 1001 | pSMB->Remaining = 0; |
828 | pSMB->MaxCount = cpu_to_le16(count & 0xFFFF); | 1002 | pSMB->MaxCount = cpu_to_le16(count & 0xFFFF); |
829 | pSMB->MaxCountHigh = cpu_to_le32(count >> 16); | 1003 | pSMB->MaxCountHigh = cpu_to_le32(count >> 16); |
830 | pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */ | 1004 | if(wct == 12) |
831 | 1005 | pSMB->ByteCount = 0; /* no need to do le conversion since 0 */ | |
1006 | else { | ||
1007 | /* old style read */ | ||
1008 | struct smb_com_readx_req * pSMBW = | ||
1009 | (struct smb_com_readx_req *)pSMB; | ||
1010 | pSMBW->ByteCount = 0; | ||
1011 | } | ||
1012 | |||
832 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1013 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
833 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 1014 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
1015 | cifs_stats_inc(&tcon->num_reads); | ||
834 | if (rc) { | 1016 | if (rc) { |
835 | cERROR(1, ("Send error in read = %d", rc)); | 1017 | cERROR(1, ("Send error in read = %d", rc)); |
836 | } else { | 1018 | } else { |
@@ -876,12 +1058,20 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, | |||
876 | int rc = -EACCES; | 1058 | int rc = -EACCES; |
877 | WRITE_REQ *pSMB = NULL; | 1059 | WRITE_REQ *pSMB = NULL; |
878 | WRITE_RSP *pSMBr = NULL; | 1060 | WRITE_RSP *pSMBr = NULL; |
879 | int bytes_returned; | 1061 | int bytes_returned, wct; |
880 | __u32 bytes_sent; | 1062 | __u32 bytes_sent; |
881 | __u16 byte_count; | 1063 | __u16 byte_count; |
882 | 1064 | ||
883 | /* cFYI(1,("write at %lld %d bytes",offset,count));*/ | 1065 | /* cFYI(1,("write at %lld %d bytes",offset,count));*/ |
884 | rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB, | 1066 | if(tcon->ses == NULL) |
1067 | return -ECONNABORTED; | ||
1068 | |||
1069 | if(tcon->ses->capabilities & CAP_LARGE_FILES) | ||
1070 | wct = 14; | ||
1071 | else | ||
1072 | wct = 12; | ||
1073 | |||
1074 | rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB, | ||
885 | (void **) &pSMBr); | 1075 | (void **) &pSMBr); |
886 | if (rc) | 1076 | if (rc) |
887 | return rc; | 1077 | return rc; |
@@ -892,7 +1082,11 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, | |||
892 | pSMB->AndXCommand = 0xFF; /* none */ | 1082 | pSMB->AndXCommand = 0xFF; /* none */ |
893 | pSMB->Fid = netfid; | 1083 | pSMB->Fid = netfid; |
894 | pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); | 1084 | pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); |
895 | pSMB->OffsetHigh = cpu_to_le32(offset >> 32); | 1085 | if(wct == 14) |
1086 | pSMB->OffsetHigh = cpu_to_le32(offset >> 32); | ||
1087 | else if((offset >> 32) > 0) /* can not handle this big offset for old */ | ||
1088 | return -EIO; | ||
1089 | |||
896 | pSMB->Reserved = 0xFFFFFFFF; | 1090 | pSMB->Reserved = 0xFFFFFFFF; |
897 | pSMB->WriteMode = 0; | 1091 | pSMB->WriteMode = 0; |
898 | pSMB->Remaining = 0; | 1092 | pSMB->Remaining = 0; |
@@ -911,7 +1105,7 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, | |||
911 | if (bytes_sent > count) | 1105 | if (bytes_sent > count) |
912 | bytes_sent = count; | 1106 | bytes_sent = count; |
913 | pSMB->DataOffset = | 1107 | pSMB->DataOffset = |
914 | cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4); | 1108 | cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4); |
915 | if(buf) | 1109 | if(buf) |
916 | memcpy(pSMB->Data,buf,bytes_sent); | 1110 | memcpy(pSMB->Data,buf,bytes_sent); |
917 | else if(ubuf) { | 1111 | else if(ubuf) { |
@@ -919,20 +1113,31 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, | |||
919 | cifs_buf_release(pSMB); | 1113 | cifs_buf_release(pSMB); |
920 | return -EFAULT; | 1114 | return -EFAULT; |
921 | } | 1115 | } |
922 | } else { | 1116 | } else if (count != 0) { |
923 | /* No buffer */ | 1117 | /* No buffer */ |
924 | cifs_buf_release(pSMB); | 1118 | cifs_buf_release(pSMB); |
925 | return -EINVAL; | 1119 | return -EINVAL; |
1120 | } /* else setting file size with write of zero bytes */ | ||
1121 | if(wct == 14) | ||
1122 | byte_count = bytes_sent + 1; /* pad */ | ||
1123 | else /* wct == 12 */ { | ||
1124 | byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */ | ||
926 | } | 1125 | } |
927 | |||
928 | byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */ | ||
929 | pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF); | 1126 | pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF); |
930 | pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16); | 1127 | pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16); |
931 | pSMB->hdr.smb_buf_length += bytes_sent+1; | 1128 | pSMB->hdr.smb_buf_length += byte_count; |
932 | pSMB->ByteCount = cpu_to_le16(byte_count); | 1129 | |
1130 | if(wct == 14) | ||
1131 | pSMB->ByteCount = cpu_to_le16(byte_count); | ||
1132 | else { /* old style write has byte count 4 bytes earlier so 4 bytes pad */ | ||
1133 | struct smb_com_writex_req * pSMBW = | ||
1134 | (struct smb_com_writex_req *)pSMB; | ||
1135 | pSMBW->ByteCount = cpu_to_le16(byte_count); | ||
1136 | } | ||
933 | 1137 | ||
934 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1138 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
935 | (struct smb_hdr *) pSMBr, &bytes_returned, long_op); | 1139 | (struct smb_hdr *) pSMBr, &bytes_returned, long_op); |
1140 | cifs_stats_inc(&tcon->num_writes); | ||
936 | if (rc) { | 1141 | if (rc) { |
937 | cFYI(1, ("Send error in write = %d", rc)); | 1142 | cFYI(1, ("Send error in write = %d", rc)); |
938 | *nbytes = 0; | 1143 | *nbytes = 0; |
@@ -951,56 +1156,74 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, | |||
951 | } | 1156 | } |
952 | 1157 | ||
953 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 1158 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
954 | int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, | 1159 | int |
1160 | CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, | ||
955 | const int netfid, const unsigned int count, | 1161 | const int netfid, const unsigned int count, |
956 | const __u64 offset, unsigned int *nbytes, const char __user *buf, | 1162 | const __u64 offset, unsigned int *nbytes, struct kvec *iov, |
957 | const int long_op) | 1163 | int n_vec, const int long_op) |
958 | { | 1164 | { |
959 | int rc = -EACCES; | 1165 | int rc = -EACCES; |
960 | WRITE_REQ *pSMB = NULL; | 1166 | WRITE_REQ *pSMB = NULL; |
961 | WRITE_RSP *pSMBr = NULL; | 1167 | int bytes_returned, wct; |
962 | /*int bytes_returned;*/ | 1168 | int smb_hdr_len; |
963 | unsigned bytes_sent; | ||
964 | __u16 byte_count; | ||
965 | 1169 | ||
966 | rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB); | 1170 | /* BB removeme BB */ |
967 | 1171 | cFYI(1,("write2 at %lld %d bytes", (long long)offset, count)); | |
1172 | |||
1173 | if(tcon->ses->capabilities & CAP_LARGE_FILES) | ||
1174 | wct = 14; | ||
1175 | else | ||
1176 | wct = 12; | ||
1177 | rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB); | ||
968 | if (rc) | 1178 | if (rc) |
969 | return rc; | 1179 | return rc; |
970 | |||
971 | pSMBr = (WRITE_RSP *)pSMB; /* BB removeme BB */ | ||
972 | |||
973 | /* tcon and ses pointer are checked in smb_init */ | 1180 | /* tcon and ses pointer are checked in smb_init */ |
974 | if (tcon->ses->server == NULL) | 1181 | if (tcon->ses->server == NULL) |
975 | return -ECONNABORTED; | 1182 | return -ECONNABORTED; |
976 | 1183 | ||
977 | pSMB->AndXCommand = 0xFF; /* none */ | 1184 | pSMB->AndXCommand = 0xFF; /* none */ |
978 | pSMB->Fid = netfid; | 1185 | pSMB->Fid = netfid; |
979 | pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); | 1186 | pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); |
980 | pSMB->OffsetHigh = cpu_to_le32(offset >> 32); | 1187 | if(wct == 14) |
1188 | pSMB->OffsetHigh = cpu_to_le32(offset >> 32); | ||
1189 | else if((offset >> 32) > 0) /* can not handle this big offset for old */ | ||
1190 | return -EIO; | ||
981 | pSMB->Reserved = 0xFFFFFFFF; | 1191 | pSMB->Reserved = 0xFFFFFFFF; |
982 | pSMB->WriteMode = 0; | 1192 | pSMB->WriteMode = 0; |
983 | pSMB->Remaining = 0; | 1193 | pSMB->Remaining = 0; |
984 | bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF; | 1194 | |
985 | if (bytes_sent > count) | ||
986 | bytes_sent = count; | ||
987 | pSMB->DataLengthHigh = 0; | ||
988 | pSMB->DataOffset = | 1195 | pSMB->DataOffset = |
989 | cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4); | 1196 | cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4); |
990 | 1197 | ||
991 | byte_count = bytes_sent + 1 /* pad */ ; | 1198 | pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF); |
992 | pSMB->DataLengthLow = cpu_to_le16(bytes_sent); | 1199 | pSMB->DataLengthHigh = cpu_to_le16(count >> 16); |
993 | pSMB->DataLengthHigh = 0; | 1200 | smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */ |
994 | pSMB->hdr.smb_buf_length += byte_count; | 1201 | if(wct == 14) |
995 | pSMB->ByteCount = cpu_to_le16(byte_count); | 1202 | pSMB->hdr.smb_buf_length += count+1; |
1203 | else /* wct == 12 */ | ||
1204 | pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */ | ||
1205 | if(wct == 14) | ||
1206 | pSMB->ByteCount = cpu_to_le16(count + 1); | ||
1207 | else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ { | ||
1208 | struct smb_com_writex_req * pSMBW = | ||
1209 | (struct smb_com_writex_req *)pSMB; | ||
1210 | pSMBW->ByteCount = cpu_to_le16(count + 5); | ||
1211 | } | ||
1212 | iov[0].iov_base = pSMB; | ||
1213 | iov[0].iov_len = smb_hdr_len + 4; | ||
996 | 1214 | ||
997 | /* rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1215 | 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 */ | 1216 | long_op); |
1217 | cifs_stats_inc(&tcon->num_writes); | ||
999 | if (rc) { | 1218 | if (rc) { |
1000 | cFYI(1, ("Send error in write2 (large write) = %d", rc)); | 1219 | cFYI(1, ("Send error Write2 = %d", rc)); |
1001 | *nbytes = 0; | 1220 | *nbytes = 0; |
1002 | } else | 1221 | } else { |
1003 | *nbytes = le16_to_cpu(pSMBr->Count); | 1222 | WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB; |
1223 | *nbytes = le16_to_cpu(pSMBr->CountHigh); | ||
1224 | *nbytes = (*nbytes) << 16; | ||
1225 | *nbytes += le16_to_cpu(pSMBr->Count); | ||
1226 | } | ||
1004 | 1227 | ||
1005 | cifs_small_buf_release(pSMB); | 1228 | cifs_small_buf_release(pSMB); |
1006 | 1229 | ||
@@ -1009,6 +1232,8 @@ int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, | |||
1009 | 1232 | ||
1010 | return rc; | 1233 | return rc; |
1011 | } | 1234 | } |
1235 | |||
1236 | |||
1012 | #endif /* CIFS_EXPERIMENTAL */ | 1237 | #endif /* CIFS_EXPERIMENTAL */ |
1013 | 1238 | ||
1014 | int | 1239 | int |
@@ -1065,7 +1290,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
1065 | 1290 | ||
1066 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1291 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
1067 | (struct smb_hdr *) pSMBr, &bytes_returned, timeout); | 1292 | (struct smb_hdr *) pSMBr, &bytes_returned, timeout); |
1068 | 1293 | cifs_stats_inc(&tcon->num_locks); | |
1069 | if (rc) { | 1294 | if (rc) { |
1070 | cFYI(1, ("Send error in Lock = %d", rc)); | 1295 | cFYI(1, ("Send error in Lock = %d", rc)); |
1071 | } | 1296 | } |
@@ -1099,6 +1324,7 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id) | |||
1099 | pSMB->ByteCount = 0; | 1324 | pSMB->ByteCount = 0; |
1100 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1325 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
1101 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 1326 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
1327 | cifs_stats_inc(&tcon->num_closes); | ||
1102 | if (rc) { | 1328 | if (rc) { |
1103 | if(rc!=-EINTR) { | 1329 | if(rc!=-EINTR) { |
1104 | /* EINTR is expected when user ctl-c to kill app */ | 1330 | /* EINTR is expected when user ctl-c to kill app */ |
@@ -1171,16 +1397,11 @@ renameRetry: | |||
1171 | 1397 | ||
1172 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1398 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
1173 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 1399 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
1400 | cifs_stats_inc(&tcon->num_renames); | ||
1174 | if (rc) { | 1401 | if (rc) { |
1175 | cFYI(1, ("Send error in rename = %d", rc)); | 1402 | cFYI(1, ("Send error in rename = %d", rc)); |
1176 | } | 1403 | } |
1177 | 1404 | ||
1178 | #ifdef CONFIG_CIFS_STATS | ||
1179 | else { | ||
1180 | atomic_inc(&tcon->num_renames); | ||
1181 | } | ||
1182 | #endif | ||
1183 | |||
1184 | cifs_buf_release(pSMB); | 1405 | cifs_buf_release(pSMB); |
1185 | 1406 | ||
1186 | if (rc == -EAGAIN) | 1407 | if (rc == -EAGAIN) |
@@ -1255,14 +1476,11 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon, | |||
1255 | pSMB->ByteCount = cpu_to_le16(byte_count); | 1476 | pSMB->ByteCount = cpu_to_le16(byte_count); |
1256 | rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB, | 1477 | rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB, |
1257 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 1478 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
1479 | cifs_stats_inc(&pTcon->num_t2renames); | ||
1258 | if (rc) { | 1480 | if (rc) { |
1259 | cFYI(1,("Send error in Rename (by file handle) = %d", rc)); | 1481 | cFYI(1,("Send error in Rename (by file handle) = %d", rc)); |
1260 | } | 1482 | } |
1261 | #ifdef CONFIG_CIFS_STATS | 1483 | |
1262 | else { | ||
1263 | atomic_inc(&pTcon->num_t2renames); | ||
1264 | } | ||
1265 | #endif | ||
1266 | cifs_buf_release(pSMB); | 1484 | cifs_buf_release(pSMB); |
1267 | 1485 | ||
1268 | /* Note: On -EAGAIN error only caller can retry on handle based calls | 1486 | /* Note: On -EAGAIN error only caller can retry on handle based calls |
@@ -1362,7 +1580,7 @@ createSymLinkRetry: | |||
1362 | 1580 | ||
1363 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 1581 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
1364 | name_len = | 1582 | name_len = |
1365 | cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, PATH_MAX | 1583 | cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX |
1366 | /* find define for this maxpathcomponent */ | 1584 | /* find define for this maxpathcomponent */ |
1367 | , nls_codepage); | 1585 | , nls_codepage); |
1368 | name_len++; /* trailing null */ | 1586 | name_len++; /* trailing null */ |
@@ -1386,7 +1604,7 @@ createSymLinkRetry: | |||
1386 | data_offset = (char *) (&pSMB->hdr.Protocol) + offset; | 1604 | data_offset = (char *) (&pSMB->hdr.Protocol) + offset; |
1387 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 1605 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
1388 | name_len_target = | 1606 | name_len_target = |
1389 | cifs_strtoUCS((wchar_t *) data_offset, toName, PATH_MAX | 1607 | cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX |
1390 | /* find define for this maxpathcomponent */ | 1608 | /* find define for this maxpathcomponent */ |
1391 | , nls_codepage); | 1609 | , nls_codepage); |
1392 | name_len_target++; /* trailing null */ | 1610 | name_len_target++; /* trailing null */ |
@@ -1416,6 +1634,7 @@ createSymLinkRetry: | |||
1416 | pSMB->ByteCount = cpu_to_le16(byte_count); | 1634 | pSMB->ByteCount = cpu_to_le16(byte_count); |
1417 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1635 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
1418 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 1636 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
1637 | cifs_stats_inc(&tcon->num_symlinks); | ||
1419 | if (rc) { | 1638 | if (rc) { |
1420 | cFYI(1, | 1639 | cFYI(1, |
1421 | ("Send error in SetPathInfo (create symlink) = %d", | 1640 | ("Send error in SetPathInfo (create symlink) = %d", |
@@ -1505,6 +1724,7 @@ createHardLinkRetry: | |||
1505 | pSMB->ByteCount = cpu_to_le16(byte_count); | 1724 | pSMB->ByteCount = cpu_to_le16(byte_count); |
1506 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1725 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
1507 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 1726 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
1727 | cifs_stats_inc(&tcon->num_hardlinks); | ||
1508 | if (rc) { | 1728 | if (rc) { |
1509 | cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc)); | 1729 | cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc)); |
1510 | } | 1730 | } |
@@ -1575,6 +1795,7 @@ winCreateHardLinkRetry: | |||
1575 | 1795 | ||
1576 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1796 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
1577 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 1797 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
1798 | cifs_stats_inc(&tcon->num_hardlinks); | ||
1578 | if (rc) { | 1799 | if (rc) { |
1579 | cFYI(1, ("Send error in hard link (NT rename) = %d", rc)); | 1800 | cFYI(1, ("Send error in hard link (NT rename) = %d", rc)); |
1580 | } | 1801 | } |
@@ -1609,7 +1830,7 @@ querySymLinkRetry: | |||
1609 | 1830 | ||
1610 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 1831 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
1611 | name_len = | 1832 | name_len = |
1612 | cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX | 1833 | cifs_strtoUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX |
1613 | /* find define for this maxpathcomponent */ | 1834 | /* find define for this maxpathcomponent */ |
1614 | , nls_codepage); | 1835 | , nls_codepage); |
1615 | name_len++; /* trailing null */ | 1836 | name_len++; /* trailing null */ |
@@ -1666,7 +1887,7 @@ querySymLinkRetry: | |||
1666 | min_t(const int, buflen,count) / 2); | 1887 | min_t(const int, buflen,count) / 2); |
1667 | /* BB FIXME investigate remapping reserved chars here */ | 1888 | /* BB FIXME investigate remapping reserved chars here */ |
1668 | cifs_strfromUCS_le(symlinkinfo, | 1889 | cifs_strfromUCS_le(symlinkinfo, |
1669 | (wchar_t *) ((char *)&pSMBr->hdr.Protocol + | 1890 | (__le16 *) ((char *)&pSMBr->hdr.Protocol + |
1670 | data_offset), | 1891 | data_offset), |
1671 | name_len, nls_codepage); | 1892 | name_len, nls_codepage); |
1672 | } else { | 1893 | } else { |
@@ -1757,7 +1978,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, | |||
1757 | reparse_buf->TargetNameOffset), | 1978 | reparse_buf->TargetNameOffset), |
1758 | min(buflen/2, reparse_buf->TargetNameLen / 2)); | 1979 | min(buflen/2, reparse_buf->TargetNameLen / 2)); |
1759 | cifs_strfromUCS_le(symlinkinfo, | 1980 | cifs_strfromUCS_le(symlinkinfo, |
1760 | (wchar_t *) (reparse_buf->LinkNamesBuf + | 1981 | (__le16 *) (reparse_buf->LinkNamesBuf + |
1761 | reparse_buf->TargetNameOffset), | 1982 | reparse_buf->TargetNameOffset), |
1762 | name_len, nls_codepage); | 1983 | name_len, nls_codepage); |
1763 | } else { /* ASCII names */ | 1984 | } else { /* ASCII names */ |
@@ -1775,8 +1996,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, | |||
1775 | } | 1996 | } |
1776 | } | 1997 | } |
1777 | qreparse_out: | 1998 | qreparse_out: |
1778 | if (pSMB) | 1999 | cifs_buf_release(pSMB); |
1779 | cifs_buf_release(pSMB); | ||
1780 | 2000 | ||
1781 | /* Note: On -EAGAIN error only caller can retry on handle based calls | 2001 | /* Note: On -EAGAIN error only caller can retry on handle based calls |
1782 | since file handle passed in no longer valid */ | 2002 | since file handle passed in no longer valid */ |
@@ -1790,9 +2010,9 @@ qreparse_out: | |||
1790 | static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace) | 2010 | static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace) |
1791 | { | 2011 | { |
1792 | /* u8 cifs fields do not need le conversion */ | 2012 | /* u8 cifs fields do not need le conversion */ |
1793 | ace->e_perm = (__u16)cifs_ace->cifs_e_perm; | 2013 | ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm); |
1794 | ace->e_tag = (__u16)cifs_ace->cifs_e_tag; | 2014 | ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag); |
1795 | ace->e_id = (__u32)le64_to_cpu(cifs_ace->cifs_uid); | 2015 | ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid)); |
1796 | /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */ | 2016 | /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */ |
1797 | 2017 | ||
1798 | return; | 2018 | return; |
@@ -1844,7 +2064,7 @@ static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen, | |||
1844 | } else if(size > buflen) { | 2064 | } else if(size > buflen) { |
1845 | return -ERANGE; | 2065 | return -ERANGE; |
1846 | } else /* buffer big enough */ { | 2066 | } else /* buffer big enough */ { |
1847 | local_acl->a_version = POSIX_ACL_XATTR_VERSION; | 2067 | local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION); |
1848 | for(i = 0;i < count ;i++) { | 2068 | for(i = 0;i < count ;i++) { |
1849 | cifs_convert_ace(&local_acl->a_entries[i],pACE); | 2069 | cifs_convert_ace(&local_acl->a_entries[i],pACE); |
1850 | pACE ++; | 2070 | pACE ++; |
@@ -1858,14 +2078,14 @@ static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace, | |||
1858 | { | 2078 | { |
1859 | __u16 rc = 0; /* 0 = ACL converted ok */ | 2079 | __u16 rc = 0; /* 0 = ACL converted ok */ |
1860 | 2080 | ||
1861 | cifs_ace->cifs_e_perm = (__u8)cpu_to_le16(local_ace->e_perm); | 2081 | cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm); |
1862 | cifs_ace->cifs_e_tag = (__u8)cpu_to_le16(local_ace->e_tag); | 2082 | cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag); |
1863 | /* BB is there a better way to handle the large uid? */ | 2083 | /* BB is there a better way to handle the large uid? */ |
1864 | if(local_ace->e_id == -1) { | 2084 | if(local_ace->e_id == cpu_to_le32(-1)) { |
1865 | /* Probably no need to le convert -1 on any arch but can not hurt */ | 2085 | /* Probably no need to le convert -1 on any arch but can not hurt */ |
1866 | cifs_ace->cifs_uid = cpu_to_le64(-1); | 2086 | cifs_ace->cifs_uid = cpu_to_le64(-1); |
1867 | } else | 2087 | } else |
1868 | cifs_ace->cifs_uid = (__u64)cpu_to_le32(local_ace->e_id); | 2088 | cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id)); |
1869 | /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/ | 2089 | /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/ |
1870 | return rc; | 2090 | return rc; |
1871 | } | 2091 | } |
@@ -1885,16 +2105,17 @@ static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int bufl | |||
1885 | 2105 | ||
1886 | count = posix_acl_xattr_count((size_t)buflen); | 2106 | count = posix_acl_xattr_count((size_t)buflen); |
1887 | cFYI(1,("setting acl with %d entries from buf of length %d and version of %d", | 2107 | cFYI(1,("setting acl with %d entries from buf of length %d and version of %d", |
1888 | count,buflen,local_acl->a_version)); | 2108 | count, buflen, le32_to_cpu(local_acl->a_version))); |
1889 | if(local_acl->a_version != 2) { | 2109 | if(le32_to_cpu(local_acl->a_version) != 2) { |
1890 | cFYI(1,("unknown POSIX ACL version %d",local_acl->a_version)); | 2110 | cFYI(1,("unknown POSIX ACL version %d", |
2111 | le32_to_cpu(local_acl->a_version))); | ||
1891 | return 0; | 2112 | return 0; |
1892 | } | 2113 | } |
1893 | cifs_acl->version = cpu_to_le16(1); | 2114 | cifs_acl->version = cpu_to_le16(1); |
1894 | if(acl_type == ACL_TYPE_ACCESS) | 2115 | if(acl_type == ACL_TYPE_ACCESS) |
1895 | cifs_acl->access_entry_count = count; | 2116 | cifs_acl->access_entry_count = cpu_to_le16(count); |
1896 | else if(acl_type == ACL_TYPE_DEFAULT) | 2117 | else if(acl_type == ACL_TYPE_DEFAULT) |
1897 | cifs_acl->default_entry_count = count; | 2118 | cifs_acl->default_entry_count = cpu_to_le16(count); |
1898 | else { | 2119 | else { |
1899 | cFYI(1,("unknown ACL type %d",acl_type)); | 2120 | cFYI(1,("unknown ACL type %d",acl_type)); |
1900 | return 0; | 2121 | return 0; |
@@ -2165,6 +2386,67 @@ GetExtAttrOut: | |||
2165 | 2386 | ||
2166 | #endif /* CONFIG_POSIX */ | 2387 | #endif /* CONFIG_POSIX */ |
2167 | 2388 | ||
2389 | /* Legacy Query Path Information call for lookup to old servers such | ||
2390 | as Win9x/WinME */ | ||
2391 | int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon, | ||
2392 | const unsigned char *searchName, | ||
2393 | FILE_ALL_INFO * pFinfo, | ||
2394 | const struct nls_table *nls_codepage, int remap) | ||
2395 | { | ||
2396 | QUERY_INFORMATION_REQ * pSMB; | ||
2397 | QUERY_INFORMATION_RSP * pSMBr; | ||
2398 | int rc = 0; | ||
2399 | int bytes_returned; | ||
2400 | int name_len; | ||
2401 | |||
2402 | cFYI(1, ("In SMBQPath path %s", searchName)); | ||
2403 | QInfRetry: | ||
2404 | rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB, | ||
2405 | (void **) &pSMBr); | ||
2406 | if (rc) | ||
2407 | return rc; | ||
2408 | |||
2409 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | ||
2410 | name_len = | ||
2411 | cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, | ||
2412 | PATH_MAX, nls_codepage, remap); | ||
2413 | name_len++; /* trailing null */ | ||
2414 | name_len *= 2; | ||
2415 | } else { | ||
2416 | name_len = strnlen(searchName, PATH_MAX); | ||
2417 | name_len++; /* trailing null */ | ||
2418 | strncpy(pSMB->FileName, searchName, name_len); | ||
2419 | } | ||
2420 | pSMB->BufferFormat = 0x04; | ||
2421 | name_len++; /* account for buffer type byte */ | ||
2422 | pSMB->hdr.smb_buf_length += (__u16) name_len; | ||
2423 | pSMB->ByteCount = cpu_to_le16(name_len); | ||
2424 | |||
2425 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | ||
2426 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | ||
2427 | if (rc) { | ||
2428 | cFYI(1, ("Send error in QueryInfo = %d", rc)); | ||
2429 | } else if (pFinfo) { /* decode response */ | ||
2430 | memset(pFinfo, 0, sizeof(FILE_ALL_INFO)); | ||
2431 | pFinfo->AllocationSize = | ||
2432 | cpu_to_le64(le32_to_cpu(pSMBr->size)); | ||
2433 | pFinfo->EndOfFile = pFinfo->AllocationSize; | ||
2434 | pFinfo->Attributes = | ||
2435 | cpu_to_le32(le16_to_cpu(pSMBr->attr)); | ||
2436 | } else | ||
2437 | rc = -EIO; /* bad buffer passed in */ | ||
2438 | |||
2439 | cifs_buf_release(pSMB); | ||
2440 | |||
2441 | if (rc == -EAGAIN) | ||
2442 | goto QInfRetry; | ||
2443 | |||
2444 | return rc; | ||
2445 | } | ||
2446 | |||
2447 | |||
2448 | |||
2449 | |||
2168 | int | 2450 | int |
2169 | CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, | 2451 | CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, |
2170 | const unsigned char *searchName, | 2452 | const unsigned char *searchName, |
@@ -2396,7 +2678,7 @@ findUniqueRetry: | |||
2396 | if (rc) { | 2678 | if (rc) { |
2397 | cFYI(1, ("Send error in FindFileDirInfo = %d", rc)); | 2679 | cFYI(1, ("Send error in FindFileDirInfo = %d", rc)); |
2398 | } else { /* decode response */ | 2680 | } else { /* decode response */ |
2399 | 2681 | cifs_stats_inc(&tcon->num_ffirst); | |
2400 | /* BB fill in */ | 2682 | /* BB fill in */ |
2401 | } | 2683 | } |
2402 | 2684 | ||
@@ -2414,7 +2696,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, | |||
2414 | const char *searchName, | 2696 | const char *searchName, |
2415 | const struct nls_table *nls_codepage, | 2697 | const struct nls_table *nls_codepage, |
2416 | __u16 * pnetfid, | 2698 | __u16 * pnetfid, |
2417 | struct cifs_search_info * psrch_inf, int remap) | 2699 | struct cifs_search_info * psrch_inf, int remap, const char dirsep) |
2418 | { | 2700 | { |
2419 | /* level 257 SMB_ */ | 2701 | /* level 257 SMB_ */ |
2420 | TRANSACTION2_FFIRST_REQ *pSMB = NULL; | 2702 | TRANSACTION2_FFIRST_REQ *pSMB = NULL; |
@@ -2441,7 +2723,7 @@ findFirstRetry: | |||
2441 | it got remapped to 0xF03A as if it were part of the | 2723 | it got remapped to 0xF03A as if it were part of the |
2442 | directory name instead of a wildcard */ | 2724 | directory name instead of a wildcard */ |
2443 | name_len *= 2; | 2725 | name_len *= 2; |
2444 | pSMB->FileName[name_len] = '\\'; | 2726 | pSMB->FileName[name_len] = dirsep; |
2445 | pSMB->FileName[name_len+1] = 0; | 2727 | pSMB->FileName[name_len+1] = 0; |
2446 | pSMB->FileName[name_len+2] = '*'; | 2728 | pSMB->FileName[name_len+2] = '*'; |
2447 | pSMB->FileName[name_len+3] = 0; | 2729 | pSMB->FileName[name_len+3] = 0; |
@@ -2455,7 +2737,7 @@ findFirstRetry: | |||
2455 | if(name_len > buffersize-header) | 2737 | if(name_len > buffersize-header) |
2456 | free buffer exit; BB */ | 2738 | free buffer exit; BB */ |
2457 | strncpy(pSMB->FileName, searchName, name_len); | 2739 | strncpy(pSMB->FileName, searchName, name_len); |
2458 | pSMB->FileName[name_len] = '\\'; | 2740 | pSMB->FileName[name_len] = dirsep; |
2459 | pSMB->FileName[name_len+1] = '*'; | 2741 | pSMB->FileName[name_len+1] = '*'; |
2460 | pSMB->FileName[name_len+2] = 0; | 2742 | pSMB->FileName[name_len+2] = 0; |
2461 | name_len += 3; | 2743 | name_len += 3; |
@@ -2496,6 +2778,7 @@ findFirstRetry: | |||
2496 | 2778 | ||
2497 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2779 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
2498 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 2780 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
2781 | cifs_stats_inc(&tcon->num_ffirst); | ||
2499 | 2782 | ||
2500 | if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */ | 2783 | 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 */ | 2784 | /* BB Add code to handle unsupported level rc */ |
@@ -2617,7 +2900,7 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, | |||
2617 | 2900 | ||
2618 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2901 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
2619 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 2902 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
2620 | 2903 | cifs_stats_inc(&tcon->num_fnext); | |
2621 | if (rc) { | 2904 | if (rc) { |
2622 | if (rc == -EBADF) { | 2905 | if (rc == -EBADF) { |
2623 | psrch_inf->endOfSearch = TRUE; | 2906 | psrch_inf->endOfSearch = TRUE; |
@@ -2694,6 +2977,7 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle | |||
2694 | if (rc) { | 2977 | if (rc) { |
2695 | cERROR(1, ("Send error in FindClose = %d", rc)); | 2978 | cERROR(1, ("Send error in FindClose = %d", rc)); |
2696 | } | 2979 | } |
2980 | cifs_stats_inc(&tcon->num_fclose); | ||
2697 | cifs_small_buf_release(pSMB); | 2981 | cifs_small_buf_release(pSMB); |
2698 | 2982 | ||
2699 | /* Since session is dead, search handle closed on server already */ | 2983 | /* Since session is dead, search handle closed on server already */ |
@@ -2703,7 +2987,6 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle | |||
2703 | return rc; | 2987 | return rc; |
2704 | } | 2988 | } |
2705 | 2989 | ||
2706 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
2707 | int | 2990 | int |
2708 | CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, | 2991 | CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, |
2709 | const unsigned char *searchName, | 2992 | const unsigned char *searchName, |
@@ -2797,7 +3080,6 @@ GetInodeNumOut: | |||
2797 | goto GetInodeNumberRetry; | 3080 | goto GetInodeNumberRetry; |
2798 | return rc; | 3081 | return rc; |
2799 | } | 3082 | } |
2800 | #endif /* CIFS_EXPERIMENTAL */ | ||
2801 | 3083 | ||
2802 | int | 3084 | int |
2803 | CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, | 3085 | CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, |
@@ -2827,7 +3109,10 @@ getDFSRetry: | |||
2827 | (void **) &pSMBr); | 3109 | (void **) &pSMBr); |
2828 | if (rc) | 3110 | if (rc) |
2829 | return rc; | 3111 | return rc; |
2830 | 3112 | ||
3113 | /* server pointer checked in called function, | ||
3114 | but should never be null here anyway */ | ||
3115 | pSMB->hdr.Mid = GetNextMid(ses->server); | ||
2831 | pSMB->hdr.Tid = ses->ipc_tid; | 3116 | pSMB->hdr.Tid = ses->ipc_tid; |
2832 | pSMB->hdr.Uid = ses->Suid; | 3117 | pSMB->hdr.Uid = ses->Suid; |
2833 | if (ses->capabilities & CAP_STATUS32) { | 3118 | if (ses->capabilities & CAP_STATUS32) { |
@@ -2946,7 +3231,7 @@ getDFSRetry: | |||
2946 | temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset); | 3231 | temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset); |
2947 | if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) { | 3232 | if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) { |
2948 | cifs_strfromUCS_le(*targetUNCs, | 3233 | cifs_strfromUCS_le(*targetUNCs, |
2949 | (wchar_t *) temp, name_len, nls_codepage); | 3234 | (__le16 *) temp, name_len, nls_codepage); |
2950 | } else { | 3235 | } else { |
2951 | strncpy(*targetUNCs,temp,name_len); | 3236 | strncpy(*targetUNCs,temp,name_len); |
2952 | } | 3237 | } |
@@ -2968,6 +3253,92 @@ GetDFSRefExit: | |||
2968 | return rc; | 3253 | return rc; |
2969 | } | 3254 | } |
2970 | 3255 | ||
3256 | /* Query File System Info such as free space to old servers such as Win 9x */ | ||
3257 | int | ||
3258 | SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData) | ||
3259 | { | ||
3260 | /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */ | ||
3261 | TRANSACTION2_QFSI_REQ *pSMB = NULL; | ||
3262 | TRANSACTION2_QFSI_RSP *pSMBr = NULL; | ||
3263 | FILE_SYSTEM_ALLOC_INFO *response_data; | ||
3264 | int rc = 0; | ||
3265 | int bytes_returned = 0; | ||
3266 | __u16 params, byte_count; | ||
3267 | |||
3268 | cFYI(1, ("OldQFSInfo")); | ||
3269 | oldQFSInfoRetry: | ||
3270 | rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, | ||
3271 | (void **) &pSMBr); | ||
3272 | if (rc) | ||
3273 | return rc; | ||
3274 | rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, | ||
3275 | (void **) &pSMBr); | ||
3276 | if (rc) | ||
3277 | return rc; | ||
3278 | |||
3279 | params = 2; /* level */ | ||
3280 | pSMB->TotalDataCount = 0; | ||
3281 | pSMB->MaxParameterCount = cpu_to_le16(2); | ||
3282 | pSMB->MaxDataCount = cpu_to_le16(1000); | ||
3283 | pSMB->MaxSetupCount = 0; | ||
3284 | pSMB->Reserved = 0; | ||
3285 | pSMB->Flags = 0; | ||
3286 | pSMB->Timeout = 0; | ||
3287 | pSMB->Reserved2 = 0; | ||
3288 | byte_count = params + 1 /* pad */ ; | ||
3289 | pSMB->TotalParameterCount = cpu_to_le16(params); | ||
3290 | pSMB->ParameterCount = pSMB->TotalParameterCount; | ||
3291 | pSMB->ParameterOffset = cpu_to_le16(offsetof( | ||
3292 | struct smb_com_transaction2_qfsi_req, InformationLevel) - 4); | ||
3293 | pSMB->DataCount = 0; | ||
3294 | pSMB->DataOffset = 0; | ||
3295 | pSMB->SetupCount = 1; | ||
3296 | pSMB->Reserved3 = 0; | ||
3297 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); | ||
3298 | pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION); | ||
3299 | pSMB->hdr.smb_buf_length += byte_count; | ||
3300 | pSMB->ByteCount = cpu_to_le16(byte_count); | ||
3301 | |||
3302 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | ||
3303 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | ||
3304 | if (rc) { | ||
3305 | cFYI(1, ("Send error in QFSInfo = %d", rc)); | ||
3306 | } else { /* decode response */ | ||
3307 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | ||
3308 | |||
3309 | if (rc || (pSMBr->ByteCount < 18)) | ||
3310 | rc = -EIO; /* bad smb */ | ||
3311 | else { | ||
3312 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | ||
3313 | cFYI(1,("qfsinf resp BCC: %d Offset %d", | ||
3314 | pSMBr->ByteCount, data_offset)); | ||
3315 | |||
3316 | response_data = | ||
3317 | (FILE_SYSTEM_ALLOC_INFO *) | ||
3318 | (((char *) &pSMBr->hdr.Protocol) + data_offset); | ||
3319 | FSData->f_bsize = | ||
3320 | le16_to_cpu(response_data->BytesPerSector) * | ||
3321 | le32_to_cpu(response_data-> | ||
3322 | SectorsPerAllocationUnit); | ||
3323 | FSData->f_blocks = | ||
3324 | le32_to_cpu(response_data->TotalAllocationUnits); | ||
3325 | FSData->f_bfree = FSData->f_bavail = | ||
3326 | le32_to_cpu(response_data->FreeAllocationUnits); | ||
3327 | cFYI(1, | ||
3328 | ("Blocks: %lld Free: %lld Block size %ld", | ||
3329 | (unsigned long long)FSData->f_blocks, | ||
3330 | (unsigned long long)FSData->f_bfree, | ||
3331 | FSData->f_bsize)); | ||
3332 | } | ||
3333 | } | ||
3334 | cifs_buf_release(pSMB); | ||
3335 | |||
3336 | if (rc == -EAGAIN) | ||
3337 | goto oldQFSInfoRetry; | ||
3338 | |||
3339 | return rc; | ||
3340 | } | ||
3341 | |||
2971 | int | 3342 | int |
2972 | CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData) | 3343 | CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData) |
2973 | { | 3344 | { |
@@ -2989,7 +3360,7 @@ QFSInfoRetry: | |||
2989 | params = 2; /* level */ | 3360 | params = 2; /* level */ |
2990 | pSMB->TotalDataCount = 0; | 3361 | pSMB->TotalDataCount = 0; |
2991 | pSMB->MaxParameterCount = cpu_to_le16(2); | 3362 | pSMB->MaxParameterCount = cpu_to_le16(2); |
2992 | pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ | 3363 | pSMB->MaxDataCount = cpu_to_le16(1000); |
2993 | pSMB->MaxSetupCount = 0; | 3364 | pSMB->MaxSetupCount = 0; |
2994 | pSMB->Reserved = 0; | 3365 | pSMB->Reserved = 0; |
2995 | pSMB->Flags = 0; | 3366 | pSMB->Flags = 0; |
@@ -3012,17 +3383,14 @@ QFSInfoRetry: | |||
3012 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3383 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
3013 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 3384 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
3014 | if (rc) { | 3385 | if (rc) { |
3015 | cERROR(1, ("Send error in QFSInfo = %d", rc)); | 3386 | cFYI(1, ("Send error in QFSInfo = %d", rc)); |
3016 | } else { /* decode response */ | 3387 | } else { /* decode response */ |
3017 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 3388 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
3018 | 3389 | ||
3019 | if (rc || (pSMBr->ByteCount < 24)) /* BB alsO CHEck enough total bytes returned */ | 3390 | if (rc || (pSMBr->ByteCount < 24)) |
3020 | rc = -EIO; /* bad smb */ | 3391 | rc = -EIO; /* bad smb */ |
3021 | else { | 3392 | else { |
3022 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 3393 | __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 | 3394 | ||
3027 | response_data = | 3395 | response_data = |
3028 | (FILE_SYSTEM_INFO | 3396 | (FILE_SYSTEM_INFO |
@@ -3257,6 +3625,77 @@ QFSUnixRetry: | |||
3257 | return rc; | 3625 | return rc; |
3258 | } | 3626 | } |
3259 | 3627 | ||
3628 | int | ||
3629 | CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap) | ||
3630 | { | ||
3631 | /* level 0x200 SMB_SET_CIFS_UNIX_INFO */ | ||
3632 | TRANSACTION2_SETFSI_REQ *pSMB = NULL; | ||
3633 | TRANSACTION2_SETFSI_RSP *pSMBr = NULL; | ||
3634 | int rc = 0; | ||
3635 | int bytes_returned = 0; | ||
3636 | __u16 params, param_offset, offset, byte_count; | ||
3637 | |||
3638 | cFYI(1, ("In SETFSUnixInfo")); | ||
3639 | SETFSUnixRetry: | ||
3640 | rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, | ||
3641 | (void **) &pSMBr); | ||
3642 | if (rc) | ||
3643 | return rc; | ||
3644 | |||
3645 | params = 4; /* 2 bytes zero followed by info level. */ | ||
3646 | pSMB->MaxSetupCount = 0; | ||
3647 | pSMB->Reserved = 0; | ||
3648 | pSMB->Flags = 0; | ||
3649 | pSMB->Timeout = 0; | ||
3650 | pSMB->Reserved2 = 0; | ||
3651 | param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4; | ||
3652 | offset = param_offset + params; | ||
3653 | |||
3654 | pSMB->MaxParameterCount = cpu_to_le16(4); | ||
3655 | pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */ | ||
3656 | pSMB->SetupCount = 1; | ||
3657 | pSMB->Reserved3 = 0; | ||
3658 | pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION); | ||
3659 | byte_count = 1 /* pad */ + params + 12; | ||
3660 | |||
3661 | pSMB->DataCount = cpu_to_le16(12); | ||
3662 | pSMB->ParameterCount = cpu_to_le16(params); | ||
3663 | pSMB->TotalDataCount = pSMB->DataCount; | ||
3664 | pSMB->TotalParameterCount = pSMB->ParameterCount; | ||
3665 | pSMB->ParameterOffset = cpu_to_le16(param_offset); | ||
3666 | pSMB->DataOffset = cpu_to_le16(offset); | ||
3667 | |||
3668 | /* Params. */ | ||
3669 | pSMB->FileNum = 0; | ||
3670 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO); | ||
3671 | |||
3672 | /* Data. */ | ||
3673 | pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION); | ||
3674 | pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION); | ||
3675 | pSMB->ClientUnixCap = cpu_to_le64(cap); | ||
3676 | |||
3677 | pSMB->hdr.smb_buf_length += byte_count; | ||
3678 | pSMB->ByteCount = cpu_to_le16(byte_count); | ||
3679 | |||
3680 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | ||
3681 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | ||
3682 | if (rc) { | ||
3683 | cERROR(1, ("Send error in SETFSUnixInfo = %d", rc)); | ||
3684 | } else { /* decode response */ | ||
3685 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | ||
3686 | if (rc) { | ||
3687 | rc = -EIO; /* bad smb */ | ||
3688 | } | ||
3689 | } | ||
3690 | cifs_buf_release(pSMB); | ||
3691 | |||
3692 | if (rc == -EAGAIN) | ||
3693 | goto SETFSUnixRetry; | ||
3694 | |||
3695 | return rc; | ||
3696 | } | ||
3697 | |||
3698 | |||
3260 | 3699 | ||
3261 | int | 3700 | int |
3262 | CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, | 3701 | CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, |
@@ -3321,16 +3760,16 @@ QFSPosixRetry: | |||
3321 | le64_to_cpu(response_data->TotalBlocks); | 3760 | le64_to_cpu(response_data->TotalBlocks); |
3322 | FSData->f_bfree = | 3761 | FSData->f_bfree = |
3323 | le64_to_cpu(response_data->BlocksAvail); | 3762 | le64_to_cpu(response_data->BlocksAvail); |
3324 | if(response_data->UserBlocksAvail == -1) { | 3763 | if(response_data->UserBlocksAvail == cpu_to_le64(-1)) { |
3325 | FSData->f_bavail = FSData->f_bfree; | 3764 | FSData->f_bavail = FSData->f_bfree; |
3326 | } else { | 3765 | } else { |
3327 | FSData->f_bavail = | 3766 | FSData->f_bavail = |
3328 | le64_to_cpu(response_data->UserBlocksAvail); | 3767 | le64_to_cpu(response_data->UserBlocksAvail); |
3329 | } | 3768 | } |
3330 | if(response_data->TotalFileNodes != -1) | 3769 | if(response_data->TotalFileNodes != cpu_to_le64(-1)) |
3331 | FSData->f_files = | 3770 | FSData->f_files = |
3332 | le64_to_cpu(response_data->TotalFileNodes); | 3771 | le64_to_cpu(response_data->TotalFileNodes); |
3333 | if(response_data->FreeFileNodes != -1) | 3772 | if(response_data->FreeFileNodes != cpu_to_le64(-1)) |
3334 | FSData->f_ffree = | 3773 | FSData->f_ffree = |
3335 | le64_to_cpu(response_data->FreeFileNodes); | 3774 | le64_to_cpu(response_data->FreeFileNodes); |
3336 | } | 3775 | } |
@@ -3376,7 +3815,7 @@ SetEOFRetry: | |||
3376 | PATH_MAX, nls_codepage, remap); | 3815 | PATH_MAX, nls_codepage, remap); |
3377 | name_len++; /* trailing null */ | 3816 | name_len++; /* trailing null */ |
3378 | name_len *= 2; | 3817 | name_len *= 2; |
3379 | } else { /* BB improve the check for buffer overruns BB */ | 3818 | } else { /* BB improve the check for buffer overruns BB */ |
3380 | name_len = strnlen(fileName, PATH_MAX); | 3819 | name_len = strnlen(fileName, PATH_MAX); |
3381 | name_len++; /* trailing null */ | 3820 | name_len++; /* trailing null */ |
3382 | strncpy(pSMB->FileName, fileName, name_len); | 3821 | strncpy(pSMB->FileName, fileName, name_len); |
@@ -3384,7 +3823,7 @@ SetEOFRetry: | |||
3384 | params = 6 + name_len; | 3823 | params = 6 + name_len; |
3385 | data_count = sizeof (struct file_end_of_file_info); | 3824 | data_count = sizeof (struct file_end_of_file_info); |
3386 | pSMB->MaxParameterCount = cpu_to_le16(2); | 3825 | pSMB->MaxParameterCount = cpu_to_le16(2); |
3387 | pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */ | 3826 | pSMB->MaxDataCount = cpu_to_le16(4100); |
3388 | pSMB->MaxSetupCount = 0; | 3827 | pSMB->MaxSetupCount = 0; |
3389 | pSMB->Reserved = 0; | 3828 | pSMB->Reserved = 0; |
3390 | pSMB->Flags = 0; | 3829 | pSMB->Flags = 0; |
@@ -3766,7 +4205,7 @@ setPermsRetry: | |||
3766 | PATH_MAX, nls_codepage, remap); | 4205 | PATH_MAX, nls_codepage, remap); |
3767 | name_len++; /* trailing null */ | 4206 | name_len++; /* trailing null */ |
3768 | name_len *= 2; | 4207 | name_len *= 2; |
3769 | } else { /* BB improve the check for buffer overruns BB */ | 4208 | } else { /* BB improve the check for buffer overruns BB */ |
3770 | name_len = strnlen(fileName, PATH_MAX); | 4209 | name_len = strnlen(fileName, PATH_MAX); |
3771 | name_len++; /* trailing null */ | 4210 | name_len++; /* trailing null */ |
3772 | strncpy(pSMB->FileName, fileName, name_len); | 4211 | strncpy(pSMB->FileName, fileName, name_len); |
@@ -3839,12 +4278,14 @@ setPermsRetry: | |||
3839 | } | 4278 | } |
3840 | 4279 | ||
3841 | int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, | 4280 | int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, |
3842 | const int notify_subdirs, const __u16 netfid, | 4281 | const int notify_subdirs, const __u16 netfid, |
3843 | __u32 filter, const struct nls_table *nls_codepage) | 4282 | __u32 filter, struct file * pfile, int multishot, |
4283 | const struct nls_table *nls_codepage) | ||
3844 | { | 4284 | { |
3845 | int rc = 0; | 4285 | int rc = 0; |
3846 | struct smb_com_transaction_change_notify_req * pSMB = NULL; | 4286 | struct smb_com_transaction_change_notify_req * pSMB = NULL; |
3847 | struct smb_com_transaction_change_notify_rsp * pSMBr = NULL; | 4287 | struct smb_com_transaction_change_notify_rsp * pSMBr = NULL; |
4288 | struct dir_notify_req *dnotify_req; | ||
3848 | int bytes_returned; | 4289 | int bytes_returned; |
3849 | 4290 | ||
3850 | cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid)); | 4291 | cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid)); |
@@ -3877,6 +4318,28 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, | |||
3877 | (struct smb_hdr *) pSMBr, &bytes_returned, -1); | 4318 | (struct smb_hdr *) pSMBr, &bytes_returned, -1); |
3878 | if (rc) { | 4319 | if (rc) { |
3879 | cFYI(1, ("Error in Notify = %d", rc)); | 4320 | cFYI(1, ("Error in Notify = %d", rc)); |
4321 | } else { | ||
4322 | /* Add file to outstanding requests */ | ||
4323 | /* BB change to kmem cache alloc */ | ||
4324 | dnotify_req = (struct dir_notify_req *) kmalloc( | ||
4325 | sizeof(struct dir_notify_req), | ||
4326 | GFP_KERNEL); | ||
4327 | if(dnotify_req) { | ||
4328 | dnotify_req->Pid = pSMB->hdr.Pid; | ||
4329 | dnotify_req->PidHigh = pSMB->hdr.PidHigh; | ||
4330 | dnotify_req->Mid = pSMB->hdr.Mid; | ||
4331 | dnotify_req->Tid = pSMB->hdr.Tid; | ||
4332 | dnotify_req->Uid = pSMB->hdr.Uid; | ||
4333 | dnotify_req->netfid = netfid; | ||
4334 | dnotify_req->pfile = pfile; | ||
4335 | dnotify_req->filter = filter; | ||
4336 | dnotify_req->multishot = multishot; | ||
4337 | spin_lock(&GlobalMid_Lock); | ||
4338 | list_add_tail(&dnotify_req->lhead, | ||
4339 | &GlobalDnotifyReqList); | ||
4340 | spin_unlock(&GlobalMid_Lock); | ||
4341 | } else | ||
4342 | rc = -ENOMEM; | ||
3880 | } | 4343 | } |
3881 | cifs_buf_release(pSMB); | 4344 | cifs_buf_release(pSMB); |
3882 | return rc; | 4345 | return rc; |