diff options
-rw-r--r-- | fs/cifs/cifs_debug.c | 10 | ||||
-rw-r--r-- | fs/cifs/cifs_fs_sb.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 10 | ||||
-rw-r--r-- | fs/cifs/cifspdu.h | 56 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 13 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 181 | ||||
-rw-r--r-- | fs/cifs/connect.c | 27 | ||||
-rw-r--r-- | fs/cifs/dir.c | 54 | ||||
-rw-r--r-- | fs/cifs/fcntl.c | 2 | ||||
-rw-r--r-- | fs/cifs/file.c | 24 | ||||
-rw-r--r-- | fs/cifs/inode.c | 24 | ||||
-rw-r--r-- | fs/cifs/link.c | 15 | ||||
-rw-r--r-- | fs/cifs/netmisc.c | 4 | ||||
-rw-r--r-- | fs/cifs/readdir.c | 27 | ||||
-rw-r--r-- | fs/cifs/transport.c | 225 | ||||
-rw-r--r-- | fs/cifs/xattr.c | 8 |
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 | ||
28 | struct cifs_sb_info { | 30 | struct 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 | ||
312 | static 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 */ |
311 | struct mid_q_entry { | 321 | struct 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 | ||
1426 | typedef 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 | |||
1453 | typedef 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 | |||
1414 | typedef struct smb_com_transaction2_get_dfs_refer_req { | 1460 | typedef 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 | |||
1560 | typedef struct { | 1614 | typedef 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); | |||
40 | extern void _FreeXid(unsigned int); | 40 | extern 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));} |
43 | extern char *build_path_from_dentry(struct dentry *); | 43 | extern char *build_path_from_dentry(struct dentry *, const struct cifs_sb_info *cifs_sb); |
44 | extern char *build_wildcard_path_from_dentry(struct dentry *direntry); | 44 | extern char *build_wildcard_path_from_dentry(struct dentry *direntry); |
45 | extern void renew_parental_timestamps(struct dentry *direntry); | 45 | extern void renew_parental_timestamps(struct dentry *direntry); |
46 | extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *, | 46 | extern 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); |
50 | extern 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); | ||
50 | extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid); | 54 | extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid); |
51 | extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length); | 55 | extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length); |
52 | extern int is_valid_oplock_break(struct smb_hdr *smb); | 56 | extern int is_valid_oplock_break(struct smb_hdr *smb); |
@@ -89,7 +93,7 @@ extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
89 | 93 | ||
90 | extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, | 94 | extern 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 | ||
94 | extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, | 98 | extern 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); |
126 | extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, | 130 | extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, |
127 | struct kstatfs *FSData); | 131 | struct kstatfs *FSData); |
132 | extern int CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, | ||
133 | __u64 cap); | ||
134 | |||
128 | extern int CIFSSMBQFSAttributeInfo(const int xid, | 135 | extern int CIFSSMBQFSAttributeInfo(const int xid, |
129 | struct cifsTconInfo *tcon); | 136 | struct cifsTconInfo *tcon); |
130 | extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon); | 137 | extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon); |
@@ -222,7 +229,7 @@ extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, | |||
222 | extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, | 229 | extern 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); |
226 | extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, | 233 | extern 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 |
954 | int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, | 960 | int |
961 | CIFSSMBWrite2(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 | ||
1014 | int | 1035 | int |
@@ -1775,8 +1796,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, | |||
1775 | } | 1796 | } |
1776 | } | 1797 | } |
1777 | qreparse_out: | 1798 | qreparse_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 | ||
3290 | int | ||
3291 | CIFSSMBSetFSUnixInfo(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")); | ||
3301 | SETFSUnixRetry: | ||
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 | ||
3261 | int | 3362 | int |
3262 | CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, | 3363 | CIFSSMBQFSPosixInfo(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 */ |
45 | char * | 45 | char * |
46 | build_path_from_dentry(struct dentry *direntry) | 46 | build_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[] = { | |||
133 | int | 133 | int |
134 | cifs_inet_pton(int address_family, char *cp,void *dst) | 134 | cifs_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 */ | 184 | static int |
184 | /* and also adding support for operations that need to parse the response smb */ | 185 | smb_send2(struct socket *ssocket, struct smb_hdr *smb_buffer, |
185 | 186 | unsigned int smb_hdr_length, const char * data, unsigned int datalen, | |
186 | int | 187 | struct sockaddr *sin) |
187 | smb_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 | |||
250 | int | 261 | int |
251 | CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses, | 262 | SendReceive2(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); |
373 | cifs_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 | } | ||
491 | cifs_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 | ||
501 | out_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 | ||
388 | int | 513 | int |
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); |