[CIFS] POSIX extensions, SetFSInfo added

Signed-off-by: Steve French@sfrench@us.ibm.com
Signed-off-by: Jeremy Allison (jra@samba.org)
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index ec00d61..5dc5fe6 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -24,6 +24,7 @@
 #define CIFS_MOUNT_DIRECT_IO    8 /* do not write nor read through page cache */
 #define CIFS_MOUNT_NO_XATTR  0x10 /* if set - disable xattr support */
 #define CIFS_MOUNT_MAP_SPECIAL_CHR 0x20 /* remap illegal chars in filenames */
+#define CIFS_MOUNT_POSIX_PATHS 0x40 /* Negotiate posix pathnames if possible. */
 
 struct cifs_sb_info {
 	struct cifsTconInfo *tcon;	/* primary mount */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 4ed9c13..d3773e5 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -309,6 +309,13 @@
 	return sb->s_fs_info;
 }
 
+static inline const char CIFS_DIR_SEP(const struct cifs_sb_info *cifs_sb)
+{
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
+		return '/';
+	else
+		return '\\';
+}
 
 /* one of these for every pending CIFS request to the server */
 struct mid_q_entry {
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index aede6a8..84d37f8 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -59,6 +59,7 @@
 #define TRANS2_FIND_FIRST             0x01
 #define TRANS2_FIND_NEXT              0x02
 #define TRANS2_QUERY_FS_INFORMATION   0x03
+#define TRANS2_SET_FS_INFORMATION     0x04
 #define TRANS2_QUERY_PATH_INFORMATION 0x05
 #define TRANS2_SET_PATH_INFORMATION   0x06
 #define TRANS2_QUERY_FILE_INFORMATION 0x07
@@ -1411,6 +1412,43 @@
 	__u8 Pad;		/* may be three bytes *//* followed by data area */
 } TRANSACTION2_QFSI_RSP;
 
+
+/* SETFSInfo Levels */
+#define SMB_SET_CIFS_UNIX_INFO    0x200
+typedef struct smb_com_transaction2_setfsi_req {
+	struct smb_hdr hdr;	/* wct = 15 */
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
+	__le16 MaxParameterCount;
+	__le16 MaxDataCount;
+	__u8 MaxSetupCount;
+	__u8 Reserved;
+	__le16 Flags;
+	__le32 Timeout;
+	__u16 Reserved2;
+	__le16 ParameterCount;	/* 4 */
+	__le16 ParameterOffset;
+	__le16 DataCount;	/* 12 */
+	__le16 DataOffset;
+	__u8 SetupCount;	/* one */
+	__u8 Reserved3;
+	__le16 SubCommand;	/* TRANS2_SET_FS_INFORMATION */
+	__le16 ByteCount;
+	__u8 Pad;
+	__u16 FileNum;		/* Parameters start. */
+	__le16 InformationLevel;/* Parameters end. */
+	__le16 ClientUnixMajor; /* Data start. */
+	__le16 ClientUnixMinor;
+	__le64 ClientUnixCap;   /* Data end */
+} TRANSACTION2_SETFSI_REQ;
+
+typedef struct smb_com_transaction2_setfsi_rsp {
+	struct smb_hdr hdr;	/* wct = 10 */
+	struct trans2_resp t2;
+	__u16 ByteCount;
+} TRANSACTION2_SETFSI_RSP;
+
+
 typedef struct smb_com_transaction2_get_dfs_refer_req {
 	struct smb_hdr hdr;	/* wct = 15 */
 	__le16 TotalParameterCount;
@@ -1551,12 +1589,20 @@
 	__le16 MinorVersionNumber;
 	__le64 Capability;
 } FILE_SYSTEM_UNIX_INFO;	/* Unix extensions info, level 0x200 */
+
+/* Version numbers for CIFS UNIX major and minor. */
+#define CIFS_UNIX_MAJOR_VERSION 1
+#define CIFS_UNIX_MINOR_VERSION 0
+
 /* Linux/Unix extensions capability flags */
 #define CIFS_UNIX_FCNTL_CAP             0x00000001 /* support for fcntl locks */
 #define CIFS_UNIX_POSIX_ACL_CAP         0x00000002 /* support getfacl/setfacl */
 #define CIFS_UNIX_XATTR_CAP             0x00000004 /* support new namespace   */
 #define CIFS_UNIX_EXTATTR_CAP           0x00000008 /* support chattr/chflag   */
