bk://cifs.bkbits.net/linux-2.5cifs stevef@stevef95.austin.ibm.com|ChangeSet|20050126233051|51837 stevef # This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2005/01/28 14:28:52-08:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-cifs # # fs/cifs/connect.c # 2005/01/28 14:28:47-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/01/26 17:30:51-06:00 stevef@stevef95.austin.ibm.com # [CIFS] Add support for updating Windows NT times/dates (part 1) # # Signed-off-by: Steve French (sfrench@us.ibm.com) # # fs/cifs/inode.c # 2005/01/26 17:30:40-06:00 stevef@stevef95.austin.ibm.com +5 -6 # Add support for updating Windows NT times/dates # # fs/cifs/cifssmb.c # 2005/01/26 17:30:40-06:00 stevef@stevef95.austin.ibm.com +6 -3 # Add support for updating Windows NT times/dates # # fs/cifs/cifspdu.h # 2005/01/26 17:30:40-06:00 stevef@stevef95.austin.ibm.com +25 -10 # Add support for updating Windows NT times/dates # # ChangeSet # 2005/01/21 12:19:55-08:00 akpm@bix.(none) # Merge bk://cifs.bkbits.net/linux-2.5cifs # into bix.(none):/usr/src/bk-cifs # # fs/cifs/connect.c # 2005/01/21 12:19:51-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/01/20 21:37:57-06:00 sfrench@sambaltcdom.austin.ibm.com # [CIFS] misc cleanup - compare pointers to NULL not zero # # Signed-off-by: Steve French (sfrench@us.ibm.com) # # fs/cifs/connect.c # 2005/01/20 21:37:49-06:00 sfrench@sambaltcdom.austin.ibm.com +7 -7 # compare pointers to NULL not zero # # fs/cifs/cifssmb.c # 2005/01/20 21:37:49-06:00 sfrench@sambaltcdom.austin.ibm.com +3 -3 # compare pointers to NULL not zero # # fs/cifs/asn1.c # 2005/01/20 21:37:49-06:00 sfrench@sambaltcdom.austin.ibm.com +1 -1 # compare pointers to NULL not zero # # ChangeSet # 2005/01/18 01:39:33-08:00 akpm@bix.(none) # Merge bk://cifs.bkbits.net/linux-2.5cifs # into bix.(none):/usr/src/bk-cifs # # fs/cifs/file.c # 2005/01/18 01:39:29-08:00 akpm@bix.(none) +0 -0 # Auto merged # # fs/cifs/connect.c # 2005/01/18 01:39:29-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/01/17 20:08:33-06:00 sfrench@sambaltcdom.austin.ibm.com # [CIFS] Fix length check for short smbs in cifs demultiplexing and remove unneeded debug messages # # Signed-off-by: Steve French (sfrench@us.ibm.com) # # fs/cifs/connect.c # 2005/01/17 20:08:24-06:00 sfrench@sambaltcdom.austin.ibm.com +2 -4 # Fix length check for short smbs in cifs demultiplexing. Remove unneeded debug messages # # ChangeSet # 2005/01/17 08:36:45-06:00 sfrench@sambaltcdom.austin.ibm.com # [CIFS] get rid of tcp peek usage on cifs socket. Makes more sense to read normally # first four bytes off the socket (then read the rest of the frame) rather than peek # first few bytes then read because we were having to retry the peek multiple times # when peek would return less than four bytes and four bytes is the minimum we # ever get. # # Signed-off-by: Steve French (sfrench@us.ibm.com) # # fs/cifs/transport.c # 2005/01/17 08:36:36-06:00 sfrench@sambaltcdom.austin.ibm.com +66 -1 # get rid of tcp peek usage on cifs socket # # fs/cifs/connect.c # 2005/01/17 08:36:36-06:00 sfrench@sambaltcdom.austin.ibm.com +27 -59 # Add new send function (part 1) to avoid extra memcopy in smb sending # # ChangeSet # 2005/01/17 08:29:15-06:00 sfrench@sambaltcdom.austin.ibm.com # [CIFS] remove old cifs_readdir routine # # Signed-off-by: Steve French (sfrench@us.ibm.com) # # fs/cifs/readdir.c # 2005/01/17 08:29:06-06:00 sfrench@sambaltcdom.austin.ibm.com +3 -3 # remove old readdir routines # # fs/cifs/file.c # 2005/01/17 08:29:06-06:00 sfrench@sambaltcdom.austin.ibm.com +5 -598 # remove old readdir routines # # fs/cifs/CHANGES # 2005/01/17 08:29:06-06:00 sfrench@sambaltcdom.austin.ibm.com +2 -1 # Update cifs changelog # # ChangeSet # 2005/01/09 22:41:05-08:00 akpm@bix.(none) # Merge bk://cifs.bkbits.net/linux-2.5cifs # into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifsfs.c # 2005/01/09 22:41:01-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/01/09 08:20:07-08:00 cifs.adm@bkbits.net # Merge bk://linux.bkbits.net/linux-2.5 # into bkbits.net:/repos/c/cifs/linux-2.5cifs # # fs/cifs/cifsfs.c # 2005/01/09 08:20:01-08:00 cifs.adm@bkbits.net +0 -0 # Auto merged # # ChangeSet # 2005/01/08 18:40:59-08:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-cifs # # fs/cifs/cifsfs.c # 2005/01/08 18:40:55-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/01/05 15:09:34-08:00 akpm@bix.(none) # Merge bk://cifs.bkbits.net/linux-2.5cifs # into bix.(none):/usr/src/bk-cifs # # fs/cifs/file.c # 2005/01/05 15:09:30-08:00 akpm@bix.(none) +0 -0 # Auto merged # # fs/cifs/connect.c # 2005/01/05 15:09:29-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/01/05 15:06:36-08:00 cifs.adm@bkbits.net # Merge bk://linux.bkbits.net/linux-2.5 # into bkbits.net:/repos/c/cifs/linux-2.5cifs # # fs/cifs/file.c # 2005/01/05 15:06:29-08:00 cifs.adm@bkbits.net +0 -0 # Auto merged # # fs/cifs/connect.c # 2005/01/05 15:06:28-08:00 cifs.adm@bkbits.net +0 -0 # Auto merged # # ChangeSet # 2005/01/04 22:35:03-08:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-cifs # # fs/cifs/file.c # 2005/01/04 22:34:59-08:00 akpm@bix.(none) +0 -0 # Auto merged # # fs/cifs/connect.c # 2005/01/04 22:34:58-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/01/04 18:11:57-06:00 stevef@stevef95.austin.ibm.com # [CIFS] Fix default mode on cifs module parms in sysfs # # Pointed out by Domen Puncer # # Signed-off-by: Steve French (sfrench@us.ibm.com) # # fs/cifs/cifsfs.h # 2005/01/04 18:11:46-06:00 stevef@stevef95.austin.ibm.com +1 -1 # update cifs contributors # # fs/cifs/cifsfs.c # 2005/01/04 18:11:46-06:00 stevef@stevef95.austin.ibm.com +4 -4 # Fix default mode on cifs module parms in sysfs # # fs/cifs/CHANGES # 2005/01/04 18:11:46-06:00 stevef@stevef95.austin.ibm.com +6 -1 # update to cifs version 1.29 # # fs/cifs/AUTHORS # 2005/01/04 18:11:46-06:00 stevef@stevef95.austin.ibm.com +2 -0 # update cifs contributors # # ChangeSet # 2004/12/22 12:11:36-06:00 stevef@smfhome.smfdom # [CIFS] Fix whitespace # # Signed-off-by: Steve French (sfrench@us.ibm.com) # # fs/cifs/cifssmb.c # 2004/12/22 12:11:27-06:00 stevef@smfhome.smfdom +3 -3 # Fix whitespace # # ChangeSet # 2004/12/21 11:08:59-06:00 sfrench@sambaltcdom.austin.ibm.com # [CIFS] Enable reads over 64K by setting large read and write capability at SMB session negotiation # # Signed-off-by: Steve French (sfrench@us.ibm.com) # # fs/cifs/connect.c # 2004/12/21 11:08:51-06:00 sfrench@sambaltcdom.austin.ibm.com +1 -1 # Enable reads over 64K by setting large read and write capability at SMB session negotiation # # ChangeSet # 2004/12/19 10:19:16-06:00 sfrench@sambaltcdom.austin.ibm.com # [CIFS] Fix set of mount option rsize so it can be set above negotiated buffer size. # # Signed-off-by: Steve French (sfrench@us.ibm.com) # # fs/cifs/connect.c # 2004/12/19 10:19:08-06:00 sfrench@sambaltcdom.austin.ibm.com +1 -1 # Fix set of mount option rsize so it can be set above negotiated buffer size. # # ChangeSet # 2004/12/18 16:01:31-06:00 sfrench@sambaltcdom.austin.ibm.com # check rc of copy_to_user (pointed out by John Cherry) # fix wsize mount parm so it works to control writes # allow reads bigger than 64K (although Samba does not handle them yet). # # Signed-off-by: Steve French (sfrench@us.ibm.com) # # fs/cifs/file.c # 2004/12/18 16:01:12-06:00 sfrench@sambaltcdom.austin.ibm.com +14 -10 # check rc of copy_to_user to fix warning pointed out by John Cherry # # fs/cifs/connect.c # 2004/12/18 16:01:12-06:00 sfrench@sambaltcdom.austin.ibm.com +2 -2 # adjust wsize default, and fix wsize mount parm so it is used # # fs/cifs/cifssmb.c # 2004/12/18 16:01:12-06:00 sfrench@sambaltcdom.austin.ibm.com +39 -22 # misc large read/write fixes, for sizes > 64K # # fs/cifs/cifspdu.h # 2004/12/18 16:01:11-06:00 sfrench@sambaltcdom.austin.ibm.com +2 -2 # Definition of write frame missing high offset of count field. # diff -Nru a/fs/cifs/AUTHORS b/fs/cifs/AUTHORS --- a/fs/cifs/AUTHORS 2005-01-28 14:30:34 -08:00 +++ b/fs/cifs/AUTHORS 2005-01-28 14:30:34 -08:00 @@ -25,6 +25,8 @@ Richard Hughes Yury Umanets Mark Hamzy +Domen Puncer +Jesper Juhl Test case and Bug Report contributors ------------------------------------- diff -Nru a/fs/cifs/CHANGES b/fs/cifs/CHANGES --- a/fs/cifs/CHANGES 2005-01-28 14:30:34 -08:00 +++ b/fs/cifs/CHANGES 2005-01-28 14:30:34 -08:00 @@ -1,3 +1,8 @@ +Version 1.29 +------------ +Fix default mode in sysfs of cifs module parms. Remove old readdir routine. +Fix capabilities flags for large readx so as to allow reads larger than 64K. + Version 1.28 ------------ Add module init parm for large SMB buffer size (to allow it to be changed @@ -7,7 +12,8 @@ SpnegoNegotiated returning invalid error. Fix case to retry better when peek returns from 1 to 3 bytes on socket which should have more data. Fixed path based calls (such as cifs lookup) to handle path names -longer than 530 (now can handle PATH_MAX). +longer than 530 (now can handle PATH_MAX). Fix pass through authentication +from Samba server to DC (Samba required dummy LM password). Version 1.27 ------------ diff -Nru a/fs/cifs/asn1.c b/fs/cifs/asn1.c --- a/fs/cifs/asn1.c 2005-01-28 14:30:34 -08:00 +++ b/fs/cifs/asn1.c 2005-01-28 14:30:34 -08:00 @@ -210,7 +210,7 @@ { unsigned char ch; - if (eoc == 0) { + if (eoc == NULL) { if (!asn1_octet_decode(ctx, &ch)) return 0; diff -Nru a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c --- a/fs/cifs/cifsfs.c 2005-01-28 14:30:34 -08:00 +++ b/fs/cifs/cifsfs.c 2005-01-28 14:30:34 -08:00 @@ -59,16 +59,16 @@ unsigned int sign_CIFS_PDUs = 1; struct task_struct * oplockThread = NULL; unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE; -module_param(CIFSMaxBufSize, int, CIFS_MAX_MSGSIZE); +module_param(CIFSMaxBufSize, int, 0); MODULE_PARM_DESC(CIFSMaxBufSize,"Network buffer size (not including header). Default: 16384 Range: 8192 to 130048"); unsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL; -module_param(cifs_min_rcv, int, CIFS_MIN_RCV_POOL); +module_param(cifs_min_rcv, int, 0); MODULE_PARM_DESC(cifs_min_rcv,"Network buffers in pool. Default: 4 Range: 1 to 64"); unsigned int cifs_min_small = 30; -module_param(cifs_min_small, int, 30); +module_param(cifs_min_small, int, 0); MODULE_PARM_DESC(cifs_small_rcv,"Small network buffers in pool. Default: 30 Range: 2 to 256"); unsigned int cifs_max_pending = CIFS_MAX_REQ; -module_param(cifs_max_pending, int, CIFS_MAX_REQ); +module_param(cifs_max_pending, int, 0); MODULE_PARM_DESC(cifs_max_pending,"Simultaneous requests to server. Default: 50 Range: 2 to 256"); diff -Nru a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h --- a/fs/cifs/cifsfs.h 2005-01-28 14:30:34 -08:00 +++ b/fs/cifs/cifsfs.h 2005-01-28 14:30:34 -08:00 @@ -90,5 +90,5 @@ size_t, int); extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); -#define CIFS_VERSION "1.28" +#define CIFS_VERSION "1.29" #endif /* _CIFSFS_H */ diff -Nru a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h --- a/fs/cifs/cifspdu.h 2005-01-28 14:30:34 -08:00 +++ b/fs/cifs/cifspdu.h 2005-01-28 14:30:34 -08:00 @@ -568,7 +568,6 @@ #define SMB_SHARE_IS_IN_DFS 0x0002 typedef struct smb_com_logoff_andx_req { - struct smb_hdr hdr; /* wct = 2 */ __u8 AndXCommand; __u8 AndXReserved; @@ -695,7 +694,8 @@ __le16 AndXOffset; __le16 Count; __le16 Remaining; - __le32 Reserved; + __le16 CountHigh; + __u16 Reserved; __u16 ByteCount; } WRITE_RSP; @@ -1592,17 +1592,32 @@ char LinkDest[1]; } FILE_UNIX_LINK_INFO; /* level 0x201 QPathInfo */ +/* The following three structures are needed only for + setting time to NT4 and some older servers via + the primitive DOS time format */ +typedef struct { + __u16 Day:5; + __u16 Month:4; + __u16 Year:7; +} SMB_DATE; + typedef struct { - __u16 CreationDate; - __u16 CreationTime; - __u16 LastAccessDate; - __u16 LastAccessTime; - __u16 LastWriteDate; - __u16 LastWriteTime; - __u32 DataSize; /* File Size (EOF) */ - __u32 AllocationSize; - __u16 Attributes; /* verify not u32 */ - __u32 EASize; + __u16 TwoSeconds:5; + __u16 Minutes:6; + __u16 Hours:5; +} SMB_TIME; + +typedef struct { + __le16 CreationDate; /* SMB Date see above */ + __le16 CreationTime; /* SMB Time */ + __le16 LastAccessDate; + __le16 LastAccessTime; + __le16 LastWriteDate; + __le16 LastWriteTime; + __le32 DataSize; /* File Size (EOF) */ + __le32 AllocationSize; + __le16 Attributes; /* verify not u32 */ + __le32 EASize; } FILE_INFO_STANDARD; /* level 1 SetPath/FileInfo */ typedef struct { diff -Nru a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c --- a/fs/cifs/cifssmb.c 2005-01-28 14:30:34 -08:00 +++ b/fs/cifs/cifssmb.c 2005-01-28 14:30:34 -08:00 @@ -154,7 +154,7 @@ return rc; *request_buf = cifs_small_buf_get(); - if (*request_buf == 0) { + if (*request_buf == NULL) { /* BB should we add a retry in here if not a writepage? */ return -ENOMEM; } @@ -246,7 +246,7 @@ return rc; *request_buf = cifs_buf_get(); - if (*request_buf == 0) { + if (*request_buf == NULL) { /* BB should we add a retry in here if not a writepage? */ return -ENOMEM; } @@ -448,7 +448,7 @@ return 0; } - if((tcon->ses == 0) || (tcon->ses->server == 0)) { + if((tcon->ses == NULL) || (tcon->ses->server == NULL)) { up(&tcon->tconSem); return -EIO; } @@ -802,6 +802,8 @@ char *pReadData = NULL; int bytes_returned; + cFYI(1,("Reading %d bytes on fid %d",count,netfid)); + *nbytes = 0; rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -817,8 +819,8 @@ pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF); pSMB->OffsetHigh = cpu_to_le32(lseek >> 32); pSMB->Remaining = 0; - pSMB->MaxCount = cpu_to_le16(count); - pSMB->MaxCountHigh = 0; + pSMB->MaxCount = cpu_to_le16(count & 0xFFFF); + pSMB->MaxCountHigh = cpu_to_le32(count >> 16); pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, @@ -826,8 +828,11 @@ if (rc) { cERROR(1, ("Send error in read = %d", rc)); } else { - __u16 data_length = le16_to_cpu(pSMBr->DataLength); + int data_length = le16_to_cpu(pSMBr->DataLengthHigh); + data_length = data_length << 16; + data_length += le16_to_cpu(pSMBr->DataLength); *nbytes = data_length; + /*check that DataLength would not go beyond end of SMB */ if ((data_length > CIFSMaxBufSize) || (data_length > count)) { @@ -868,9 +873,10 @@ WRITE_REQ *pSMB = NULL; WRITE_RSP *pSMBr = NULL; int bytes_returned; - unsigned bytes_sent; + __u32 bytes_sent; __u16 byte_count; + /* cFYI(1,("write at %lld %d bytes",offset,count));*/ rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB, (void **) &pSMBr); if (rc) @@ -886,31 +892,41 @@ pSMB->Reserved = 0xFFFFFFFF; pSMB->WriteMode = 0; pSMB->Remaining = 0; - /* BB can relax this if buffer is big enough in some cases - ie we can - send more if LARGE_WRITE_X capability returned by the server and if + + /* Can increase buffer size if buffer is big enough in some cases - ie we + can send more if LARGE_WRITE_X capability returned by the server and if our buffer is big enough or if we convert to iovecs on socket writes and eliminate the copy to the CIFS buffer */ - bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF; + if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) { + bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count); + } else { + bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) + & ~0xFF; + } + if (bytes_sent > count) bytes_sent = count; - pSMB->DataLengthHigh = 0; pSMB->DataOffset = cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4); - if(buf) + if(buf) memcpy(pSMB->Data,buf,bytes_sent); - else if(ubuf) - copy_from_user(pSMB->Data,ubuf,bytes_sent); - else { + else if(ubuf) { + if(copy_from_user(pSMB->Data,ubuf,bytes_sent)) { + if(pSMB) + cifs_buf_release(pSMB); + return -EFAULT; + } + } else { /* No buffer */ if(pSMB) cifs_buf_release(pSMB); return -EINVAL; } - byte_count = bytes_sent + 1 /* pad */ ; - pSMB->DataLengthLow = cpu_to_le16(bytes_sent); - pSMB->DataLengthHigh = 0; - pSMB->hdr.smb_buf_length += byte_count; + byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */ + pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF); + pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16); + pSMB->hdr.smb_buf_length += bytes_sent+1; pSMB->ByteCount = cpu_to_le16(byte_count); rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, @@ -918,8 +934,11 @@ if (rc) { cFYI(1, ("Send error in write = %d", rc)); *nbytes = 0; - } else - *nbytes = le16_to_cpu(pSMBr->Count); + } else { + *nbytes = le16_to_cpu(pSMBr->CountHigh); + *nbytes = (*nbytes) << 16; + *nbytes += le16_to_cpu(pSMBr->Count); + } if (pSMB) cifs_buf_release(pSMB); @@ -1913,14 +1932,13 @@ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX - /* BB fixme find define for this maxpathcomponent */ , nls_codepage); name_len++; /* trailing null */ name_len *= 2; pSMB->FileName[name_len] = 0; pSMB->FileName[name_len+1] = 0; } else { /* BB improve the check for buffer overruns BB */ - name_len = strnlen(searchName, PATH_MAX /* BB fixme */); + name_len = strnlen(searchName, PATH_MAX); name_len++; /* trailing null */ strncpy(pSMB->FileName, searchName, name_len); } @@ -1996,10 +2014,9 @@ (void **) &pSMBr); if (rc) return rc; - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX - /* BB fixme find define for this maxpathcomponent */ , nls_codepage); name_len++; /* trailing null */ name_len *= 2; @@ -2051,9 +2068,9 @@ setACLerrorExit: if (pSMB) cifs_buf_release(pSMB); - if (rc == -EAGAIN) + if (rc == -EAGAIN) goto setAclRetry; - return rc; + return rc; } #endif @@ -2072,7 +2089,7 @@ int name_len; __u16 params, byte_count; -/* cFYI(1, ("In QPathInfo path %s", searchName)); */ /* BB fixme BB */ +/* cFYI(1, ("In QPathInfo path %s", searchName)); */ QPathInfoRetry: rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -3574,10 +3591,11 @@ int CIFSSMBSetTimesLegacy(int xid, struct cifsTconInfo *tcon, char *fileName, - FILE_INFO_STANDARD * data, const struct nls_table *nls_codepage) + FILE_BASIC_INFO * data, const struct nls_table *nls_codepage) { TRANSACTION2_SPI_REQ *pSMB = NULL; TRANSACTION2_SPI_RSP *pSMBr = NULL; + FILE_INFO_STANDARD *pfinfo; int name_len; int rc = 0; int bytes_returned = 0; @@ -3607,7 +3625,6 @@ /* BB fixme - we have to map to FILE_STANDARD_INFO (level 1 info in parent function, from the better and ususal FILE_BASIC_INFO */ params = 6 + name_len; - count = sizeof (FILE_INFO_STANDARD); pSMB->MaxParameterCount = cpu_to_le16(2); pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ pSMB->MaxSetupCount = 0; @@ -3619,11 +3636,15 @@ InformationLevel) - 4; offset = param_offset + params; data_offset = (char *) (&pSMB->hdr.Protocol) + offset; + pfinfo = (FILE_INFO_STANDARD *)data_offset; + /* BB add conversion for FILE_BASIC_INFO data struct to + FILE_INFO_STANDARD finfo struct */ pSMB->ParameterOffset = cpu_to_le16(param_offset); pSMB->DataOffset = cpu_to_le16(offset); pSMB->SetupCount = 1; pSMB->Reserved3 = 0; pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION); + count = sizeof(FILE_INFO_STANDARD); byte_count = 3 /* pad */ + params + count; pSMB->DataCount = cpu_to_le16(count); @@ -3633,7 +3654,6 @@ pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD); pSMB->Reserved4 = 0; pSMB->hdr.smb_buf_length += byte_count; - memcpy(data_offset, data, sizeof (FILE_INFO_STANDARD)); pSMB->ByteCount = cpu_to_le16(byte_count); rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); diff -Nru a/fs/cifs/connect.c b/fs/cifs/connect.c --- a/fs/cifs/connect.c 2005-01-28 14:30:34 -08:00 +++ b/fs/cifs/connect.c 2005-01-28 14:30:34 -08:00 @@ -210,7 +210,7 @@ current->flags |= PF_MEMALLOC; server->tsk = current; /* save process info to wake at shutdown */ cFYI(1, ("Demultiplex PID: %d", current->pid)); - write_lock(&GlobalSMBSeslock); + write_lock(&GlobalSMBSeslock); atomic_inc(&tcpSesAllocCount); length = tcpSesAllocCount.counter; write_unlock(&GlobalSMBSeslock); @@ -233,17 +233,12 @@ continue; } iov.iov_base = smb_buffer; - iov.iov_len = sizeof (struct smb_hdr) - 1; - /* 1 byte less above since wct is not always returned in error cases */ + iov.iov_len = 4; smb_msg.msg_control = NULL; smb_msg.msg_controllen = 0; - length = kernel_recvmsg(csocket, &smb_msg, - &iov, 1, - sizeof (struct smb_hdr) - - 1 /* RFC1001 header and SMB header */ , - MSG_PEEK /* flags see socket.h */ ); + &iov, 1, 4, 0 /* BB see socket.h flags */); if(server->tcpStatus == CifsExiting) { break; @@ -253,8 +248,7 @@ cFYI(1,("call to reconnect done")); csocket = server->ssocket; continue; - } else if ((length == -ERESTARTSYS) || (length == -EAGAIN) - || ((length > 0) && (length <= 3)) ) { + } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1); /* minimum sleep to prevent looping allowing socket to clear and app threads to set @@ -277,26 +271,16 @@ csocket = server->ssocket; wake_up(&server->response_q); continue; - } - - pdu_length = 4 + ntohl(smb_buffer->smb_buf_length); + } else if (length > 3) { + pdu_length = ntohl(smb_buffer->smb_buf_length); /* Only read pdu_length after below checks for too short (due to e.g. int overflow) and too long ie beyond end of buf */ - cFYI(1, ("Peek length rcvd: 0x%x beginning 0x%x)", length, pdu_length)); + cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4)); - temp = (char *) smb_buffer; - if (length > 3) { + temp = (char *) smb_buffer; if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) { - iov.iov_base = smb_buffer; - iov.iov_len = 4; - length = kernel_recvmsg(csocket, &smb_msg, - &iov, 1, 4, 0); cFYI(0,("Received 4 byte keep alive packet")); } else if (temp[0] == (char) RFC1002_POSITIVE_SESSION_RESPONSE) { - iov.iov_base = smb_buffer; - iov.iov_len = 4; - length = kernel_recvmsg(csocket, &smb_msg, - &iov, 1, 4, 0); cFYI(1,("Good RFC 1002 session rsp")); } else if ((temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) && (length == 5)) { @@ -330,38 +314,22 @@ csocket = server->ssocket; continue; } else { - if (length < 16) { - /* We can not validate the SMB unless - at least this much of SMB available - so give the socket time to copy - a few more bytes and retry */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(10); - continue; - } else if( (pdu_length > - CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) - || (pdu_length < - sizeof (struct smb_hdr) - 1) - || (checkSMBhdr - (smb_buffer, smb_buffer->Mid))) { + if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) + || (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) { cERROR(1, - ("Invalid size or format for SMB found with length %d and pdu_length %d", - length, pdu_length)); - cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr)+3); - /* could we fix this network corruption by finding next - smb header (instead of killing the session) and - restart reading from next valid SMB found? */ + ("Invalid size SMB length %d and pdu_length %d", + length, pdu_length+4)); cifs_reconnect(server); csocket = server->ssocket; + wake_up(&server->response_q); continue; - } else { /* length ok */ - + } else { /* length ok */ length = 0; - iov.iov_base = smb_buffer; + iov.iov_base = 4 + (char *)smb_buffer; iov.iov_len = pdu_length; for (total_read = 0; total_read < pdu_length; - total_read += length) { + total_read += length) { length = kernel_recvmsg(csocket, &smb_msg, &iov, 1, pdu_length - total_read, 0); @@ -371,14 +339,16 @@ pdu_length - total_read)); cifs_reconnect(server); csocket = server->ssocket; + wake_up(&server->response_q); continue; } } + length += 4; /* account for rfc1002 hdr */ } dump_smb(smb_buffer, length); if (checkSMB - (smb_buffer, smb_buffer->Mid, total_read)) { + (smb_buffer, smb_buffer->Mid, total_read+4)) { cERROR(1, ("Bad SMB Received ")); continue; } @@ -410,17 +380,13 @@ } } } else { - cFYI(0, - ("Frame less than four bytes received %d bytes long.", + cFYI(1, + ("Frame less than four bytes received %d bytes long.", length)); - if (length > 0) { - length = kernel_recvmsg(csocket, &smb_msg, - &iov, 1, - length, 0); /* throw away junk frame */ - cFYI(1, - (" with junk 0x%x in it ", - *(__u32 *) smb_buffer)); - } + cifs_reconnect(server); + csocket = server->ssocket; + wake_up(&server->response_q); + continue; } } spin_lock(&GlobalMid_Lock); @@ -845,7 +811,7 @@ return 1; } } - if(vol->UNCip == 0) + if(vol->UNCip == NULL) vol->UNCip = &vol->UNC[2]; return 0; @@ -1409,14 +1375,14 @@ /* search for existing tcon to this server share */ if (!rc) { - if((volume_info.rsize) && (volume_info.rsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf)) + if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize)) cifs_sb->rsize = volume_info.rsize; else cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */ - if((volume_info.wsize) && (volume_info.wsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf)) + if((volume_info.wsize) && (volume_info.wsize <= CIFSMaxBufSize)) cifs_sb->wsize = volume_info.wsize; else - cifs_sb->wsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */ + cifs_sb->wsize = CIFSMaxBufSize; /* default */ if(cifs_sb->rsize < PAGE_CACHE_SIZE) { cifs_sb->rsize = PAGE_CACHE_SIZE; cERROR(1,("Attempt to set readsize for mount to less than one page (4096)")); @@ -1504,7 +1470,7 @@ /* If find_unc succeeded then rc == 0 so we can not end */ if (tcon) /* up accidently freeing someone elses tcon struct */ tconInfoFree(tcon); - if (existingCifsSes == 0) { + if (existingCifsSes == NULL) { if (pSesInfo) { if ((pSesInfo->server) && (pSesInfo->status == CifsGood)) { @@ -1575,7 +1541,7 @@ user = ses->userName; domain = ses->domainName; smb_buffer = cifs_buf_get(); - if (smb_buffer == 0) { + if (smb_buffer == NULL) { return -ENOMEM; } smb_buffer_response = smb_buffer; @@ -1592,7 +1558,7 @@ if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; - capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS; + capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | CAP_LARGE_WRITE_X | CAP_LARGE_READ_X; if (ses->capabilities & CAP_UNICODE) { smb_buffer->Flags2 |= SMBFLG2_UNICODE; capabilities |= CAP_UNICODE; @@ -1828,7 +1794,7 @@ domain = ses->domainName; smb_buffer = cifs_buf_get(); - if (smb_buffer == 0) { + if (smb_buffer == NULL) { return -ENOMEM; } smb_buffer_response = smb_buffer; @@ -2093,7 +2059,7 @@ domain = ses->domainName; *pNTLMv2_flag = FALSE; smb_buffer = cifs_buf_get(); - if (smb_buffer == 0) { + if (smb_buffer == NULL) { return -ENOMEM; } smb_buffer_response = smb_buffer; @@ -2435,7 +2401,7 @@ user = ses->userName; domain = ses->domainName; smb_buffer = cifs_buf_get(); - if (smb_buffer == 0) { + if (smb_buffer == NULL) { return -ENOMEM; } smb_buffer_response = smb_buffer; @@ -2809,7 +2775,7 @@ return -EIO; smb_buffer = cifs_buf_get(); - if (smb_buffer == 0) { + if (smb_buffer == NULL) { return -ENOMEM; } smb_buffer_response = smb_buffer; diff -Nru a/fs/cifs/file.c b/fs/cifs/file.c --- a/fs/cifs/file.c 2005-01-28 14:30:34 -08:00 +++ b/fs/cifs/file.c 2005-01-28 14:30:34 -08:00 @@ -35,8 +35,6 @@ #include "cifs_debug.h" #include "cifs_fs_sb.h" -extern int cifs_readdir2(struct file *file, void *direntry, filldir_t filldir); /* BB removeme BB */ - int cifs_open(struct inode *inode, struct file *file) { @@ -680,10 +678,10 @@ } rc = CIFSSMBWrite(xid, pTcon, - open_file->netfid, - write_size - total_written, *poffset, - &bytes_written, - NULL, write_data + total_written, long_op); + open_file->netfid, + min_t(const int,cifs_sb->wsize,write_size - total_written), + *poffset, &bytes_written, + NULL, write_data + total_written, long_op); } if (rc || (bytes_written == 0)) { if (total_written) @@ -800,10 +798,10 @@ } rc = CIFSSMBWrite(xid, pTcon, - open_file->netfid, - write_size - total_written, *poffset, - &bytes_written, - write_data + total_written, NULL, long_op); + open_file->netfid, + min_t(const int,cifs_sb->wsize,write_size - total_written), + *poffset,&bytes_written, + write_data + total_written, NULL, long_op); } if (rc || (bytes_written == 0)) { if (total_written) @@ -945,7 +943,11 @@ int xid; xid = GetXid(); -/* call 16K write then Setpageuptodate */ + + /* Find contiguous pages then iterate through repeating */ +/* call 16K write then Setpageuptodate or if LARGE_WRITE_X +support then send larger writes via kevec so as to eliminate +a memcpy */ FreeXid(xid); return rc; } @@ -1145,7 +1147,6 @@ if((file->f_flags & O_ACCMODE) == O_WRONLY) { cFYI(1,("attempting read on write only file instance")); } - for (total_read = 0,current_offset=read_data; read_size > total_read; total_read += bytes_read,current_offset+=bytes_read) { current_read_size = min_t(const int,read_size - total_read,cifs_sb->rsize); @@ -1165,8 +1166,12 @@ &bytes_read, &smb_read_data); pSMBr = (struct smb_com_read_rsp *)smb_read_data; - copy_to_user(current_offset,smb_read_data + 4/* RFC1001 hdr*/ - + le16_to_cpu(pSMBr->DataOffset), bytes_read); + if(copy_to_user(current_offset,smb_read_data + 4/* RFC1001 hdr*/ + + le16_to_cpu(pSMBr->DataOffset), bytes_read)) { + rc = -EFAULT; + FreeXid(xid); + return rc; + } if(smb_read_data) { cifs_buf_release(smb_read_data); smb_read_data = NULL; @@ -1800,600 +1805,6 @@ return rc; } -static void reset_resume_key(struct file * dir_file, - unsigned char * filename, - unsigned int len,int Unicode,struct nls_table * nls_tab) { - struct cifsFileInfo *cifsFile; - - cifsFile = (struct cifsFileInfo *)dir_file->private_data; - if(cifsFile == NULL) - return; - if(cifsFile->search_resume_name) { - kfree(cifsFile->search_resume_name); - } - - if(Unicode) - len *= 2; - cifsFile->resume_name_length = len; - - cifsFile->search_resume_name = - kmalloc(cifsFile->resume_name_length, GFP_KERNEL); - - if(cifsFile->search_resume_name == NULL) { - cERROR(1,("failed new resume key allocate, length %d", - cifsFile->resume_name_length)); - return; - } - if(Unicode) - cifs_strtoUCS((wchar_t *) cifsFile->search_resume_name, - filename, len, nls_tab); - else - memcpy(cifsFile->search_resume_name, filename, - cifsFile->resume_name_length); - cFYI(1,("Reset resume key to: %s with len %d",filename,len)); - return; -} - - - -static int -cifs_filldir(struct qstr *pqstring, FILE_DIRECTORY_INFO * pfindData, - struct file *file, filldir_t filldir, void *direntry) -{ - struct inode *tmp_inode; - struct dentry *tmp_dentry; - int object_type,rc; - - pqstring->name = pfindData->FileName; - /* pqstring->len is already set by caller */ - - rc = construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry); - if((tmp_inode == NULL) || (tmp_dentry == NULL)) { - return -ENOMEM; - } - fill_in_inode(tmp_inode, pfindData, &object_type); - if(rc) { - /* We have no reliable way to get inode numbers - from servers w/o Unix extensions yet so we can not set - i_ino from pfindData yet */ - - /* new inode created, let us hash it */ - insert_inode_hash(tmp_inode); - } /* else if inode number changed do we rehash it? */ - rc = filldir(direntry, pfindData->FileName, pqstring->len, file->f_pos, - tmp_inode->i_ino, object_type); - if(rc) { - /* due to readdir error we need to recalculate resume - key so next readdir will restart on right entry */ - cFYI(1,("Error %d on filldir of %s",rc ,pfindData->FileName)); - } - dput(tmp_dentry); - return rc; -} - -static int -cifs_filldir_unix(struct qstr *pqstring, - FILE_UNIX_INFO * pUnixFindData, struct file *file, - filldir_t filldir, void *direntry) -{ - struct inode *tmp_inode; - struct dentry *tmp_dentry; - int object_type, rc; - - pqstring->name = pUnixFindData->FileName; - pqstring->len = strnlen(pUnixFindData->FileName, MAX_PATHCONF); - - rc = construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry); - if((tmp_inode == NULL) || (tmp_dentry == NULL)) { - return -ENOMEM; - } - if(rc) { - struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb); - - if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { - tmp_inode->i_ino = - (unsigned long)pUnixFindData->UniqueId; - } - insert_inode_hash(tmp_inode); - } /* else if i_ino has changed should we rehash it? */ - unix_fill_in_inode(tmp_inode, pUnixFindData, &object_type); - rc = filldir(direntry, pUnixFindData->FileName, pqstring->len, - file->f_pos, tmp_inode->i_ino, object_type); - if(rc) { - /* due to readdir error we need to recalculate resume - key so next readdir will restart on right entry */ - cFYI(1,("Error %d on filldir of %s",rc ,pUnixFindData->FileName)); - } - dput(tmp_dentry); - return rc; -} - -int -cifs_readdir(struct file *file, void *direntry, filldir_t filldir) -{ - int rc = 0; - int xid; - int Unicode = FALSE; - int UnixSearch = FALSE; - unsigned int bufsize, i; - __u16 searchHandle; - struct cifs_sb_info *cifs_sb; - struct cifsTconInfo *pTcon; - struct cifsFileInfo *cifsFile = NULL; - char *full_path = NULL; - char *data; - struct qstr qstring; - T2_FFIRST_RSP_PARMS findParms; - T2_FNEXT_RSP_PARMS findNextParms; - FILE_DIRECTORY_INFO *pfindData; - FILE_DIRECTORY_INFO *lastFindData; - FILE_UNIX_INFO *pfindDataUnix; - - - /* BB removeme begin */ - if(!experimEnabled) - return cifs_readdir2(file,direntry,filldir); - /* BB removeme end */ - - - xid = GetXid(); - - if(file->f_dentry == NULL) { - rc = -EIO; - FreeXid(xid); - return rc; - } - cifs_sb = CIFS_SB(file->f_dentry->d_sb); - pTcon = cifs_sb->tcon; - bufsize = pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; - if(bufsize > CIFSMaxBufSize) { - rc = -EIO; - FreeXid(xid); - return rc; - } - data = kmalloc(bufsize, GFP_KERNEL); - pfindData = (FILE_DIRECTORY_INFO *) data; - if(data == NULL) { - rc = -ENOMEM; - FreeXid(xid); - return rc; - } - down(&file->f_dentry->d_sb->s_vfs_rename_sem); - full_path = build_wildcard_path_from_dentry(file->f_dentry); - up(&file->f_dentry->d_sb->s_vfs_rename_sem); - - if(full_path == NULL) { - kfree(data); - FreeXid(xid); - return -ENOMEM; - } - cFYI(1, ("Full path: %s start at: %lld ", full_path, file->f_pos)); - - switch ((int) file->f_pos) { - case 0: - if (filldir(direntry, ".", 1, file->f_pos, - file->f_dentry->d_inode->i_ino, DT_DIR) < 0) { - cERROR(1, ("Filldir for current dir failed ")); - break; - } - file->f_pos++; - /* fallthrough */ - case 1: - if (filldir(direntry, "..", 2, file->f_pos, - file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) { - cERROR(1, ("Filldir for parent dir failed ")); - break; - } - file->f_pos++; - /* fallthrough */ - case 2: - if (file->private_data != NULL) { - cifsFile = - (struct cifsFileInfo *) file->private_data; - if (cifsFile->srch_inf.endOfSearch) { - if(cifsFile->srch_inf.emptyDir) { - cFYI(1, ("End of search, empty dir")); - rc = 0; - break; - } - } else { - cifsFile->invalidHandle = TRUE; - CIFSFindClose(xid, pTcon, cifsFile->netfid); - } - if(cifsFile->search_resume_name) { - kfree(cifsFile->search_resume_name); - cifsFile->search_resume_name = NULL; - } - } - rc = CIFSFindFirst(xid, pTcon, full_path, pfindData, - &findParms, cifs_sb->local_nls, - &Unicode, &UnixSearch); - cFYI(1, ("Count: %d End: %d ", - le16_to_cpu(findParms.SearchCount), - le16_to_cpu(findParms.EndofSearch))); - - if (rc == 0) { - __u16 count = le16_to_cpu(findParms.SearchCount); - searchHandle = findParms.SearchHandle; - if(file->private_data == NULL) - file->private_data = - kmalloc(sizeof(struct cifsFileInfo),GFP_KERNEL); - if (file->private_data) { - memset(file->private_data, 0, - sizeof (struct cifsFileInfo)); - cifsFile = - (struct cifsFileInfo *) file->private_data; - cifsFile->netfid = searchHandle; - cifsFile->invalidHandle = FALSE; - init_MUTEX(&cifsFile->fh_sem); - } else { - rc = -ENOMEM; - break; - } - - renew_parental_timestamps(file->f_dentry); - lastFindData = - (FILE_DIRECTORY_INFO *) ((char *) pfindData + - le16_to_cpu(findParms.LastNameOffset)); - if((char *)lastFindData > (char *)pfindData + bufsize) { - cFYI(1,("last search entry past end of packet")); - rc = -EIO; - break; - } - /* Offset of resume key same for levels 257 and 514 */ - cifsFile->srch_inf.resume_key = lastFindData->FileIndex; - if(UnixSearch == FALSE) { - cifsFile->resume_name_length = - le32_to_cpu(lastFindData->FileNameLength); - if(cifsFile->resume_name_length > bufsize - 64) { - cFYI(1,("Illegal resume file name length %d", - cifsFile->resume_name_length)); - rc = -ENOMEM; - break; - } - cifsFile->search_resume_name = - kmalloc(cifsFile->resume_name_length, GFP_KERNEL); - cFYI(1,("Last file: %s with name %d bytes long", - lastFindData->FileName, - cifsFile->resume_name_length)); - if(cifsFile->search_resume_name == NULL) { - rc = -ENOMEM; - break; - } - memcpy(cifsFile->search_resume_name, - lastFindData->FileName, - cifsFile->resume_name_length); - } else { - pfindDataUnix = (FILE_UNIX_INFO *)lastFindData; - if (Unicode == TRUE) { - for(i=0;(pfindDataUnix->FileName[i] - | pfindDataUnix->FileName[i+1]); - i+=2) { - if(i > bufsize-64) - break; - } - cifsFile->resume_name_length = i + 2; - } else { - cifsFile->resume_name_length = - strnlen(pfindDataUnix->FileName, - bufsize-63); - } - if(cifsFile->resume_name_length > bufsize - 64) { - cFYI(1,("Illegal resume file name length %d", - cifsFile->resume_name_length)); - rc = -ENOMEM; - break; - } - cifsFile->search_resume_name = - kmalloc(cifsFile->resume_name_length, GFP_KERNEL); - cFYI(1,("Last file: %s with name %d bytes long", - pfindDataUnix->FileName, - cifsFile->resume_name_length)); - if(cifsFile->search_resume_name == NULL) { - rc = -ENOMEM; - break; - } - memcpy(cifsFile->search_resume_name, - pfindDataUnix->FileName, - cifsFile->resume_name_length); - } - for (i = 2; i < count + 2; i++) { - if (UnixSearch == FALSE) { - __u32 len = le32_to_cpu(pfindData->FileNameLength); - if (Unicode == TRUE) - len = - cifs_strfromUCS_le - (pfindData->FileName, - (wchar_t *) - pfindData->FileName, - len / 2, - cifs_sb->local_nls); - qstring.len = len; - if (((len != 1) - || (pfindData->FileName[0] != '.')) - && ((len != 2) - || (pfindData-> - FileName[0] != '.') - || (pfindData-> - FileName[1] != '.'))) { - if(cifs_filldir(&qstring, - pfindData, - file, filldir, - direntry)) { - /* do not end search if - kernel not ready to take - remaining entries yet */ - reset_resume_key(file, pfindData->FileName,qstring.len, - Unicode, cifs_sb->local_nls); - findParms.EndofSearch = 0; - break; - } - file->f_pos++; - } - } else { /* UnixSearch */ - pfindDataUnix = - (FILE_UNIX_INFO *) pfindData; - if (Unicode == TRUE) - qstring.len = - cifs_strfromUCS_le - (pfindDataUnix->FileName, - (wchar_t *) - pfindDataUnix->FileName, - MAX_PATHCONF, - cifs_sb->local_nls); - else - qstring.len = - strnlen(pfindDataUnix-> - FileName, - MAX_PATHCONF); - if (((qstring.len != 1) - || (pfindDataUnix-> - FileName[0] != '.')) - && ((qstring.len != 2) - || (pfindDataUnix-> - FileName[0] != '.') - || (pfindDataUnix-> - FileName[1] != '.'))) { - if(cifs_filldir_unix(&qstring, - pfindDataUnix, - file, - filldir, - direntry)) { - /* do not end search if - kernel not ready to take - remaining entries yet */ - findParms.EndofSearch = 0; - reset_resume_key(file, pfindDataUnix->FileName, - qstring.len,Unicode,cifs_sb->local_nls); - break; - } - file->f_pos++; - } - } - /* works also for Unix ff struct since first field of both */ - pfindData = - (FILE_DIRECTORY_INFO *) ((char *) pfindData - + le32_to_cpu(pfindData->NextEntryOffset)); - /* BB also should check to make sure that pointer is not beyond the end of the SMB */ - /* if(pfindData > lastFindData) rc = -EIO; break; */ - } /* end for loop */ - if ((findParms.EndofSearch != 0) && cifsFile) { - cifsFile->srch_inf.endOfSearch = TRUE; - if(findParms.SearchCount == cpu_to_le16(2)) - cifsFile->srch_inf.emptyDir = TRUE; - } - } else { - if (cifsFile) - cifsFile->srch_inf.endOfSearch = TRUE; - /* unless parent directory gone do not return error */ - rc = 0; - } - break; - default: - if (file->private_data == NULL) { - rc = -EBADF; - cFYI(1, - ("Readdir on closed srch, pos = %lld", - file->f_pos)); - } else { - cifsFile = (struct cifsFileInfo *) file->private_data; - if (cifsFile->srch_inf.endOfSearch) { - rc = 0; - cFYI(1, ("End of search ")); - break; - } - searchHandle = cifsFile->netfid; - rc = CIFSFindNext(xid, pTcon, pfindData, - &findNextParms, searchHandle, - cifsFile->search_resume_name, - cifsFile->resume_name_length, - cifsFile->srch_inf.resume_key, - &Unicode, &UnixSearch); - cFYI(1,("Count: %d End: %d ", - le16_to_cpu(findNextParms.SearchCount), - le16_to_cpu(findNextParms.EndofSearch))); - if ((rc == 0) && (findNextParms.SearchCount != 0)) { - /* BB save off resume key, key name and name length */ - __u16 count = le16_to_cpu(findNextParms.SearchCount); - lastFindData = - (FILE_DIRECTORY_INFO *) ((char *) pfindData - + le16_to_cpu(findNextParms.LastNameOffset)); - if((char *)lastFindData > (char *)pfindData + bufsize) { - cFYI(1,("last search entry past end of packet")); - rc = -EIO; - break; - } - /* Offset of resume key same for levels 257 and 514 */ - cifsFile->srch_inf.resume_key = lastFindData->FileIndex; - - if(UnixSearch == FALSE) { - cifsFile->resume_name_length = - le32_to_cpu(lastFindData->FileNameLength); - if(cifsFile->resume_name_length > bufsize - 64) { - cFYI(1,("Illegal resume file name length %d", - cifsFile->resume_name_length)); - rc = -ENOMEM; - break; - } - /* Free the memory allocated by previous findfirst - or findnext call - we can not reuse the memory since - the resume name may not be same string length */ - if(cifsFile->search_resume_name) - kfree(cifsFile->search_resume_name); - cifsFile->search_resume_name = - kmalloc(cifsFile->resume_name_length, GFP_KERNEL); - cFYI(1,("Last file: %s with name %d bytes long", - lastFindData->FileName, - cifsFile->resume_name_length)); - if(cifsFile->search_resume_name == NULL) { - rc = -ENOMEM; - break; - } - - memcpy(cifsFile->search_resume_name, - lastFindData->FileName, - cifsFile->resume_name_length); - } else { - pfindDataUnix = (FILE_UNIX_INFO *)lastFindData; - if (Unicode == TRUE) { - for(i=0;(pfindDataUnix->FileName[i] - | pfindDataUnix->FileName[i+1]); - i+=2) { - if(i > bufsize-64) - break; - } - cifsFile->resume_name_length = i + 2; - } else { - cifsFile->resume_name_length = - strnlen(pfindDataUnix-> - FileName, - MAX_PATHCONF); - } - if(cifsFile->resume_name_length > bufsize - 64) { - cFYI(1,("Illegal resume file name length %d", - cifsFile->resume_name_length)); - rc = -ENOMEM; - break; - } - /* Free the memory allocated by previous findfirst - or findnext call - we can not reuse the memory since - the resume name may not be same string length */ - if(cifsFile->search_resume_name) - kfree(cifsFile->search_resume_name); - cifsFile->search_resume_name = - kmalloc(cifsFile->resume_name_length, GFP_KERNEL); - cFYI(1,("fnext last file: %s with name %d bytes long", - pfindDataUnix->FileName, - cifsFile->resume_name_length)); - if(cifsFile->search_resume_name == NULL) { - rc = -ENOMEM; - break; - } - memcpy(cifsFile->search_resume_name, - pfindDataUnix->FileName, - cifsFile->resume_name_length); - } - - for (i = 0; i < count; i++) { - __u32 len = le32_to_cpu(pfindData-> - FileNameLength); - if (UnixSearch == FALSE) { - if (Unicode == TRUE) - len = - cifs_strfromUCS_le - (pfindData->FileName, - (wchar_t *) - pfindData->FileName, - len / 2, - cifs_sb->local_nls); - qstring.len = len; - if (((len != 1) - || (pfindData->FileName[0] != '.')) - && ((len != 2) - || (pfindData->FileName[0] != '.') - || (pfindData->FileName[1] != - '.'))) { - if(cifs_filldir - (&qstring, - pfindData, - file, filldir, - direntry)) { - /* do not end search if - kernel not ready to take - remaining entries yet */ - findNextParms.EndofSearch = 0; - reset_resume_key(file, pfindData->FileName,qstring.len, - Unicode,cifs_sb->local_nls); - break; - } - file->f_pos++; - } - } else { /* UnixSearch */ - pfindDataUnix = - (FILE_UNIX_INFO *) - pfindData; - if (Unicode == TRUE) - qstring.len = - cifs_strfromUCS_le - (pfindDataUnix->FileName, - (wchar_t *) - pfindDataUnix->FileName, - MAX_PATHCONF, - cifs_sb->local_nls); - else - qstring.len = - strnlen - (pfindDataUnix-> - FileName, - MAX_PATHCONF); - if (((qstring.len != 1) - || (pfindDataUnix-> - FileName[0] != '.')) - && ((qstring.len != 2) - || (pfindDataUnix-> - FileName[0] != '.') - || (pfindDataUnix-> - FileName[1] != - '.'))) { - if(cifs_filldir_unix - (&qstring, - pfindDataUnix, - file, filldir, - direntry)) { - /* do not end search if - kernel not ready to take - remaining entries yet */ - findNextParms.EndofSearch = 0; - reset_resume_key(file, pfindDataUnix->FileName,qstring.len, - Unicode,cifs_sb->local_nls); - break; - } - file->f_pos++; - } - } - pfindData = (FILE_DIRECTORY_INFO *) ((char *) pfindData + - le32_to_cpu(pfindData->NextEntryOffset)); - /* works also for Unix find struct since first field of both */ - /* BB also should check to ensure pointer not beyond end of SMB */ - } /* end for loop */ - if (findNextParms.EndofSearch != 0) { - cifsFile->srch_inf.endOfSearch = TRUE; - } - } else { - cifsFile->srch_inf.endOfSearch = TRUE; - rc = 0; /* unless parent directory disappeared - do not - return error here (eg Access Denied or no more files) */ - } - } - } /* end switch */ - if (data) - kfree(data); - if (full_path) - kfree(full_path); - FreeXid(xid); - - return rc; -} int cifs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to) { diff -Nru a/fs/cifs/inode.c b/fs/cifs/inode.c --- a/fs/cifs/inode.c 2005-01-28 14:30:34 -08:00 +++ b/fs/cifs/inode.c 2005-01-28 14:30:34 -08:00 @@ -982,13 +982,12 @@ cifs_sb->local_nls); if(rc == -EOPNOTSUPP) { cFYI(1,("OS2 level of SetPathInfo not implemented")); - /* Need to convert time_buf into old format, - but probably better to do that inside the function - below rather than here */ - /* Better to return EOPNOTSUPP until function - below is ready */ + /* For older servers converts time_buf into old DOS style + level which uses two second granularity */ + + /* return EOPNOTSUPP until function below is ready */ /* CIFSSMBSetTimesLegacy(xid, pTcon, full_path, - FILE_INFO_STANDARD * data, cifs_sb->local_nls); */ + &time_buf, cifs_sb->local_nls); */ } } diff -Nru a/fs/cifs/readdir.c b/fs/cifs/readdir.c --- a/fs/cifs/readdir.c 2005-01-28 14:30:34 -08:00 +++ b/fs/cifs/readdir.c 2005-01-28 14:30:34 -08:00 @@ -394,7 +394,7 @@ static int -cifs_filldir2(char * pfindEntry, struct file *file, +cifs_filldir(char * pfindEntry, struct file *file, filldir_t filldir, void *direntry,char * scratch_buf) { int rc = 0; @@ -515,7 +515,7 @@ return rc; } -int cifs_readdir2(struct file *file, void *direntry, filldir_t filldir) +int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) { int rc = 0; int xid,i; @@ -625,7 +625,7 @@ fill in inode new_inode (which makes number locally) } also create local inode for per reasons unless new mount parm says otherwise */ - rc = cifs_filldir2(current_entry, file, + rc = cifs_filldir(current_entry, file, filldir, direntry,tmp_buf); file->f_pos++; if(file->f_pos == cifsFile->srch_inf.index_of_last_entry) { diff -Nru a/fs/cifs/transport.c b/fs/cifs/transport.c --- a/fs/cifs/transport.c 2005-01-28 14:30:34 -08:00 +++ b/fs/cifs/transport.c 2005-01-28 14:30:34 -08:00 @@ -179,6 +179,71 @@ #ifdef CIFS_EXPERIMENTAL /* BB finish off this function, adding support for writing set of pages as iovec */ /* and also adding support for operations that need to parse the response smb */ + +int +smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer, + unsigned int smb_buf_length, struct kvec * write_vector /* page list */, struct sockaddr *sin) +{ + int rc = 0; + int i = 0; + struct msghdr smb_msg; + number_of_pages += 1; /* account for SMB header */ + struct kvec * piov = kmalloc(number_of_pages * sizeof(struct kvec)); + if(i=0;ismb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length); + cFYI(1, ("Sending smb of length %d ", smb_buf_length)); + dump_smb(smb_buffer, len); + + while (len > 0) { + rc = kernel_sendmsg(ssocket, &smb_msg, &iov, number_of_pages, len?); + if ((rc == -ENOSPC) || (rc == -EAGAIN)) { + i++; + if(i > 60) { + cERROR(1, + ("sends on sock %p stuck for 30 seconds", + ssocket)); + rc = -EAGAIN; + break; + } + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ/2); + continue; + } + if (rc < 0) + break; + iov.iov_base += rc; + iov.iov_len -= rc; + len -= rc; + } + + if (rc < 0) { + cERROR(1,("Error %d sending data on socket to server.", rc)); + } else { + rc = 0; + } + + return rc; +} + + int CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses, struct smb_hdr *in_buf, struct kvec * write_vector /* page list */, int *pbytes_returned, const int long_op) @@ -285,7 +350,7 @@ rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number); midQ->midState = MID_REQUEST_SUBMITTED; -/* rc = smb_send2(ses->server->ssocket, in_buf, in_buf->smb_buf_length, piovec, +/* rc = smb_sendv(ses->server->ssocket, in_buf, in_buf->smb_buf_length, piovec, (struct sockaddr *) &(ses->server->addr.sockAddr));*/ if(rc < 0) { DeleteMidQEntry(midQ);