aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/cifs_fs_sb.h1
-rw-r--r--fs/cifs/cifsglob.h7
-rw-r--r--fs/cifs/cifspdu.h46
-rw-r--r--fs/cifs/cifsproto.h7
-rw-r--r--fs/cifs/cifssmb.c77
-rw-r--r--fs/cifs/connect.c20
-rw-r--r--fs/cifs/dir.c10
-rw-r--r--fs/cifs/fcntl.c2
-rw-r--r--fs/cifs/file.c4
-rw-r--r--fs/cifs/inode.c14
-rw-r--r--fs/cifs/link.c15
-rw-r--r--fs/cifs/readdir.c4
-rw-r--r--fs/cifs/xattr.c8
13 files changed, 182 insertions, 33 deletions
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index ec00d61d5308..5dc5fe6b486d 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -24,6 +24,7 @@
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. */
27 28
28struct cifs_sb_info { 29struct cifs_sb_info {
29 struct cifsTconInfo *tcon; /* primary mount */ 30 struct cifsTconInfo *tcon; /* primary mount */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 4ed9c13fff55..d3773e57acf9 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -309,6 +309,13 @@ CIFS_SB(struct super_block *sb)
309 return sb->s_fs_info; 309 return sb->s_fs_info;
310} 310}
311 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}
312 319
313/* one of these for every pending CIFS request to the server */ 320/* one of these for every pending CIFS request to the server */
314struct mid_q_entry { 321struct mid_q_entry {
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index aede6a813167..84d37f8e986e 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
@@ -1411,6 +1412,43 @@ typedef struct smb_com_transaction_qfsi_rsp {
1411 __u8 Pad; /* may be three bytes *//* followed by data area */ 1412 __u8 Pad; /* may be three bytes *//* followed by data area */
1412} TRANSACTION2_QFSI_RSP; 1413} TRANSACTION2_QFSI_RSP;
1413 1414
1415
1416/* SETFSInfo Levels */
1417#define SMB_SET_CIFS_UNIX_INFO 0x200
1418typedef struct smb_com_transaction2_setfsi_req {
1419 struct smb_hdr hdr; /* wct = 15 */
1420 __le16 TotalParameterCount;
1421 __le16 TotalDataCount;
1422 __le16 MaxParameterCount;
1423 __le16 MaxDataCount;
1424 __u8 MaxSetupCount;
1425 __u8 Reserved;
1426 __le16 Flags;
1427 __le32 Timeout;
1428 __u16 Reserved2;
1429 __le16 ParameterCount; /* 4 */
1430 __le16 ParameterOffset;
1431 __le16 DataCount; /* 12 */
1432 __le16 DataOffset;
1433 __u8 SetupCount; /* one */
1434 __u8 Reserved3;
1435 __le16 SubCommand; /* TRANS2_SET_FS_INFORMATION */
1436 __le16 ByteCount;
1437 __u8 Pad;
1438 __u16 FileNum; /* Parameters start. */
1439 __le16 InformationLevel;/* Parameters end. */
1440 __le16 ClientUnixMajor; /* Data start. */
1441 __le16 ClientUnixMinor;
1442 __le64 ClientUnixCap; /* Data end */
1443} TRANSACTION2_SETFSI_REQ;
1444
1445typedef struct smb_com_transaction2_setfsi_rsp {
1446 struct smb_hdr hdr; /* wct = 10 */
1447 struct trans2_resp t2;
1448 __u16 ByteCount;
1449} TRANSACTION2_SETFSI_RSP;
1450
1451
1414typedef struct smb_com_transaction2_get_dfs_refer_req { 1452typedef struct smb_com_transaction2_get_dfs_refer_req {
1415 struct smb_hdr hdr; /* wct = 15 */ 1453 struct smb_hdr hdr; /* wct = 15 */
1416 __le16 TotalParameterCount; 1454 __le16 TotalParameterCount;
@@ -1551,12 +1589,20 @@ typedef struct {
1551 __le16 MinorVersionNumber; 1589 __le16 MinorVersionNumber;
1552 __le64 Capability; 1590 __le64 Capability;
1553} FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */ 1591} FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */
1592
1593/* Version numbers for CIFS UNIX major and minor. */
1594#define CIFS_UNIX_MAJOR_VERSION 1
1595#define CIFS_UNIX_MINOR_VERSION 0
1596
1554/* Linux/Unix extensions capability flags */ 1597/* Linux/Unix extensions capability flags */
1555#define CIFS_UNIX_FCNTL_CAP 0x00000001 /* support for fcntl locks */ 1598#define CIFS_UNIX_FCNTL_CAP 0x00000001 /* support for fcntl locks */
1556#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 /* support getfacl/setfacl */ 1599#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 /* support getfacl/setfacl */
1557#define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */ 1600#define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */
1558#define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */ 1601#define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */
1602#define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x00000010 /* Use POSIX pathnames on the wire. */
1603
1559#define CIFS_POSIX_EXTENSIONS 0x00000010 /* support for new QFSInfo */ 1604#define CIFS_POSIX_EXTENSIONS 0x00000010 /* support for new QFSInfo */
1605
1560typedef struct { 1606typedef struct {
1561 /* For undefined recommended transfer size return -1 in that field */ 1607 /* For undefined recommended transfer size return -1 in that field */
1562 __le32 OptimalTransferSize; /* bsize on some os, iosize on other os */ 1608 __le32 OptimalTransferSize; /* bsize on some os, iosize on other os */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index ea239dea571e..db2adf0b206c 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -40,7 +40,7 @@ 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 *,
@@ -89,7 +89,7 @@ extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
89 89
90extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, 90extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
91 const char *searchName, const struct nls_table *nls_codepage, 91 const char *searchName, const struct nls_table *nls_codepage,
92 __u16 *searchHandle, struct cifs_search_info * psrch_inf, int map); 92 __u16 *searchHandle, struct cifs_search_info * psrch_inf, int map, const char dirsep);
93 93
94extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, 94extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
95 __u16 searchHandle, struct cifs_search_info * psrch_inf); 95 __u16 searchHandle, struct cifs_search_info * psrch_inf);
@@ -125,6 +125,9 @@ extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
125 int remap); 125 int remap);
126extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, 126extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
127 struct kstatfs *FSData); 127 struct kstatfs *FSData);
128extern int CIFSSMBSETFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
129 __u64 cap);
130
128extern int CIFSSMBQFSAttributeInfo(const int xid, 131extern int CIFSSMBQFSAttributeInfo(const int xid,
129 struct cifsTconInfo *tcon); 132 struct cifsTconInfo *tcon);
130extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon); 133extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index b31158a2643d..81c9d3f393f5 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -2416,7 +2416,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
2416 const char *searchName, 2416 const char *searchName,
2417 const struct nls_table *nls_codepage, 2417 const struct nls_table *nls_codepage,
2418 __u16 * pnetfid, 2418 __u16 * pnetfid,
2419 struct cifs_search_info * psrch_inf, int remap) 2419 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
2420{ 2420{
2421/* level 257 SMB_ */ 2421/* level 257 SMB_ */
2422 TRANSACTION2_FFIRST_REQ *pSMB = NULL; 2422 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
@@ -2443,7 +2443,7 @@ findFirstRetry:
2443 it got remapped to 0xF03A as if it were part of the 2443 it got remapped to 0xF03A as if it were part of the
2444 directory name instead of a wildcard */ 2444 directory name instead of a wildcard */
2445 name_len *= 2; 2445 name_len *= 2;
2446 pSMB->FileName[name_len] = '\\'; 2446 pSMB->FileName[name_len] = dirsep;
2447 pSMB->FileName[name_len+1] = 0; 2447 pSMB->FileName[name_len+1] = 0;
2448 pSMB->FileName[name_len+2] = '*'; 2448 pSMB->FileName[name_len+2] = '*';
2449 pSMB->FileName[name_len+3] = 0; 2449 pSMB->FileName[name_len+3] = 0;
@@ -2457,7 +2457,7 @@ findFirstRetry:
2457 if(name_len > buffersize-header) 2457 if(name_len > buffersize-header)
2458 free buffer exit; BB */ 2458 free buffer exit; BB */
2459 strncpy(pSMB->FileName, searchName, name_len); 2459 strncpy(pSMB->FileName, searchName, name_len);
2460 pSMB->FileName[name_len] = '\\'; 2460 pSMB->FileName[name_len] = dirsep;
2461 pSMB->FileName[name_len+1] = '*'; 2461 pSMB->FileName[name_len+1] = '*';
2462 pSMB->FileName[name_len+2] = 0; 2462 pSMB->FileName[name_len+2] = 0;
2463 name_len += 3; 2463 name_len += 3;
@@ -3265,6 +3265,77 @@ QFSUnixRetry:
3265 return rc; 3265 return rc;
3266} 3266}
3267 3267
3268int
3269CIFSSMBSETFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
3270{
3271/* level 0x200 SMB_SET_CIFS_UNIX_INFO */
3272 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
3273 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
3274 int rc = 0;
3275 int bytes_returned = 0;
3276 __u16 params, param_offset, offset, byte_count;
3277
3278 cFYI(1, ("In SETFSUnixInfo"));
3279SETFSUnixRetry:
3280 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3281 (void **) &pSMBr);
3282 if (rc)
3283 return rc;
3284
3285 params = 4; /* 2 bytes zero followed by info level. */
3286 pSMB->MaxSetupCount = 0;
3287 pSMB->Reserved = 0;
3288 pSMB->Flags = 0;
3289 pSMB->Timeout = 0;
3290 pSMB->Reserved2 = 0;
3291 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
3292 offset = param_offset + params;
3293
3294 pSMB->MaxParameterCount = cpu_to_le16(4);
3295 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3296 pSMB->SetupCount = 1;
3297 pSMB->Reserved3 = 0;
3298 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
3299 byte_count = 1 /* pad */ + params + 12;
3300
3301 pSMB->DataCount = cpu_to_le16(12);
3302 pSMB->ParameterCount = cpu_to_le16(params);
3303 pSMB->TotalDataCount = pSMB->DataCount;
3304 pSMB->TotalParameterCount = pSMB->ParameterCount;
3305 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3306 pSMB->DataOffset = cpu_to_le16(offset);
3307
3308 /* Params. */
3309 pSMB->FileNum = 0;
3310 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
3311
3312 /* Data. */
3313 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
3314 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
3315 pSMB->ClientUnixCap = cpu_to_le64(cap);
3316
3317 pSMB->hdr.smb_buf_length += byte_count;
3318 pSMB->ByteCount = cpu_to_le16(byte_count);
3319
3320 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3321 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3322 if (rc) {
3323 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
3324 } else { /* decode response */
3325 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3326 if (rc) {
3327 rc = -EIO; /* bad smb */
3328 }
3329 }
3330 cifs_buf_release(pSMB);
3331
3332 if (rc == -EAGAIN)
3333 goto SETFSUnixRetry;
3334
3335 return rc;
3336}
3337
3338
3268 3339
3269int 3340int
3270CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, 3341CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index e568cc47a7f9..bef5d6f30975 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -74,6 +74,7 @@ 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. */
77 unsigned int rsize; 78 unsigned int rsize;
78 unsigned int wsize; 79 unsigned int wsize;
79 unsigned int sockopt; 80 unsigned int sockopt;
@@ -745,6 +746,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) */ 746 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
746 vol->rw = TRUE; 747 vol->rw = TRUE;
747 748
749 /* default is always to request posix paths. */
750 vol->posix_paths = 1;
751
748 if (!options) 752 if (!options)
749 return 1; 753 return 1;
750 754
@@ -1023,6 +1027,10 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
1023 vol->remap = 1; 1027 vol->remap = 1;
1024 } else if (strnicmp(data, "nomapchars", 10) == 0) { 1028 } else if (strnicmp(data, "nomapchars", 10) == 0) {
1025 vol->remap = 0; 1029 vol->remap = 0;
1030 } else if (strnicmp(data, "posixpaths", 10) == 0) {
1031 vol->posix_paths = 1;
1032 } else if (strnicmp(data, "noposixpaths", 12) == 0) {
1033 vol->posix_paths = 0;
1026 } else if (strnicmp(data, "setuids", 7) == 0) { 1034 } else if (strnicmp(data, "setuids", 7) == 0) {
1027 vol->setuids = 1; 1035 vol->setuids = 1;
1028 } else if (strnicmp(data, "nosetuids", 9) == 0) { 1036 } else if (strnicmp(data, "nosetuids", 9) == 0) {
@@ -1679,6 +1687,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1679 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR; 1687 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1680 if(volume_info.no_xattr) 1688 if(volume_info.no_xattr)
1681 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR; 1689 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1690
1682 if(volume_info.direct_io) { 1691 if(volume_info.direct_io) {
1683 cERROR(1,("mounting share using direct i/o")); 1692 cERROR(1,("mounting share using direct i/o"));
1684 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; 1693 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
@@ -1781,6 +1790,17 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1781 cFYI(1,("server negotiated posix acl support")); 1790 cFYI(1,("server negotiated posix acl support"));
1782 sb->s_flags |= MS_POSIXACL; 1791 sb->s_flags |= MS_POSIXACL;
1783 } 1792 }
1793
1794 /* Try and negotiate POSIX pathnames if we can. */
1795 if (volume_info.posix_paths && (CIFS_UNIX_POSIX_PATHNAMES_CAP &
1796 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
1797 if (!CIFSSMBSETFSUnixInfo(xid, tcon, CIFS_UNIX_POSIX_PATHNAMES_CAP, 0)) {
1798 cFYI(1,("negotiated posix pathnames support"));
1799 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
1800 } else {
1801 cFYI(1,("posix pathnames support requested but not supported"));
1802 }
1803 }
1784 } 1804 }
1785 } 1805 }
1786 } 1806 }
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 3f3538d4a1fa..9360d8fb9ef7 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);
@@ -299,7 +299,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev
299 pTcon = cifs_sb->tcon; 299 pTcon = cifs_sb->tcon;
300 300
301 down(&direntry->d_sb->s_vfs_rename_sem); 301 down(&direntry->d_sb->s_vfs_rename_sem);
302 full_path = build_path_from_dentry(direntry); 302 full_path = build_path_from_dentry(direntry, cifs_sb);
303 up(&direntry->d_sb->s_vfs_rename_sem); 303 up(&direntry->d_sb->s_vfs_rename_sem);
304 if(full_path == NULL) 304 if(full_path == NULL)
305 rc = -ENOMEM; 305 rc = -ENOMEM;
@@ -360,7 +360,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
360 /* can not grab the rename sem here since it would 360 /* can not grab the rename sem here since it would
361 deadlock in the cases (beginning of sys_rename itself) 361 deadlock in the cases (beginning of sys_rename itself)
362 in which we already have the sb rename sem */ 362 in which we already have the sb rename sem */
363 full_path = build_path_from_dentry(direntry); 363 full_path = build_path_from_dentry(direntry, cifs_sb);
364 if(full_path == NULL) { 364 if(full_path == NULL) {
365 FreeXid(xid); 365 FreeXid(xid);
366 return ERR_PTR(-ENOMEM); 366 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..8dd11fecaaca 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);
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 8d336a900255..95354da606d6 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -412,7 +412,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 412 /* Unlink can be called from rename so we can not grab the sem here
413 since we deadlock otherwise */ 413 since we deadlock otherwise */
414/* down(&direntry->d_sb->s_vfs_rename_sem);*/ 414/* down(&direntry->d_sb->s_vfs_rename_sem);*/
415 full_path = build_path_from_dentry(direntry); 415 full_path = build_path_from_dentry(direntry, cifs_sb);
416/* up(&direntry->d_sb->s_vfs_rename_sem);*/ 416/* up(&direntry->d_sb->s_vfs_rename_sem);*/
417 if (full_path == NULL) { 417 if (full_path == NULL) {
418 FreeXid(xid); 418 FreeXid(xid);
@@ -556,7 +556,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
556 pTcon = cifs_sb->tcon; 556 pTcon = cifs_sb->tcon;
557 557
558 down(&inode->i_sb->s_vfs_rename_sem); 558 down(&inode->i_sb->s_vfs_rename_sem);
559 full_path = build_path_from_dentry(direntry); 559 full_path = build_path_from_dentry(direntry, cifs_sb);
560 up(&inode->i_sb->s_vfs_rename_sem); 560 up(&inode->i_sb->s_vfs_rename_sem);
561 if (full_path == NULL) { 561 if (full_path == NULL) {
562 FreeXid(xid); 562 FreeXid(xid);
@@ -627,7 +627,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
627 pTcon = cifs_sb->tcon; 627 pTcon = cifs_sb->tcon;
628 628
629 down(&inode->i_sb->s_vfs_rename_sem); 629 down(&inode->i_sb->s_vfs_rename_sem);
630 full_path = build_path_from_dentry(direntry); 630 full_path = build_path_from_dentry(direntry, cifs_sb);
631 up(&inode->i_sb->s_vfs_rename_sem); 631 up(&inode->i_sb->s_vfs_rename_sem);
632 if (full_path == NULL) { 632 if (full_path == NULL) {
633 FreeXid(xid); 633 FreeXid(xid);
@@ -680,8 +680,8 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
680 680
681 /* we already have the rename sem so we do not need to grab it again 681 /* we already have the rename sem so we do not need to grab it again
682 here to protect the path integrity */ 682 here to protect the path integrity */
683 fromName = build_path_from_dentry(source_direntry); 683 fromName = build_path_from_dentry(source_direntry, cifs_sb_source);
684 toName = build_path_from_dentry(target_direntry); 684 toName = build_path_from_dentry(target_direntry, cifs_sb_target);
685 if ((fromName == NULL) || (toName == NULL)) { 685 if ((fromName == NULL) || (toName == NULL)) {
686 rc = -ENOMEM; 686 rc = -ENOMEM;
687 goto cifs_rename_exit; 687 goto cifs_rename_exit;
@@ -797,7 +797,7 @@ int cifs_revalidate(struct dentry *direntry)
797 797
798 /* can not safely grab the rename sem here if rename calls revalidate 798 /* can not safely grab the rename sem here if rename calls revalidate
799 since that would deadlock */ 799 since that would deadlock */
800 full_path = build_path_from_dentry(direntry); 800 full_path = build_path_from_dentry(direntry, cifs_sb);
801 if (full_path == NULL) { 801 if (full_path == NULL) {
802 FreeXid(xid); 802 FreeXid(xid);
803 return -ENOMEM; 803 return -ENOMEM;
@@ -946,7 +946,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
946 pTcon = cifs_sb->tcon; 946 pTcon = cifs_sb->tcon;
947 947
948 down(&direntry->d_sb->s_vfs_rename_sem); 948 down(&direntry->d_sb->s_vfs_rename_sem);
949 full_path = build_path_from_dentry(direntry); 949 full_path = build_path_from_dentry(direntry, cifs_sb);
950 up(&direntry->d_sb->s_vfs_rename_sem); 950 up(&direntry->d_sb->s_vfs_rename_sem);
951 if (full_path == NULL) { 951 if (full_path == NULL) {
952 FreeXid(xid); 952 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/readdir.c b/fs/cifs/readdir.c
index 487221eeddb7..42310281871c 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -354,7 +354,7 @@ static int initiate_cifs_search(const int xid, struct file *file)
354 return -EINVAL; 354 return -EINVAL;
355 355
356 down(&file->f_dentry->d_sb->s_vfs_rename_sem); 356 down(&file->f_dentry->d_sb->s_vfs_rename_sem);
357 full_path = build_path_from_dentry(file->f_dentry); 357 full_path = build_path_from_dentry(file->f_dentry, cifs_sb);
358 up(&file->f_dentry->d_sb->s_vfs_rename_sem); 358 up(&file->f_dentry->d_sb->s_vfs_rename_sem);
359 359
360 if(full_path == NULL) { 360 if(full_path == NULL) {
@@ -375,7 +375,7 @@ ffirst_retry:
375 375
376 rc = CIFSFindFirst(xid, pTcon,full_path,cifs_sb->local_nls, 376 rc = CIFSFindFirst(xid, pTcon,full_path,cifs_sb->local_nls,
377 &cifsFile->netfid, &cifsFile->srch_inf, 377 &cifsFile->netfid, &cifsFile->srch_inf,
378 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 378 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb));
379 if(rc == 0) 379 if(rc == 0)
380 cifsFile->invalidHandle = FALSE; 380 cifsFile->invalidHandle = FALSE;
381 if((rc == -EOPNOTSUPP) && 381 if((rc == -EOPNOTSUPP) &&
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);