+#define CIFS_UNIX_POSIX_PATHNAMES_CAP   0x00000010 /* Use POSIX pathnames on the wire. */
+
 #define CIFS_POSIX_EXTENSIONS           0x00000010 /* support for new QFSInfo */
+
 typedef struct {
 	/* For undefined recommended transfer size return -1 in that field */
 	__le32 OptimalTransferSize;  /* bsize on some os, iosize on other os */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index ea239de..db2adf0 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -40,7 +40,7 @@
 extern void _FreeXid(unsigned int);
 #define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->fsuid));
 #define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,(int)rc));}
-extern char *build_path_from_dentry(struct dentry *);
+extern char *build_path_from_dentry(struct dentry *, const struct cifs_sb_info *cifs_sb);
 extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
 extern void renew_parental_timestamps(struct dentry *direntry);
 extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
@@ -89,7 +89,7 @@
 
 extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
             const char *searchName, const struct nls_table *nls_codepage,
-            __u16 *searchHandle, struct cifs_search_info * psrch_inf, int map);
+            __u16 *searchHandle, struct cifs_search_info * psrch_inf, int map, const char dirsep);
 
 extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
             __u16 searchHandle, struct cifs_search_info * psrch_inf);
@@ -125,6 +125,9 @@
 			int remap);
 extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
 			struct kstatfs *FSData);
+extern int CIFSSMBSETFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
+			__u64 cap);
+
 extern int CIFSSMBQFSAttributeInfo(const int xid,
 			struct cifsTconInfo *tcon);
 extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index b31158a..81c9d3f 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -2416,7 +2416,7 @@
 	      const char *searchName, 
 	      const struct nls_table *nls_codepage,
 	      __u16 *	pnetfid,
-	      struct cifs_search_info * psrch_inf, int remap)
+	      struct cifs_search_info * psrch_inf, int remap, const char dirsep)
 {
 /* level 257 SMB_ */
 	TRANSACTION2_FFIRST_REQ *pSMB = NULL;
@@ -2443,7 +2443,7 @@
 		it got remapped to 0xF03A as if it were part of the
 		directory name instead of a wildcard */
 		name_len *= 2;
-		pSMB->FileName[name_len] = '\\';
+		pSMB->FileName[name_len] = dirsep;
 		pSMB->FileName[name_len+1] = 0;
 		pSMB->FileName[name_len+2] = '*';
 		pSMB->FileName[name_len+3] = 0;
@@ -2457,7 +2457,7 @@
 		if(name_len > buffersize-header)
 			free buffer exit; BB */
 		strncpy(pSMB->FileName, searchName, name_len);
-		pSMB->FileName[name_len] = '\\';
+		pSMB->FileName[name_len] = dirsep;
 		pSMB->FileName[name_len+1] = '*';
 		pSMB->FileName[name_len+2] = 0;
 		name_len += 3;
@@ -3265,6 +3265,77 @@
 	return rc;
 }
 
+int
+CIFSSMBSETFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
+{
+/* level 0x200  SMB_SET_CIFS_UNIX_INFO */
+	TRANSACTION2_SETFSI_REQ *pSMB = NULL;
+	TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
+	int rc = 0;
+	int bytes_returned = 0;
+	__u16 params, param_offset, offset, byte_count;
+
+	cFYI(1, ("In SETFSUnixInfo"));
+SETFSUnixRetry:
+	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	params = 4;	/* 2 bytes zero followed by info level. */
+	pSMB->MaxSetupCount = 0;
+	pSMB->Reserved = 0;
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+	pSMB->Reserved2 = 0;
+	param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
+	offset = param_offset + params;
+
+	pSMB->MaxParameterCount = cpu_to_le16(4);
+	pSMB->MaxDataCount = cpu_to_le16(100);	/* BB find exact max SMB PDU from sess structure BB */
+	pSMB->SetupCount = 1;
+	pSMB->Reserved3 = 0;
+	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
+	byte_count = 1 /* pad */ + params + 12;
+
+	pSMB->DataCount = cpu_to_le16(12);
+	pSMB->ParameterCount = cpu_to_le16(params);
+	pSMB->TotalDataCount = pSMB->DataCount;
+	pSMB->TotalParameterCount = pSMB->ParameterCount;
+	pSMB->ParameterOffset = cpu_to_le16(param_offset);
+	pSMB->DataOffset = cpu_to_le16(offset);
+
+	/* Params. */
+	pSMB->FileNum = 0;
+	pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
+
+	/* Data. */
+	pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
+	pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
+	pSMB->ClientUnixCap = cpu_to_le64(cap);
+
+	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) {
+		cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
+	} else {		/* decode response */
+		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+		if (rc) {
+			rc = -EIO;	/* bad smb */
+		}
+	}
+	cifs_buf_release(pSMB);
+
+	if (rc == -EAGAIN)
+		goto SETFSUnixRetry;
+
+	return rc;
+}
+
+
 
 int
 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index e568cc4..bef5d6f 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -74,6 +74,7 @@
 	unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
 	unsigned direct_io:1;
 	unsigned remap:1;   /* set to remap seven reserved chars in filenames */
