aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/cifssmb.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r--fs/cifs/cifssmb.c529
1 files changed, 450 insertions, 79 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 0db0b313d715..c8ae3ef422ba 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -166,11 +166,9 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
166 166
167 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct); 167 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
168 168
169#ifdef CONFIG_CIFS_STATS 169 if(tcon != NULL)
170 if(tcon != NULL) { 170 cifs_stats_inc(&tcon->num_smbs_sent);
171 atomic_inc(&tcon->num_smbs_sent); 171
172 }
173#endif /* CONFIG_CIFS_STATS */
174 return rc; 172 return rc;
175} 173}
176 174
@@ -269,11 +267,9 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
269 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon, 267 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
270 wct /*wct */ ); 268 wct /*wct */ );
271 269
272#ifdef CONFIG_CIFS_STATS 270 if(tcon != NULL)
273 if(tcon != NULL) { 271 cifs_stats_inc(&tcon->num_smbs_sent);
274 atomic_inc(&tcon->num_smbs_sent); 272
275 }
276#endif /* CONFIG_CIFS_STATS */
277 return rc; 273 return rc;
278} 274}
279 275
@@ -330,7 +326,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
330 (void **) &pSMB, (void **) &pSMBr); 326 (void **) &pSMB, (void **) &pSMBr);
331 if (rc) 327 if (rc)
332 return rc; 328 return rc;
333 329 pSMB->hdr.Mid = GetNextMid(server);
334 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; 330 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
335 if (extended_security) 331 if (extended_security)
336 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; 332 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
@@ -422,8 +418,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
422 } 418 }
423 419
424 } 420 }
425 if (pSMB) 421
426 cifs_buf_release(pSMB); 422 cifs_buf_release(pSMB);
427 return rc; 423 return rc;
428} 424}
429 425
@@ -518,6 +514,8 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
518 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */ 514 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
519 515
520 if(ses->server) { 516 if(ses->server) {
517 pSMB->hdr.Mid = GetNextMid(ses->server);
518
521 if(ses->server->secMode & 519 if(ses->server->secMode &
522 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) 520 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
523 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; 521 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
@@ -537,9 +535,8 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
537 rc = -ESHUTDOWN; 535 rc = -ESHUTDOWN;
538 } 536 }
539 } 537 }
540 if (pSMB)
541 cifs_small_buf_release(pSMB);
542 up(&ses->sesSem); 538 up(&ses->sesSem);
539 cifs_small_buf_release(pSMB);
543 540
544 /* if session dead then we do not need to do ulogoff, 541 /* if session dead then we do not need to do ulogoff,
545 since server closed smb session, no sense reporting 542 since server closed smb session, no sense reporting
@@ -583,14 +580,10 @@ DelFileRetry:
583 pSMB->ByteCount = cpu_to_le16(name_len + 1); 580 pSMB->ByteCount = cpu_to_le16(name_len + 1);
584 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 581 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
585 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 582 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
583 cifs_stats_inc(&tcon->num_deletes);
586 if (rc) { 584 if (rc) {
587 cFYI(1, ("Error in RMFile = %d", rc)); 585 cFYI(1, ("Error in RMFile = %d", rc));
588 } 586 }
589#ifdef CONFIG_CIFS_STATS
590 else {
591 atomic_inc(&tcon->num_deletes);
592 }
593#endif
594 587
595 cifs_buf_release(pSMB); 588 cifs_buf_release(pSMB);
596 if (rc == -EAGAIN) 589 if (rc == -EAGAIN)
@@ -632,14 +625,10 @@ RmDirRetry:
632 pSMB->ByteCount = cpu_to_le16(name_len + 1); 625 pSMB->ByteCount = cpu_to_le16(name_len + 1);
633 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 626 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
634 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 627 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
628 cifs_stats_inc(&tcon->num_rmdirs);
635 if (rc) { 629 if (rc) {
636 cFYI(1, ("Error in RMDir = %d", rc)); 630 cFYI(1, ("Error in RMDir = %d", rc));
637 } 631 }
638#ifdef CONFIG_CIFS_STATS
639 else {
640 atomic_inc(&tcon->num_rmdirs);
641 }
642#endif
643 632
644 cifs_buf_release(pSMB); 633 cifs_buf_release(pSMB);
645 if (rc == -EAGAIN) 634 if (rc == -EAGAIN)
@@ -680,20 +669,157 @@ MkDirRetry:
680 pSMB->ByteCount = cpu_to_le16(name_len + 1); 669 pSMB->ByteCount = cpu_to_le16(name_len + 1);
681 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 670 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
682 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 671 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
672 cifs_stats_inc(&tcon->num_mkdirs);
683 if (rc) { 673 if (rc) {
684 cFYI(1, ("Error in Mkdir = %d", rc)); 674 cFYI(1, ("Error in Mkdir = %d", rc));
685 } 675 }
686#ifdef CONFIG_CIFS_STATS 676
687 else {
688 atomic_inc(&tcon->num_mkdirs);
689 }
690#endif
691 cifs_buf_release(pSMB); 677 cifs_buf_release(pSMB);
692 if (rc == -EAGAIN) 678 if (rc == -EAGAIN)
693 goto MkDirRetry; 679 goto MkDirRetry;
694 return rc; 680 return rc;
695} 681}
696 682
683static __u16 convert_disposition(int disposition)
684{
685 __u16 ofun = 0;
686
687 switch (disposition) {
688 case FILE_SUPERSEDE:
689 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
690 break;
691 case FILE_OPEN:
692 ofun = SMBOPEN_OAPPEND;
693 break;
694 case FILE_CREATE:
695 ofun = SMBOPEN_OCREATE;
696 break;
697 case FILE_OPEN_IF:
698 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
699 break;
700 case FILE_OVERWRITE:
701 ofun = SMBOPEN_OTRUNC;
702 break;
703 case FILE_OVERWRITE_IF:
704 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
705 break;
706 default:
707 cFYI(1,("unknown disposition %d",disposition));
708 ofun = SMBOPEN_OAPPEND; /* regular open */
709 }
710 return ofun;
711}
712
713int
714SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
715 const char *fileName, const int openDisposition,
716 const int access_flags, const int create_options, __u16 * netfid,
717 int *pOplock, FILE_ALL_INFO * pfile_info,
718 const struct nls_table *nls_codepage, int remap)
719{
720 int rc = -EACCES;
721 OPENX_REQ *pSMB = NULL;
722 OPENX_RSP *pSMBr = NULL;
723 int bytes_returned;
724 int name_len;
725 __u16 count;
726
727OldOpenRetry:
728 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
729 (void **) &pSMBr);
730 if (rc)
731 return rc;
732
733 pSMB->AndXCommand = 0xFF; /* none */
734
735 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
736 count = 1; /* account for one byte pad to word boundary */
737 name_len =
738 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
739 fileName, PATH_MAX, nls_codepage, remap);
740 name_len++; /* trailing null */
741 name_len *= 2;
742 } else { /* BB improve check for buffer overruns BB */
743 count = 0; /* no pad */
744 name_len = strnlen(fileName, PATH_MAX);
745 name_len++; /* trailing null */
746 strncpy(pSMB->fileName, fileName, name_len);
747 }
748 if (*pOplock & REQ_OPLOCK)
749 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
750 else if (*pOplock & REQ_BATCHOPLOCK) {
751 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
752 }
753 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
754 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
755 /* 0 = read
756 1 = write
757 2 = rw
758 3 = execute
759 */
760 pSMB->Mode = cpu_to_le16(2);
761 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
762 /* set file as system file if special file such
763 as fifo and server expecting SFU style and
764 no Unix extensions */
765
766 if(create_options & CREATE_OPTION_SPECIAL)
767 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
768 else
769 pSMB->FileAttributes = cpu_to_le16(ATTR_NORMAL);
770
771 /* if ((omode & S_IWUGO) == 0)
772 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
773 /* Above line causes problems due to vfs splitting create into two
774 pieces - need to set mode after file created not while it is
775 being created */
776
777 /* BB FIXME BB */
778/* pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); */
779 /* BB FIXME END BB */
780 pSMB->OpenFunction = convert_disposition(openDisposition);
781 count += name_len;
782 pSMB->hdr.smb_buf_length += count;
783
784 pSMB->ByteCount = cpu_to_le16(count);
785 /* long_op set to 1 to allow for oplock break timeouts */
786 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
787 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
788 cifs_stats_inc(&tcon->num_opens);
789 if (rc) {
790 cFYI(1, ("Error in Open = %d", rc));
791 } else {
792 /* BB verify if wct == 15 */
793
794/* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
795
796 *netfid = pSMBr->Fid; /* cifs fid stays in le */
797 /* Let caller know file was created so we can set the mode. */
798 /* Do we care about the CreateAction in any other cases? */
799 /* BB FIXME BB */
800/* if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
801 *pOplock |= CIFS_CREATE_ACTION; */
802 /* BB FIXME END */
803
804 if(pfile_info) {
805 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
806 pfile_info->LastAccessTime = 0; /* BB fixme */
807 pfile_info->LastWriteTime = 0; /* BB fixme */
808 pfile_info->ChangeTime = 0; /* BB fixme */
809 pfile_info->Attributes = pSMBr->FileAttributes;
810 /* the file_info buf is endian converted by caller */
811 pfile_info->AllocationSize = pSMBr->EndOfFile;
812 pfile_info->EndOfFile = pSMBr->EndOfFile;
813 pfile_info->NumberOfLinks = cpu_to_le32(1);
814 }
815 }
816
817 cifs_buf_release(pSMB);
818 if (rc == -EAGAIN)
819 goto OldOpenRetry;
820 return rc;
821}
822
697int 823int
698CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, 824CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
699 const char *fileName, const int openDisposition, 825 const char *fileName, const int openDisposition,
@@ -738,7 +864,13 @@ openRetry:
738 } 864 }
739 pSMB->DesiredAccess = cpu_to_le32(access_flags); 865 pSMB->DesiredAccess = cpu_to_le32(access_flags);
740 pSMB->AllocationSize = 0; 866 pSMB->AllocationSize = 0;
741 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL); 867 /* set file as system file if special file such
868 as fifo and server expecting SFU style and
869 no Unix extensions */
870 if(create_options & CREATE_OPTION_SPECIAL)
871 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
872 else
873 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
742 /* XP does not handle ATTR_POSIX_SEMANTICS */ 874 /* XP does not handle ATTR_POSIX_SEMANTICS */
743 /* but it helps speed up case sensitive checks for other 875 /* but it helps speed up case sensitive checks for other
744 servers such as Samba */ 876 servers such as Samba */
@@ -752,7 +884,7 @@ openRetry:
752 being created */ 884 being created */
753 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL); 885 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
754 pSMB->CreateDisposition = cpu_to_le32(openDisposition); 886 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
755 pSMB->CreateOptions = cpu_to_le32(create_options); 887 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
756 /* BB Expirement with various impersonation levels and verify */ 888 /* BB Expirement with various impersonation levels and verify */
757 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); 889 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
758 pSMB->SecurityFlags = 890 pSMB->SecurityFlags =
@@ -765,6 +897,7 @@ openRetry:
765 /* long_op set to 1 to allow for oplock break timeouts */ 897 /* long_op set to 1 to allow for oplock break timeouts */
766 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 898 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
767 (struct smb_hdr *) pSMBr, &bytes_returned, 1); 899 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
900 cifs_stats_inc(&tcon->num_opens);
768 if (rc) { 901 if (rc) {
769 cFYI(1, ("Error in Open = %d", rc)); 902 cFYI(1, ("Error in Open = %d", rc));
770 } else { 903 } else {
@@ -782,17 +915,89 @@ openRetry:
782 pfile_info->EndOfFile = pSMBr->EndOfFile; 915 pfile_info->EndOfFile = pSMBr->EndOfFile;
783 pfile_info->NumberOfLinks = cpu_to_le32(1); 916 pfile_info->NumberOfLinks = cpu_to_le32(1);
784 } 917 }
785
786#ifdef CONFIG_CIFS_STATS
787 atomic_inc(&tcon->num_opens);
788#endif
789 } 918 }
919
790 cifs_buf_release(pSMB); 920 cifs_buf_release(pSMB);
791 if (rc == -EAGAIN) 921 if (rc == -EAGAIN)
792 goto openRetry; 922 goto openRetry;
793 return rc; 923 return rc;
794} 924}
795 925
926int
927SMBLegacyRead(const int xid, struct cifsTconInfo *tcon,
928 const int netfid, unsigned int count,
929 const __u64 lseek, unsigned int *nbytes, char **buf)
930{
931 int rc = -EACCES;
932 READX_REQ *pSMB = NULL;
933 READ_RSP *pSMBr = NULL;
934 char *pReadData = NULL;
935 int bytes_returned;
936
937 cFYI(1,("Legacy read %d bytes fid %d",count,netfid));
938
939 /* field is shorter in legacy read, only 16 bits */
940 if(count > 2048)
941 count = 2048; /* BB FIXME make this configurable */
942
943 if(lseek > 0xFFFFFFFF)
944 return -EIO; /* can not read that far into file on old server */
945
946 *nbytes = 0;
947 rc = smb_init(SMB_COM_READ_ANDX, 10, tcon, (void **) &pSMB,
948 (void **) &pSMBr);
949 if (rc)
950 return rc;
951
952 /* tcon and ses pointer are checked in smb_init */
953 if (tcon->ses->server == NULL)
954 return -ECONNABORTED;
955
956 pSMB->AndXCommand = 0xFF; /* none */
957 pSMB->Fid = netfid;
958 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
959 pSMB->Remaining = 0;
960 pSMB->MaxCount = cpu_to_le16(count);
961 pSMB->Reserved = 0; /* Must Be Zero */
962 pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */
963
964 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
965 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
966 cifs_stats_inc(&tcon->num_reads);
967 if (rc) {
968 cERROR(1, ("Send error in legacy read = %d", rc));
969 } else {
970 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
971 data_length = data_length << 16;
972 data_length += le16_to_cpu(pSMBr->DataLength);
973 *nbytes = data_length;
974
975 /*check that DataLength would not go beyond end of SMB */
976 if ((data_length > CIFSMaxBufSize) || (data_length > count)) {
977 cFYI(1,("bad length %d for count %d",data_length,count));
978 rc = -EIO;
979 *nbytes = 0;
980 } else {
981 pReadData = (char *) (&pSMBr->hdr.Protocol) +
982 le16_to_cpu(pSMBr->DataOffset);
983/* if(rc = copy_to_user(buf, pReadData, data_length)) {
984 cERROR(1,("Faulting on read rc = %d",rc));
985 rc = -EFAULT;
986 }*/ /* can not use copy_to_user when using page cache*/
987 if(*buf)
988 memcpy(*buf,pReadData,data_length);
989 }
990 }
991 if(*buf)
992 cifs_buf_release(pSMB);
993 else
994 *buf = (char *)pSMB;
995
996 /* Note: On -EAGAIN error only caller can retry on handle based calls
997 since file handle passed in no longer valid */
998 return rc;
999}
1000
796/* If no buffer passed in, then caller wants to do the copy 1001/* If no buffer passed in, then caller wants to do the copy
797 as in the case of readpages so the SMB buffer must be 1002 as in the case of readpages so the SMB buffer must be
798 freed by the caller */ 1003 freed by the caller */
@@ -831,6 +1036,7 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
831 1036
832 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1037 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
833 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1038 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1039 cifs_stats_inc(&tcon->num_reads);
834 if (rc) { 1040 if (rc) {
835 cERROR(1, ("Send error in read = %d", rc)); 1041 cERROR(1, ("Send error in read = %d", rc));
836 } else { 1042 } else {
@@ -933,6 +1139,7 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
933 1139
934 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1140 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
935 (struct smb_hdr *) pSMBr, &bytes_returned, long_op); 1141 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1142 cifs_stats_inc(&tcon->num_writes);
936 if (rc) { 1143 if (rc) {
937 cFYI(1, ("Send error in write = %d", rc)); 1144 cFYI(1, ("Send error in write = %d", rc));
938 *nbytes = 0; 1145 *nbytes = 0;
@@ -951,56 +1158,70 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
951} 1158}
952 1159
953#ifdef CONFIG_CIFS_EXPERIMENTAL 1160#ifdef CONFIG_CIFS_EXPERIMENTAL
954int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, 1161int
1162CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
955 const int netfid, const unsigned int count, 1163 const int netfid, const unsigned int count,
956 const __u64 offset, unsigned int *nbytes, const char __user *buf, 1164 const __u64 offset, unsigned int *nbytes, const char *buf,
957 const int long_op) 1165 const int long_op)
958{ 1166{
959 int rc = -EACCES; 1167 int rc = -EACCES;
960 WRITE_REQ *pSMB = NULL; 1168 WRITE_REQ *pSMB = NULL;
961 WRITE_RSP *pSMBr = NULL; 1169 int bytes_returned;
962 /*int bytes_returned;*/ 1170 int smb_hdr_len;
963 unsigned bytes_sent; 1171 __u32 bytes_sent;
964 __u16 byte_count; 1172 __u16 byte_count;
965 1173
1174 cFYI(1,("write2 at %lld %d bytes",offset,count)); /* BB removeme BB */
966 rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB); 1175 rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB);
967
968 if (rc) 1176 if (rc)
969 return rc; 1177 return rc;
970
971 pSMBr = (WRITE_RSP *)pSMB; /* BB removeme BB */
972
973 /* tcon and ses pointer are checked in smb_init */ 1178 /* tcon and ses pointer are checked in smb_init */
974 if (tcon->ses->server == NULL) 1179 if (tcon->ses->server == NULL)
975 return -ECONNABORTED; 1180 return -ECONNABORTED;
976 1181
977 pSMB->AndXCommand = 0xFF; /* none */ 1182 pSMB->AndXCommand = 0xFF; /* none */
978 pSMB->Fid = netfid; 1183 pSMB->Fid = netfid;
979 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); 1184 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
980 pSMB->OffsetHigh = cpu_to_le32(offset >> 32); 1185 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
981 pSMB->Reserved = 0xFFFFFFFF; 1186 pSMB->Reserved = 0xFFFFFFFF;
982 pSMB->WriteMode = 0; 1187 pSMB->WriteMode = 0;
983 pSMB->Remaining = 0; 1188 pSMB->Remaining = 0;
984 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF; 1189
1190 /* Can increase buffer size if buffer is big enough in some cases - ie
1191 can send more if LARGE_WRITE_X capability returned by the server and if
1192 our buffer is big enough or if we convert to iovecs on socket writes
1193 and eliminate the copy to the CIFS buffer */
1194 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1195 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1196 } else {
1197 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1198 & ~0xFF;
1199 }
1200
985 if (bytes_sent > count) 1201 if (bytes_sent > count)
986 bytes_sent = count; 1202 bytes_sent = count;
987 pSMB->DataLengthHigh = 0;
988 pSMB->DataOffset = 1203 pSMB->DataOffset =
989 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4); 1204 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
990 1205
991 byte_count = bytes_sent + 1 /* pad */ ; 1206 byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
992 pSMB->DataLengthLow = cpu_to_le16(bytes_sent); 1207 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
993 pSMB->DataLengthHigh = 0; 1208 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
994 pSMB->hdr.smb_buf_length += byte_count; 1209 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1210 pSMB->hdr.smb_buf_length += bytes_sent+1;
995 pSMB->ByteCount = cpu_to_le16(byte_count); 1211 pSMB->ByteCount = cpu_to_le16(byte_count);
996 1212
997/* rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB, 1213 rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB, smb_hdr_len,
998 (struct smb_hdr *) pSMBr, buf, buflen, &bytes_returned, long_op); */ /* BB fixme BB */ 1214 buf, bytes_sent, &bytes_returned, long_op);
1215 cifs_stats_inc(&tcon->num_writes);
999 if (rc) { 1216 if (rc) {
1000 cFYI(1, ("Send error in write2 (large write) = %d", rc)); 1217 cFYI(1, ("Send error in write = %d", rc));
1001 *nbytes = 0; 1218 *nbytes = 0;
1002 } else 1219 } else {
1003 *nbytes = le16_to_cpu(pSMBr->Count); 1220 WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB;
1221 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1222 *nbytes = (*nbytes) << 16;
1223 *nbytes += le16_to_cpu(pSMBr->Count);
1224 }
1004 1225
1005 cifs_small_buf_release(pSMB); 1226 cifs_small_buf_release(pSMB);
1006 1227
@@ -1009,6 +1230,8 @@ int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1009 1230
1010 return rc; 1231 return rc;
1011} 1232}
1233
1234
1012#endif /* CIFS_EXPERIMENTAL */ 1235#endif /* CIFS_EXPERIMENTAL */
1013 1236
1014int 1237int
@@ -1065,7 +1288,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1065 1288
1066 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1289 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1067 (struct smb_hdr *) pSMBr, &bytes_returned, timeout); 1290 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1068 1291 cifs_stats_inc(&tcon->num_locks);
1069 if (rc) { 1292 if (rc) {
1070 cFYI(1, ("Send error in Lock = %d", rc)); 1293 cFYI(1, ("Send error in Lock = %d", rc));
1071 } 1294 }
@@ -1099,6 +1322,7 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1099 pSMB->ByteCount = 0; 1322 pSMB->ByteCount = 0;
1100 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1323 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1101 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1324 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1325 cifs_stats_inc(&tcon->num_closes);
1102 if (rc) { 1326 if (rc) {
1103 if(rc!=-EINTR) { 1327 if(rc!=-EINTR) {
1104 /* EINTR is expected when user ctl-c to kill app */ 1328 /* EINTR is expected when user ctl-c to kill app */
@@ -1171,16 +1395,11 @@ renameRetry:
1171 1395
1172 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1396 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1173 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1397 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1398 cifs_stats_inc(&tcon->num_renames);
1174 if (rc) { 1399 if (rc) {
1175 cFYI(1, ("Send error in rename = %d", rc)); 1400 cFYI(1, ("Send error in rename = %d", rc));
1176 } 1401 }
1177 1402
1178#ifdef CONFIG_CIFS_STATS
1179 else {
1180 atomic_inc(&tcon->num_renames);
1181 }
1182#endif
1183
1184 cifs_buf_release(pSMB); 1403 cifs_buf_release(pSMB);
1185 1404
1186 if (rc == -EAGAIN) 1405 if (rc == -EAGAIN)
@@ -1255,14 +1474,11 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1255 pSMB->ByteCount = cpu_to_le16(byte_count); 1474 pSMB->ByteCount = cpu_to_le16(byte_count);
1256 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB, 1475 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1257 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1476 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1477 cifs_stats_inc(&pTcon->num_t2renames);
1258 if (rc) { 1478 if (rc) {
1259 cFYI(1,("Send error in Rename (by file handle) = %d", rc)); 1479 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1260 } 1480 }
1261#ifdef CONFIG_CIFS_STATS 1481
1262 else {
1263 atomic_inc(&pTcon->num_t2renames);
1264 }
1265#endif
1266 cifs_buf_release(pSMB); 1482 cifs_buf_release(pSMB);
1267 1483
1268 /* Note: On -EAGAIN error only caller can retry on handle based calls 1484 /* Note: On -EAGAIN error only caller can retry on handle based calls
@@ -1416,6 +1632,7 @@ createSymLinkRetry:
1416 pSMB->ByteCount = cpu_to_le16(byte_count); 1632 pSMB->ByteCount = cpu_to_le16(byte_count);
1417 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1633 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1418 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1634 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1635 cifs_stats_inc(&tcon->num_symlinks);
1419 if (rc) { 1636 if (rc) {
1420 cFYI(1, 1637 cFYI(1,
1421 ("Send error in SetPathInfo (create symlink) = %d", 1638 ("Send error in SetPathInfo (create symlink) = %d",
@@ -1505,6 +1722,7 @@ createHardLinkRetry:
1505 pSMB->ByteCount = cpu_to_le16(byte_count); 1722 pSMB->ByteCount = cpu_to_le16(byte_count);
1506 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1723 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1507 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1724 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1725 cifs_stats_inc(&tcon->num_hardlinks);
1508 if (rc) { 1726 if (rc) {
1509 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc)); 1727 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
1510 } 1728 }
@@ -1575,6 +1793,7 @@ winCreateHardLinkRetry:
1575 1793
1576 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1794 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1577 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1795 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1796 cifs_stats_inc(&tcon->num_hardlinks);
1578 if (rc) { 1797 if (rc) {
1579 cFYI(1, ("Send error in hard link (NT rename) = %d", rc)); 1798 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
1580 } 1799 }
@@ -1775,8 +1994,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1775 } 1994 }
1776 } 1995 }
1777qreparse_out: 1996qreparse_out:
1778 if (pSMB) 1997 cifs_buf_release(pSMB);
1779 cifs_buf_release(pSMB);
1780 1998
1781 /* Note: On -EAGAIN error only caller can retry on handle based calls 1999 /* Note: On -EAGAIN error only caller can retry on handle based calls
1782 since file handle passed in no longer valid */ 2000 since file handle passed in no longer valid */
@@ -2165,6 +2383,65 @@ GetExtAttrOut:
2165 2383
2166#endif /* CONFIG_POSIX */ 2384#endif /* CONFIG_POSIX */
2167 2385
2386/* Legacy Query Path Information call for lookup to old servers such
2387 as Win9x/WinME */
2388int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
2389 const unsigned char *searchName,
2390 FILE_ALL_INFO * pFinfo,
2391 const struct nls_table *nls_codepage, int remap)
2392{
2393 QUERY_INFORMATION_REQ * pSMB;
2394 QUERY_INFORMATION_RSP * pSMBr;
2395 int rc = 0;
2396 int bytes_returned;
2397 int name_len;
2398
2399 cFYI(1, ("In SMBQPath path %s", searchName));
2400QInfRetry:
2401 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
2402 (void **) &pSMBr);
2403 if (rc)
2404 return rc;
2405
2406 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2407 name_len =
2408 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2409 PATH_MAX, nls_codepage, remap);
2410 name_len++; /* trailing null */
2411 name_len *= 2;
2412 } else {
2413 name_len = strnlen(searchName, PATH_MAX);
2414 name_len++; /* trailing null */
2415 strncpy(pSMB->FileName, searchName, name_len);
2416 }
2417 pSMB->BufferFormat = 0x04;
2418 name_len++; /* account for buffer type byte */
2419 pSMB->hdr.smb_buf_length += (__u16) name_len;
2420 pSMB->ByteCount = cpu_to_le16(name_len);
2421
2422 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2423 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2424 if (rc) {
2425 cFYI(1, ("Send error in QueryInfo = %d", rc));
2426 } else if (pFinfo) { /* decode response */
2427 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
2428 pFinfo->AllocationSize = (__le64) pSMBr->size;
2429 pFinfo->EndOfFile = (__le64) pSMBr->size;
2430 pFinfo->Attributes = (__le32) pSMBr->attr;
2431 } else
2432 rc = -EIO; /* bad buffer passed in */
2433
2434 cifs_buf_release(pSMB);
2435
2436 if (rc == -EAGAIN)
2437 goto QInfRetry;
2438
2439 return rc;
2440}
2441
2442
2443
2444
2168int 2445int
2169CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, 2446CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2170 const unsigned char *searchName, 2447 const unsigned char *searchName,
@@ -2396,7 +2673,7 @@ findUniqueRetry:
2396 if (rc) { 2673 if (rc) {
2397 cFYI(1, ("Send error in FindFileDirInfo = %d", rc)); 2674 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
2398 } else { /* decode response */ 2675 } else { /* decode response */
2399 2676 cifs_stats_inc(&tcon->num_ffirst);
2400 /* BB fill in */ 2677 /* BB fill in */
2401 } 2678 }
2402 2679
@@ -2414,7 +2691,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
2414 const char *searchName, 2691 const char *searchName,
2415 const struct nls_table *nls_codepage, 2692 const struct nls_table *nls_codepage,
2416 __u16 * pnetfid, 2693 __u16 * pnetfid,
2417 struct cifs_search_info * psrch_inf, int remap) 2694 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
2418{ 2695{
2419/* level 257 SMB_ */ 2696/* level 257 SMB_ */
2420 TRANSACTION2_FFIRST_REQ *pSMB = NULL; 2697 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
@@ -2441,7 +2718,7 @@ findFirstRetry:
2441 it got remapped to 0xF03A as if it were part of the 2718 it got remapped to 0xF03A as if it were part of the
2442 directory name instead of a wildcard */ 2719 directory name instead of a wildcard */
2443 name_len *= 2; 2720 name_len *= 2;
2444 pSMB->FileName[name_len] = '\\'; 2721 pSMB->FileName[name_len] = dirsep;
2445 pSMB->FileName[name_len+1] = 0; 2722 pSMB->FileName[name_len+1] = 0;
2446 pSMB->FileName[name_len+2] = '*'; 2723 pSMB->FileName[name_len+2] = '*';
2447 pSMB->FileName[name_len+3] = 0; 2724 pSMB->FileName[name_len+3] = 0;
@@ -2455,7 +2732,7 @@ findFirstRetry:
2455 if(name_len > buffersize-header) 2732 if(name_len > buffersize-header)
2456 free buffer exit; BB */ 2733 free buffer exit; BB */
2457 strncpy(pSMB->FileName, searchName, name_len); 2734 strncpy(pSMB->FileName, searchName, name_len);
2458 pSMB->FileName[name_len] = '\\'; 2735 pSMB->FileName[name_len] = dirsep;
2459 pSMB->FileName[name_len+1] = '*'; 2736 pSMB->FileName[name_len+1] = '*';
2460 pSMB->FileName[name_len+2] = 0; 2737 pSMB->FileName[name_len+2] = 0;
2461 name_len += 3; 2738 name_len += 3;
@@ -2496,6 +2773,7 @@ findFirstRetry:
2496 2773
2497 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 2774 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2498 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 2775 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2776 cifs_stats_inc(&tcon->num_ffirst);
2499 2777
2500 if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */ 2778 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 */ 2779 /* BB Add code to handle unsupported level rc */
@@ -2617,7 +2895,7 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
2617 2895
2618 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 2896 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2619 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 2897 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2620 2898 cifs_stats_inc(&tcon->num_fnext);
2621 if (rc) { 2899 if (rc) {
2622 if (rc == -EBADF) { 2900 if (rc == -EBADF) {
2623 psrch_inf->endOfSearch = TRUE; 2901 psrch_inf->endOfSearch = TRUE;
@@ -2694,6 +2972,7 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle
2694 if (rc) { 2972 if (rc) {
2695 cERROR(1, ("Send error in FindClose = %d", rc)); 2973 cERROR(1, ("Send error in FindClose = %d", rc));
2696 } 2974 }
2975 cifs_stats_inc(&tcon->num_fclose);
2697 cifs_small_buf_release(pSMB); 2976 cifs_small_buf_release(pSMB);
2698 2977
2699 /* Since session is dead, search handle closed on server already */ 2978 /* Since session is dead, search handle closed on server already */
@@ -2827,7 +3106,10 @@ getDFSRetry:
2827 (void **) &pSMBr); 3106 (void **) &pSMBr);
2828 if (rc) 3107 if (rc)
2829 return rc; 3108 return rc;
2830 3109
3110 /* server pointer checked in called function,
3111 but should never be null here anyway */
3112 pSMB->hdr.Mid = GetNextMid(ses->server);
2831 pSMB->hdr.Tid = ses->ipc_tid; 3113 pSMB->hdr.Tid = ses->ipc_tid;
2832 pSMB->hdr.Uid = ses->Suid; 3114 pSMB->hdr.Uid = ses->Suid;
2833 if (ses->capabilities & CAP_STATUS32) { 3115 if (ses->capabilities & CAP_STATUS32) {
@@ -3257,6 +3539,77 @@ QFSUnixRetry:
3257 return rc; 3539 return rc;
3258} 3540}
3259 3541
3542int
3543CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
3544{
3545/* level 0x200 SMB_SET_CIFS_UNIX_INFO */
3546 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
3547 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
3548 int rc = 0;
3549 int bytes_returned = 0;
3550 __u16 params, param_offset, offset, byte_count;
3551
3552 cFYI(1, ("In SETFSUnixInfo"));
3553SETFSUnixRetry:
3554 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3555 (void **) &pSMBr);
3556 if (rc)
3557 return rc;
3558
3559 params = 4; /* 2 bytes zero followed by info level. */
3560 pSMB->MaxSetupCount = 0;
3561 pSMB->Reserved = 0;
3562 pSMB->Flags = 0;
3563 pSMB->Timeout = 0;
3564 pSMB->Reserved2 = 0;
3565 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
3566 offset = param_offset + params;
3567
3568 pSMB->MaxParameterCount = cpu_to_le16(4);
3569 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3570 pSMB->SetupCount = 1;
3571 pSMB->Reserved3 = 0;
3572 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
3573 byte_count = 1 /* pad */ + params + 12;
3574
3575 pSMB->DataCount = cpu_to_le16(12);
3576 pSMB->ParameterCount = cpu_to_le16(params);
3577 pSMB->TotalDataCount = pSMB->DataCount;
3578 pSMB->TotalParameterCount = pSMB->ParameterCount;
3579 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3580 pSMB->DataOffset = cpu_to_le16(offset);
3581
3582 /* Params. */
3583 pSMB->FileNum = 0;
3584 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
3585
3586 /* Data. */
3587 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
3588 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
3589 pSMB->ClientUnixCap = cpu_to_le64(cap);
3590
3591 pSMB->hdr.smb_buf_length += byte_count;
3592 pSMB->ByteCount = cpu_to_le16(byte_count);
3593
3594 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3595 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3596 if (rc) {
3597 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
3598 } else { /* decode response */
3599 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3600 if (rc) {
3601 rc = -EIO; /* bad smb */
3602 }
3603 }
3604 cifs_buf_release(pSMB);
3605
3606 if (rc == -EAGAIN)
3607 goto SETFSUnixRetry;
3608
3609 return rc;
3610}
3611
3612
3260 3613
3261int 3614int
3262CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, 3615CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
@@ -3839,12 +4192,14 @@ setPermsRetry:
3839} 4192}
3840 4193
3841int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, 4194int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
3842 const int notify_subdirs, const __u16 netfid, 4195 const int notify_subdirs, const __u16 netfid,
3843 __u32 filter, const struct nls_table *nls_codepage) 4196 __u32 filter, struct file * pfile, int multishot,
4197 const struct nls_table *nls_codepage)
3844{ 4198{
3845 int rc = 0; 4199 int rc = 0;
3846 struct smb_com_transaction_change_notify_req * pSMB = NULL; 4200 struct smb_com_transaction_change_notify_req * pSMB = NULL;
3847 struct smb_com_transaction_change_notify_rsp * pSMBr = NULL; 4201 struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
4202 struct dir_notify_req *dnotify_req;
3848 int bytes_returned; 4203 int bytes_returned;
3849 4204
3850 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid)); 4205 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
@@ -3877,6 +4232,22 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
3877 (struct smb_hdr *) pSMBr, &bytes_returned, -1); 4232 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
3878 if (rc) { 4233 if (rc) {
3879 cFYI(1, ("Error in Notify = %d", rc)); 4234 cFYI(1, ("Error in Notify = %d", rc));
4235 } else {
4236 /* Add file to outstanding requests */
4237 dnotify_req = (struct dir_notify_req *) kmalloc(
4238 sizeof(struct dir_notify_req), GFP_KERNEL);
4239 dnotify_req->Pid = pSMB->hdr.Pid;
4240 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
4241 dnotify_req->Mid = pSMB->hdr.Mid;
4242 dnotify_req->Tid = pSMB->hdr.Tid;
4243 dnotify_req->Uid = pSMB->hdr.Uid;
4244 dnotify_req->netfid = netfid;
4245 dnotify_req->pfile = pfile;
4246 dnotify_req->filter = filter;
4247 dnotify_req->multishot = multishot;
4248 spin_lock(&GlobalMid_Lock);
4249 list_add_tail(&dnotify_req->lhead, &GlobalDnotifyReqList);
4250 spin_unlock(&GlobalMid_Lock);
3880 } 4251 }
3881 cifs_buf_release(pSMB); 4252 cifs_buf_release(pSMB);
3882 return rc; 4253 return rc;