bk://cifs.bkbits.net/linux-2.5cifs stevef@stevef95.austin.ibm.com|ChangeSet|20041117233156|58403 stevef # This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/11/17 17:31:56-06:00 stevef@stevef95.austin.ibm.com # [CIFS] Improve SMB buffer allocation make SMB sending more efficient part 1 # # Signed-off-by: Steve French (sfrench@us.ibm.com) # # fs/cifs/transport.c # 2004/11/17 17:31:46-06:00 stevef@stevef95.austin.ibm.com +123 -0 # Create more efficient SMB send path # # fs/cifs/cifspdu.h # 2004/11/17 17:31:46-06:00 stevef@stevef95.austin.ibm.com +14 -11 # Improve SMB buffer allocation # # ChangeSet # 2004/11/17 10:59:24-06:00 sfrench@smft41.(none) # CIFS: additional smb trans2 cleanup # # Signed-off-by: Steve French (sfrench@us.ibm.com) # # fs/cifs/cifssmb.c # 2004/11/17 10:59:14-06:00 sfrench@smft41.(none) +88 -70 # additional smb trans2 cleanup # # ChangeSet # 2004/11/16 17:54:04-06:00 stevef@stevef95.austin.ibm.com # [CIFS] smb transact2 cleanup # # Signed-of-by: Steve French (sfrench@us.ibm.com) # # fs/cifs/cifssmb.c # 2004/11/16 17:53:54-06:00 stevef@stevef95.austin.ibm.com +8 -8 # smb transact2 cleanup # # fs/cifs/cifspdu.h # 2004/11/16 17:53:54-06:00 stevef@stevef95.austin.ibm.com +5 -45 # smb transact2 cleanup # # ChangeSet # 2004/11/14 22:42:26-06:00 sfrench@smft41.(none) # [CIFS] Improve SMB transact2 error checking and fix typo in warning message # # Signed-off-by: Steve French (sfrench@us.ibm.com) # # fs/cifs/connect.c # 2004/11/14 22:42:17-06:00 sfrench@smft41.(none) +1 -1 # fix typo in warning message # # fs/cifs/cifssmb.c # 2004/11/14 22:42:17-06:00 sfrench@smft41.(none) +26 -3 # fixup SMB transact2 structures and improve transact2 error checking # # fs/cifs/cifspdu.h # 2004/11/14 22:42:17-06:00 sfrench@smft41.(none) +22 -22 # fixup SMB transact2 structures # # ChangeSet # 2004/11/14 16:30:21-06:00 sfrench@smft41.(none) # [CIFS] CIFS readdir fixes part 4 # # Signed-off-by: Steve French (sfrench@us.ibm.com) # # fs/cifs/cifssmb.c # 2004/11/14 16:30:11-06:00 sfrench@smft41.(none) +7 -7 # update transact2 structure definitions # # fs/cifs/cifspdu.h # 2004/11/14 16:30:11-06:00 sfrench@smft41.(none) +3 -23 # update transact2 structure definitions # # ChangeSet # 2004/11/13 17:54:03-06:00 sfrench@smft41.(none) # [CIFS] cifs readdir changes part 3 # # Signed-off-by: Steve French (sfrench@us.ibm.com) # # fs/cifs/cifssmb.c # 2004/11/13 17:53:53-06:00 sfrench@smft41.(none) +61 -15 # cifs readdir changes part 3 # # fs/cifs/cifspdu.h # 2004/11/13 17:53:53-06:00 sfrench@smft41.(none) +137 -90 # cifs readdir changes part 3 # # ChangeSet # 2004/11/12 18:15:15-06:00 stevef@stevef95.austin.ibm.com # cifs readdir fixes part 2 # # Signed-off-by: Steve French (sfrench@us.ibm.com) # # fs/cifs/readdir.c # 2004/11/12 18:15:03-06:00 stevef@stevef95.austin.ibm.com +51 -15 # cifs readdir fixes part 2 # # fs/cifs/cifsglob.h # 2004/11/12 18:15:03-06:00 stevef@stevef95.austin.ibm.com +5 -3 # cifs readdir fixes part 2 # # ChangeSet # 2004/11/11 16:40:47-06:00 stevef@stevef95.austin.ibm.com # [CIFS] cifs readdir fixes part 1 # # Signed-off-by: Steve French (sfrench@us.ibm.com) # # fs/cifs/readdir.c # 2004/11/11 16:40:37-06:00 stevef@stevef95.austin.ibm.com +169 -0 # # fs/cifs/readdir.c # 2004/11/11 16:40:37-06:00 stevef@stevef95.austin.ibm.com +0 -0 # BitKeeper file /home/stevef/linux-2.5cifs/fs/cifs/readdir.c # # fs/cifs/cifssmb.c # 2004/11/11 16:40:37-06:00 stevef@stevef95.austin.ibm.com +128 -0 # cifs readdir fixes part 1 # # ChangeSet # 2004/11/09 21:43:59-06:00 sfrench@smft41.(none) # [CIFS] level 261 findfirst part 2 # # Signed-off-by: Steve French (sfrench@us.ibm.com) # # fs/cifs/cifspdu.h # 2004/11/09 21:43:41-06:00 sfrench@smft41.(none) +5 -4 # fix level 258 and 261 findfirst layout # # ChangeSet # 2004/11/09 13:16:33-06:00 sfrench@smft41.(none) # [CIFS] level 261 findfirst part one (will help with returning stable # server inode numbers from Windows servers) # # Signed-of-by: Steve French (sfrench@us.ibm.com) # # fs/cifs/cifspdu.h # 2004/11/09 13:16:23-06:00 sfrench@smft41.(none) +19 -1 # level 261 findfirst part one # # fs/cifs/README # 2004/11/09 13:16:23-06:00 sfrench@smft41.(none) +16 -0 # update description of cifs mount parms # # ChangeSet # 2004/11/07 19:40:43-06:00 sfrench@smft41.(none) # [CIFS] Add cifs serverino mount parm to allow use of inode numbers reported from # the server (rather than generated by the client). Some apps require inode # numbers to persist or inode numbers of hardlinked files to match and # this requires trusting the servers inode number. # # Signed-off-by: Steve French (sfrench@us.ibm.com) # # # # fs/cifs/inode.c # 2004/11/07 19:40:36-06:00 sfrench@smft41.(none) +22 -0 # Add serverino mount parm to allow use of inode numbers reported from the server (rather than generated by the client) # # fs/cifs/file.c # 2004/11/07 19:40:36-06:00 sfrench@smft41.(none) +29 -9 # Add serverino mount parm to allow use of inode numbers reported from the server (rather than generated by the client) # # fs/cifs/fcntl.c # 2004/11/07 19:40:36-06:00 sfrench@smft41.(none) +1 -1 # fix whitespace # # fs/cifs/connect.c # 2004/11/07 19:40:36-06:00 sfrench@smft41.(none) +7 -0 # Add serverino mount parm to allow use of inode numbers reported from the server (rather than generated by the client) # # fs/cifs/cifspdu.h # 2004/11/07 19:40:36-06:00 sfrench@smft41.(none) +34 -0 # new trans2 findfirst info levels # # fs/cifs/cifsfs.h # 2004/11/07 19:40:36-06:00 sfrench@smft41.(none) +1 -1 # update cifs version to 1.24 # # fs/cifs/cifs_fs_sb.h # 2004/11/07 19:40:36-06:00 sfrench@smft41.(none) +2 -1 # Add serverino mount parm to allow use of inode numbers reported from the server (rather than generated by the client) # # fs/cifs/CHANGES # 2004/11/07 19:40:36-06:00 sfrench@smft41.(none) +6 -0 # Update cifs change log for cifs version 1.24 # # ChangeSet # 2004/10/21 22:36:00-05:00 sfrench@smft41.(none) # [CIFS] treat NTFS junctions (reparse points) as directories rather than symlinks since we can not follow them # # Signed-off-by: Steve French (sfrench@us.ibm.com) # # fs/cifs/inode.c # 2004/10/21 22:35:51-05:00 sfrench@smft41.(none) +4 -4 # treat NTFS junctions (reparse points) as directories rather than symlinks since we can not follow them # # fs/cifs/file.c # 2004/10/21 22:35:51-05:00 sfrench@smft41.(none) +5 -6 # treat NTFS junctions (reparse points) as directories rather than symlinks since we can not follow them # # fs/cifs/README # 2004/10/21 22:35:51-05:00 sfrench@smft41.(none) +4 -0 # Update readme for missing cifs mount options # # fs/cifs/CHANGES # 2004/10/21 22:35:51-05:00 sfrench@smft41.(none) +2 -1 # update cifs change log # # ChangeSet # 2004/10/19 17:59:37-05:00 sfrench@smft41.(none) # Merge bk://cifs.bkbits.net/linux-2.5cifs # into smft41.(none):/home/sfrench/linux-2.5cifs # # fs/cifs/CHANGES # 2004/10/19 17:59:29-05:00 sfrench@smft41.(none) +0 -0 # Auto merged # # ChangeSet # 2004/10/19 17:56:53-05:00 sfrench@smft41.(none) # [CIFS] ignore guest mount option do not log warning on it # # Signed-off-by: Steve French (sfrench@us.ibm.com) # # fs/cifs/connect.c # 2004/10/19 17:56:46-05:00 sfrench@smft41.(none) +2 -0 # ignore guest mount option do not log warning on it # # fs/cifs/cifspdu.h # 2004/10/19 17:56:46-05:00 sfrench@smft41.(none) +2 -0 # missing defines for a few info levels # # fs/cifs/cifsfs.h # 2004/10/19 17:56:46-05:00 sfrench@smft41.(none) +1 -1 # Update change log for version 1.23 of cifs vfs # # fs/cifs/CHANGES # 2004/10/19 17:56:46-05:00 sfrench@smft41.(none) +6 -0 # Update change log for version 1.23 of cifs vfs # diff -Nru a/fs/cifs/CHANGES b/fs/cifs/CHANGES --- a/fs/cifs/CHANGES 2004-11-17 19:45:14 -08:00 +++ b/fs/cifs/CHANGES 2004-11-17 19:45:14 -08:00 @@ -1,3 +1,16 @@ +Version 1.24 +------------ +Optionally allow using server side inode numbers, rather than client generated +ones by specifying mount option "serverino" - this is required for some apps +to work which double check hardlinked files and have persistent inode numbers. + +Version 1.23 +------------ +Multiple bigendian fixes. On little endian systems (for reconnect after +network failure) fix tcp session reconnect code so we do not try first +to reconnect on reverse of port 445. Treat reparse points (NTFS junctions) +as directories rather than symlinks because we can do follow link on them. + Version 1.22 ------------ Add config option to enable XATTR (extended attribute) support, mapping diff -Nru a/fs/cifs/README b/fs/cifs/README --- a/fs/cifs/README 2004-11-17 19:45:15 -08:00 +++ b/fs/cifs/README 2004-11-17 19:45:15 -08:00 @@ -266,6 +266,10 @@ If you do not trust the servers in your network (your mount targets) it is recommended that you specify this option for greater security. + exec Permit execution of binaries on the mount. + noexec Do not permit execution of binaries on the mount. + dev Recognize block devices on the remote mount. + nodev Do not recognize devices on the remote mount. suid Allow remote files on this mountpoint with suid enabled to be executed (default for mounts when executed as root, nosuid is default for user mounts). @@ -292,6 +296,22 @@ Note that this does not affect the normal ACL check on the target machine done by the server software (of the server ACL against the user name provided at mount time). + serverino Use servers inode numbers instead of generating automatically + incrementing inode numbers on the client. Although this will + make it easier to spot hardlinked files (as they will have + the same inode numbers) and inode numbers may be persistent, + note that the server does not guarantee that the inode numbers + are unique if multiple server side mounts are exported under a + single share (since inode numbers on the servers might not + be unique if multiple filesystems are mounted under the same + shared higher level directory). Note that this requires that + the server support the CIFS Unix Extensions as other servers + do not return a unique IndexNumber on SMB FindFirst (most + servers return zero as the IndexNumber). Parameter has no + effect to Windows servers and others which do not support the + CIFS Unix Extensions. + noserverino Client generates inode numbers (rather than using the actual one + from the server) by default. setuids If the CIFS Unix extensions are negotiated with the server the client will attempt to set the effective uid and gid of the local process on newly created files, directories, and diff -Nru a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h --- a/fs/cifs/cifs_fs_sb.h 2004-11-17 19:45:14 -08:00 +++ b/fs/cifs/cifs_fs_sb.h 2004-11-17 19:45:14 -08:00 @@ -18,8 +18,9 @@ #ifndef _CIFS_FS_SB_H #define _CIFS_FS_SB_H -#define CIFS_MOUNT_NO_PERM 1 /* do not do client vfs_perm check */ +#define CIFS_MOUNT_NO_PERM 1 /* do not do client vfs_perm check */ #define CIFS_MOUNT_SET_UID 2 /* set current->euid in create etc. */ +#define CIFS_MOUNT_SERVER_INUM 4 /* inode numbers from uniqueid from server */ struct cifs_sb_info { struct cifsTconInfo *tcon; /* primary mount */ diff -Nru a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h --- a/fs/cifs/cifsfs.h 2004-11-17 19:45:14 -08:00 +++ b/fs/cifs/cifsfs.h 2004-11-17 19:45:14 -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.20" +#define CIFS_VERSION "1.24" #endif /* _CIFSFS_H */ diff -Nru a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h --- a/fs/cifs/cifsglob.h 2004-11-17 19:45:14 -08:00 +++ b/fs/cifs/cifsglob.h 2004-11-17 19:45:14 -08:00 @@ -255,9 +255,11 @@ unsigned emptyDir:1; unsigned invalidHandle:1; /* file closed via session abend */ struct semaphore fh_sem; /* prevents reopen race after dead ses*/ - char * search_resume_name; - unsigned int resume_name_length; - __u32 resume_key; + char * search_resume_name; /* BB removeme BB */ + unsigned int resume_name_length; /* BB removeme BB */ + __u32 resume_key; /* BB removeme BB */ + loff_t index_of_last_entry_in_buf; + int entries_in_buffer; }; /* diff -Nru a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h --- a/fs/cifs/cifspdu.h 2004-11-17 19:45:14 -08:00 +++ b/fs/cifs/cifspdu.h 2004-11-17 19:45:14 -08:00 @@ -28,27 +28,30 @@ #define BAD_PROT CIFS_PROT+1 /* SMB command codes */ -#define SMB_COM_CREATE_DIRECTORY 0x00 -#define SMB_COM_DELETE_DIRECTORY 0x01 -#define SMB_COM_CLOSE 0x04 -#define SMB_COM_DELETE 0x06 -#define SMB_COM_RENAME 0x07 -#define SMB_COM_LOCKING_ANDX 0x24 -#define SMB_COM_COPY 0x29 +/* Some commands have minimal (wct=0,bcc=0), or uninteresting, responses + (ie which include no useful data other than the SMB error code itself). + Knowing this helps avoid response buffer allocations and copy in some cases */ +#define SMB_COM_CREATE_DIRECTORY 0x00 /* trivial response */ +#define SMB_COM_DELETE_DIRECTORY 0x01 /* trivial response */ +#define SMB_COM_CLOSE 0x04 /* trivial rsp, timestamp ignored */ +#define SMB_COM_DELETE 0x06 /* trivial response */ +#define SMB_COM_RENAME 0x07 /* trivial response */ +#define SMB_COM_LOCKING_ANDX 0x24 /* trivial response */ +#define SMB_COM_COPY 0x29 /* trivial rsp, fail filename ignrd*/ #define SMB_COM_READ_ANDX 0x2E #define SMB_COM_WRITE_ANDX 0x2F #define SMB_COM_TRANSACTION2 0x32 #define SMB_COM_TRANSACTION2_SECONDARY 0x33 -#define SMB_COM_FIND_CLOSE2 0x34 -#define SMB_COM_TREE_DISCONNECT 0x71 +#define SMB_COM_FIND_CLOSE2 0x34 /* trivial response */ +#define SMB_COM_TREE_DISCONNECT 0x71 /* trivial response */ #define SMB_COM_NEGOTIATE 0x72 #define SMB_COM_SESSION_SETUP_ANDX 0x73 -#define SMB_COM_LOGOFF_ANDX 0x74 +#define SMB_COM_LOGOFF_ANDX 0x74 /* trivial response */ #define SMB_COM_TREE_CONNECT_ANDX 0x75 #define SMB_COM_NT_TRANSACT 0xA0 #define SMB_COM_NT_TRANSACT_SECONDARY 0xA1 #define SMB_COM_NT_CREATE_ANDX 0xA2 -#define SMB_COM_NT_RENAME 0xA5 +#define SMB_COM_NT_RENAME 0xA5 /* trivial response */ /* Transact2 subcommand codes */ #define TRANS2_OPEN 0x00 @@ -1004,45 +1007,55 @@ #define QUOTA_LIST_START 0x100 #define QUOTA_FOR_SID 0x101 -typedef union smb_com_transaction2 { - struct { - struct smb_hdr hdr; /* wct = 14+ */ - __u16 TotalParameterCount; - __u16 TotalDataCount; - __u16 MaxParameterCount; - __u16 MaxDataCount; - __u8 MaxSetupCount; - __u8 Reserved; - __u16 Flags; - __u32 Timeout; - __u16 Reserved2; - __u16 ParameterCount; - __u16 ParameterOffset; - __u16 DataCount; - __u16 DataOffset; - __u8 SetupCount; - __u8 Reserved3; - __u16 SubCommand; /* 1st setup word - can be followed by SetupCount words */ - __u16 ByteCount; /* careful - setupcount is not always one */ - } req; - struct { - struct smb_hdr hdr; /* wct = 0 */ - __u16 TotalParameterCount; - __u16 TotalDataCount; - __u16 Reserved; - __u16 ParameterCount; - __u16 ParamterOffset; - __u16 ParameterDisplacement; - __u16 DataCount; - __u16 DataOffset; - __u16 DataDisplacement; - __u8 SetupCount; - __u8 Reserved1; /* should be zero setup words following */ - __u16 ByteCount; - __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */ - /* data area follows */ - } resp; -} TRANSACTION2; +struct trans2_req { + /* struct smb_hdr hdr precedes. Set wct = 14+ */ + __le16 TotalParameterCount; + __le16 TotalDataCount; + __le16 MaxParameterCount; + __le16 MaxDataCount; + __u8 MaxSetupCount; + __u8 Reserved; + __le16 Flags; + __le32 Timeout; + __u16 Reserved2; + __le16 ParameterCount; + __le16 ParameterOffset; + __le16 DataCount; + __le16 DataOffset; + __u8 SetupCount; + __u8 Reserved3; + __le16 SubCommand; /* 1st setup word - SetupCount words follow */ + __le16 ByteCount; +}; + +struct smb_t2_req { + struct smb_hdr hdr; + struct trans2_req t2_req; +}; + +struct trans2_resp { + /* struct smb_hdr hdr precedes. Note wct = 10 + setup count */ + __le16 TotalParameterCount; + __le16 TotalDataCount; + __u16 Reserved; + __le16 ParameterCount; + __le16 ParameterOffset; + __le16 ParameterDisplacement; + __le16 DataCount; + __le16 DataOffset; + __le16 DataDisplacement; + __u8 SetupCount; + __u8 Reserved1; + /* SetupWords[SetupCount]; + __u16 ByteCount; + __u16 Reserved2;*/ + /* data area follows */ +}; + +struct smb_t2_rsp { + struct smb_hdr hdr; + struct trans2_resp t2_rsp; +}; /* PathInfo/FileInfo infolevels */ #define SMB_INFO_STANDARD 1 @@ -1063,6 +1076,13 @@ #define SMB_QUERY_FILE_COMPRESSION_INFO 0x10B #define SMB_QUERY_FILE_UNIX_BASIC 0x200 #define SMB_QUERY_FILE_UNIX_LINK 0x201 +#define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee +#define SMB_QUERY_FILE_ACCESS_INFO 0x3f0 +#define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */ +#define SMB_QUERY_FILE_POSITION_INFO 0x3f6 +#define SMB_QUERY_FILE_MODE_INFO 0x3f8 +#define SMB_QUERY_FILE_ALGN_INFO 0x3f9 + #define SMB_SET_FILE_BASIC_INFO 0x101 #define SMB_SET_FILE_DISPOSITION_INFO 0x102 @@ -1072,7 +1092,7 @@ #define SMB_SET_FILE_UNIX_LINK 0x201 #define SMB_SET_FILE_UNIX_HLINK 0x203 #define SMB_SET_FILE_BASIC_INFO2 0x3ec -#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 +#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo level too */ #define SMB_FILE_ALL_INFO2 0x3fa #define SMB_SET_FILE_ALLOCATION_INFO2 0x3fb #define SMB_SET_FILE_END_OF_FILE_INFO2 0x3fc @@ -1086,6 +1106,8 @@ #define SMB_FIND_FILE_FULL_DIRECTORY_INFO 0x102 #define SMB_FIND_FILE_NAMES_INFO 0x103 #define SMB_FIND_FILE_BOTH_DIRECTORY_INFO 0x104 +#define SMB_FIND_FILE_ID_FULL_DIR_INFO 0x105 +#define SMB_FIND_FILE_ID_BOTH_DIR_INFO 0x106 #define SMB_FIND_FILE_UNIX 0x202 typedef struct smb_com_transaction2_qpi_req { @@ -1115,17 +1137,7 @@ typedef struct smb_com_transaction2_qpi_rsp { struct smb_hdr hdr; /* wct = 10 + SetupCount */ - __le16 TotalParameterCount; - __le16 TotalDataCount; - __le16 Reserved; - __le16 ParameterCount; - __le16 ParameterOffset; - __le16 ParameterDisplacement; - __le16 DataCount; - __le16 DataOffset; - __le16 DataDisplacement; - __u8 SetupCount; - __u8 Reserved1; /* should be zero setup words following */ + struct trans2_resp t2; __u16 ByteCount; __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */ } TRANSACTION2_QPI_RSP; @@ -1158,17 +1170,7 @@ typedef struct smb_com_transaction2_spi_rsp { struct smb_hdr hdr; /* wct = 10 + SetupCount */ - __le16 TotalParameterCount; - __le16 TotalDataCount; - __u16 Reserved; - __le16 ParameterCount; - __le16 ParameterOffset; - __le16 ParameterDisplacement; - __le16 DataCount; - __le16 DataOffset; - __le16 DataDisplacement; - __u8 SetupCount; - __u8 Reserved1; /* should be zero setup words following */ + struct trans2_resp t2; __u16 ByteCount; __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */ } TRANSACTION2_SPI_RSP; @@ -1208,17 +1210,7 @@ struct smb_com_transaction2_sfi_rsp { struct smb_hdr hdr; /* wct = 10 + SetupCount */ - __le16 TotalParameterCount; - __le16 TotalDataCount; - __u16 Reserved; - __le16 ParameterCount; - __le16 ParameterOffset; - __le16 ParameterDisplacement; - __le16 DataCount; - __le16 DataOffset; - __le16 DataDisplacement; - __u8 SetupCount; - __u8 Reserved1; /* should be zero setup words following */ + struct trans2_resp t2; __u16 ByteCount; __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */ }; @@ -1268,17 +1260,7 @@ typedef struct smb_com_transaction2_ffirst_rsp { struct smb_hdr hdr; /* wct = 10 */ - __le16 TotalParameterCount; - __le16 TotalDataCount; - __u16 Reserved; - __le16 ParameterCount; - __le16 ParameterOffset; - __le16 ParameterDisplacement; - __le16 DataCount; - __le16 DataOffset; - __le16 DataDisplacement; - __u8 SetupCount; - __u8 Reserved1; /* should be zero setup words following */ + struct trans2_resp t2; __u16 ByteCount; } TRANSACTION2_FFIRST_RSP; @@ -1320,17 +1302,7 @@ typedef struct smb_com_transaction2_fnext_rsp { struct smb_hdr hdr; /* wct = 10 */ - __le16 TotalParameterCount; - __le16 TotalDataCount; - __u16 Reserved; - __le16 ParameterCount; - __le16 ParameterOffset; - __le16 ParameterDisplacement; - __le16 DataCount; - __le16 DataOffset; - __le16 DataDisplacement; - __u8 SetupCount; - __u8 Reserved1; /* should be zero setup words following */ + struct trans2_resp t2; __u16 ByteCount; } TRANSACTION2_FNEXT_RSP; @@ -1351,6 +1323,8 @@ #define SMB_QUERY_CIFS_UNIX_INFO 0x200 #define SMB_QUERY_LABEL_INFO 0x3ea #define SMB_QUERY_FS_QUOTA_INFO 0x3ee +#define SMB_QUERY_FS_FULL_SIZE_INFO 0x3ef +#define SMB_QUERY_OBJECTID_INFO 0x3f0 typedef struct smb_com_transaction2_qfsi_req { struct smb_hdr hdr; /* wct = 14+ */ @@ -1377,17 +1351,7 @@ typedef struct smb_com_transaction_qfsi_rsp { struct smb_hdr hdr; /* wct = 10 + SetupCount */ - __le16 TotalParameterCount; - __le16 TotalDataCount; - __u16 Reserved; - __le16 ParameterCount; - __le16 ParameterOffset; - __le16 ParameterDisplacement; - __le16 DataCount; - __le16 DataOffset; - __le16 DataDisplacement; - __u8 SetupCount; - __u8 Reserved1; /* should be zero setup words following */ + struct trans2_resp t2; __u16 ByteCount; __u8 Pad; /* may be three bytes *//* followed by data area */ } TRANSACTION2_QFSI_RSP; @@ -1430,17 +1394,7 @@ typedef struct smb_com_transaction_get_dfs_refer_rsp { struct smb_hdr hdr; /* wct = 10 */ - __le16 TotalParameterCount; - __le16 TotalDataCount; - __u16 Reserved; - __le16 ParameterCount; - __le16 ParameterOffset; - __le16 ParameterDisplacement; - __le16 DataCount; - __le16 DataOffset; - __le16 DataDisplacement; - __u8 SetupCount; - __u8 Reserved1; /* zero setup words following */ + struct trans2_resp t2; __u16 ByteCount; __u8 Pad; __le16 PathConsumed; @@ -1575,10 +1529,13 @@ __le32 Attributes; __le32 MaxPathNameComponentLength; __le32 FileSystemNameLen; - char FileSystemName[52]; /* do not really need to save this - so potentially get only subset of name */ + char FileSystemName[52]; /* do not really need to save this - so potentially get only subset of name */ } FILE_SYSTEM_ATTRIBUTE_INFO; -typedef struct { /* data block encoding of response to level 263 QPathInfo */ +/******************************************************************************/ +/* QueryFileInfo/QueryPathinfo (also for SetPath/SetFile) data buffer formats */ +/******************************************************************************/ +typedef struct { /* data block encoding of response to level 263 QPathInfo */ __le64 CreationTime; __le64 LastAccessTime; __le64 LastWriteTime; @@ -1600,12 +1557,20 @@ __le32 AlignmentRequirement; __le32 FileNameLength; char FileName[1]; -} FILE_ALL_INFO; /* level 263 QPathInfo */ +} FILE_ALL_INFO; /* level 0x107 QPathInfo */ +/* defines for enumerating possible values of the Unix type field below */ +#define UNIX_FILE 0 +#define UNIX_DIR 1 +#define UNIX_SYMLINK 2 +#define UNIX_CHARDEV 3 +#define UNIX_BLOCKDEV 4 +#define UNIX_FIFO 5 +#define UNIX_SOCKET 6 typedef struct { __le64 EndOfFile; __le64 NumOfBytes; - __le64 LastStatusChange; /*SNIA spec says DCE time for the three time fields */ + __le64 LastStatusChange; /*SNIA specs DCE time for the 3 time fields */ __le64 LastAccessTime; __le64 LastModificationTime; __le64 Uid; @@ -1616,11 +1581,11 @@ __u64 UniqueId; __le64 Permissions; __le64 Nlinks; -} FILE_UNIX_BASIC_INFO; /* level 512 QPathInfo */ +} FILE_UNIX_BASIC_INFO; /* level 0x200 QPathInfo */ typedef struct { char LinkDest[1]; -} FILE_UNIX_LINK_INFO; /* level 513 QPathInfo */ +} FILE_UNIX_LINK_INFO; /* level 0x201 QPathInfo */ typedef struct { __u16 CreationDate; @@ -1635,21 +1600,67 @@ __u32 EASize; } FILE_INFO_STANDARD; /* level 1 SetPath/FileInfo */ -/* defines for enumerating possible values of the Unix type field below */ -#define UNIX_FILE 0 -#define UNIX_DIR 1 -#define UNIX_SYMLINK 2 -#define UNIX_CHARDEV 3 -#define UNIX_BLOCKDEV 4 -#define UNIX_FIFO 5 -#define UNIX_SOCKET 6 +typedef struct { + __le64 CreationTime; + __le64 LastAccessTime; + __le64 LastWriteTime; + __le64 ChangeTime; + __le32 Attributes; + __u32 Pad; +} FILE_BASIC_INFO; /* size info, level 0x101 */ + +struct file_allocation_info { + __le64 AllocationSize; /* Note old Samba srvr rounds this up too much */ +}; /* size used on disk, level 0x103 for set, 0x105 for query */ + +struct file_end_of_file_info { + __le64 FileSize; /* offset to end of file */ +}; /* size info, level 0x104 for set, 0x106 for query */ + +struct file_alt_name_info { + __u8 alt_name[1]; +}; /* level 0x0108 */ + +struct file_stream_info { + __le32 number_of_streams; /* BB check sizes and verify location */ + /* followed by info on streams themselves + u64 size; + u64 allocation_size + stream info */ +}; /* level 0x109 */ + +struct file_compression_info { + __le64 compressed_size; + __le16 format; + __u8 unit_shift; + __u8 ch_shift; + __u8 cl_shift; + __u8 pad[3]; +}; /* level 0x10b */ + +struct file_internal_info { + __u64 UniqueId; /* inode number */ +}; /* level 0x3ee */ +struct file_mode_info { + __le32 Mode; +}; /* level 0x3f8 */ + +struct file_attrib_tag { + __le32 Attribute; + __le32 ReparseTag; +}; /* level 0x40b */ + + +/********************************************************/ +/* FindFirst/FindNext transact2 data buffer formats */ +/********************************************************/ typedef struct { __le32 NextEntryOffset; __le32 ResumeKey; __le64 EndOfFile; __le64 NumOfBytes; - __le64 LastStatusChange; /*SNIA spec says DCE time for the three time fields */ + __le64 LastStatusChange; /*SNIA specs DCE time for the 3 time fields */ __le64 LastAccessTime; __le64 LastModificationTime; __le64 Uid; @@ -1657,28 +1668,40 @@ __le32 Type; __le64 DevMajor; __le64 DevMinor; - __le64 UniqueId; + __u64 UniqueId; __le64 Permissions; __le64 Nlinks; char FileName[1]; -} FILE_UNIX_INFO; +} FILE_UNIX_INFO; /* level 0x202 */ typedef struct { + __le32 NextEntryOffset; + __u32 FileIndex; __le64 CreationTime; __le64 LastAccessTime; __le64 LastWriteTime; __le64 ChangeTime; - __le32 Attributes; - __u32 Pad; -} FILE_BASIC_INFO; /* size info, level 0x101 */ - -struct file_allocation_info { + __le64 EndOfFile; __le64 AllocationSize; -}; /* size info, level 0x103 */ + __le32 ExtFileAttributes; + __le32 FileNameLength; + char FileName[1]; +} FILE_DIRECTORY_INFO; /* level 0x101 FF response data area */ -struct file_end_of_file_info { - __le64 FileSize; /* offset to end of file */ -}; /* size info, level 0x104 */ +typedef struct { + __le32 NextEntryOffset; + __u32 FileIndex; + __le64 CreationTime; + __le64 LastAccessTime; + __le64 LastWriteTime; + __le64 ChangeTime; + __le64 EndOfFile; + __le64 AllocationSize; + __le32 ExtFileAttributes; + __le32 FileNameLength; + __le32 EaSize; /* length of the xattrs */ + char FileName[1]; +} FILE_FULL_DIRECTORY_INFO; /* level 0x102 FF response data area */ typedef struct { __le32 NextEntryOffset; @@ -1691,8 +1714,30 @@ __le64 AllocationSize; __le32 ExtFileAttributes; __le32 FileNameLength; + __le32 EaSize; /* EA size */ + __le32 Reserved; + __u64 UniqueId; /* inode num - le since Samba puts ino in low 32 bit*/ + char FileName[1]; +} SEARCH_ID_FULL_DIR_INFO; /* level 0x105 FF response data area */ + +typedef struct { + __le32 NextEntryOffset; + __u32 FileIndex; + __le64 CreationTime; + __le64 LastAccessTime; + __le64 LastWriteTime; + __le64 ChangeTime; + __le64 EndOfFile; + __le64 AllocationSize; + __le32 ExtFileAttributes; + __le32 FileNameLength; + __le32 EaSize; /* length of the xattrs */ + __u8 ShortNameLength; + __u8 Reserved; + __u8 ShortName[12]; char FileName[1]; -} FILE_DIRECTORY_INFO; /* level 257 FF response data area */ +} FILE_BOTH_DIRECTORY_INFO; /* level 0x104 FF response data area */ + struct gea { unsigned char name_len; diff -Nru a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c --- a/fs/cifs/cifssmb.c 2004-11-17 19:45:14 -08:00 +++ b/fs/cifs/cifssmb.c 2004-11-17 19:45:14 -08:00 @@ -174,7 +174,38 @@ #endif return rc; } - +static int validate_t2(struct smb_t2_rsp * pSMB) +{ + int rc = -EINVAL; + int total_size; + char * pBCC; + + /* check for plausible wct, bcc and t2 data and parm sizes */ + /* check for parm and data offset going beyond end of smb */ + if(pSMB->hdr.WordCount >= 10) { + if((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) && + (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) { + /* check that bcc is at least as big as parms + data */ + /* check that bcc is less than negotiated smb buffer */ + total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount); + if(total_size < 512) { + total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount); + /* BCC le converted in SendReceive */ + pBCC = (pSMB->hdr.WordCount * 2) + sizeof(struct smb_hdr) + + (char *)pSMB; + if((total_size <= (*(u16 *)pBCC)) && + (total_size < + CIFS_MAX_MSGSIZE+MAX_CIFS_HDR_SIZE)) { + return 0; + } + + } + } + } + cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB, + sizeof(struct smb_t2_rsp) + 16); + return rc; +} int CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) { @@ -1432,13 +1463,17 @@ (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc)); - } else { /* decode response */ - __u16 data_offset = le16_to_cpu(pSMBr->DataOffset); - __u16 count = le16_to_cpu(pSMBr->DataCount); - if ((pSMBr->ByteCount < 2) || (data_offset > 512)) + } else { + /* decode response */ + + rc = validate_t2((struct smb_t2_rsp *)pSMBr); + if (rc || (pSMBr->ByteCount < 2)) /* BB also check enough total bytes returned */ rc = -EIO; /* bad smb */ else { + __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); + __u16 count = le16_to_cpu(pSMBr->t2.DataCount); + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = UniStrnlen((wchar_t *) ((char *) &pSMBr->hdr.Protocol +data_offset), @@ -1613,13 +1648,12 @@ if (rc) { cFYI(1, ("Send error in QPathInfo = %d", rc)); } else { /* decode response */ - __u16 data_offset = le16_to_cpu(pSMBr->DataOffset); - /* BB also check enough total bytes returned */ - /* BB we need to improve the validity checking - of these trans2 responses */ - if ((pSMBr->ByteCount < 40) || (data_offset > 512)) + rc = validate_t2((struct smb_t2_rsp *)pSMBr); + + if (rc || (pSMBr->ByteCount < 40)) rc = -EIO; /* bad smb */ else if (pFindData){ + __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); memcpy((char *) pFindData, (char *) &pSMBr->hdr.Protocol + data_offset, sizeof (FILE_ALL_INFO)); @@ -1698,15 +1732,12 @@ if (rc) { cFYI(1, ("Send error in QPathInfo = %d", rc)); } else { /* decode response */ - __u16 data_offset = le16_to_cpu(pSMBr->DataOffset); - /* BB also check if enough total bytes returned */ - if ((pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO)) || - (data_offset > 512) || - (data_offset < sizeof(struct smb_hdr))) { - cFYI(1,("UnixQPathinfo invalid data offset %d bytes returned %d", - (int)data_offset,bytes_returned)); + rc = validate_t2((struct smb_t2_rsp *)pSMBr); + + if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) { rc = -EIO; /* bad smb */ } else { + __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); memcpy((char *) pFindData, (char *) &pSMBr->hdr.Protocol + data_offset, @@ -1880,20 +1911,25 @@ if (rc) { /* BB add logic to retry regular search if Unix search rejected unexpectedly by server */ cFYI(1, ("Error in FindFirst = %d", rc)); - } else { /* decode response */ + } else { + rc = validate_t2((struct smb_t2_rsp *)pSMBr); + if(!rc) { + /* decode response */ /* BB add safety checks for these memcpys */ - if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) - *pUnicodeFlag = TRUE; - else - *pUnicodeFlag = FALSE; - memcpy(findParms, - (char *) &pSMBr->hdr.Protocol + - le16_to_cpu(pSMBr->ParameterOffset), - sizeof (T2_FFIRST_RSP_PARMS)); - response_data = - (char *) &pSMBr->hdr.Protocol + - le16_to_cpu(pSMBr->DataOffset); - memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount)); + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) + *pUnicodeFlag = TRUE; + else + *pUnicodeFlag = FALSE; + memcpy(findParms, + (char *) &pSMBr->hdr.Protocol + + le16_to_cpu(pSMBr->t2.ParameterOffset), + sizeof (T2_FFIRST_RSP_PARMS)); + response_data = + (char *) &pSMBr->hdr.Protocol + + le16_to_cpu(pSMBr->t2.DataOffset); + memcpy(findData, response_data, + le16_to_cpu(pSMBr->t2.DataCount)); + } } if (pSMB) cifs_buf_release(pSMB); @@ -1904,6 +1940,133 @@ return rc; } +#ifdef CIFS_EXPERIMENTAL +/* xid, tcon, searchName and codepage are input parms, rest are returned */ +int +CIFSFindFirst2(const int xid, struct cifsTconInfo *tcon, + const char *searchName, + const struct nls_table *nls_codepage, + char ** ppfindData /* first search entries */, + char ** ppbuf /* beginning of smb response */, + int *searchCount, __u16 *searchHandle, + int *pUnicodeFlag, int *pEndOfSearchFlag, + int *level) +{ +/* level 257 SMB_ */ + TRANSACTION2_FFIRST_REQ *pSMB = NULL; + TRANSACTION2_FFIRST_RSP *pSMBr = NULL; + T2_FFIRST_RSP_PARMS * parms; + int rc = 0; + int bytes_returned; + int name_len; + __u16 params, byte_count; + + cFYI(1, ("In FindFirst2")); + + if(ppbuf) + *ppbuf = NULL; + else + return -EINVAL; + +findFirst2Retry: + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, + (void **) &pSMBr); + if (rc) + return rc; + + if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { + name_len = + cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530 + /* find define for this maxpathcomponent */ + , nls_codepage); + name_len++; /* trailing null */ + name_len *= 2; + } else { /* BB improve the check for buffer overruns BB */ + name_len = strnlen(searchName, 530); + name_len++; /* trailing null */ + strncpy(pSMB->FileName, searchName, name_len); + } + + params = 12 + name_len /* includes null */ ; + pSMB->TotalDataCount = 0; /* no EAs */ + pSMB->MaxParameterCount = cpu_to_le16(10); + pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf - + MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); + pSMB->MaxSetupCount = 0; + pSMB->Reserved = 0; + pSMB->Flags = 0; + pSMB->Timeout = 0; + pSMB->Reserved2 = 0; + byte_count = params + 1 /* pad */ ; + pSMB->TotalParameterCount = cpu_to_le16(params); + pSMB->ParameterCount = pSMB->TotalParameterCount; + pSMB->ParameterOffset = cpu_to_le16(offsetof(struct + smb_com_transaction2_ffirst_req, SearchAttributes) - 4); + pSMB->DataCount = 0; + pSMB->DataOffset = 0; + pSMB->SetupCount = 1; /* one byte no need to make endian neutral */ + pSMB->Reserved3 = 0; + pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST); + pSMB->SearchAttributes = + cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | + ATTR_DIRECTORY); + pSMB->SearchCount = cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO)); /* should this be shrunk even more ? */ + pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME); + + /* test for Unix extensions */ + if (tcon->ses->capabilities & CAP_UNIX) { + pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX); + *level = SMB_FIND_FILE_UNIX; + } else { + pSMB->InformationLevel = + cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO); + *level = SMB_FIND_FILE_DIRECTORY_INFO; + } + pSMB->SearchStorageType = 0; /* BB what should we set this to? It is not clear if it matters BB */ + pSMB->hdr.smb_buf_length += byte_count; + pSMB->ByteCount = cpu_to_le16(byte_count); + + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, + (struct smb_hdr *) pSMBr, &bytes_returned, 0); + + if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */ + /* BB Add code to handle unsupported level rc */ + cFYI(1, ("Error in FindFirst = %d", rc)); + + if (pSMB) + cifs_buf_release(pSMB); + + /* BB eventually could optimize out free and realloc of buf */ + /* for this case */ + if (rc == -EAGAIN) + goto findFirst2Retry; + } else { /* decode response */ + /* BB remember to free buffer if error BB */ + rc = validate_t2((struct smb_t2_rsp *)pSMBr); + if(rc == 0) { + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) + *pUnicodeFlag = TRUE; + else + *pUnicodeFlag = FALSE; + + if(ppfindData) + *ppfindData = (char *) &pSMBr->hdr.Protocol + + le16_to_cpu(pSMBr->t2.DataOffset); + + parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol + + le16_to_cpu(pSMBr->t2.ParameterOffset)); + + *pEndOfSearchFlag = parms->EndofSearch; + *searchCount = parms->SearchCount; + *searchHandle = parms->SearchHandle; + } + + } + + return rc; +} +#endif /* CIFS_EXPERIMENTAL */ + int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, FILE_DIRECTORY_INFO * findData, T2_FNEXT_RSP_PARMS * findParms, @@ -1984,19 +2147,23 @@ else cFYI(1, ("FindNext returned = %d", rc)); } else { /* decode response */ + rc = validate_t2((struct smb_t2_rsp *)pSMBr); + /* BB add safety checks for these memcpys */ - if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) - *pUnicodeFlag = TRUE; - else - *pUnicodeFlag = FALSE; - memcpy(findParms, - (char *) &pSMBr->hdr.Protocol + - le16_to_cpu(pSMBr->ParameterOffset), - sizeof (T2_FNEXT_RSP_PARMS)); - response_data = - (char *) &pSMBr->hdr.Protocol + - le16_to_cpu(pSMBr->DataOffset); - memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount)); + if(rc == 0) { + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) + *pUnicodeFlag = TRUE; + else + *pUnicodeFlag = FALSE; + memcpy(findParms, + (char *) &pSMBr->hdr.Protocol + + le16_to_cpu(pSMBr->t2.ParameterOffset), + sizeof (T2_FNEXT_RSP_PARMS)); + response_data = + (char *) &pSMBr->hdr.Protocol + + le16_to_cpu(pSMBr->t2.DataOffset); + memcpy(findData,response_data,le16_to_cpu(pSMBr->t2.DataCount)); + } } if (pSMB) cifs_buf_release(pSMB); @@ -2042,6 +2209,39 @@ return rc; } +#ifdef CIFS_EXPERIMENTAL +int +CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, + const unsigned char *searchName, + __u64 * inode_number, + const struct nls_table *nls_codepage) +{ + int rc = 0; + TRANSACTION2_QPI_REQ *pSMB = NULL; + TRANSACTION2_QPI_RSP *pSMBr = NULL; + + cFYI(1,("In GetSrvInodeNumber for %s",searchName)); + if(tcon == NULL) + return -ENODEV; + + cFYI(1, ("In QPathInfo path %s", searchName)); +GetInodeNumberRetry: + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, + (void **) &pSMBr); + if (rc) + return rc; + +/* BB add missing code here */ + + if (pSMB) + cifs_buf_release(pSMB); + + if (rc == -EAGAIN) + goto GetInodeNumberRetry; + return rc; +} +#endif /* CIFS_EXPERIMENTAL */ + int CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, const unsigned char *searchName, @@ -2124,14 +2324,17 @@ cFYI(1, ("Send error in GetDFSRefer = %d", rc)); } else { /* decode response */ /* BB Add logic to parse referrals here */ - __u16 data_offset = le16_to_cpu(pSMBr->DataOffset); - __u16 data_count = le16_to_cpu(pSMBr->DataCount); - cFYI(1, - ("Decoding GetDFSRefer response. BCC: %d Offset %d", - pSMBr->ByteCount, data_offset)); - if ((pSMBr->ByteCount < 17) || (data_offset > 512)) /* BB also check enough total bytes returned */ - rc = -EIO; /* bad smb */ + rc = validate_t2((struct smb_t2_rsp *)pSMBr); + + if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */ + rc = -EIO; /* bad smb */ else { + __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); + __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount); + + cFYI(1, + ("Decoding GetDFSRefer response. BCC: %d Offset %d", + pSMBr->ByteCount, data_offset)); referrals = (struct dfs_referral_level_3 *) (8 /* sizeof start of data block */ + @@ -2257,13 +2460,16 @@ if (rc) { cERROR(1, ("Send error in QFSInfo = %d", rc)); } else { /* decode response */ - __u16 data_offset = le16_to_cpu(pSMBr->DataOffset); - cFYI(1, - ("Decoding qfsinfo response. BCC: %d Offset %d", - pSMBr->ByteCount, data_offset)); - if ((pSMBr->ByteCount < 24) || (data_offset > 512)) /* BB also check enough total bytes returned */ + rc = validate_t2((struct smb_t2_rsp *)pSMBr); + + if (rc || (pSMBr->ByteCount < 24)) /* BB alsO CHEck enough total bytes returned */ rc = -EIO; /* bad smb */ else { + __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); + cFYI(1, + ("Decoding qfsinfo response. BCC: %d Offset %d", + pSMBr->ByteCount, data_offset)); + response_data = (FILE_SYSTEM_INFO *) (((char *) &pSMBr->hdr.Protocol) + @@ -2339,10 +2545,12 @@ if (rc) { cERROR(1, ("Send error in QFSAttributeInfo = %d", rc)); } else { /* decode response */ - __u16 data_offset = le16_to_cpu(pSMBr->DataOffset); - if ((pSMBr->ByteCount < 13) || (data_offset > 512)) { /* BB also check enough bytes returned */ + rc = validate_t2((struct smb_t2_rsp *)pSMBr); + + if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */ rc = -EIO; /* bad smb */ } else { + __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); response_data = (FILE_SYSTEM_ATTRIBUTE_INFO *) (((char *) &pSMBr->hdr.Protocol) + @@ -2408,11 +2616,12 @@ if (rc) { cFYI(1, ("Send error in QFSDeviceInfo = %d", rc)); } else { /* decode response */ - __u16 data_offset = le16_to_cpu(pSMBr->DataOffset); - if ((pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)) - || (data_offset > 512)) + rc = validate_t2((struct smb_t2_rsp *)pSMBr); + + if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO))) rc = -EIO; /* bad smb */ else { + __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); response_data = (FILE_SYSTEM_DEVICE_INFO *) (((char *) &pSMBr->hdr.Protocol) + @@ -2477,10 +2686,12 @@ if (rc) { cERROR(1, ("Send error in QFSUnixInfo = %d", rc)); } else { /* decode response */ - __u16 data_offset = le16_to_cpu(pSMBr->DataOffset); - if ((pSMBr->ByteCount < 13) || (data_offset > 512)) { + rc = validate_t2((struct smb_t2_rsp *)pSMBr); + + if (rc || (pSMBr->ByteCount < 13)) { rc = -EIO; /* bad smb */ } else { + __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); response_data = (FILE_SYSTEM_UNIX_INFO *) (((char *) &pSMBr->hdr.Protocol) + @@ -3056,11 +3267,12 @@ if (rc) { cFYI(1, ("Send error in QueryAllEAs = %d", rc)); } else { /* decode response */ - __u16 data_offset = le16_to_cpu(pSMBr->DataOffset); + rc = validate_t2((struct smb_t2_rsp *)pSMBr); + /* BB also check enough total bytes returned */ /* BB we need to improve the validity checking of these trans2 responses */ - if ((pSMBr->ByteCount < 4) || (data_offset > 512)) + if (rc || (pSMBr->ByteCount < 4)) rc = -EIO; /* bad smb */ /* else if (pFindData){ memcpy((char *) pFindData, @@ -3072,6 +3284,7 @@ of list */ /* check that each element of each entry does not go beyond end of list */ + __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); struct fealist * ea_response_data; rc = 0; /* validate_trans2_offsets() */ @@ -3198,11 +3411,12 @@ if (rc) { cFYI(1, ("Send error in Query EA = %d", rc)); } else { /* decode response */ - __u16 data_offset = le16_to_cpu(pSMBr->DataOffset); + rc = validate_t2((struct smb_t2_rsp *)pSMBr); + /* BB also check enough total bytes returned */ /* BB we need to improve the validity checking of these trans2 responses */ - if ((pSMBr->ByteCount < 4) || (data_offset > 512)) + if (rc || (pSMBr->ByteCount < 4)) rc = -EIO; /* bad smb */ /* else if (pFindData){ memcpy((char *) pFindData, @@ -3214,6 +3428,7 @@ of list */ /* check that each element of each entry does not go beyond end of list */ + __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); struct fealist * ea_response_data; rc = -ENOENT; /* validate_trans2_offsets() */ diff -Nru a/fs/cifs/connect.c b/fs/cifs/connect.c --- a/fs/cifs/connect.c 2004-11-17 19:45:14 -08:00 +++ b/fs/cifs/connect.c 2004-11-17 19:45:15 -08:00 @@ -69,6 +69,7 @@ unsigned intr:1; unsigned setuids:1; unsigned noperm:1; + unsigned server_ino:1; /* use inode numbers from server ie UniqueId */ unsigned int rsize; unsigned int wsize; unsigned int sockopt; @@ -335,7 +336,7 @@ (checkSMBhdr (smb_buffer, smb_buffer->Mid))) { cERROR(1, - ("Invalid size or format for SMB found with length %d and pdu_lenght %d", + ("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)); /* could we fix this network corruption by finding next @@ -742,6 +743,8 @@ /* ignore */ } else if (strnicmp(data, "version", 3) == 0) { /* ignore */ + } else if (strnicmp(data, "guest",5) == 0) { + /* ignore */ } else if (strnicmp(data, "rw", 2) == 0) { vol->rw = TRUE; } else if ((strnicmp(data, "suid", 4) == 0) || @@ -780,6 +783,10 @@ vol->intr = 0; } else if (strnicmp(data, "intr", 4) == 0) { vol->intr = 1; + } else if (strnicmp(data, "serverino",7) == 0) { + vol->server_ino = 1; + } else if (strnicmp(data, "noserverino",9) == 0) { + vol->server_ino = 0; } else if (strnicmp(data, "noac", 4) == 0) { printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n"); } else @@ -1393,6 +1400,8 @@ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM; if(volume_info.setuids) cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID; + if(volume_info.server_ino) + cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM; tcon = find_unc(sin_server.sin_addr.s_addr, volume_info.UNC, diff -Nru a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c --- a/fs/cifs/fcntl.c 2004-11-17 19:45:14 -08:00 +++ b/fs/cifs/fcntl.c 2004-11-17 19:45:14 -08:00 @@ -37,7 +37,7 @@ struct cifsTconInfo *pTcon; char *full_path = NULL; __u32 filter = FILE_NOTIFY_CHANGE_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES; - __u16 netfid; + __u16 netfid; xid = GetXid(); cifs_sb = CIFS_SB(file->f_dentry->d_sb); diff -Nru a/fs/cifs/file.c b/fs/cifs/file.c --- a/fs/cifs/file.c 2004-11-17 19:45:14 -08:00 +++ b/fs/cifs/file.c 2004-11-17 19:45:14 -08:00 @@ -1376,23 +1376,22 @@ cFYI(0, ("CIFS FFIRST: Attributes came in as 0x%x", attr)); - if (attr & ATTR_REPARSE) { - *pobject_type = DT_LNK; - /* BB can this and S_IFREG or S_IFDIR be set as in Windows? */ - tmp_inode->i_mode |= S_IFLNK; - } else if (attr & ATTR_DIRECTORY) { + if (attr & ATTR_DIRECTORY) { *pobject_type = DT_DIR; /* override default perms since we do not lock dirs */ if(atomic_read(&cifsInfo->inUse) == 0) { tmp_inode->i_mode = cifs_sb->mnt_dir_mode; } tmp_inode->i_mode |= S_IFDIR; +/* we no longer mark these because we could not follow them */ +/* } else if (attr & ATTR_REPARSE) { + *pobject_type = DT_LNK; + tmp_inode->i_mode |= S_IFLNK;*/ } else { *pobject_type = DT_REG; tmp_inode->i_mode |= S_IFREG; if(attr & ATTR_READONLY) tmp_inode->i_mode &= ~(S_IWUGO); - }/* could add code here - to validate if device or weird share type? */ /* can not fill in nlink here as in qpathinfo version and Unx search */ @@ -1516,13 +1515,16 @@ } } -static void +/* Returns one if new inode created (which therefore needs to be hashed) */ +/* Might check in the future if inode number changed so we can rehash inode */ +static int construct_dentry(struct qstr *qstring, struct file *file, struct inode **ptmp_inode, struct dentry **pnew_dentry) { struct dentry *tmp_dentry; struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; + int rc = 0; cFYI(1, ("For %s ", qstring->name)); cifs_sb = CIFS_SB(file->f_dentry->d_sb); @@ -1537,29 +1539,30 @@ if(*ptmp_inode == NULL) { *ptmp_inode = new_inode(file->f_dentry->d_sb); if(*ptmp_inode == NULL) - return; + return rc; + rc = 1; d_instantiate(tmp_dentry, *ptmp_inode); - insert_inode_hash(*ptmp_inode); } } else { tmp_dentry = d_alloc(file->f_dentry, qstring); if(tmp_dentry == NULL) { cERROR(1,("Failed allocating dentry")); *ptmp_inode = NULL; - return; + return rc; } *ptmp_inode = new_inode(file->f_dentry->d_sb); tmp_dentry->d_op = &cifs_dentry_ops; if(*ptmp_inode == NULL) - return; + return rc; + rc = 1; d_instantiate(tmp_dentry, *ptmp_inode); d_rehash(tmp_dentry); - insert_inode_hash(*ptmp_inode); } tmp_dentry->d_time = jiffies; *pnew_dentry = tmp_dentry; + return rc; } static void reset_resume_key(struct file * dir_file, @@ -1609,11 +1612,19 @@ pqstring->name = pfindData->FileName; /* pqstring->len is already set by caller */ - construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry); + 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) { @@ -1637,11 +1648,19 @@ pqstring->name = pUnixFindData->FileName; pqstring->len = strnlen(pUnixFindData->FileName, MAX_PATHCONF); - construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry); + 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); diff -Nru a/fs/cifs/inode.c b/fs/cifs/inode.c --- a/fs/cifs/inode.c 2004-11-17 19:45:14 -08:00 +++ b/fs/cifs/inode.c 2004-11-17 19:45:14 -08:00 @@ -85,6 +85,13 @@ *pinode = new_inode(sb); if(*pinode == NULL) return -ENOMEM; + /* Is an i_ino of zero legal? */ + /* Are there sanity checks we can use to ensure that + the server is really filling in that field? */ + if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { + (*pinode)->i_ino = + (unsigned long)findData.UniqueId; + } /* note ino incremented to unique num in new_inode */ insert_inode_hash(*pinode); } @@ -244,6 +251,21 @@ *pinode = new_inode(sb); if(*pinode == NULL) return -ENOMEM; + /* Is an i_ino of zero legal? */ + /* Are there sanity checks we can use to ensure that + the server is really filling in that field? */ + + /* We can not use the IndexNumber from either + Windows or Samba as it is frequently set to zero */ + /* There may be higher info levels that work but + Are there Windows server or network appliances + for which IndexNumber field is not guaranteed unique? */ + + /* if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { + (*pinode)->i_ino = + (unsigned long)pfindData->IndexNumber; + } */ /*NB: ino incremented to unique num in new_inode*/ + insert_inode_hash(*pinode); } inode = *pinode; @@ -273,10 +295,10 @@ /* new inode, can safely set these fields */ inode->i_mode = cifs_sb->mnt_file_mode; - if (attr & ATTR_REPARSE) { - /* Can IFLNK be set as it basically is on windows with IFREG or IFDIR? */ - inode->i_mode |= S_IFLNK; - } else if (attr & ATTR_DIRECTORY) { +/* if (attr & ATTR_REPARSE) */ +/* We no longer handle these as symlinks because we could not */ +/* follow them due to the absolute path with drive letter */ + if (attr & ATTR_DIRECTORY) { /* override default perms since we do not do byte range locking on dirs */ inode->i_mode = cifs_sb->mnt_dir_mode; inode->i_mode |= S_IFDIR; diff -Nru a/fs/cifs/readdir.c b/fs/cifs/readdir.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/fs/cifs/readdir.c 2004-11-17 19:45:15 -08:00 @@ -0,0 +1,205 @@ +/* + * fs/cifs/readdir.c + * + * Directory search handling + * + * Copyright (C) International Business Machines Corp., 2004 + * Author(s): Steve French (sfrench@us.ibm.com) + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include "cifspdu.h" +#include "cifsglob.h" +#include "cifsproto.h" +#include "cifs_unicode.h" +#include "cifs_debug.h" +#include "cifs_fs_sb.h" + +#ifdef CIFS_EXPERIMENTAL +extern int CIFSFindFirst2(const int xid, struct cifsTconInfo *tcon, + const char *searchName, const struct nls_table *nls_codepage, + char ** ppfindData /* first search entries */, + char ** ppbuf /* beginning of smb response */, + int *searchCount, __u16 *searchHandle, + int *pUnicodeFlag, int *pEndOfSearchFlag, int *level); + +static int initiate_cifs_search(const int xid, struct file * file, char * full_path) +{ + int rc = 0; + struct cifsFileInfo * cifsFile; + struct cifs_sb_info *cifs_sb; + struct cifsTconInfo *pTcon; + char * pfindData; + char * pbuf; + int Unicode; + int EndOfSearch; + int level; + + if(file->private_data == NULL) { + file->private_data = + kmalloc(sizeof(struct cifsFileInfo),GFP_KERNEL); + + if(file->private_data == NULL) { + return -ENOMEM; + } else { + memset(file->private_data,0,sizeof(struct cifsFileInfo)); + } + } + /* if not end of search do we have to close it first? */ + cifsFile = (struct cifsFileInfo *)file->private_data; + cifsFile->invalidHandle = TRUE; + + cifs_sb = CIFS_SB(file->f_dentry->d_sb); + if(cifs_sb == NULL) + return -EINVAL; + + pTcon = cifs_sb->tcon; + if(pTcon == NULL) + return -EINVAL; + + rc = CIFSFindFirst2(xid, pTcon,full_path,cifs_sb->local_nls, + &pfindData /* first search entries */, + &pbuf /* beginning of smb response */, + &cifsFile->entries_in_buffer, &cifsFile->netfid, + &EndOfSearch,&Unicode,&level); + + if(EndOfSearch) + cifsFile->endOfSearch = TRUE; + + return rc; +} + +/* find the corresponding entry in the search */ +static int find_cifs_entry(loff_t index_to_find /* BB add missing parm */) +{ + int rc = 0; + + return rc; +} + +int cifs_readdir2(struct file *file, void *direntry, filldir_t filldir) +{ + int rc = 0; + int xid; + struct cifs_sb_info *cifs_sb; + struct cifsTconInfo *pTcon; + struct cifsFileInfo *cifsFile = NULL; + char *full_path = NULL; + +/* int Unicode = FALSE; + int UnixSearch = FALSE; + unsigned int bufsize, i; + __u16 searchHandle; + 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;*/ + + xid = GetXid(); + + if(file->f_dentry == NULL) { + FreeXid(xid); + return -EIO; + } + + cifs_sb = CIFS_SB(file->f_dentry->d_sb); + pTcon = cifs_sb->tcon; + if(pTcon == NULL) + return -EINVAL; + + 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) { + 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 ")); + rc = -ENOMEM; + 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 ")); + rc = -ENOMEM; + break; + } + file->f_pos++; + /* fallthrough */ + default: + /* 1) If search is active, + is in current search buffer? + if it before then restart search + if after then keep searching till find it */ + + if(file->private_data == NULL) { + rc = initiate_cifs_search(xid,file,full_path); + if(rc) { + FreeXid(xid); + if(full_path) + kfree(full_path); + return rc; + } + } + + find_cifs_entry(file->f_pos); + /*close search or seek to right position */ + if (file->private_data) { + cifsFile = (struct cifsFileInfo *) file->private_data; + if (cifsFile->endOfSearch) { + if(cifsFile->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; + } + } + /* 2) initiate search, */ + /* 3) seek into search buffer */ + /* 4) if not found && later - FindNext */ + /* else if earlier in search, close search and + restart, continuing search till found or EndOfSearch */ + } + + if (full_path) + kfree(full_path); + + FreeXid(xid); + return rc; +} +#endif /* CIFS_EXPERIMENTAL */ diff -Nru a/fs/cifs/transport.c b/fs/cifs/transport.c --- a/fs/cifs/transport.c 2004-11-17 19:45:14 -08:00 +++ b/fs/cifs/transport.c 2004-11-17 19:45:14 -08:00 @@ -176,6 +176,129 @@ return rc; } +#ifdef CIFS_EXPERIMENTAL + +int +CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses, + struct smb_hdr *in_buf, struct kvec * /* page list */, int *pbytes_returned, const int long_op) +{ + int rc = 0; + unsigned int receive_len; + unsigned long timeout; + struct mid_q_entry *midQ; + + if (ses == NULL) { + cERROR(1,("Null smb session")); + return -EIO; + } + if(ses->server == NULL) { + cERROR(1,("Null tcp session")); + return -EIO; + } + + /* Ensure that we do not send more than 50 overlapping requests + to the same server. We may make this configurable later or + use ses->maxReq */ + if(long_op == -1) { + /* oplock breaks must not be held up */ + atomic_inc(&ses->server->inFlight); + } else { + spin_lock(&GlobalMid_Lock); + while(1) { + if(atomic_read(&ses->server->inFlight) >= CIFS_MAX_REQ){ + spin_unlock(&GlobalMid_Lock); + wait_event(ses->server->request_q, + atomic_read(&ses->server->inFlight) + < CIFS_MAX_REQ); + spin_lock(&GlobalMid_Lock); + } else { + if(ses->server->tcpStatus == CifsExiting) { + spin_unlock(&GlobalMid_Lock); + return -ENOENT; + } + + /* can not count locking commands against total since + they are allowed to block on server */ + + if(long_op < 3) { + /* update # of requests on the wire to server */ + atomic_inc(&ses->server->inFlight); + } + spin_unlock(&GlobalMid_Lock); + break; + } + } + } + /* make sure that we sign in the same order that we send on this socket + and avoid races inside tcp sendmsg code that could cause corruption + of smb data */ + + down(&ses->server->tcpSem); + + if (ses->server->tcpStatus == CifsExiting) { + rc = -ENOENT; + goto cifs_out_label; + } else if (ses->server->tcpStatus == CifsNeedReconnect) { + cFYI(1,("tcp session dead - return to caller to retry")); + rc = -EAGAIN; + goto cifs_out_label; + } else if (ses->status != CifsGood) { + /* check if SMB session is bad because we are setting it up */ + if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && + (in_buf->Command != SMB_COM_NEGOTIATE)) { + rc = -EAGAIN; + goto cifs_out_label; + } /* else ok - we are setting up session */ + } + midQ = AllocMidQEntry(in_buf, ses); + if (midQ == NULL) { + up(&ses->server->tcpSem); + /* If not lock req, update # of requests on wire to server */ + if(long_op < 3) { + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); + } + return -ENOMEM; + } + + if (in_buf->smb_buf_length > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4) { + up(&ses->server->tcpSem); + cERROR(1, + ("Illegal length, greater than maximum frame, %d ", + in_buf->smb_buf_length)); + DeleteMidQEntry(midQ); + /* If not lock req, update # of requests on wire to server */ + if(long_op < 3) { + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); + } + return -EIO; + } + + /* BB can we sign efficiently in this path? */ + 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, + (struct sockaddr *) &(ses->server->addr.sockAddr)); + if(rc < 0) { + DeleteMidQEntry(midQ); + up(&ses->server->tcpSem); + /* If not lock req, update # of requests on wire to server */ + if(long_op < 3) { + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); + } + return rc; + } else + up(&ses->server->tcpSem); + + return rc; +} + + +#endif /* CIFS_EXPERIMENTAL */ + int SendReceive(const unsigned int xid, struct cifsSesInfo *ses, struct smb_hdr *in_buf, struct smb_hdr *out_buf,