+	unsigned posix_paths:1;   /* unset to not ask for posix pathnames. */
 	unsigned int rsize;
 	unsigned int wsize;
 	unsigned int sockopt;
@@ -745,6 +746,9 @@
 	/* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
 	vol->rw = TRUE;
 
+	/* default is always to request posix paths. */
+	vol->posix_paths = 1;
+
 	if (!options)
 		return 1;
 
@@ -1023,6 +1027,10 @@
 			vol->remap = 1;
 		} else if (strnicmp(data, "nomapchars", 10) == 0) {
 			vol->remap = 0;
+		} else if (strnicmp(data, "posixpaths", 10) == 0) {
+			vol->posix_paths = 1;
+		} else if (strnicmp(data, "noposixpaths", 12) == 0) {
+			vol->posix_paths = 0;
 		} else if (strnicmp(data, "setuids", 7) == 0) {
 			vol->setuids = 1;
 		} else if (strnicmp(data, "nosetuids", 9) == 0) {
@@ -1679,6 +1687,7 @@
 			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
 		if(volume_info.no_xattr)
 			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
+
 		if(volume_info.direct_io) {
 			cERROR(1,("mounting share using direct i/o"));
 			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
@@ -1781,6 +1790,17 @@
 						cFYI(1,("server negotiated posix acl support"));
 						sb->s_flags |= MS_POSIXACL;
 				}
+
+				/* Try and negotiate POSIX pathnames if we can. */
+				if (volume_info.posix_paths && (CIFS_UNIX_POSIX_PATHNAMES_CAP &
+				    le64_to_cpu(tcon->fsUnixInfo.Capability))) {
+					if (!CIFSSMBSETFSUnixInfo(xid, tcon, CIFS_UNIX_POSIX_PATHNAMES_CAP, 0))  {
+						cFYI(1,("negotiated posix pathnames support"));
+						cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
+					} else {
+						cFYI(1,("posix pathnames support requested but not supported"));
+					}
+				}
 			}
 		}
 	}
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 3f3538d..9360d8f 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -43,7 +43,7 @@
 
 /* Note: caller must free return buffer */
 char *
