aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/cifs_debug.c10
-rw-r--r--fs/cifs/cifs_fs_sb.h2
-rw-r--r--fs/cifs/cifsglob.h10
-rw-r--r--fs/cifs/cifspdu.h56
-rw-r--r--fs/cifs/cifsproto.h13
-rw-r--r--fs/cifs/cifssmb.c181
-rw-r--r--fs/cifs/connect.c27
-rw-r--r--fs/cifs/dir.c54
-rw-r--r--fs/cifs/fcntl.c2
-rw-r--r--fs/cifs/file.c24
-rw-r--r--fs/cifs/inode.c24
-rw-r--r--fs/cifs/link.c15
-rw-r--r--fs/cifs/netmisc.c4
-rw-r--r--fs/cifs/readdir.c27
-rw-r--r--fs/cifs/transport.c225
-rw-r--r--fs/cifs/xattr.c8
16 files changed, 541 insertions, 141 deletions
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 4061e43471c1..838171328076 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -283,6 +283,12 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
283 atomic_read(&tcon->num_t2renames)); 283 atomic_read(&tcon->num_t2renames));
284 buf += item_length; 284 buf += item_length;
285 length += item_length; 285 length += item_length;
286 item_length = sprintf(buf,"\nFindFirst: %d FNext %d FClose %d",
287 atomic_read(&tcon->num_ffirst),
288 atomic_read(&tcon->num_fnext),
289 atomic_read(&tcon->num_fclose));
290 buf += item_length;
291 length += item_length;
286 } 292 }
287 read_unlock(&GlobalSMBSeslock); 293 read_unlock(&GlobalSMBSeslock);
288 294
@@ -360,7 +366,7 @@ cifs_proc_init(void)
360 if (pde) 366 if (pde)
361 pde->write_proc = oplockEnabled_write; 367 pde->write_proc = oplockEnabled_write;
362 368
363 pde = create_proc_read_entry("ReenableOldCifsReaddirCode", 0, proc_fs_cifs, 369 pde = create_proc_read_entry("Experimental", 0, proc_fs_cifs,
364 quotaEnabled_read, NULL); 370 quotaEnabled_read, NULL);
365 if (pde) 371 if (pde)
366 pde->write_proc = quotaEnabled_write; 372 pde->write_proc = quotaEnabled_write;
@@ -419,7 +425,7 @@ cifs_proc_clean(void)
419 remove_proc_entry("ExtendedSecurity",proc_fs_cifs); 425 remove_proc_entry("ExtendedSecurity",proc_fs_cifs);
420 remove_proc_entry("PacketSigningEnabled",proc_fs_cifs); 426 remove_proc_entry("PacketSigningEnabled",proc_fs_cifs);
421 remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs); 427 remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs);
422 remove_proc_entry("ReenableOldCifsReaddirCode",proc_fs_cifs); 428 remove_proc_entry("Experimental",proc_fs_cifs);
423 remove_proc_entry("LookupCacheEnabled",proc_fs_cifs); 429 remove_proc_entry("LookupCacheEnabled",proc_fs_cifs);
424 remove_proc_entry("cifs", proc_root_fs); 430 remove_proc_entry("cifs", proc_root_fs);
425} 431}
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index ec00d61d5308..6b93587c490e 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -24,6 +24,8 @@
24#define CIFS_MOUNT_DIRECT_IO 8 /* do not write nor read through page cache */ 24#define CIFS_MOUNT_DIRECT_IO 8 /* do not write nor read through page cache */
25#define CIFS_MOUNT_NO_XATTR 0x10 /* if set - disable xattr support */ 25#define CIFS_MOUNT_NO_XATTR 0x10 /* if set - disable xattr support */
26#define CIFS_MOUNT_MAP_SPECIAL_CHR 0x20 /* remap illegal chars in filenames */ 26#define CIFS_MOUNT_MAP_SPECIAL_CHR 0x20 /* remap illegal chars in filenames */
27#define CIFS_MOUNT_POSIX_PATHS 0x40 /* Negotiate posix pathnames if possible. */
28#define CIFS_MOUNT_UNX_EMUL 0x80 /* Network compat with SFUnix emulation */
27 29
28struct cifs_sb_info { 30struct cifs_sb_info {
29 struct cifsTconInfo *tcon; /* primary mount */ 31 struct cifsTconInfo *tcon; /* primary mount */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 81babab265e1..d3773e57acf9 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -219,6 +219,9 @@ struct cifsTconInfo {
219 atomic_t num_rmdirs; 219 atomic_t num_rmdirs;
220 atomic_t num_renames; 220 atomic_t num_renames;
221 atomic_t num_t2renames; 221 atomic_t num_t2renames;
222 atomic_t num_ffirst;
223 atomic_t num_fnext;
224 atomic_t num_fclose;
222 __u64 bytes_read; 225 __u64 bytes_read;
223 __u64 bytes_written; 226 __u64 bytes_written;
224 spinlock_t stat_lock; 227 spinlock_t stat_lock;
@@ -306,6 +309,13 @@ CIFS_SB(struct super_block *sb)
306 return sb->s_fs_info; 309 return sb->s_fs_info;
307} 310}
308 311
312static inline const char CIFS_DIR_SEP(const struct cifs_sb_info *cifs_sb)
313{
314 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
315 return '/';
316 else
317 return '\\';
318}
309 319
310/* one of these for every pending CIFS request to the server */ 320/* one of these for every pending CIFS request to the server */
311struct mid_q_entry { 321struct mid_q_entry {
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index aede6a813167..3cef57b7a34f 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -59,6 +59,7 @@
59#define TRANS2_FIND_FIRST 0x01 59#define TRANS2_FIND_FIRST 0x01
60#define TRANS2_FIND_NEXT 0x02 60#define TRANS2_FIND_NEXT 0x02
61#define TRANS2_QUERY_FS_INFORMATION 0x03 61#define TRANS2_QUERY_FS_INFORMATION 0x03
62#define TRANS2_SET_FS_INFORMATION 0x04
62#define TRANS2_QUERY_PATH_INFORMATION 0x05 63#define TRANS2_QUERY_PATH_INFORMATION 0x05
63#define TRANS2_SET_PATH_INFORMATION 0x06 64#define TRANS2_SET_PATH_INFORMATION 0x06
64#define TRANS2_QUERY_FILE_INFORMATION 0x07 65#define TRANS2_QUERY_FILE_INFORMATION 0x07
@@ -267,10 +268,18 @@
267/* CreateOptions */ 268/* CreateOptions */
268#define CREATE_NOT_FILE 0x00000001 /* if set must not be file */ 269#define CREATE_NOT_FILE 0x00000001 /* if set must not be file */
269#define CREATE_WRITE_THROUGH 0x00000002 270#define CREATE_WRITE_THROUGH 0x00000002
270#define CREATE_NOT_DIR 0x00000040 /* if set must not be directory */ 271#define CREATE_SEQUENTIAL 0x00000004
272#define CREATE_SYNC_ALERT 0x00000010
273#define CREATE_ASYNC_ALERT 0x00000020
274#define CREATE_NOT_DIR 0x00000040 /* if set must not be directory */
275#define CREATE_NO_EA_KNOWLEDGE 0x00000200
276#define CREATE_EIGHT_DOT_THREE 0x00000400
271#define CREATE_RANDOM_ACCESS 0x00000800 277#define CREATE_RANDOM_ACCESS 0x00000800
272#define CREATE_DELETE_ON_CLOSE 0x00001000 278#define CREATE_DELETE_ON_CLOSE 0x00001000
279#define CREATE_OPEN_BY_ID 0x00002000
273#define OPEN_REPARSE_POINT 0x00200000 280#define OPEN_REPARSE_POINT 0x00200000
281#define CREATE_OPTIONS_MASK 0x007FFFFF
282#define CREATE_OPTION_SPECIAL 0x20000000 /* system. NB not sent over wire */
274 283
275/* ImpersonationLevel flags */ 284/* ImpersonationLevel flags */
276#define SECURITY_ANONYMOUS 0 285#define SECURITY_ANONYMOUS 0
@@ -1411,6 +1420,43 @@ typedef struct smb_com_transaction_qfsi_rsp {
1411 __u8 Pad; /* may be three bytes *//* followed by data area */ 1420 __u8 Pad; /* may be three bytes *//* followed by data area */
1412} TRANSACTION2_QFSI_RSP; 1421} TRANSACTION2_QFSI_RSP;
1413 1422
1423
1424/* SETFSInfo Levels */
1425#define SMB_SET_CIFS_UNIX_INFO 0x200
1426typedef struct smb_com_transaction2_setfsi_req {
1427 struct smb_hdr hdr; /* wct = 15 */
1428 __le16 TotalParameterCount;
1429 __le16 TotalDataCount;
1430 __le16 MaxParameterCount;
1431 __le16 MaxDataCount;
1432 __u8 MaxSetupCount;
1433 __u8 Reserved;
1434 __le16 Flags;
1435 __le32 Timeout;
1436 __u16 Reserved2;
1437 __le16 ParameterCount; /* 4 */
1438 __le16 ParameterOffset;
1439 __le16 DataCount; /* 12 */
1440 __le16 DataOffset;
1441 __u8 SetupCount; /* one */
1442 __u8 Reserved3;
1443 __le16 SubCommand; /* TRANS2_SET_FS_INFORMATION */
1444 __le16 ByteCount;
1445 __u8 Pad;
1446 __u16 FileNum; /* Parameters start. */
1447 __le16 InformationLevel;/* Parameters end. */
1448 __le16 ClientUnixMajor; /* Data start. */
1449 __le16 ClientUnixMinor;
1450 __le64 ClientUnixCap; /* Data end */
1451} TRANSACTION2_SETFSI_REQ;
1452
1453typedef struct smb_com_transaction2_setfsi_rsp {
1454 struct smb_hdr hdr; /* wct = 10 */
1455 struct trans2_resp t2;
1456 __u16 ByteCount;
1457} TRANSACTION2_SETFSI_RSP;
1458
1459
1414typedef struct smb_com_transaction2_get_dfs_refer_req { 1460typedef struct smb_com_transaction2_get_dfs_refer_req {
1415 struct smb_hdr hdr; /* wct = 15 */ 1461 struct smb_hdr hdr; /* wct = 15 */
1416 __le16 TotalParameterCount; 1462 __le16 TotalParameterCount;
@@ -1551,12 +1597,20 @@ typedef struct {
1551 __le16 MinorVersionNumber; 1597 __le16 MinorVersionNumber;
1552 __le64 Capability; 1598 __le64 Capability;
1553} FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */ 1599} FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */
1600
1601/* Version numbers for CIFS UNIX major and minor. */
1602#define CIFS_UNIX_MAJOR_VERSION 1
1603#define CIFS_UNIX_MINOR_VERSION 0
1604
1554/* Linux/Unix extensions capability flags */ 1605/* Linux/Unix extensions capability flags */
1555#define CIFS_UNIX_FCNTL_CAP 0x00000001 /* support for fcntl locks */ 1606#define CIFS_UNIX_FCNTL_CAP 0x00000001 /* support for fcntl locks */
1556#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 /* support getfacl/setfacl */ 1607#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 /* support getfacl/setfacl */
1557#define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */ 1608#define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */
1558#define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */ 1609#define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */
1610#define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x00000010 /* Use POSIX pathnames on the wire. */
1611
1559#define CIFS_POSIX_EXTENSIONS 0x00000010 /* support for new QFSInfo */ 1612#define CIFS_POSIX_EXTENSIONS 0x00000010 /* support for new QFSInfo */
1613
1560typedef struct { 1614typedef struct {
1561 /* For undefined recommended transfer size return -1 in that field */ 1615 /* For undefined recommended transfer size return -1 in that field */
1562 __le32 OptimalTransferSize; /* bsize on some os, iosize on other os */ 1616 __le32 OptimalTransferSize; /* bsize on some os, iosize on other os */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index ea239dea571e..66eaa6b40373 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -40,13 +40,17 @@ extern unsigned int _GetXid(void);
40extern void _FreeXid(unsigned int); 40extern void _FreeXid(unsigned int);
41#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->fsuid)); 41#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->fsuid));
42#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,(int)rc));} 42#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,(int)rc));}
43extern char *build_path_from_dentry(struct dentry *); 43extern char *build_path_from_dentry(struct dentry *, const struct cifs_sb_info *cifs_sb);
44extern char *build_wildcard_path_from_dentry(struct dentry *direntry); 44extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
45extern void renew_parental_timestamps(struct dentry *direntry); 45extern void renew_parental_timestamps(struct dentry *direntry);
46extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *, 46extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
47 struct smb_hdr * /* input */ , 47 struct smb_hdr * /* input */ ,
48 struct smb_hdr * /* out */ , 48 struct smb_hdr * /* out */ ,
49 int * /* bytes returned */ , const int long_op); 49 int * /* bytes returned */ , const int long_op);
50extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *,
51 struct smb_hdr * /* input */ , int hdr_len,
52 const char * /* SMB data to send */ , int data_len,
53 int * /* bytes returned */ , const int long_op);
50extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid); 54extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid);
51extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length); 55extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length);
52extern int is_valid_oplock_break(struct smb_hdr *smb); 56extern int is_valid_oplock_break(struct smb_hdr *smb);
@@ -89,7 +93,7 @@ extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
89 93
90extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, 94extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
91 const char *searchName, const struct nls_table *nls_codepage, 95 const char *searchName, const struct nls_table *nls_codepage,
92 __u16 *searchHandle, struct cifs_search_info * psrch_inf, int map); 96 __u16 *searchHandle, struct cifs_search_info * psrch_inf, int map, const char dirsep);
93 97
94extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, 98extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
95 __u16 searchHandle, struct cifs_search_info * psrch_inf); 99 __u16 searchHandle, struct cifs_search_info * psrch_inf);
@@ -125,6 +129,9 @@ extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
125 int remap); 129 int remap);
126extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, 130extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
127 struct kstatfs *FSData); 131 struct kstatfs *FSData);
132extern int CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
133 __u64 cap);
134
128extern int CIFSSMBQFSAttributeInfo(const int xid, 135extern int CIFSSMBQFSAttributeInfo(const int xid,
129 struct cifsTconInfo *tcon); 136 struct cifsTconInfo *tcon);
130extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon); 137extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon);
@@ -222,7 +229,7 @@ extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
222extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, 229extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
223 const int netfid, const unsigned int count, 230 const int netfid, const unsigned int count,
224 const __u64 offset, unsigned int *nbytes, 231 const __u64 offset, unsigned int *nbytes,
225 const char __user *buf,const int long_op); 232 const char *buf,const int long_op);
226extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, 233extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
227 const unsigned char *searchName, __u64 * inode_number, 234 const unsigned char *searchName, __u64 * inode_number,
228 const struct nls_table *nls_codepage, 235 const struct nls_table *nls_codepage,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 0db0b313d715..459320222cf7 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -415,15 +415,16 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
415 if(server->secMode & SECMODE_SIGN_REQUIRED) 415 if(server->secMode & SECMODE_SIGN_REQUIRED)
416 cERROR(1, 416 cERROR(1,
417 ("Server requires /proc/fs/cifs/PacketSigningEnabled")); 417 ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
418 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED); 418 server->secMode &= ~(SECMODE_SIGN_ENABLED |
419 SECMODE_SIGN_REQUIRED);
419 } else if(sign_CIFS_PDUs == 1) { 420 } else if(sign_CIFS_PDUs == 1) {
420 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0) 421 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
421 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED); 422 server->secMode &= ~(SECMODE_SIGN_ENABLED |
423 SECMODE_SIGN_REQUIRED);
422 } 424 }
423 425
424 } 426 }
425 if (pSMB) 427 cifs_buf_release(pSMB);
426 cifs_buf_release(pSMB);
427 return rc; 428 return rc;
428} 429}
429 430
@@ -537,9 +538,8 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
537 rc = -ESHUTDOWN; 538 rc = -ESHUTDOWN;
538 } 539 }
539 } 540 }
540 if (pSMB) 541 up(&ses->sesSem)
541 cifs_small_buf_release(pSMB); 542 cifs_small_buf_release(pSMB);
542 up(&ses->sesSem);
543 543
544 /* if session dead then we do not need to do ulogoff, 544 /* if session dead then we do not need to do ulogoff,
545 since server closed smb session, no sense reporting 545 since server closed smb session, no sense reporting
@@ -738,7 +738,13 @@ openRetry:
738 } 738 }
739 pSMB->DesiredAccess = cpu_to_le32(access_flags); 739 pSMB->DesiredAccess = cpu_to_le32(access_flags);
740 pSMB->AllocationSize = 0; 740 pSMB->AllocationSize = 0;
741 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL); 741 /* set file as system file if special file such
742 as fifo and server expecting SFU style and
743 no Unix extensions */
744 if(create_options & CREATE_OPTION_SPECIAL)
745 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
746 else
747 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
742 /* XP does not handle ATTR_POSIX_SEMANTICS */ 748 /* XP does not handle ATTR_POSIX_SEMANTICS */
743 /* but it helps speed up case sensitive checks for other 749 /* but it helps speed up case sensitive checks for other
744 servers such as Samba */ 750 servers such as Samba */
@@ -752,7 +758,7 @@ openRetry:
752 being created */ 758 being created */
753 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL); 759 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
754 pSMB->CreateDisposition = cpu_to_le32(openDisposition); 760 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
755 pSMB->CreateOptions = cpu_to_le32(create_options); 761 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
756 /* BB Expirement with various impersonation levels and verify */ 762 /* BB Expirement with various impersonation levels and verify */
757 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); 763 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
758 pSMB->SecurityFlags = 764 pSMB->SecurityFlags =
@@ -951,56 +957,69 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
951} 957}
952 958
953#ifdef CONFIG_CIFS_EXPERIMENTAL 959#ifdef CONFIG_CIFS_EXPERIMENTAL
954int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, 960int
961CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
955 const int netfid, const unsigned int count, 962 const int netfid, const unsigned int count,
956 const __u64 offset, unsigned int *nbytes, const char __user *buf, 963 const __u64 offset, unsigned int *nbytes, const char *buf,
957 const int long_op) 964 const int long_op)
958{ 965{
959 int rc = -EACCES; 966 int rc = -EACCES;
960 WRITE_REQ *pSMB = NULL; 967 WRITE_REQ *pSMB = NULL;
961 WRITE_RSP *pSMBr = NULL; 968 int bytes_returned;
962 /*int bytes_returned;*/ 969 int smb_hdr_len;
963 unsigned bytes_sent; 970 __u32 bytes_sent;
964 __u16 byte_count; 971 __u16 byte_count;
965 972
973 cFYI(1,("write2 at %lld %d bytes",offset,count)); /* BB removeme BB */
966 rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB); 974 rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB);
967
968 if (rc) 975 if (rc)
969 return rc; 976 return rc;
970
971 pSMBr = (WRITE_RSP *)pSMB; /* BB removeme BB */
972
973 /* tcon and ses pointer are checked in smb_init */ 977 /* tcon and ses pointer are checked in smb_init */
974 if (tcon->ses->server == NULL) 978 if (tcon->ses->server == NULL)
975 return -ECONNABORTED; 979 return -ECONNABORTED;
976 980
977 pSMB->AndXCommand = 0xFF; /* none */ 981 pSMB->AndXCommand = 0xFF; /* none */
978 pSMB->Fid = netfid; 982 pSMB->Fid = netfid;
979 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); 983 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
980 pSMB->OffsetHigh = cpu_to_le32(offset >> 32); 984 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
981 pSMB->Reserved = 0xFFFFFFFF; 985 pSMB->Reserved = 0xFFFFFFFF;
982 pSMB->WriteMode = 0; 986 pSMB->WriteMode = 0;
983 pSMB->Remaining = 0; 987 pSMB->Remaining = 0;
984 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF; 988
989 /* Can increase buffer size if buffer is big enough in some cases - ie
990 can send more if LARGE_WRITE_X capability returned by the server and if
991 our buffer is big enough or if we convert to iovecs on socket writes
992 and eliminate the copy to the CIFS buffer */
993 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
994 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
995 } else {
996 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
997 & ~0xFF;
998 }
999
985 if (bytes_sent > count) 1000 if (bytes_sent > count)
986 bytes_sent = count; 1001 bytes_sent = count;
987 pSMB->DataLengthHigh = 0;
988 pSMB->DataOffset = 1002 pSMB->DataOffset =
989 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4); 1003 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
990 1004
991 byte_count = bytes_sent + 1 /* pad */ ; 1005 byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
992 pSMB->DataLengthLow = cpu_to_le16(bytes_sent); 1006 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
993 pSMB->DataLengthHigh = 0; 1007 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
994 pSMB->hdr.smb_buf_length += byte_count; 1008 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1009 pSMB->hdr.smb_buf_length += bytes_sent+1;
995 pSMB->ByteCount = cpu_to_le16(byte_count); 1010 pSMB->ByteCount = cpu_to_le16(byte_count);
996 1011
997/* rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB, 1012 rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB, smb_hdr_len,
998 (struct smb_hdr *) pSMBr, buf, buflen, &bytes_returned, long_op); */ /* BB fixme BB */ 1013 buf, bytes_sent, &bytes_returned, long_op);
999 if (rc) { 1014 if (rc) {
1000 cFYI(1, ("Send error in write2 (large write) = %d", rc)); 1015 cFYI(1, ("Send error in write = %d", rc));
1001 *nbytes = 0; 1016 *nbytes = 0;
1002 } else 1017 } else {
1003 *nbytes = le16_to_cpu(pSMBr->Count); 1018 WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB;
1019 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1020 *nbytes = (*nbytes) << 16;
1021 *nbytes += le16_to_cpu(pSMBr->Count);
1022 }
1004 1023
1005 cifs_small_buf_release(pSMB); 1024 cifs_small_buf_release(pSMB);
1006 1025
@@ -1009,6 +1028,8 @@ int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1009 1028
1010 return rc; 1029 return rc;
1011} 1030}
1031
1032
1012#endif /* CIFS_EXPERIMENTAL */ 1033#endif /* CIFS_EXPERIMENTAL */
1013 1034
1014int 1035int
@@ -1775,8 +1796,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1775 } 1796 }
1776 } 1797 }
1777qreparse_out: 1798qreparse_out:
1778 if (pSMB) 1799 cifs_buf_release(pSMB);
1779 cifs_buf_release(pSMB);
1780 1800
1781 /* Note: On -EAGAIN error only caller can retry on handle based calls 1801 /* Note: On -EAGAIN error only caller can retry on handle based calls
1782 since file handle passed in no longer valid */ 1802 since file handle passed in no longer valid */
@@ -2396,7 +2416,9 @@ findUniqueRetry:
2396 if (rc) { 2416 if (rc) {
2397 cFYI(1, ("Send error in FindFileDirInfo = %d", rc)); 2417 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
2398 } else { /* decode response */ 2418 } else { /* decode response */
2399 2419#ifdef CONFIG_CIFS_STATS
2420 atomic_inc(&tcon->num_ffirst);
2421#endif
2400 /* BB fill in */ 2422 /* BB fill in */
2401 } 2423 }
2402 2424
@@ -2414,7 +2436,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
2414 const char *searchName, 2436 const char *searchName,
2415 const struct nls_table *nls_codepage, 2437 const struct nls_table *nls_codepage,
2416 __u16 * pnetfid, 2438 __u16 * pnetfid,
2417 struct cifs_search_info * psrch_inf, int remap) 2439 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
2418{ 2440{
2419/* level 257 SMB_ */ 2441/* level 257 SMB_ */
2420 TRANSACTION2_FFIRST_REQ *pSMB = NULL; 2442 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
@@ -2441,7 +2463,7 @@ findFirstRetry:
2441 it got remapped to 0xF03A as if it were part of the 2463 it got remapped to 0xF03A as if it were part of the
2442 directory name instead of a wildcard */ 2464 directory name instead of a wildcard */
2443 name_len *= 2; 2465 name_len *= 2;
2444 pSMB->FileName[name_len] = '\\'; 2466 pSMB->FileName[name_len] = dirsep;
2445 pSMB->FileName[name_len+1] = 0; 2467 pSMB->FileName[name_len+1] = 0;
2446 pSMB->FileName[name_len+2] = '*'; 2468 pSMB->FileName[name_len+2] = '*';
2447 pSMB->FileName[name_len+3] = 0; 2469 pSMB->FileName[name_len+3] = 0;
@@ -2455,7 +2477,7 @@ findFirstRetry:
2455 if(name_len > buffersize-header) 2477 if(name_len > buffersize-header)
2456 free buffer exit; BB */ 2478 free buffer exit; BB */
2457 strncpy(pSMB->FileName, searchName, name_len); 2479 strncpy(pSMB->FileName, searchName, name_len);
2458 pSMB->FileName[name_len] = '\\'; 2480 pSMB->FileName[name_len] = dirsep;
2459 pSMB->FileName[name_len+1] = '*'; 2481 pSMB->FileName[name_len+1] = '*';
2460 pSMB->FileName[name_len+2] = 0; 2482 pSMB->FileName[name_len+2] = 0;
2461 name_len += 3; 2483 name_len += 3;
@@ -2497,18 +2519,20 @@ findFirstRetry:
2497 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 2519 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2498 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 2520 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2499 2521
2500 if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */ 2522 if (rc) {/* BB add logic to retry regular search if Unix search
2523 rejected unexpectedly by server */
2501 /* BB Add code to handle unsupported level rc */ 2524 /* BB Add code to handle unsupported level rc */
2502 cFYI(1, ("Error in FindFirst = %d", rc)); 2525 cFYI(1, ("Error in FindFirst = %d", rc));
2503 2526 cifs_buf_release(pSMB);
2504 if (pSMB)
2505 cifs_buf_release(pSMB);
2506 2527
2507 /* BB eventually could optimize out free and realloc of buf */ 2528 /* BB eventually could optimize out free and realloc of buf */
2508 /* for this case */ 2529 /* for this case */
2509 if (rc == -EAGAIN) 2530 if (rc == -EAGAIN)
2510 goto findFirstRetry; 2531 goto findFirstRetry;
2511 } else { /* decode response */ 2532 } else { /* decode response */
2533#ifdef CONFIG_CIFS_STATS
2534 atomic_inc(&tcon->num_ffirst);
2535#endif
2512 /* BB remember to free buffer if error BB */ 2536 /* BB remember to free buffer if error BB */
2513 rc = validate_t2((struct smb_t2_rsp *)pSMBr); 2537 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2514 if(rc == 0) { 2538 if(rc == 0) {
@@ -2625,6 +2649,9 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
2625 } else 2649 } else
2626 cFYI(1, ("FindNext returned = %d", rc)); 2650 cFYI(1, ("FindNext returned = %d", rc));
2627 } else { /* decode response */ 2651 } else { /* decode response */
2652#ifdef CONFIG_CIFS_STATS
2653 atomic_inc(&tcon->num_fnext);
2654#endif
2628 rc = validate_t2((struct smb_t2_rsp *)pSMBr); 2655 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2629 2656
2630 if(rc == 0) { 2657 if(rc == 0) {
@@ -2694,6 +2721,9 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle
2694 if (rc) { 2721 if (rc) {
2695 cERROR(1, ("Send error in FindClose = %d", rc)); 2722 cERROR(1, ("Send error in FindClose = %d", rc));
2696 } 2723 }
2724#ifdef CONFIG_CIFS_STATS
2725 atomic_inc(&tcon->num_fclose);
2726#endif
2697 cifs_small_buf_release(pSMB); 2727 cifs_small_buf_release(pSMB);
2698 2728
2699 /* Since session is dead, search handle closed on server already */ 2729 /* Since session is dead, search handle closed on server already */
@@ -3257,6 +3287,77 @@ QFSUnixRetry:
3257 return rc; 3287 return rc;
3258} 3288}
3259 3289
3290int
3291CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
3292{
3293/* level 0x200 SMB_SET_CIFS_UNIX_INFO */
3294 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
3295 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
3296 int rc = 0;
3297 int bytes_returned = 0;
3298 __u16 params, param_offset, offset, byte_count;
3299
3300 cFYI(1, ("In SETFSUnixInfo"));
3301SETFSUnixRetry:
3302 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3303 (void **) &pSMBr);
3304 if (rc)
3305 return rc;
3306
3307 params = 4; /* 2 bytes zero followed by info level. */
3308 pSMB->MaxSetupCount = 0;
3309 pSMB->Reserved = 0;
3310 pSMB->Flags = 0;
3311 pSMB->Timeout = 0;
3312 pSMB->Reserved2 = 0;
3313 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
3314 offset = param_offset + params;
3315
3316 pSMB->MaxParameterCount = cpu_to_le16(4);
3317 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3318 pSMB->SetupCount = 1;
3319 pSMB->Reserved3 = 0;
3320 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
3321 byte_count = 1 /* pad */ + params + 12;
3322
3323 pSMB->DataCount = cpu_to_le16(12);
3324 pSMB->ParameterCount = cpu_to_le16(params);
3325 pSMB->TotalDataCount = pSMB->DataCount;
3326 pSMB->TotalParameterCount = pSMB->ParameterCount;
3327 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3328 pSMB->DataOffset = cpu_to_le16(offset);
3329
3330 /* Params. */
3331 pSMB->FileNum = 0;
3332 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
3333
3334 /* Data. */
3335 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
3336 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
3337 pSMB->ClientUnixCap = cpu_to_le64(cap);
3338
3339 pSMB->hdr.smb_buf_length += byte_count;
3340 pSMB->ByteCount = cpu_to_le16(byte_count);
3341
3342 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3343 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3344 if (rc) {
3345 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
3346 } else { /* decode response */
3347 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3348 if (rc) {
3349 rc = -EIO; /* bad smb */
3350 }
3351 }
3352 cifs_buf_release(pSMB);
3353
3354 if (rc == -EAGAIN)
3355 goto SETFSUnixRetry;
3356
3357 return rc;
3358}
3359
3360
3260 3361
3261int 3362int
3262CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, 3363CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index e568cc47a7f9..36f78596c81a 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -74,6 +74,8 @@ struct smb_vol {
74 unsigned server_ino:1; /* use inode numbers from server ie UniqueId */ 74 unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
75 unsigned direct_io:1; 75 unsigned direct_io:1;
76 unsigned remap:1; /* set to remap seven reserved chars in filenames */ 76 unsigned remap:1; /* set to remap seven reserved chars in filenames */
77 unsigned posix_paths:1; /* unset to not ask for posix pathnames. */
78 unsigned sfu_emul:1;
77 unsigned int rsize; 79 unsigned int rsize;
78 unsigned int wsize; 80 unsigned int wsize;
79 unsigned int sockopt; 81 unsigned int sockopt;
@@ -745,6 +747,9 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
745 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ 747 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
746 vol->rw = TRUE; 748 vol->rw = TRUE;
747 749
750 /* default is always to request posix paths. */
751 vol->posix_paths = 1;
752
748 if (!options) 753 if (!options)
749 return 1; 754 return 1;
750 755
@@ -1023,6 +1028,14 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
1023 vol->remap = 1; 1028 vol->remap = 1;
1024 } else if (strnicmp(data, "nomapchars", 10) == 0) { 1029 } else if (strnicmp(data, "nomapchars", 10) == 0) {
1025 vol->remap = 0; 1030 vol->remap = 0;
1031 } else if (strnicmp(data, "sfu", 3) == 0) {
1032 vol->sfu_emul = 1;
1033 } else if (strnicmp(data, "nosfu", 5) == 0) {
1034 vol->sfu_emul = 0;
1035 } else if (strnicmp(data, "posixpaths", 10) == 0) {
1036 vol->posix_paths = 1;
1037 } else if (strnicmp(data, "noposixpaths", 12) == 0) {
1038 vol->posix_paths = 0;
1026 } else if (strnicmp(data, "setuids", 7) == 0) { 1039 } else if (strnicmp(data, "setuids", 7) == 0) {
1027 vol->setuids = 1; 1040 vol->setuids = 1;
1028 } else if (strnicmp(data, "nosetuids", 9) == 0) { 1041 } else if (strnicmp(data, "nosetuids", 9) == 0) {
@@ -1679,6 +1692,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1679 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR; 1692 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1680 if(volume_info.no_xattr) 1693 if(volume_info.no_xattr)
1681 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR; 1694 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1695 if(volume_info.sfu_emul)
1696 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
1697
1682 if(volume_info.direct_io) { 1698 if(volume_info.direct_io) {
1683 cERROR(1,("mounting share using direct i/o")); 1699 cERROR(1,("mounting share using direct i/o"));
1684 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; 1700 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
@@ -1781,6 +1797,17 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1781 cFYI(1,("server negotiated posix acl support")); 1797 cFYI(1,("server negotiated posix acl support"));
1782 sb->s_flags |= MS_POSIXACL; 1798 sb->s_flags |= MS_POSIXACL;
1783 } 1799 }
1800
1801 /* Try and negotiate POSIX pathnames if we can. */
1802 if (volume_info.posix_paths && (CIFS_UNIX_POSIX_PATHNAMES_CAP &
1803 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
1804 if (!CIFSSMBSetFSUnixInfo(xid, tcon, CIFS_UNIX_POSIX_PATHNAMES_CAP)) {
1805 cFYI(1,("negotiated posix pathnames support"));
1806 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
1807 } else {
1808 cFYI(1,("posix pathnames support requested but not supported"));
1809 }
1810 }
1784 } 1811 }
1785 } 1812 }
1786 } 1813 }
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 3f3538d4a1fa..c619d45060ce 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -43,7 +43,7 @@ renew_parental_timestamps(struct dentry *direntry)
43 43
44/* Note: caller must free return buffer */ 44/* Note: caller must free return buffer */
45char * 45char *
46build_path_from_dentry(struct dentry *direntry) 46build_path_from_dentry(struct dentry *direntry, const struct cifs_sb_info *cifs_sb)
47{ 47{
48 struct dentry *temp; 48 struct dentry *temp;
49 int namelen = 0; 49 int namelen = 0;
@@ -74,7 +74,7 @@ cifs_bp_rename_retry:
74 if (namelen < 0) { 74 if (namelen < 0) {
75 break; 75 break;
76 } else { 76 } else {
77 full_path[namelen] = '\\'; 77 full_path[namelen] = CIFS_DIR_SEP(cifs_sb);
78 strncpy(full_path + namelen + 1, temp->d_name.name, 78 strncpy(full_path + namelen + 1, temp->d_name.name,
79 temp->d_name.len); 79 temp->d_name.len);
80 cFYI(0, (" name: %s ", full_path + namelen)); 80 cFYI(0, (" name: %s ", full_path + namelen));
@@ -138,7 +138,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
138 pTcon = cifs_sb->tcon; 138 pTcon = cifs_sb->tcon;
139 139
140 down(&direntry->d_sb->s_vfs_rename_sem); 140 down(&direntry->d_sb->s_vfs_rename_sem);
141 full_path = build_path_from_dentry(direntry); 141 full_path = build_path_from_dentry(direntry, cifs_sb);
142 up(&direntry->d_sb->s_vfs_rename_sem); 142 up(&direntry->d_sb->s_vfs_rename_sem);
143 if(full_path == NULL) { 143 if(full_path == NULL) {
144 FreeXid(xid); 144 FreeXid(xid);
@@ -209,7 +209,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
209 CIFS_MOUNT_MAP_SPECIAL_CHR); 209 CIFS_MOUNT_MAP_SPECIAL_CHR);
210 } 210 }
211 else { 211 else {
212 /* BB implement via Windows security descriptors */ 212 /* BB implement mode setting via Windows security descriptors */
213 /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/ 213 /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
214 /* could set r/o dos attribute if mode & 0222 == 0 */ 214 /* could set r/o dos attribute if mode & 0222 == 0 */
215 } 215 }
@@ -226,7 +226,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
226 } 226 }
227 227
228 if (rc != 0) { 228 if (rc != 0) {
229 cFYI(1,("Create worked but get_inode_info failed with rc = %d", 229 cFYI(1,
230 ("Create worked but get_inode_info failed rc = %d",
230 rc)); 231 rc));
231 } else { 232 } else {
232 direntry->d_op = &cifs_dentry_ops; 233 direntry->d_op = &cifs_dentry_ops;
@@ -299,12 +300,11 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev
299 pTcon = cifs_sb->tcon; 300 pTcon = cifs_sb->tcon;
300 301
301 down(&direntry->d_sb->s_vfs_rename_sem); 302 down(&direntry->d_sb->s_vfs_rename_sem);
302 full_path = build_path_from_dentry(direntry); 303 full_path = build_path_from_dentry(direntry, cifs_sb);
303 up(&direntry->d_sb->s_vfs_rename_sem); 304 up(&direntry->d_sb->s_vfs_rename_sem);
304 if(full_path == NULL) 305 if(full_path == NULL)
305 rc = -ENOMEM; 306 rc = -ENOMEM;
306 307 else if (pTcon->ses->capabilities & CAP_UNIX) {
307 if (full_path && (pTcon->ses->capabilities & CAP_UNIX)) {
308 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 308 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
309 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, 309 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
310 mode,(__u64)current->euid,(__u64)current->egid, 310 mode,(__u64)current->euid,(__u64)current->egid,
@@ -326,6 +326,42 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev
326 if(rc == 0) 326 if(rc == 0)
327 d_instantiate(direntry, newinode); 327 d_instantiate(direntry, newinode);
328 } 328 }
329 } else {
330 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
331 int oplock = 0;
332 u16 fileHandle;
333 FILE_ALL_INFO * buf;
334
335 cFYI(1,("sfu compat create special file"));
336
337 buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
338 if(buf == NULL) {
339 kfree(full_path);
340 FreeXid(xid);
341 return -ENOMEM;
342 }
343
344 rc = CIFSSMBOpen(xid, pTcon, full_path,
345 FILE_CREATE, /* fail if exists */
346 GENERIC_WRITE /* BB would
347 WRITE_OWNER | WRITE_DAC be better? */,
348 /* Create a file and set the
349 file attribute to SYSTEM */
350 CREATE_NOT_DIR | CREATE_OPTION_SPECIAL,
351 &fileHandle, &oplock, buf,
352 cifs_sb->local_nls,
353 cifs_sb->mnt_cifs_flags &
354 CIFS_MOUNT_MAP_SPECIAL_CHR);
355
356 if(!rc) {
357 /* BB Do not bother to decode buf since no
358 local inode yet to put timestamps in */
359 CIFSSMBClose(xid, pTcon, fileHandle);
360 d_drop(direntry);
361 }
362 kfree(buf);
363 /* add code here to set EAs */
364 }
329 } 365 }
330 366
331 kfree(full_path); 367 kfree(full_path);
@@ -360,7 +396,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
360 /* can not grab the rename sem here since it would 396 /* can not grab the rename sem here since it would
361 deadlock in the cases (beginning of sys_rename itself) 397 deadlock in the cases (beginning of sys_rename itself)
362 in which we already have the sb rename sem */ 398 in which we already have the sb rename sem */
363 full_path = build_path_from_dentry(direntry); 399 full_path = build_path_from_dentry(direntry, cifs_sb);
364 if(full_path == NULL) { 400 if(full_path == NULL) {
365 FreeXid(xid); 401 FreeXid(xid);
366 return ERR_PTR(-ENOMEM); 402 return ERR_PTR(-ENOMEM);
diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c
index 7d2a9202c39a..d47ce7f49dc3 100644
--- a/fs/cifs/fcntl.c
+++ b/fs/cifs/fcntl.c
@@ -83,7 +83,7 @@ int cifs_dir_notify(struct file * file, unsigned long arg)
83 pTcon = cifs_sb->tcon; 83 pTcon = cifs_sb->tcon;
84 84
85 down(&file->f_dentry->d_sb->s_vfs_rename_sem); 85 down(&file->f_dentry->d_sb->s_vfs_rename_sem);
86 full_path = build_path_from_dentry(file->f_dentry); 86 full_path = build_path_from_dentry(file->f_dentry, cifs_sb);
87 up(&file->f_dentry->d_sb->s_vfs_rename_sem); 87 up(&file->f_dentry->d_sb->s_vfs_rename_sem);
88 88
89 if(full_path == NULL) { 89 if(full_path == NULL) {
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 30ab70ce5547..ddb25a0a63d5 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -196,7 +196,7 @@ int cifs_open(struct inode *inode, struct file *file)
196 } 196 }
197 197
198 down(&inode->i_sb->s_vfs_rename_sem); 198 down(&inode->i_sb->s_vfs_rename_sem);
199 full_path = build_path_from_dentry(file->f_dentry); 199 full_path = build_path_from_dentry(file->f_dentry, cifs_sb);
200 up(&inode->i_sb->s_vfs_rename_sem); 200 up(&inode->i_sb->s_vfs_rename_sem);
201 if (full_path == NULL) { 201 if (full_path == NULL) {
202 FreeXid(xid); 202 FreeXid(xid);
@@ -359,7 +359,7 @@ static int cifs_reopen_file(struct inode *inode, struct file *file,
359 those that already have the rename sem can end up causing writepage 359 those that already have the rename sem can end up causing writepage
360 to get called and if the server was down that means we end up here, 360 to get called and if the server was down that means we end up here,
361 and we can never tell if the caller already has the rename_sem */ 361 and we can never tell if the caller already has the rename_sem */
362 full_path = build_path_from_dentry(file->f_dentry); 362 full_path = build_path_from_dentry(file->f_dentry, cifs_sb);
363 if (full_path == NULL) { 363 if (full_path == NULL) {
364 up(&pCifsFile->fh_sem); 364 up(&pCifsFile->fh_sem);
365 FreeXid(xid); 365 FreeXid(xid);
@@ -791,9 +791,8 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
791 791
792 pTcon = cifs_sb->tcon; 792 pTcon = cifs_sb->tcon;
793 793
794 /* cFYI(1, 794 cFYI(1,(" write %d bytes to offset %lld of %s", write_size,
795 (" write %d bytes to offset %lld of %s", write_size, 795 *poffset, file->f_dentry->d_name.name)); /* BB removeme BB */
796 *poffset, file->f_dentry->d_name.name)); */
797 796
798 if (file->private_data == NULL) 797 if (file->private_data == NULL)
799 return -EBADF; 798 return -EBADF;
@@ -846,7 +845,20 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
846 if (rc != 0) 845 if (rc != 0)
847 break; 846 break;
848 } 847 }
849 848#ifdef CONFIG_CIFS_EXPERIMENTAL
849 /* BB FIXME We can not sign across two buffers yet */
850 if((experimEnabled) && ((pTcon->ses->server->secMode &
851 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) == 0)) {
852 rc = CIFSSMBWrite2(xid, pTcon,
853 open_file->netfid,
854 min_t(const int, cifs_sb->wsize,
855 write_size - total_written),
856 *poffset, &bytes_written,
857 write_data + total_written,
858 long_op);
859 } else
860 /* BB FIXME fixup indentation of line below */
861#endif
850 rc = CIFSSMBWrite(xid, pTcon, 862 rc = CIFSSMBWrite(xid, pTcon,
851 open_file->netfid, 863 open_file->netfid,
852 min_t(const int, cifs_sb->wsize, 864 min_t(const int, cifs_sb->wsize,
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 8d336a900255..628aa1a9fe64 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -320,6 +320,16 @@ int cifs_get_inode_info(struct inode **pinode,
320 on dirs */ 320 on dirs */
321 inode->i_mode = cifs_sb->mnt_dir_mode; 321 inode->i_mode = cifs_sb->mnt_dir_mode;
322 inode->i_mode |= S_IFDIR; 322 inode->i_mode |= S_IFDIR;
323 } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
324 (cifsInfo->cifsAttrs & ATTR_SYSTEM) &&
325 /* No need to le64 convert size of zero */
326 (pfindData->EndOfFile == 0)) {
327 inode->i_mode = cifs_sb->mnt_file_mode;
328 inode->i_mode |= S_IFIFO;
329/* BB Finish for SFU style symlinks and devies */
330/* } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
331 (cifsInfo->cifsAttrs & ATTR_SYSTEM) && ) */
332
323 } else { 333 } else {
324 inode->i_mode |= S_IFREG; 334 inode->i_mode |= S_IFREG;
325 /* treat the dos attribute of read-only as read-only 335 /* treat the dos attribute of read-only as read-only
@@ -412,7 +422,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
412 /* Unlink can be called from rename so we can not grab the sem here 422 /* Unlink can be called from rename so we can not grab the sem here
413 since we deadlock otherwise */ 423 since we deadlock otherwise */
414/* down(&direntry->d_sb->s_vfs_rename_sem);*/ 424/* down(&direntry->d_sb->s_vfs_rename_sem);*/
415 full_path = build_path_from_dentry(direntry); 425 full_path = build_path_from_dentry(direntry, cifs_sb);
416/* up(&direntry->d_sb->s_vfs_rename_sem);*/ 426/* up(&direntry->d_sb->s_vfs_rename_sem);*/
417 if (full_path == NULL) { 427 if (full_path == NULL) {
418 FreeXid(xid); 428 FreeXid(xid);
@@ -556,7 +566,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
556 pTcon = cifs_sb->tcon; 566 pTcon = cifs_sb->tcon;
557 567
558 down(&inode->i_sb->s_vfs_rename_sem); 568 down(&inode->i_sb->s_vfs_rename_sem);
559 full_path = build_path_from_dentry(direntry); 569 full_path = build_path_from_dentry(direntry, cifs_sb);
560 up(&inode->i_sb->s_vfs_rename_sem); 570 up(&inode->i_sb->s_vfs_rename_sem);
561 if (full_path == NULL) { 571 if (full_path == NULL) {
562 FreeXid(xid); 572 FreeXid(xid);
@@ -627,7 +637,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
627 pTcon = cifs_sb->tcon; 637 pTcon = cifs_sb->tcon;
628 638
629 down(&inode->i_sb->s_vfs_rename_sem); 639 down(&inode->i_sb->s_vfs_rename_sem);
630 full_path = build_path_from_dentry(direntry); 640 full_path = build_path_from_dentry(direntry, cifs_sb);
631 up(&inode->i_sb->s_vfs_rename_sem); 641 up(&inode->i_sb->s_vfs_rename_sem);
632 if (full_path == NULL) { 642 if (full_path == NULL) {
633 FreeXid(xid); 643 FreeXid(xid);
@@ -680,8 +690,8 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
680 690
681 /* we already have the rename sem so we do not need to grab it again 691 /* we already have the rename sem so we do not need to grab it again
682 here to protect the path integrity */ 692 here to protect the path integrity */
683 fromName = build_path_from_dentry(source_direntry); 693 fromName = build_path_from_dentry(source_direntry, cifs_sb_source);
684 toName = build_path_from_dentry(target_direntry); 694 toName = build_path_from_dentry(target_direntry, cifs_sb_target);
685 if ((fromName == NULL) || (toName == NULL)) { 695 if ((fromName == NULL) || (toName == NULL)) {
686 rc = -ENOMEM; 696 rc = -ENOMEM;
687 goto cifs_rename_exit; 697 goto cifs_rename_exit;
@@ -797,7 +807,7 @@ int cifs_revalidate(struct dentry *direntry)
797 807
798 /* can not safely grab the rename sem here if rename calls revalidate 808 /* can not safely grab the rename sem here if rename calls revalidate
799 since that would deadlock */ 809 since that would deadlock */
800 full_path = build_path_from_dentry(direntry); 810 full_path = build_path_from_dentry(direntry, cifs_sb);
801 if (full_path == NULL) { 811 if (full_path == NULL) {
802 FreeXid(xid); 812 FreeXid(xid);
803 return -ENOMEM; 813 return -ENOMEM;
@@ -946,7 +956,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
946 pTcon = cifs_sb->tcon; 956 pTcon = cifs_sb->tcon;
947 957
948 down(&direntry->d_sb->s_vfs_rename_sem); 958 down(&direntry->d_sb->s_vfs_rename_sem);
949 full_path = build_path_from_dentry(direntry); 959 full_path = build_path_from_dentry(direntry, cifs_sb);
950 up(&direntry->d_sb->s_vfs_rename_sem); 960 up(&direntry->d_sb->s_vfs_rename_sem);
951 if (full_path == NULL) { 961 if (full_path == NULL) {
952 FreeXid(xid); 962 FreeXid(xid);
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index bde0fabfece0..214aa816f669 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -49,8 +49,8 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
49 BB note DFS case in future though (when we may have to check) */ 49 BB note DFS case in future though (when we may have to check) */
50 50
51 down(&inode->i_sb->s_vfs_rename_sem); 51 down(&inode->i_sb->s_vfs_rename_sem);
52 fromName = build_path_from_dentry(old_file); 52 fromName = build_path_from_dentry(old_file, cifs_sb_target);
53 toName = build_path_from_dentry(direntry); 53 toName = build_path_from_dentry(direntry, cifs_sb_target);
54 up(&inode->i_sb->s_vfs_rename_sem); 54 up(&inode->i_sb->s_vfs_rename_sem);
55 if((fromName == NULL) || (toName == NULL)) { 55 if((fromName == NULL) || (toName == NULL)) {
56 rc = -ENOMEM; 56 rc = -ENOMEM;
@@ -105,16 +105,17 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
105 105
106 xid = GetXid(); 106 xid = GetXid();
107 107
108 cifs_sb = CIFS_SB(inode->i_sb);
109 pTcon = cifs_sb->tcon;
110
108 down(&direntry->d_sb->s_vfs_rename_sem); 111 down(&direntry->d_sb->s_vfs_rename_sem);
109 full_path = build_path_from_dentry(direntry); 112 full_path = build_path_from_dentry(direntry, cifs_sb);
110 up(&direntry->d_sb->s_vfs_rename_sem); 113 up(&direntry->d_sb->s_vfs_rename_sem);
111 114
112 if (!full_path) 115 if (!full_path)
113 goto out_no_free; 116 goto out_no_free;
114 117
115 cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode)); 118 cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode));
116 cifs_sb = CIFS_SB(inode->i_sb);
117 pTcon = cifs_sb->tcon;
118 target_path = kmalloc(PATH_MAX, GFP_KERNEL); 119 target_path = kmalloc(PATH_MAX, GFP_KERNEL);
119 if (!target_path) { 120 if (!target_path) {
120 target_path = ERR_PTR(-ENOMEM); 121 target_path = ERR_PTR(-ENOMEM);
@@ -167,7 +168,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
167 pTcon = cifs_sb->tcon; 168 pTcon = cifs_sb->tcon;
168 169
169 down(&inode->i_sb->s_vfs_rename_sem); 170 down(&inode->i_sb->s_vfs_rename_sem);
170 full_path = build_path_from_dentry(direntry); 171 full_path = build_path_from_dentry(direntry, cifs_sb);
171 up(&inode->i_sb->s_vfs_rename_sem); 172 up(&inode->i_sb->s_vfs_rename_sem);
172 173
173 if(full_path == NULL) { 174 if(full_path == NULL) {
@@ -233,7 +234,7 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
233/* BB would it be safe against deadlock to grab this sem 234/* BB would it be safe against deadlock to grab this sem
234 even though rename itself grabs the sem and calls lookup? */ 235 even though rename itself grabs the sem and calls lookup? */
235/* down(&inode->i_sb->s_vfs_rename_sem);*/ 236/* down(&inode->i_sb->s_vfs_rename_sem);*/
236 full_path = build_path_from_dentry(direntry); 237 full_path = build_path_from_dentry(direntry, cifs_sb);
237/* up(&inode->i_sb->s_vfs_rename_sem);*/ 238/* up(&inode->i_sb->s_vfs_rename_sem);*/
238 239
239 if(full_path == NULL) { 240 if(full_path == NULL) {
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index a92af41d4411..873b812c0f40 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -133,7 +133,6 @@ static const struct smb_to_posix_error mapping_table_ERRHRD[] = {
133int 133int
134cifs_inet_pton(int address_family, char *cp,void *dst) 134cifs_inet_pton(int address_family, char *cp,void *dst)
135{ 135{
136 struct in_addr address;
137 int value; 136 int value;
138 int digit; 137 int digit;
139 int i; 138 int i;
@@ -190,8 +189,7 @@ cifs_inet_pton(int address_family, char *cp,void *dst)
190 if (value > addr_class_max[end - bytes]) 189 if (value > addr_class_max[end - bytes])
191 return 0; 190 return 0;
192 191
193 address.s_addr = *((__be32 *) bytes) | htonl(value); 192 *((__be32 *)dst) = *((__be32 *) bytes) | htonl(value);
194 *((__be32 *)dst) = address.s_addr;
195 return 1; /* success */ 193 return 1; /* success */
196} 194}
197 195
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 22557716f9af..dec3c9dd04d7 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -148,6 +148,13 @@ static void fill_in_inode(struct inode *tmp_inode,
148 tmp_inode->i_mode = cifs_sb->mnt_dir_mode; 148 tmp_inode->i_mode = cifs_sb->mnt_dir_mode;
149 } 149 }
150 tmp_inode->i_mode |= S_IFDIR; 150 tmp_inode->i_mode |= S_IFDIR;
151 } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
152 (attr & ATTR_SYSTEM) && (end_of_file == 0)) {
153 *pobject_type = DT_FIFO;
154 tmp_inode->i_mode |= S_IFIFO;
155/* BB Finish for SFU style symlinks and devies */
156/* } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
157 (attr & ATTR_SYSTEM) && ) { */
151/* we no longer mark these because we could not follow them */ 158/* we no longer mark these because we could not follow them */
152/* } else if (attr & ATTR_REPARSE) { 159/* } else if (attr & ATTR_REPARSE) {
153 *pobject_type = DT_LNK; 160 *pobject_type = DT_LNK;
@@ -190,8 +197,9 @@ static void fill_in_inode(struct inode *tmp_inode,
190 tmp_inode->i_data.a_ops = &cifs_addr_ops; 197 tmp_inode->i_data.a_ops = &cifs_addr_ops;
191 198
192 if(isNewInode) 199 if(isNewInode)
193 return; /* No sense invalidating pages for new inode since we 200 return; /* No sense invalidating pages for new inode
194 have not started caching readahead file data yet */ 201 since have not started caching readahead file
202 data yet */
195 203
196 if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && 204 if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
197 (local_size == tmp_inode->i_size)) { 205 (local_size == tmp_inode->i_size)) {
@@ -353,7 +361,7 @@ static int initiate_cifs_search(const int xid, struct file *file)
353 return -EINVAL; 361 return -EINVAL;
354 362
355 down(&file->f_dentry->d_sb->s_vfs_rename_sem); 363 down(&file->f_dentry->d_sb->s_vfs_rename_sem);
356 full_path = build_path_from_dentry(file->f_dentry); 364 full_path = build_path_from_dentry(file->f_dentry, cifs_sb);
357 up(&file->f_dentry->d_sb->s_vfs_rename_sem); 365 up(&file->f_dentry->d_sb->s_vfs_rename_sem);
358 366
359 if(full_path == NULL) { 367 if(full_path == NULL) {
@@ -374,7 +382,7 @@ ffirst_retry:
374 382
375 rc = CIFSFindFirst(xid, pTcon,full_path,cifs_sb->local_nls, 383 rc = CIFSFindFirst(xid, pTcon,full_path,cifs_sb->local_nls,
376 &cifsFile->netfid, &cifsFile->srch_inf, 384 &cifsFile->netfid, &cifsFile->srch_inf,
377 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 385 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb));
378 if(rc == 0) 386 if(rc == 0)
379 cifsFile->invalidHandle = FALSE; 387 cifsFile->invalidHandle = FALSE;
380 if((rc == -EOPNOTSUPP) && 388 if((rc == -EOPNOTSUPP) &&
@@ -536,7 +544,8 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
536 while((index_to_find >= cifsFile->srch_inf.index_of_last_entry) && 544 while((index_to_find >= cifsFile->srch_inf.index_of_last_entry) &&
537 (rc == 0) && (cifsFile->srch_inf.endOfSearch == FALSE)){ 545 (rc == 0) && (cifsFile->srch_inf.endOfSearch == FALSE)){
538 cFYI(1,("calling findnext2")); 546 cFYI(1,("calling findnext2"));
539 rc = CIFSFindNext(xid,pTcon,cifsFile->netfid, &cifsFile->srch_inf); 547 rc = CIFSFindNext(xid,pTcon,cifsFile->netfid,
548 &cifsFile->srch_inf);
540 if(rc) 549 if(rc)
541 return -ENOENT; 550 return -ENOENT;
542 } 551 }
@@ -555,7 +564,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
555 cFYI(1,("found entry - pos_in_buf %d",pos_in_buf)); 564 cFYI(1,("found entry - pos_in_buf %d",pos_in_buf));
556 current_entry = cifsFile->srch_inf.srch_entries_start; 565 current_entry = cifsFile->srch_inf.srch_entries_start;
557 for(i=0;(i<(pos_in_buf)) && (current_entry != NULL);i++) { 566 for(i=0;(i<(pos_in_buf)) && (current_entry != NULL);i++) {
558 /* go entry to next entry figuring out which we need to start with */ 567 /* go entry by entry figuring out which is first */
559 /* if( . or ..) 568 /* if( . or ..)
560 skip */ 569 skip */
561 rc = cifs_entry_is_dot(current_entry,cifsFile); 570 rc = cifs_entry_is_dot(current_entry,cifsFile);
@@ -721,7 +730,8 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
721 (FILE_DIRECTORY_INFO *)pfindEntry,&obj_type, rc); 730 (FILE_DIRECTORY_INFO *)pfindEntry,&obj_type, rc);
722 } 731 }
723 732
724 rc = filldir(direntry,qstring.name,qstring.len,file->f_pos,tmp_inode->i_ino,obj_type); 733 rc = filldir(direntry,qstring.name,qstring.len,file->f_pos,
734 tmp_inode->i_ino,obj_type);
725 if(rc) { 735 if(rc) {
726 cFYI(1,("filldir rc = %d",rc)); 736 cFYI(1,("filldir rc = %d",rc));
727 } 737 }
@@ -906,7 +916,8 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
906 cifs_save_resume_key(current_entry,cifsFile); 916 cifs_save_resume_key(current_entry,cifsFile);
907 break; 917 break;
908 } else 918 } else
909 current_entry = nxt_dir_entry(current_entry,end_of_smb); 919 current_entry = nxt_dir_entry(current_entry,
920 end_of_smb);
910 } 921 }
911 kfree(tmp_buf); 922 kfree(tmp_buf);
912 break; 923 break;
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 0046c219833d..496a2738bbe3 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -49,7 +49,8 @@ AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
49 return NULL; 49 return NULL;
50 } 50 }
51 51
52 temp = (struct mid_q_entry *) mempool_alloc(cifs_mid_poolp,SLAB_KERNEL | SLAB_NOFS); 52 temp = (struct mid_q_entry *) mempool_alloc(cifs_mid_poolp,
53 SLAB_KERNEL | SLAB_NOFS);
53 if (temp == NULL) 54 if (temp == NULL)
54 return temp; 55 return temp;
55 else { 56 else {
@@ -179,27 +180,24 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
179 return rc; 180 return rc;
180} 181}
181 182
182#ifdef CIFS_EXPERIMENTAL 183#ifdef CONFIG_CIFS_EXPERIMENTAL
183/* BB finish off this function, adding support for writing set of pages as iovec */ 184static int
184/* and also adding support for operations that need to parse the response smb */ 185smb_send2(struct socket *ssocket, struct smb_hdr *smb_buffer,
185 186 unsigned int smb_hdr_length, const char * data, unsigned int datalen,
186int 187 struct sockaddr *sin)
187smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer,
188 unsigned int smb_buf_length, struct kvec * write_vector
189 /* page list */, struct sockaddr *sin)
190{ 188{
191 int rc = 0; 189 int rc = 0;
192 int i = 0; 190 int i = 0;
193 struct msghdr smb_msg; 191 struct msghdr smb_msg;
194 number_of_pages += 1; /* account for SMB header */ 192 struct kvec iov[2];
195 struct kvec * piov = kmalloc(number_of_pages * sizeof(struct kvec)); 193 unsigned len = smb_hdr_length + 4;
196 unsigned len = smb_buf_length + 4; 194
197
198 if(ssocket == NULL) 195 if(ssocket == NULL)
199 return -ENOTSOCK; /* BB eventually add reconnect code here */ 196 return -ENOTSOCK; /* BB eventually add reconnect code here */
200 iov.iov_base = smb_buffer; 197 iov[0].iov_base = smb_buffer;
201 iov.iov_len = len; 198 iov[0].iov_len = len;
202 199 iov[1].iov_base = data;
200 iov[1].iov_len = datalen;
203 smb_msg.msg_name = sin; 201 smb_msg.msg_name = sin;
204 smb_msg.msg_namelen = sizeof (struct sockaddr); 202 smb_msg.msg_namelen = sizeof (struct sockaddr);
205 smb_msg.msg_control = NULL; 203 smb_msg.msg_control = NULL;
@@ -212,12 +210,12 @@ smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer,
212 Flags2 is converted in SendReceive */ 210 Flags2 is converted in SendReceive */
213 211
214 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length); 212 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
215 cFYI(1, ("Sending smb of length %d ", smb_buf_length)); 213 cFYI(1, ("Sending smb: hdrlen %d datalen %d",
214 smb_hdr_length,datalen));
216 dump_smb(smb_buffer, len); 215 dump_smb(smb_buffer, len);
217 216
218 while (len > 0) { 217 while (len + datalen > 0) {
219 rc = kernel_sendmsg(ssocket, &smb_msg, &iov, number_of_pages, 218 rc = kernel_sendmsg(ssocket, &smb_msg, iov, 2, len);
220 len);
221 if ((rc == -ENOSPC) || (rc == -EAGAIN)) { 219 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
222 i++; 220 i++;
223 if(i > 60) { 221 if(i > 60) {
@@ -232,9 +230,23 @@ smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer,
232 } 230 }
233 if (rc < 0) 231 if (rc < 0)
234 break; 232 break;
235 iov.iov_base += rc; 233 if(iov[0].iov_len > 0) {
236 iov.iov_len -= rc; 234 if(rc >= len) {
237 len -= rc; 235 iov[0].iov_len = 0;
236 rc -= len;
237 len = 0;
238 } else { /* some of hdr was not sent */
239 len -= rc;
240 iov[0].iov_len -= rc;
241 iov[0].iov_base += rc;
242 continue;
243 }
244 }
245 if((iov[0].iov_len == 0) && (rc > 0)){
246 iov[1].iov_base += rc;
247 iov[1].iov_len -= rc;
248 datalen -= rc;
249 }
238 } 250 }
239 251
240 if (rc < 0) { 252 if (rc < 0) {
@@ -246,14 +258,15 @@ smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer,
246 return rc; 258 return rc;
247} 259}
248 260
249
250int 261int
251CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses, 262SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
252 struct smb_hdr *in_buf, struct kvec * write_vector /* page list */, int *pbytes_returned, const int long_op) 263 struct smb_hdr *in_buf, int hdrlen, const char * data,
264 int datalen, int *pbytes_returned, const int long_op)
253{ 265{
254 int rc = 0; 266 int rc = 0;
255 unsigned long timeout = 15 * HZ; 267 unsigned int receive_len;
256 struct mid_q_entry *midQ = NULL; 268 unsigned long timeout;
269 struct mid_q_entry *midQ;
257 270
258 if (ses == NULL) { 271 if (ses == NULL) {
259 cERROR(1,("Null smb session")); 272 cERROR(1,("Null smb session"));
@@ -263,14 +276,8 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
263 cERROR(1,("Null tcp session")); 276 cERROR(1,("Null tcp session"));
264 return -EIO; 277 return -EIO;
265 } 278 }
266 if(pbytes_returned == NULL)
267 return -EIO;
268 else
269 *pbytes_returned = 0;
270 279
271 280 if(ses->server->tcpStatus == CifsExiting)
272
273 if(ses->server->tcpStatus == CIFS_EXITING)
274 return -ENOENT; 281 return -ENOENT;
275 282
276 /* Ensure that we do not send more than 50 overlapping requests 283 /* Ensure that we do not send more than 50 overlapping requests
@@ -282,7 +289,8 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
282 } else { 289 } else {
283 spin_lock(&GlobalMid_Lock); 290 spin_lock(&GlobalMid_Lock);
284 while(1) { 291 while(1) {
285 if(atomic_read(&ses->server->inFlight) >= cifs_max_pending){ 292 if(atomic_read(&ses->server->inFlight) >=
293 cifs_max_pending){
286 spin_unlock(&GlobalMid_Lock); 294 spin_unlock(&GlobalMid_Lock);
287 wait_event(ses->server->request_q, 295 wait_event(ses->server->request_q,
288 atomic_read(&ses->server->inFlight) 296 atomic_read(&ses->server->inFlight)
@@ -314,17 +322,17 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
314 322
315 if (ses->server->tcpStatus == CifsExiting) { 323 if (ses->server->tcpStatus == CifsExiting) {
316 rc = -ENOENT; 324 rc = -ENOENT;
317 goto cifs_out_label; 325 goto out_unlock2;
318 } else if (ses->server->tcpStatus == CifsNeedReconnect) { 326 } else if (ses->server->tcpStatus == CifsNeedReconnect) {
319 cFYI(1,("tcp session dead - return to caller to retry")); 327 cFYI(1,("tcp session dead - return to caller to retry"));
320 rc = -EAGAIN; 328 rc = -EAGAIN;
321 goto cifs_out_label; 329 goto out_unlock2;
322 } else if (ses->status != CifsGood) { 330 } else if (ses->status != CifsGood) {
323 /* check if SMB session is bad because we are setting it up */ 331 /* check if SMB session is bad because we are setting it up */
324 if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && 332 if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
325 (in_buf->Command != SMB_COM_NEGOTIATE)) { 333 (in_buf->Command != SMB_COM_NEGOTIATE)) {
326 rc = -EAGAIN; 334 rc = -EAGAIN;
327 goto cifs_out_label; 335 goto out_unlock2;
328 } /* else ok - we are setting up session */ 336 } /* else ok - we are setting up session */
329 } 337 }
330 midQ = AllocMidQEntry(in_buf, ses); 338 midQ = AllocMidQEntry(in_buf, ses);
@@ -352,13 +360,12 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
352 return -EIO; 360 return -EIO;
353 } 361 }
354 362
355 /* BB can we sign efficiently in this path? */ 363/* BB FIXME */
356 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); 364/* rc = cifs_sign_smb2(in_buf, data, ses->server, &midQ->sequence_number); */
357 365
358 midQ->midState = MID_REQUEST_SUBMITTED; 366 midQ->midState = MID_REQUEST_SUBMITTED;
359/* rc = smb_sendv(ses->server->ssocket, in_buf, in_buf->smb_buf_length, 367 rc = smb_send2(ses->server->ssocket, in_buf, hdrlen, data, datalen,
360 piovec, 368 (struct sockaddr *) &(ses->server->addr.sockAddr));
361 (struct sockaddr *) &(ses->server->addr.sockAddr));*/
362 if(rc < 0) { 369 if(rc < 0) {
363 DeleteMidQEntry(midQ); 370 DeleteMidQEntry(midQ);
364 up(&ses->server->tcpSem); 371 up(&ses->server->tcpSem);
@@ -370,19 +377,137 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
370 return rc; 377 return rc;
371 } else 378 } else
372 up(&ses->server->tcpSem); 379 up(&ses->server->tcpSem);
373cifs_out_label: 380 if (long_op == -1)
374 if(midQ) 381 goto cifs_no_response_exit2;
375 DeleteMidQEntry(midQ); 382 else if (long_op == 2) /* writes past end of file can take loong time */
376 383 timeout = 300 * HZ;
384 else if (long_op == 1)
385 timeout = 45 * HZ; /* should be greater than
386 servers oplock break timeout (about 43 seconds) */
387 else if (long_op > 2) {
388 timeout = MAX_SCHEDULE_TIMEOUT;
389 } else
390 timeout = 15 * HZ;
391 /* wait for 15 seconds or until woken up due to response arriving or
392 due to last connection to this server being unmounted */
393 if (signal_pending(current)) {
394 /* if signal pending do not hold up user for full smb timeout
395 but we still give response a change to complete */
396 timeout = 2 * HZ;
397 }
398
399 /* No user interrupts in wait - wreaks havoc with performance */
400 if(timeout != MAX_SCHEDULE_TIMEOUT) {
401 timeout += jiffies;
402 wait_event(ses->server->response_q,
403 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
404 time_after(jiffies, timeout) ||
405 ((ses->server->tcpStatus != CifsGood) &&
406 (ses->server->tcpStatus != CifsNew)));
407 } else {
408 wait_event(ses->server->response_q,
409 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
410 ((ses->server->tcpStatus != CifsGood) &&
411 (ses->server->tcpStatus != CifsNew)));
412 }
413
414 spin_lock(&GlobalMid_Lock);
415 if (midQ->resp_buf) {
416 spin_unlock(&GlobalMid_Lock);
417 receive_len = be32_to_cpu(*(__be32 *)midQ->resp_buf);
418 } else {
419 cERROR(1,("No response buffer"));
420 if(midQ->midState == MID_REQUEST_SUBMITTED) {
421 if(ses->server->tcpStatus == CifsExiting)
422 rc = -EHOSTDOWN;
423 else {
424 ses->server->tcpStatus = CifsNeedReconnect;
425 midQ->midState = MID_RETRY_NEEDED;
426 }
427 }
428
429 if (rc != -EHOSTDOWN) {
430 if(midQ->midState == MID_RETRY_NEEDED) {
431 rc = -EAGAIN;
432 cFYI(1,("marking request for retry"));
433 } else {
434 rc = -EIO;
435 }
436 }
437 spin_unlock(&GlobalMid_Lock);
438 DeleteMidQEntry(midQ);
439 /* If not lock req, update # of requests on wire to server */
440 if(long_op < 3) {
441 atomic_dec(&ses->server->inFlight);
442 wake_up(&ses->server->request_q);
443 }
444 return rc;
445 }
446
447 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
448 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
449 receive_len, xid));
450 rc = -EIO;
451 } else { /* rcvd frame is ok */
452
453 if (midQ->resp_buf &&
454 (midQ->midState == MID_RESPONSE_RECEIVED)) {
455 in_buf->smb_buf_length = receive_len;
456 /* BB verify that length would not overrun small buf */
457 memcpy((char *)in_buf + 4,
458 (char *)midQ->resp_buf + 4,
459 receive_len);
460
461 dump_smb(in_buf, 80);
462 /* convert the length into a more usable form */
463 if((receive_len > 24) &&
464 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
465 SECMODE_SIGN_ENABLED))) {
466 rc = cifs_verify_signature(in_buf,
467 ses->server->mac_signing_key,
468 midQ->sequence_number+1);
469 if(rc) {
470 cERROR(1,("Unexpected SMB signature"));
471 /* BB FIXME add code to kill session */
472 }
473 }
474
475 *pbytes_returned = in_buf->smb_buf_length;
476
477 /* BB special case reconnect tid and uid here? */
478 rc = map_smb_to_linux_error(in_buf);
479
480 /* convert ByteCount if necessary */
481 if (receive_len >=
482 sizeof (struct smb_hdr) -
483 4 /* do not count RFC1001 header */ +
484 (2 * in_buf->WordCount) + 2 /* bcc */ )
485 BCC(in_buf) = le16_to_cpu(BCC(in_buf));
486 } else {
487 rc = -EIO;
488 cFYI(1,("Bad MID state? "));
489 }
490 }
491cifs_no_response_exit2:
492 DeleteMidQEntry(midQ);
493
377 if(long_op < 3) { 494 if(long_op < 3) {
378 atomic_dec(&ses->server->inFlight); 495 atomic_dec(&ses->server->inFlight);
379 wake_up(&ses->server->request_q); 496 wake_up(&ses->server->request_q);
380 } 497 }
381 498
382 return rc; 499 return rc;
383}
384 500
501out_unlock2:
502 up(&ses->server->tcpSem);
503 /* If not lock req, update # of requests on wire to server */
504 if(long_op < 3) {
505 atomic_dec(&ses->server->inFlight);
506 wake_up(&ses->server->request_q);
507 }
385 508
509 return rc;
510}
386#endif /* CIFS_EXPERIMENTAL */ 511#endif /* CIFS_EXPERIMENTAL */
387 512
388int 513int
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index c1e02eff1d25..f4fc8ddebba7 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -63,7 +63,7 @@ int cifs_removexattr(struct dentry * direntry, const char * ea_name)
63 pTcon = cifs_sb->tcon; 63 pTcon = cifs_sb->tcon;
64 64
65 down(&sb->s_vfs_rename_sem); 65 down(&sb->s_vfs_rename_sem);
66 full_path = build_path_from_dentry(direntry); 66 full_path = build_path_from_dentry(direntry, cifs_sb);
67 up(&sb->s_vfs_rename_sem); 67 up(&sb->s_vfs_rename_sem);
68 if(full_path == NULL) { 68 if(full_path == NULL) {
69 FreeXid(xid); 69 FreeXid(xid);
@@ -118,7 +118,7 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name,
118 pTcon = cifs_sb->tcon; 118 pTcon = cifs_sb->tcon;
119 119
120 down(&sb->s_vfs_rename_sem); 120 down(&sb->s_vfs_rename_sem);
121 full_path = build_path_from_dentry(direntry); 121 full_path = build_path_from_dentry(direntry, cifs_sb);
122 up(&sb->s_vfs_rename_sem); 122 up(&sb->s_vfs_rename_sem);
123 if(full_path == NULL) { 123 if(full_path == NULL) {
124 FreeXid(xid); 124 FreeXid(xid);
@@ -227,7 +227,7 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
227 pTcon = cifs_sb->tcon; 227 pTcon = cifs_sb->tcon;
228 228
229 down(&sb->s_vfs_rename_sem); 229 down(&sb->s_vfs_rename_sem);
230 full_path = build_path_from_dentry(direntry); 230 full_path = build_path_from_dentry(direntry, cifs_sb);
231 up(&sb->s_vfs_rename_sem); 231 up(&sb->s_vfs_rename_sem);
232 if(full_path == NULL) { 232 if(full_path == NULL) {
233 FreeXid(xid); 233 FreeXid(xid);
@@ -328,7 +328,7 @@ ssize_t cifs_listxattr(struct dentry * direntry, char * data, size_t buf_size)
328 pTcon = cifs_sb->tcon; 328 pTcon = cifs_sb->tcon;
329 329
330 down(&sb->s_vfs_rename_sem); 330 down(&sb->s_vfs_rename_sem);
331 full_path = build_path_from_dentry(direntry); 331 full_path = build_path_from_dentry(direntry, cifs_sb);
332 up(&sb->s_vfs_rename_sem); 332 up(&sb->s_vfs_rename_sem);
333 if(full_path == NULL) { 333 if(full_path == NULL) {
334 FreeXid(xid); 334 FreeXid(xid);