-build_path_from_dentry(struct dentry *direntry)
+build_path_from_dentry(struct dentry *direntry, const struct cifs_sb_info *cifs_sb)
 {
 	struct dentry *temp;
 	int namelen = 0;
@@ -74,7 +74,7 @@
 		if (namelen < 0) {
 			break;
 		} else {
-			full_path[namelen] = '\\';
+			full_path[namelen] = CIFS_DIR_SEP(cifs_sb);
 			strncpy(full_path + namelen + 1, temp->d_name.name,
 				temp->d_name.len);
 			cFYI(0, (" name: %s ", full_path + namelen));
@@ -138,7 +138,7 @@
 	pTcon = cifs_sb->tcon;
 
 	down(&direntry->d_sb->s_vfs_rename_sem);
-	full_path = build_path_from_dentry(direntry);
+	full_path = build_path_from_dentry(direntry, cifs_sb);
 	up(&direntry->d_sb->s_vfs_rename_sem);
 	if(full_path == NULL) {
 		FreeXid(xid);
@@ -299,7 +299,7 @@
 	pTcon = cifs_sb->tcon;
 
 	down(&direntry->d_sb->s_vfs_rename_sem);
-	full_path = build_path_from_dentry(direntry);
+	full_path = build_path_from_dentry(direntry, cifs_sb);
 	up(&direntry->d_sb->s_vfs_rename_sem);
 	if(full_path == NULL)
 		rc = -ENOMEM;
@@ -360,7 +360,7 @@
 	/* can not grab the rename sem here since it would
 	deadlock in the cases (beginning of sys_rename itself)
 	in which we already have the sb rename sem */
-	full_path = build_path_from_dentry(direntry);
+	full_path = build_path_from_dentry(direntry, cifs_sb);
 	if(full_path == NULL) {
 		FreeXid(xid);
 		return ERR_PTR(-ENOMEM);
diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c
index 7d2a920..d47ce7f 100644
--- a/fs/cifs/fcntl.c
+++ b/fs/cifs/fcntl.c
@@ -83,7 +83,7 @@
 	pTcon = cifs_sb->tcon;
 
 	down(&file->f_dentry->d_sb->s_vfs_rename_sem);
-	full_path = build_path_from_dentry(file->f_dentry);
+	full_path = build_path_from_dentry(file->f_dentry, cifs_sb);
 	up(&file->f_dentry->d_sb->s_vfs_rename_sem);
 
 	if(full_path == NULL) {
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 30ab70c..8dd11fe 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -196,7 +196,7 @@
 	}
 
 	down(&inode->i_sb->s_vfs_rename_sem);
-	full_path = build_path_from_dentry(file->f_dentry);
+	full_path = build_path_from_dentry(file->f_dentry, cifs_sb);
 	up(&inode->i_sb->s_vfs_rename_sem);
 	if (full_path == NULL) {
 		FreeXid(xid);
@@ -359,7 +359,7 @@
    those that already have the rename sem can end up causing writepage
    to get called and if the server was down that means we end up here,
    and we can never tell if the caller already has the rename_sem */
-	full_path = build_path_from_dentry(file->f_dentry);
+	full_path = build_path_from_dentry(file->f_dentry, cifs_sb);
 	if (full_path == NULL) {
 		up(&pCifsFile->fh_sem);
 		FreeXid(xid);
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 8d336a9..95354da 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -412,7 +412,7 @@
 	/* Unlink can be called from rename so we can not grab the sem here
 	   since we deadlock otherwise */
 /*	down(&direntry->d_sb->s_vfs_rename_sem);*/
-	full_path = build_path_from_dentry(direntry);
+	full_path = build_path_from_dentry(direntry, cifs_sb);
 /*	up(&direntry->d_sb->s_vfs_rename_sem);*/
 	if (full_path == NULL) {
 		FreeXid(xid);
@@ -556,7 +556,7 @@
 	pTcon = cifs_sb->tcon;
 
 	down(&inode->i_sb->s_vfs_rename_sem);
-	full_path = build_path_from_dentry(direntry);
+	full_path = build_path_from_dentry(direntry, cifs_sb);
 	up(&inode->i_sb->s_vfs_rename_sem);
 	if (full_path == NULL) {
 		FreeXid(xid);
@@ -627,7 +627,7 @@
 	pTcon = cifs_sb->tcon;
 
 	down(&inode->i_sb->s_vfs_rename_sem);
-	full_path = build_path_from_dentry(direntry);
+	full_path = build_path_from_dentry(direntry, cifs_sb);
 	up(&inode->i_sb->s_vfs_rename_sem);
 	if (full_path == NULL) {
 		FreeXid(xid);
@@ -680,8 +680,8 @@
 
 	/* we already  have the rename sem so we do not need to grab it again
 	   here to protect the path integrity */
-	fromName = build_path_from_dentry(source_direntry);
-	toName = build_path_from_dentry(target_direntry);
+	fromName = build_path_from_dentry(source_direntry, cifs_sb_source);
+	toName = build_path_from_dentry(target_direntry, cifs_sb_target);
 	if ((fromName == NULL) || (toName == NULL)) {
 		rc = -ENOMEM;
 		goto cifs_rename_exit;
@@ -797,7 +797,7 @@
 
 	/* can not safely grab the rename sem here if rename calls revalidate
 	   since that would deadlock */
-	full_path = build_path_from_dentry(direntry);
+	full_path = build_path_from_dentry(direntry, cifs_sb);
 	if (full_path == NULL) {
 		FreeXid(xid);
 		return -ENOMEM;
@@ -946,7 +946,7 @@
 	pTcon = cifs_sb->tcon;
 
 	down(&direntry->d_sb->s_vfs_rename_sem);
-	full_path = build_path_from_dentry(direntry);
+	full_path = build_path_from_dentry(direntry, cifs_sb);
 	up(&direntry->d_sb->s_vfs_rename_sem);
 	if (full_path == NULL) {
 		FreeXid(xid);
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index bde0fab..214aa81 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -49,8 +49,8 @@
    BB note DFS case in future though (when we may have to check) */
 
 	down(&inode->i_sb->s_vfs_rename_sem);
-	fromName = build_path_from_dentry(old_file);
-	toName = build_path_from_dentry(direntry);
+	fromName = build_path_from_dentry(old_file, cifs_sb_target);
+	toName = build_path_from_dentry(direntry, cifs_sb_target);
 	up(&inode->i_sb->s_vfs_rename_sem);
 	if((fromName == NULL) || (toName == NULL)) {
 		rc = -ENOMEM;
@@ -105,16 +105,17 @@
 
 	xid = GetXid();
 
+	cifs_sb = CIFS_SB(inode->i_sb);
+	pTcon = cifs_sb->tcon;
+
 	down(&direntry->d_sb->s_vfs_rename_sem);
-	full_path = build_path_from_dentry(direntry);
+	full_path = build_path_from_dentry(direntry, cifs_sb);
 	up(&direntry->d_sb->s_vfs_rename_sem);
 
 	if (!full_path)
 		goto out_no_free;
 
 	cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode));
-	cifs_sb = CIFS_SB(inode->i_sb);
-	pTcon = cifs_sb->tcon;
 	target_path = kmalloc(PATH_MAX, GFP_KERNEL);
 	if (!target_path) {
 		target_path = ERR_PTR(-ENOMEM);
@@ -167,7 +168,7 @@
 	pTcon = cifs_sb->tcon;
 
 	down(&inode->i_sb->s_vfs_rename_sem);
-	full_path = build_path_from_dentry(direntry);
+	full_path = build_path_from_dentry(direntry, cifs_sb);
 	up(&inode->i_sb->s_vfs_rename_sem);
 
 	if(full_path == NULL) {
@@ -233,7 +234,7 @@
 /* BB would it be safe against deadlock to grab this sem 
       even though rename itself grabs the sem and calls lookup? */
 /*       down(&inode->i_sb->s_vfs_rename_sem);*/
-	full_path = build_path_from_dentry(direntry);
+	full_path = build_path_from_dentry(direntry, cifs_sb);
 /*       up(&inode->i_sb->s_vfs_rename_sem);*/
 
 	if(full_path == NULL) {
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 487221e..4231028 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -354,7 +354,7 @@
 		return -EINVAL;
 
 	down(&file->f_dentry->d_sb->s_vfs_rename_sem);
-	full_path = build_path_from_dentry(file->f_dentry);
+	full_path = build_path_from_dentry(file->f_dentry, cifs_sb);
 	up(&file->f_dentry->d_sb->s_vfs_rename_sem);
 
 	if(full_path == NULL) {
@@ -375,7 +375,7 @@
 
 	rc = CIFSFindFirst(xid, pTcon,full_path,cifs_sb->local_nls,
 		&cifsFile->netfid, &cifsFile->srch_inf,
-		cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+		cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb));
 	if(rc == 0)
 		cifsFile->invalidHandle = FALSE;
 	if((rc == -EOPNOTSUPP) && 
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index c1e02ef..f4fc8dd 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -63,7 +63,7 @@
 	pTcon = cifs_sb->tcon;
                                                                                      
 	down(&sb->s_vfs_rename_sem);
-	full_path = build_path_from_dentry(direntry);
+	full_path = build_path_from_dentry(direntry, cifs_sb);
 	up(&sb->s_vfs_rename_sem);
 	if(full_path == NULL) {
 		FreeXid(xid);
@@ -118,7 +118,7 @@
 	pTcon = cifs_sb->tcon;
 
 	down(&sb->s_vfs_rename_sem);
-	full_path = build_path_from_dentry(direntry);
+	full_path = build_path_from_dentry(direntry, cifs_sb);
 	up(&sb->s_vfs_rename_sem);
 	if(full_path == NULL) {
 		FreeXid(xid);
@@ -227,7 +227,7 @@
 	pTcon = cifs_sb->tcon;
 
 	down(&sb->s_vfs_rename_sem);
-	full_path = build_path_from_dentry(direntry);
+	full_path = build_path_from_dentry(direntry, cifs_sb);
 	up(&sb->s_vfs_rename_sem);
 	if(full_path == NULL) {
 		FreeXid(xid);
@@ -328,7 +328,7 @@
 	pTcon = cifs_sb->tcon;
 
 	down(&sb->s_vfs_rename_sem);
-	full_path = build_path_from_dentry(direntry);
+	full_path = build_path_from_dentry(direntry, cifs_sb);
 	up(&sb->s_vfs_rename_sem);
 	if(full_path == NULL) {
 		FreeXid(xid);