aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-08-29 18:54:07 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-08-29 18:54:07 -0400
commitdc709bd190c130b299ac19d596594256265c042a (patch)
tree53c74b614d906825d478b62c068e2ed11b883c95
parentd96299537e43681942ea272e00b0e529aa5b5fa4 (diff)
parentea4c07d780a6f7b7be2d984117bd3e0a2b772e3d (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6: [CIFS] Do not send Query All EAs SMB when mount option nouser_xattr [CIFS] endian errors in lanman protocol support [CIFS] Fix oops in cifs_close due to unitialized lock sem and list in [CIFS] Fix oops when negotiating lanman and no password specified [CIFS] [CIFS] Allow cifsd to suspend if connection is lost [CIFS] Make midState usage more consistent [CIFS] spinlock protect read of last srv response time in timeout path [CIFS] Do not time out posix brl requests when using new posix setfileinfo
-rw-r--r--fs/cifs/CHANGES10
-rw-r--r--fs/cifs/README2
-rw-r--r--fs/cifs/cifsencrypt.c3
-rw-r--r--fs/cifs/cifsfs.c6
-rw-r--r--fs/cifs/cifsfs.h2
-rw-r--r--fs/cifs/cifsglob.h18
-rw-r--r--fs/cifs/cifsproto.h4
-rw-r--r--fs/cifs/cifssmb.c28
-rw-r--r--fs/cifs/connect.c32
-rw-r--r--fs/cifs/dir.c4
-rw-r--r--fs/cifs/file.c97
-rw-r--r--fs/cifs/netmisc.c1
-rw-r--r--fs/cifs/readdir.c2
-rw-r--r--fs/cifs/sess.c2
-rw-r--r--fs/cifs/smberr.h1
-rw-r--r--fs/cifs/transport.c618
-rw-r--r--fs/cifs/xattr.c6
17 files changed, 576 insertions, 260 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index a61d17ed1827..0feb3bd49cb8 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,3 +1,13 @@
1Version 1.45
2------------
3Do not time out lockw calls when using posix extensions. Do not
4time out requests if server still responding reasonably fast
5on requests on other threads. Improve POSIX locking emulation,
6(lock cancel now works, and unlock of merged range works even
7to Windows servers now). Fix oops on mount to lanman servers
8(win9x, os/2 etc.) when null password. Do not send listxattr
9(SMB to query all EAs) if nouser_xattr specified.
10
1Version 1.44 11Version 1.44
2------------ 12------------
3Rewritten sessionsetup support, including support for legacy SMB 13Rewritten sessionsetup support, including support for legacy SMB
diff --git a/fs/cifs/README b/fs/cifs/README
index 7986d0d97ace..5f0e1bd64fee 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -408,7 +408,7 @@ A partial list of the supported mount options follows:
408 user_xattr Allow getting and setting user xattrs as OS/2 EAs (extended 408 user_xattr Allow getting and setting user xattrs as OS/2 EAs (extended
409 attributes) to the server (default) e.g. via setfattr 409 attributes) to the server (default) e.g. via setfattr
410 and getfattr utilities. 410 and getfattr utilities.
411 nouser_xattr Do not allow getfattr/setfattr to get/set xattrs 411 nouser_xattr Do not allow getfattr/setfattr to get/set/list xattrs
412 mapchars Translate six of the seven reserved characters (not backslash) 412 mapchars Translate six of the seven reserved characters (not backslash)
413 *?<>|: 413 *?<>|:
414 to the remap range (above 0xF000), which also 414 to the remap range (above 0xF000), which also
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index a89efaf78a26..4bc250b2d9fc 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -277,7 +277,8 @@ void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key)
277 return; 277 return;
278 278
279 memset(password_with_pad, 0, CIFS_ENCPWD_SIZE); 279 memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
280 strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE); 280 if(ses->password)
281 strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE);
281 282
282 if((ses->server->secMode & SECMODE_PW_ENCRYPT) == 0) 283 if((ses->server->secMode & SECMODE_PW_ENCRYPT) == 0)
283 if(extended_security & CIFSSEC_MAY_PLNTXT) { 284 if(extended_security & CIFSSEC_MAY_PLNTXT) {
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index c28ede599946..3cd750029be2 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -402,7 +402,6 @@ static struct quotactl_ops cifs_quotactl_ops = {
402}; 402};
403#endif 403#endif
404 404
405#ifdef CONFIG_CIFS_EXPERIMENTAL
406static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags) 405static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags)
407{ 406{
408 struct cifs_sb_info *cifs_sb; 407 struct cifs_sb_info *cifs_sb;
@@ -422,7 +421,7 @@ static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags)
422 tcon->tidStatus = CifsExiting; 421 tcon->tidStatus = CifsExiting;
423 up(&tcon->tconSem); 422 up(&tcon->tconSem);
424 423
425 /* cancel_brl_requests(tcon); */ 424 /* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
426 /* cancel_notify_requests(tcon); */ 425 /* cancel_notify_requests(tcon); */
427 if(tcon->ses && tcon->ses->server) 426 if(tcon->ses && tcon->ses->server)
428 { 427 {
@@ -438,7 +437,6 @@ static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags)
438 437
439 return; 438 return;
440} 439}
441#endif
442 440
443static int cifs_remount(struct super_block *sb, int *flags, char *data) 441static int cifs_remount(struct super_block *sb, int *flags, char *data)
444{ 442{
@@ -457,9 +455,7 @@ struct super_operations cifs_super_ops = {
457 unless later we add lazy close of inodes or unless the kernel forgets to call 455 unless later we add lazy close of inodes or unless the kernel forgets to call
458 us with the same number of releases (closes) as opens */ 456 us with the same number of releases (closes) as opens */
459 .show_options = cifs_show_options, 457 .show_options = cifs_show_options,
460#ifdef CONFIG_CIFS_EXPERIMENTAL
461 .umount_begin = cifs_umount_begin, 458 .umount_begin = cifs_umount_begin,
462#endif
463 .remount_fs = cifs_remount, 459 .remount_fs = cifs_remount,
464}; 460};
465 461
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 8f75c6f24701..39ee8ef3bdeb 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -100,5 +100,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
100extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); 100extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
101extern int cifs_ioctl (struct inode * inode, struct file * filep, 101extern int cifs_ioctl (struct inode * inode, struct file * filep,
102 unsigned int command, unsigned long arg); 102 unsigned int command, unsigned long arg);
103#define CIFS_VERSION "1.44" 103#define CIFS_VERSION "1.45"
104#endif /* _CIFSFS_H */ 104#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 6d7cf5f3bc0b..b24006c47df1 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -3,6 +3,7 @@
3 * 3 *
4 * Copyright (C) International Business Machines Corp., 2002,2006 4 * Copyright (C) International Business Machines Corp., 2002,2006
5 * Author(s): Steve French (sfrench@us.ibm.com) 5 * Author(s): Steve French (sfrench@us.ibm.com)
6 * Jeremy Allison (jra@samba.org)
6 * 7 *
7 * This library is free software; you can redistribute it and/or modify 8 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published 9 * it under the terms of the GNU Lesser General Public License as published
@@ -158,7 +159,8 @@ struct TCP_Server_Info {
158 /* 16th byte of RFC1001 workstation name is always null */ 159 /* 16th byte of RFC1001 workstation name is always null */
159 char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL]; 160 char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL];
160 __u32 sequence_number; /* needed for CIFS PDU signature */ 161 __u32 sequence_number; /* needed for CIFS PDU signature */
161 char mac_signing_key[CIFS_SESS_KEY_SIZE + 16]; 162 char mac_signing_key[CIFS_SESS_KEY_SIZE + 16];
163 unsigned long lstrp; /* when we got last response from this server */
162}; 164};
163 165
164/* 166/*
@@ -266,14 +268,14 @@ struct cifsTconInfo {
266}; 268};
267 269
268/* 270/*
269 * This info hangs off the cifsFileInfo structure. This is used to track 271 * This info hangs off the cifsFileInfo structure, pointed to by llist.
270 * byte stream locks on the file 272 * This is used to track byte stream locks on the file
271 */ 273 */
272struct cifsLockInfo { 274struct cifsLockInfo {
273 struct cifsLockInfo *next; 275 struct list_head llist; /* pointer to next cifsLockInfo */
274 int start; 276 __u64 offset;
275 int length; 277 __u64 length;
276 int type; 278 __u8 type;
277}; 279};
278 280
279/* 281/*
@@ -304,6 +306,8 @@ struct cifsFileInfo {
304 /* lock scope id (0 if none) */ 306 /* lock scope id (0 if none) */
305 struct file * pfile; /* needed for writepage */ 307 struct file * pfile; /* needed for writepage */
306 struct inode * pInode; /* needed for oplock break */ 308 struct inode * pInode; /* needed for oplock break */
309 struct semaphore lock_sem;
310 struct list_head llist; /* list of byte range locks we have. */
307 unsigned closePend:1; /* file is marked to close */ 311 unsigned closePend:1; /* file is marked to close */
308 unsigned invalidHandle:1; /* file closed via session abend */ 312 unsigned invalidHandle:1; /* file closed via session abend */
309 atomic_t wrtPending; /* handle in use - defer close */ 313 atomic_t wrtPending; /* handle in use - defer close */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index a5ddc62d6fe6..b35c55c3c8bb 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -50,6 +50,10 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
50extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *, 50extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *,
51 struct kvec *, int /* nvec to send */, 51 struct kvec *, int /* nvec to send */,
52 int * /* type of buf returned */ , const int long_op); 52 int * /* type of buf returned */ , const int long_op);
53extern int SendReceiveBlockingLock(const unsigned int /* xid */ , struct cifsTconInfo *,
54 struct smb_hdr * /* input */ ,
55 struct smb_hdr * /* out */ ,
56 int * /* bytes returned */);
53extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid); 57extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid);
54extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length); 58extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length);
55extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *); 59extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 19678c575dfc..075d8fb3d376 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -477,7 +477,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
477 /* BB get server time for time conversions and add 477 /* BB get server time for time conversions and add
478 code to use it and timezone since this is not UTC */ 478 code to use it and timezone since this is not UTC */
479 479
480 if (rsp->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) { 480 if (rsp->EncryptionKeyLength == cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
481 memcpy(server->cryptKey, rsp->EncryptionKey, 481 memcpy(server->cryptKey, rsp->EncryptionKey,
482 CIFS_CRYPTO_KEY_SIZE); 482 CIFS_CRYPTO_KEY_SIZE);
483 } else if (server->secMode & SECMODE_PW_ENCRYPT) { 483 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
@@ -1460,8 +1460,13 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1460 pSMB->hdr.smb_buf_length += count; 1460 pSMB->hdr.smb_buf_length += count;
1461 pSMB->ByteCount = cpu_to_le16(count); 1461 pSMB->ByteCount = cpu_to_le16(count);
1462 1462
1463 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1463 if (waitFlag) {
1464 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1465 (struct smb_hdr *) pSMBr, &bytes_returned);
1466 } else {
1467 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1464 (struct smb_hdr *) pSMBr, &bytes_returned, timeout); 1468 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1469 }
1465 cifs_stats_inc(&tcon->num_locks); 1470 cifs_stats_inc(&tcon->num_locks);
1466 if (rc) { 1471 if (rc) {
1467 cFYI(1, ("Send error in Lock = %d", rc)); 1472 cFYI(1, ("Send error in Lock = %d", rc));
@@ -1484,6 +1489,7 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1484 char *data_offset; 1489 char *data_offset;
1485 struct cifs_posix_lock *parm_data; 1490 struct cifs_posix_lock *parm_data;
1486 int rc = 0; 1491 int rc = 0;
1492 int timeout = 0;
1487 int bytes_returned = 0; 1493 int bytes_returned = 0;
1488 __u16 params, param_offset, offset, byte_count, count; 1494 __u16 params, param_offset, offset, byte_count, count;
1489 1495
@@ -1503,7 +1509,6 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1503 pSMB->MaxSetupCount = 0; 1509 pSMB->MaxSetupCount = 0;
1504 pSMB->Reserved = 0; 1510 pSMB->Reserved = 0;
1505 pSMB->Flags = 0; 1511 pSMB->Flags = 0;
1506 pSMB->Timeout = 0;
1507 pSMB->Reserved2 = 0; 1512 pSMB->Reserved2 = 0;
1508 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; 1513 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1509 offset = param_offset + params; 1514 offset = param_offset + params;
@@ -1529,8 +1534,13 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1529 (((char *) &pSMB->hdr.Protocol) + offset); 1534 (((char *) &pSMB->hdr.Protocol) + offset);
1530 1535
1531 parm_data->lock_type = cpu_to_le16(lock_type); 1536 parm_data->lock_type = cpu_to_le16(lock_type);
1532 if(waitFlag) 1537 if(waitFlag) {
1538 timeout = 3; /* blocking operation, no timeout */
1533 parm_data->lock_flags = cpu_to_le16(1); 1539 parm_data->lock_flags = cpu_to_le16(1);
1540 pSMB->Timeout = cpu_to_le32(-1);
1541 } else
1542 pSMB->Timeout = 0;
1543
1534 parm_data->pid = cpu_to_le32(current->tgid); 1544 parm_data->pid = cpu_to_le32(current->tgid);
1535 parm_data->start = cpu_to_le64(pLockData->fl_start); 1545 parm_data->start = cpu_to_le64(pLockData->fl_start);
1536 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */ 1546 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
@@ -1541,8 +1551,14 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1541 pSMB->Reserved4 = 0; 1551 pSMB->Reserved4 = 0;
1542 pSMB->hdr.smb_buf_length += byte_count; 1552 pSMB->hdr.smb_buf_length += byte_count;
1543 pSMB->ByteCount = cpu_to_le16(byte_count); 1553 pSMB->ByteCount = cpu_to_le16(byte_count);
1544 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1554 if (waitFlag) {
1545 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1555 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1556 (struct smb_hdr *) pSMBr, &bytes_returned);
1557 } else {
1558 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1559 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1560 }
1561
1546 if (rc) { 1562 if (rc) {
1547 cFYI(1, ("Send error in Posix Lock = %d", rc)); 1563 cFYI(1, ("Send error in Posix Lock = %d", rc));
1548 } else if (get_flag) { 1564 } else if (get_flag) {
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 876eb9ef85fe..5d394c726860 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -182,6 +182,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
182 182
183 while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood)) 183 while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
184 { 184 {
185 try_to_freeze();
185 if(server->protocolType == IPV6) { 186 if(server->protocolType == IPV6) {
186 rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket); 187 rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
187 } else { 188 } else {
@@ -612,6 +613,10 @@ multi_t2_fnd:
612#ifdef CONFIG_CIFS_STATS2 613#ifdef CONFIG_CIFS_STATS2
613 mid_entry->when_received = jiffies; 614 mid_entry->when_received = jiffies;
614#endif 615#endif
616 /* so we do not time out requests to server
617 which is still responding (since server could
618 be busy but not dead) */
619 server->lstrp = jiffies;
615 break; 620 break;
616 } 621 }
617 } 622 }
@@ -1266,33 +1271,35 @@ find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
1266 1271
1267 read_lock(&GlobalSMBSeslock); 1272 read_lock(&GlobalSMBSeslock);
1268 list_for_each(tmp, &GlobalTreeConnectionList) { 1273 list_for_each(tmp, &GlobalTreeConnectionList) {
1269 cFYI(1, ("Next tcon - ")); 1274 cFYI(1, ("Next tcon"));
1270 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); 1275 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
1271 if (tcon->ses) { 1276 if (tcon->ses) {
1272 if (tcon->ses->server) { 1277 if (tcon->ses->server) {
1273 cFYI(1, 1278 cFYI(1,
1274 (" old ip addr: %x == new ip %x ?", 1279 ("old ip addr: %x == new ip %x ?",
1275 tcon->ses->server->addr.sockAddr.sin_addr. 1280 tcon->ses->server->addr.sockAddr.sin_addr.
1276 s_addr, new_target_ip_addr)); 1281 s_addr, new_target_ip_addr));
1277 if (tcon->ses->server->addr.sockAddr.sin_addr. 1282 if (tcon->ses->server->addr.sockAddr.sin_addr.
1278 s_addr == new_target_ip_addr) { 1283 s_addr == new_target_ip_addr) {
1279 /* BB lock tcon and server and tcp session and increment use count here? */ 1284 /* BB lock tcon, server and tcp session and increment use count here? */
1280 /* found a match on the TCP session */ 1285 /* found a match on the TCP session */
1281 /* BB check if reconnection needed */ 1286 /* BB check if reconnection needed */
1282 cFYI(1,("Matched ip, old UNC: %s == new: %s ?", 1287 cFYI(1,("IP match, old UNC: %s new: %s",
1283 tcon->treeName, uncName)); 1288 tcon->treeName, uncName));
1284 if (strncmp 1289 if (strncmp
1285 (tcon->treeName, uncName, 1290 (tcon->treeName, uncName,
1286 MAX_TREE_SIZE) == 0) { 1291 MAX_TREE_SIZE) == 0) {
1287 cFYI(1, 1292 cFYI(1,
1288 ("Matched UNC, old user: %s == new: %s ?", 1293 ("and old usr: %s new: %s",
1289 tcon->treeName, uncName)); 1294 tcon->treeName, uncName));
1290 if (strncmp 1295 if (strncmp
1291 (tcon->ses->userName, 1296 (tcon->ses->userName,
1292 userName, 1297 userName,
1293 MAX_USERNAME_SIZE) == 0) { 1298 MAX_USERNAME_SIZE) == 0) {
1294 read_unlock(&GlobalSMBSeslock); 1299 read_unlock(&GlobalSMBSeslock);
1295 return tcon;/* also matched user (smb session)*/ 1300 /* matched smb session
1301 (user name */
1302 return tcon;
1296 } 1303 }
1297 } 1304 }
1298 } 1305 }
@@ -1969,7 +1976,18 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1969 } 1976 }
1970 1977
1971 cFYI(1,("Negotiate caps 0x%x",(int)cap)); 1978 cFYI(1,("Negotiate caps 0x%x",(int)cap));
1972 1979#ifdef CONFIG_CIFS_DEBUG2
1980 if(cap & CIFS_UNIX_FCNTL_CAP)
1981 cFYI(1,("FCNTL cap"));
1982 if(cap & CIFS_UNIX_EXTATTR_CAP)
1983 cFYI(1,("EXTATTR cap"));
1984 if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
1985 cFYI(1,("POSIX path cap"));
1986 if(cap & CIFS_UNIX_XATTR_CAP)
1987 cFYI(1,("XATTR cap"));
1988 if(cap & CIFS_UNIX_POSIX_ACL_CAP)
1989 cFYI(1,("POSIX ACL cap"));
1990#endif /* CIFS_DEBUG2 */
1973 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) { 1991 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
1974 cFYI(1,("setting capabilities failed")); 1992 cFYI(1,("setting capabilities failed"));
1975 } 1993 }
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index ba4cbe9b0684..914239d53634 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -267,6 +267,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
267 pCifsFile->invalidHandle = FALSE; 267 pCifsFile->invalidHandle = FALSE;
268 pCifsFile->closePend = FALSE; 268 pCifsFile->closePend = FALSE;
269 init_MUTEX(&pCifsFile->fh_sem); 269 init_MUTEX(&pCifsFile->fh_sem);
270 init_MUTEX(&pCifsFile->lock_sem);
271 INIT_LIST_HEAD(&pCifsFile->llist);
272 atomic_set(&pCifsFile->wrtPending,0);
273
270 /* set the following in open now 274 /* set the following in open now
271 pCifsFile->pfile = file; */ 275 pCifsFile->pfile = file; */
272 write_lock(&GlobalSMBSeslock); 276 write_lock(&GlobalSMBSeslock);
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 944d2b9e092d..e9c5ba9084fc 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -5,6 +5,7 @@
5 * 5 *
6 * Copyright (C) International Business Machines Corp., 2002,2003 6 * Copyright (C) International Business Machines Corp., 2002,2003
7 * Author(s): Steve French (sfrench@us.ibm.com) 7 * Author(s): Steve French (sfrench@us.ibm.com)
8 * Jeremy Allison (jra@samba.org)
8 * 9 *
9 * This library is free software; you can redistribute it and/or modify 10 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published 11 * it under the terms of the GNU Lesser General Public License as published
@@ -47,6 +48,8 @@ static inline struct cifsFileInfo *cifs_init_private(
47 private_data->netfid = netfid; 48 private_data->netfid = netfid;
48 private_data->pid = current->tgid; 49 private_data->pid = current->tgid;
49 init_MUTEX(&private_data->fh_sem); 50 init_MUTEX(&private_data->fh_sem);
51 init_MUTEX(&private_data->lock_sem);
52 INIT_LIST_HEAD(&private_data->llist);
50 private_data->pfile = file; /* needed for writepage */ 53 private_data->pfile = file; /* needed for writepage */
51 private_data->pInode = inode; 54 private_data->pInode = inode;
52 private_data->invalidHandle = FALSE; 55 private_data->invalidHandle = FALSE;
@@ -473,6 +476,8 @@ int cifs_close(struct inode *inode, struct file *file)
473 cifs_sb = CIFS_SB(inode->i_sb); 476 cifs_sb = CIFS_SB(inode->i_sb);
474 pTcon = cifs_sb->tcon; 477 pTcon = cifs_sb->tcon;
475 if (pSMBFile) { 478 if (pSMBFile) {
479 struct cifsLockInfo *li, *tmp;
480
476 pSMBFile->closePend = TRUE; 481 pSMBFile->closePend = TRUE;
477 if (pTcon) { 482 if (pTcon) {
478 /* no sense reconnecting to close a file that is 483 /* no sense reconnecting to close a file that is
@@ -496,6 +501,16 @@ int cifs_close(struct inode *inode, struct file *file)
496 pSMBFile->netfid); 501 pSMBFile->netfid);
497 } 502 }
498 } 503 }
504
505 /* Delete any outstanding lock records.
506 We'll lose them when the file is closed anyway. */
507 down(&pSMBFile->lock_sem);
508 list_for_each_entry_safe(li, tmp, &pSMBFile->llist, llist) {
509 list_del(&li->llist);
510 kfree(li);
511 }
512 up(&pSMBFile->lock_sem);
513
499 write_lock(&GlobalSMBSeslock); 514 write_lock(&GlobalSMBSeslock);
500 list_del(&pSMBFile->flist); 515 list_del(&pSMBFile->flist);
501 list_del(&pSMBFile->tlist); 516 list_del(&pSMBFile->tlist);
@@ -570,6 +585,21 @@ int cifs_closedir(struct inode *inode, struct file *file)
570 return rc; 585 return rc;
571} 586}
572 587
588static int store_file_lock(struct cifsFileInfo *fid, __u64 len,
589 __u64 offset, __u8 lockType)
590{
591 struct cifsLockInfo *li = kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL);
592 if (li == NULL)
593 return -ENOMEM;
594 li->offset = offset;
595 li->length = len;
596 li->type = lockType;
597 down(&fid->lock_sem);
598 list_add(&li->llist, &fid->llist);
599 up(&fid->lock_sem);
600 return 0;
601}
602
573int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) 603int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
574{ 604{
575 int rc, xid; 605 int rc, xid;
@@ -581,6 +611,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
581 struct cifsTconInfo *pTcon; 611 struct cifsTconInfo *pTcon;
582 __u16 netfid; 612 __u16 netfid;
583 __u8 lockType = LOCKING_ANDX_LARGE_FILES; 613 __u8 lockType = LOCKING_ANDX_LARGE_FILES;
614 int posix_locking;
584 615
585 length = 1 + pfLock->fl_end - pfLock->fl_start; 616 length = 1 + pfLock->fl_end - pfLock->fl_start;
586 rc = -EACCES; 617 rc = -EACCES;
@@ -639,15 +670,14 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
639 } 670 }
640 netfid = ((struct cifsFileInfo *)file->private_data)->netfid; 671 netfid = ((struct cifsFileInfo *)file->private_data)->netfid;
641 672
673 posix_locking = (cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
674 (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability));
642 675
643 /* BB add code here to normalize offset and length to 676 /* BB add code here to normalize offset and length to
644 account for negative length which we can not accept over the 677 account for negative length which we can not accept over the
645 wire */ 678 wire */
646 if (IS_GETLK(cmd)) { 679 if (IS_GETLK(cmd)) {
647 if(experimEnabled && 680 if(posix_locking) {
648 (cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
649 (CIFS_UNIX_FCNTL_CAP &
650 le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) {
651 int posix_lock_type; 681 int posix_lock_type;
652 if(lockType & LOCKING_ANDX_SHARED_LOCK) 682 if(lockType & LOCKING_ANDX_SHARED_LOCK)
653 posix_lock_type = CIFS_RDLCK; 683 posix_lock_type = CIFS_RDLCK;
@@ -683,10 +713,15 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
683 FreeXid(xid); 713 FreeXid(xid);
684 return rc; 714 return rc;
685 } 715 }
686 if (experimEnabled && 716
687 (cifs_sb->tcon->ses->capabilities & CAP_UNIX) && 717 if (!numLock && !numUnlock) {
688 (CIFS_UNIX_FCNTL_CAP & 718 /* if no lock or unlock then nothing
689 le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) { 719 to do since we do not know what it is */
720 FreeXid(xid);
721 return -EOPNOTSUPP;
722 }
723
724 if (posix_locking) {
690 int posix_lock_type; 725 int posix_lock_type;
691 if(lockType & LOCKING_ANDX_SHARED_LOCK) 726 if(lockType & LOCKING_ANDX_SHARED_LOCK)
692 posix_lock_type = CIFS_RDLCK; 727 posix_lock_type = CIFS_RDLCK;
@@ -695,18 +730,46 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
695 730
696 if(numUnlock == 1) 731 if(numUnlock == 1)
697 posix_lock_type = CIFS_UNLCK; 732 posix_lock_type = CIFS_UNLCK;
698 else if(numLock == 0) { 733
699 /* if no lock or unlock then nothing
700 to do since we do not know what it is */
701 FreeXid(xid);
702 return -EOPNOTSUPP;
703 }
704 rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */, 734 rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */,
705 length, pfLock, 735 length, pfLock,
706 posix_lock_type, wait_flag); 736 posix_lock_type, wait_flag);
707 } else 737 } else {
708 rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start, 738 struct cifsFileInfo *fid = (struct cifsFileInfo *)file->private_data;
709 numUnlock, numLock, lockType, wait_flag); 739
740 if (numLock) {
741 rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start,
742 0, numLock, lockType, wait_flag);
743
744 if (rc == 0) {
745 /* For Windows locks we must store them. */
746 rc = store_file_lock(fid, length,
747 pfLock->fl_start, lockType);
748 }
749 } else if (numUnlock) {
750 /* For each stored lock that this unlock overlaps
751 completely, unlock it. */
752 int stored_rc = 0;
753 struct cifsLockInfo *li, *tmp;
754
755 down(&fid->lock_sem);
756 list_for_each_entry_safe(li, tmp, &fid->llist, llist) {
757 if (pfLock->fl_start <= li->offset &&
758 length >= li->length) {
759 stored_rc = CIFSSMBLock(xid, pTcon, netfid,
760 li->length, li->offset,
761 1, 0, li->type, FALSE);
762 if (stored_rc)
763 rc = stored_rc;
764
765 list_del(&li->llist);
766 kfree(li);
767 }
768 }
769 up(&fid->lock_sem);
770 }
771 }
772
710 if (pfLock->fl_flags & FL_POSIX) 773 if (pfLock->fl_flags & FL_POSIX)
711 posix_lock_file_wait(file, pfLock); 774 posix_lock_file_wait(file, pfLock);
712 FreeXid(xid); 775 FreeXid(xid);
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index b66eff5dc624..ce87550e918f 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -72,6 +72,7 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = {
72 {ERRinvlevel,-EOPNOTSUPP}, 72 {ERRinvlevel,-EOPNOTSUPP},
73 {ERRdirnotempty, -ENOTEMPTY}, 73 {ERRdirnotempty, -ENOTEMPTY},
74 {ERRnotlocked, -ENOLCK}, 74 {ERRnotlocked, -ENOLCK},
75 {ERRcancelviolation, -ENOLCK},
75 {ERRalreadyexists, -EEXIST}, 76 {ERRalreadyexists, -EEXIST},
76 {ERRmoredata, -EOVERFLOW}, 77 {ERRmoredata, -EOVERFLOW},
77 {ERReasnotsupported,-EOPNOTSUPP}, 78 {ERReasnotsupported,-EOPNOTSUPP},
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 03bbcb377913..105761e3ba0e 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -556,7 +556,7 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
556 FIND_FILE_STANDARD_INFO * pFindData = 556 FIND_FILE_STANDARD_INFO * pFindData =
557 (FIND_FILE_STANDARD_INFO *)current_entry; 557 (FIND_FILE_STANDARD_INFO *)current_entry;
558 filename = &pFindData->FileName[0]; 558 filename = &pFindData->FileName[0];
559 len = le32_to_cpu(pFindData->FileNameLength); 559 len = pFindData->FileNameLength;
560 } else { 560 } else {
561 cFYI(1,("Unknown findfirst level %d",cfile->srch_inf.info_level)); 561 cFYI(1,("Unknown findfirst level %d",cfile->srch_inf.info_level));
562 } 562 }
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 7202d534ef0b..d1705ab8136e 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -372,7 +372,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
372 372
373 /* no capabilities flags in old lanman negotiation */ 373 /* no capabilities flags in old lanman negotiation */
374 374
375 pSMB->old_req.PasswordLength = CIFS_SESS_KEY_SIZE; 375 pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE);
376 /* BB calculate hash with password */ 376 /* BB calculate hash with password */
377 /* and copy into bcc */ 377 /* and copy into bcc */
378 378
diff --git a/fs/cifs/smberr.h b/fs/cifs/smberr.h
index cd41c67ff8d3..212c3c296409 100644
--- a/fs/cifs/smberr.h
+++ b/fs/cifs/smberr.h
@@ -95,6 +95,7 @@
95#define ERRinvlevel 124 95#define ERRinvlevel 124
96#define ERRdirnotempty 145 96#define ERRdirnotempty 145
97#define ERRnotlocked 158 97#define ERRnotlocked 158
98#define ERRcancelviolation 173
98#define ERRalreadyexists 183 99#define ERRalreadyexists 183
99#define ERRbadpipe 230 100#define ERRbadpipe 230
100#define ERRpipebusy 231 101#define ERRpipebusy 231
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 17ba329e2b3d..48d47b46b1fb 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -3,7 +3,8 @@
3 * 3 *
4 * Copyright (C) International Business Machines Corp., 2002,2005 4 * Copyright (C) International Business Machines Corp., 2002,2005
5 * Author(s): Steve French (sfrench@us.ibm.com) 5 * Author(s): Steve French (sfrench@us.ibm.com)
6 * 6 * Jeremy Allison (jra@samba.org) 2006.
7 *
7 * This library is free software; you can redistribute it and/or modify 8 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published 9 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or 10 * by the Free Software Foundation; either version 2.1 of the License, or
@@ -36,7 +37,7 @@ extern mempool_t *cifs_mid_poolp;
36extern kmem_cache_t *cifs_oplock_cachep; 37extern kmem_cache_t *cifs_oplock_cachep;
37 38
38static struct mid_q_entry * 39static struct mid_q_entry *
39AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses) 40AllocMidQEntry(const struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
40{ 41{
41 struct mid_q_entry *temp; 42 struct mid_q_entry *temp;
42 43
@@ -203,6 +204,10 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
203 rc = 0; 204 rc = 0;
204 } 205 }
205 206
207 /* Don't want to modify the buffer as a
208 side effect of this call. */
209 smb_buffer->smb_buf_length = smb_buf_length;
210
206 return rc; 211 return rc;
207} 212}
208 213
@@ -217,6 +222,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
217 unsigned int len = iov[0].iov_len; 222 unsigned int len = iov[0].iov_len;
218 unsigned int total_len; 223 unsigned int total_len;
219 int first_vec = 0; 224 int first_vec = 0;
225 unsigned int smb_buf_length = smb_buffer->smb_buf_length;
220 226
221 if(ssocket == NULL) 227 if(ssocket == NULL)
222 return -ENOTSOCK; /* BB eventually add reconnect code here */ 228 return -ENOTSOCK; /* BB eventually add reconnect code here */
@@ -293,36 +299,15 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
293 } else 299 } else
294 rc = 0; 300 rc = 0;
295 301
302 /* Don't want to modify the buffer as a
303 side effect of this call. */
304 smb_buffer->smb_buf_length = smb_buf_length;
305
296 return rc; 306 return rc;
297} 307}
298 308
299int 309static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op)
300SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
301 struct kvec *iov, int n_vec, int * pRespBufType /* ret */,
302 const int long_op)
303{ 310{
304 int rc = 0;
305 unsigned int receive_len;
306 unsigned long timeout;
307 struct mid_q_entry *midQ;
308 struct smb_hdr *in_buf = iov[0].iov_base;
309
310 *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
311
312 if ((ses == NULL) || (ses->server == NULL)) {
313 cifs_small_buf_release(in_buf);
314 cERROR(1,("Null session"));
315 return -EIO;
316 }
317
318 if(ses->server->tcpStatus == CifsExiting) {
319 cifs_small_buf_release(in_buf);
320 return -ENOENT;
321 }
322
323 /* Ensure that we do not send more than 50 overlapping requests
324 to the same server. We may make this configurable later or
325 use ses->maxReq */
326 if(long_op == -1) { 311 if(long_op == -1) {
327 /* oplock breaks must not be held up */ 312 /* oplock breaks must not be held up */
328 atomic_inc(&ses->server->inFlight); 313 atomic_inc(&ses->server->inFlight);
@@ -345,53 +330,140 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
345 } else { 330 } else {
346 if(ses->server->tcpStatus == CifsExiting) { 331 if(ses->server->tcpStatus == CifsExiting) {
347 spin_unlock(&GlobalMid_Lock); 332 spin_unlock(&GlobalMid_Lock);
348 cifs_small_buf_release(in_buf);
349 return -ENOENT; 333 return -ENOENT;
350 } 334 }
351 335
352 /* can not count locking commands against total since 336 /* can not count locking commands against total since
353 they are allowed to block on server */ 337 they are allowed to block on server */
354 338
355 if(long_op < 3) {
356 /* update # of requests on the wire to server */ 339 /* update # of requests on the wire to server */
340 if (long_op < 3)
357 atomic_inc(&ses->server->inFlight); 341 atomic_inc(&ses->server->inFlight);
358 }
359 spin_unlock(&GlobalMid_Lock); 342 spin_unlock(&GlobalMid_Lock);
360 break; 343 break;
361 } 344 }
362 } 345 }
363 } 346 }
364 /* make sure that we sign in the same order that we send on this socket 347 return 0;
365 and avoid races inside tcp sendmsg code that could cause corruption 348}
366 of smb data */
367
368 down(&ses->server->tcpSem);
369 349
350static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
351 struct mid_q_entry **ppmidQ)
352{
370 if (ses->server->tcpStatus == CifsExiting) { 353 if (ses->server->tcpStatus == CifsExiting) {
371 rc = -ENOENT; 354 return -ENOENT;
372 goto out_unlock2;
373 } else if (ses->server->tcpStatus == CifsNeedReconnect) { 355 } else if (ses->server->tcpStatus == CifsNeedReconnect) {
374 cFYI(1,("tcp session dead - return to caller to retry")); 356 cFYI(1,("tcp session dead - return to caller to retry"));
375 rc = -EAGAIN; 357 return -EAGAIN;
376 goto out_unlock2;
377 } else if (ses->status != CifsGood) { 358 } else if (ses->status != CifsGood) {
378 /* check if SMB session is bad because we are setting it up */ 359 /* check if SMB session is bad because we are setting it up */
379 if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && 360 if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
380 (in_buf->Command != SMB_COM_NEGOTIATE)) { 361 (in_buf->Command != SMB_COM_NEGOTIATE)) {
381 rc = -EAGAIN; 362 return -EAGAIN;
382 goto out_unlock2;
383 } /* else ok - we are setting up session */ 363 } /* else ok - we are setting up session */
384 } 364 }
385 midQ = AllocMidQEntry(in_buf, ses); 365 *ppmidQ = AllocMidQEntry(in_buf, ses);
386 if (midQ == NULL) { 366 if (*ppmidQ == NULL) {
367 return -ENOMEM;
368 }
369 return 0;
370}
371
372static int wait_for_response(struct cifsSesInfo *ses,
373 struct mid_q_entry *midQ,
374 unsigned long timeout,
375 unsigned long time_to_wait)
376{
377 unsigned long curr_timeout;
378
379 for (;;) {
380 curr_timeout = timeout + jiffies;
381 wait_event(ses->server->response_q,
382 (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
383 time_after(jiffies, curr_timeout) ||
384 ((ses->server->tcpStatus != CifsGood) &&
385 (ses->server->tcpStatus != CifsNew)));
386
387 if (time_after(jiffies, curr_timeout) &&
388 (midQ->midState == MID_REQUEST_SUBMITTED) &&
389 ((ses->server->tcpStatus == CifsGood) ||
390 (ses->server->tcpStatus == CifsNew))) {
391
392 unsigned long lrt;
393
394 /* We timed out. Is the server still
395 sending replies ? */
396 spin_lock(&GlobalMid_Lock);
397 lrt = ses->server->lstrp;
398 spin_unlock(&GlobalMid_Lock);
399
400 /* Calculate time_to_wait past last receive time.
401 Although we prefer not to time out if the
402 server is still responding - we will time
403 out if the server takes more than 15 (or 45
404 or 180) seconds to respond to this request
405 and has not responded to any request from
406 other threads on the client within 10 seconds */
407 lrt += time_to_wait;
408 if (time_after(jiffies, lrt)) {
409 /* No replies for time_to_wait. */
410 cERROR(1,("server not responding"));
411 return -1;
412 }
413 } else {
414 return 0;
415 }
416 }
417}
418
419int
420SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
421 struct kvec *iov, int n_vec, int * pRespBufType /* ret */,
422 const int long_op)
423{
424 int rc = 0;
425 unsigned int receive_len;
426 unsigned long timeout;
427 struct mid_q_entry *midQ;
428 struct smb_hdr *in_buf = iov[0].iov_base;
429
430 *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
431
432 if ((ses == NULL) || (ses->server == NULL)) {
433 cifs_small_buf_release(in_buf);
434 cERROR(1,("Null session"));
435 return -EIO;
436 }
437
438 if(ses->server->tcpStatus == CifsExiting) {
439 cifs_small_buf_release(in_buf);
440 return -ENOENT;
441 }
442
443 /* Ensure that we do not send more than 50 overlapping requests
444 to the same server. We may make this configurable later or
445 use ses->maxReq */
446
447 rc = wait_for_free_request(ses, long_op);
448 if (rc) {
449 cifs_small_buf_release(in_buf);
450 return rc;
451 }
452
453 /* make sure that we sign in the same order that we send on this socket
454 and avoid races inside tcp sendmsg code that could cause corruption
455 of smb data */
456
457 down(&ses->server->tcpSem);
458
459 rc = allocate_mid(ses, in_buf, &midQ);
460 if (rc) {
387 up(&ses->server->tcpSem); 461 up(&ses->server->tcpSem);
388 cifs_small_buf_release(in_buf); 462 cifs_small_buf_release(in_buf);
389 /* If not lock req, update # of requests on wire to server */ 463 /* Update # of requests on wire to server */
390 if(long_op < 3) { 464 atomic_dec(&ses->server->inFlight);
391 atomic_dec(&ses->server->inFlight); 465 wake_up(&ses->server->request_q);
392 wake_up(&ses->server->request_q); 466 return rc;
393 }
394 return -ENOMEM;
395 } 467 }
396 468
397 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number); 469 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
@@ -406,32 +478,23 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
406 atomic_dec(&ses->server->inSend); 478 atomic_dec(&ses->server->inSend);
407 midQ->when_sent = jiffies; 479 midQ->when_sent = jiffies;
408#endif 480#endif
409 if(rc < 0) { 481
410 DeleteMidQEntry(midQ); 482 up(&ses->server->tcpSem);
411 up(&ses->server->tcpSem); 483 cifs_small_buf_release(in_buf);
412 cifs_small_buf_release(in_buf); 484
413 /* If not lock req, update # of requests on wire to server */ 485 if(rc < 0)
414 if(long_op < 3) { 486 goto out;
415 atomic_dec(&ses->server->inFlight);
416 wake_up(&ses->server->request_q);
417 }
418 return rc;
419 } else {
420 up(&ses->server->tcpSem);
421 cifs_small_buf_release(in_buf);
422 }
423 487
424 if (long_op == -1) 488 if (long_op == -1)
425 goto cifs_no_response_exit2; 489 goto out;
426 else if (long_op == 2) /* writes past end of file can take loong time */ 490 else if (long_op == 2) /* writes past end of file can take loong time */
427 timeout = 180 * HZ; 491 timeout = 180 * HZ;
428 else if (long_op == 1) 492 else if (long_op == 1)
429 timeout = 45 * HZ; /* should be greater than 493 timeout = 45 * HZ; /* should be greater than
430 servers oplock break timeout (about 43 seconds) */ 494 servers oplock break timeout (about 43 seconds) */
431 else if (long_op > 2) { 495 else
432 timeout = MAX_SCHEDULE_TIMEOUT;
433 } else
434 timeout = 15 * HZ; 496 timeout = 15 * HZ;
497
435 /* wait for 15 seconds or until woken up due to response arriving or 498 /* wait for 15 seconds or until woken up due to response arriving or
436 due to last connection to this server being unmounted */ 499 due to last connection to this server being unmounted */
437 if (signal_pending(current)) { 500 if (signal_pending(current)) {
@@ -441,19 +504,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
441 } 504 }
442 505
443 /* No user interrupts in wait - wreaks havoc with performance */ 506 /* No user interrupts in wait - wreaks havoc with performance */
444 if(timeout != MAX_SCHEDULE_TIMEOUT) { 507 wait_for_response(ses, midQ, timeout, 10 * HZ);
445 timeout += jiffies;
446 wait_event(ses->server->response_q,
447 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
448 time_after(jiffies, timeout) ||
449 ((ses->server->tcpStatus != CifsGood) &&
450 (ses->server->tcpStatus != CifsNew)));
451 } else {
452 wait_event(ses->server->response_q,
453 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
454 ((ses->server->tcpStatus != CifsGood) &&
455 (ses->server->tcpStatus != CifsNew)));
456 }
457 508
458 spin_lock(&GlobalMid_Lock); 509 spin_lock(&GlobalMid_Lock);
459 if (midQ->resp_buf) { 510 if (midQ->resp_buf) {
@@ -481,11 +532,9 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
481 } 532 }
482 spin_unlock(&GlobalMid_Lock); 533 spin_unlock(&GlobalMid_Lock);
483 DeleteMidQEntry(midQ); 534 DeleteMidQEntry(midQ);
484 /* If not lock req, update # of requests on wire to server */ 535 /* Update # of requests on wire to server */
485 if(long_op < 3) { 536 atomic_dec(&ses->server->inFlight);
486 atomic_dec(&ses->server->inFlight); 537 wake_up(&ses->server->request_q);
487 wake_up(&ses->server->request_q);
488 }
489 return rc; 538 return rc;
490 } 539 }
491 540
@@ -536,24 +585,12 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
536 cFYI(1,("Bad MID state?")); 585 cFYI(1,("Bad MID state?"));
537 } 586 }
538 } 587 }
539cifs_no_response_exit2:
540 DeleteMidQEntry(midQ);
541
542 if(long_op < 3) {
543 atomic_dec(&ses->server->inFlight);
544 wake_up(&ses->server->request_q);
545 }
546 588
547 return rc; 589out:
548 590
549out_unlock2: 591 DeleteMidQEntry(midQ);
550 up(&ses->server->tcpSem); 592 atomic_dec(&ses->server->inFlight);
551 cifs_small_buf_release(in_buf); 593 wake_up(&ses->server->request_q);
552 /* If not lock req, update # of requests on wire to server */
553 if(long_op < 3) {
554 atomic_dec(&ses->server->inFlight);
555 wake_up(&ses->server->request_q);
556 }
557 594
558 return rc; 595 return rc;
559} 596}
@@ -583,85 +620,34 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
583 /* Ensure that we do not send more than 50 overlapping requests 620 /* Ensure that we do not send more than 50 overlapping requests
584 to the same server. We may make this configurable later or 621 to the same server. We may make this configurable later or
585 use ses->maxReq */ 622 use ses->maxReq */
586 if(long_op == -1) {
587 /* oplock breaks must not be held up */
588 atomic_inc(&ses->server->inFlight);
589 } else {
590 spin_lock(&GlobalMid_Lock);
591 while(1) {
592 if(atomic_read(&ses->server->inFlight) >=
593 cifs_max_pending){
594 spin_unlock(&GlobalMid_Lock);
595#ifdef CONFIG_CIFS_STATS2
596 atomic_inc(&ses->server->num_waiters);
597#endif
598 wait_event(ses->server->request_q,
599 atomic_read(&ses->server->inFlight)
600 < cifs_max_pending);
601#ifdef CONFIG_CIFS_STATS2
602 atomic_dec(&ses->server->num_waiters);
603#endif
604 spin_lock(&GlobalMid_Lock);
605 } else {
606 if(ses->server->tcpStatus == CifsExiting) {
607 spin_unlock(&GlobalMid_Lock);
608 return -ENOENT;
609 }
610 623
611 /* can not count locking commands against total since 624 rc = wait_for_free_request(ses, long_op);
612 they are allowed to block on server */ 625 if (rc)
613 626 return rc;
614 if(long_op < 3) { 627
615 /* update # of requests on the wire to server */
616 atomic_inc(&ses->server->inFlight);
617 }
618 spin_unlock(&GlobalMid_Lock);
619 break;
620 }
621 }
622 }
623 /* make sure that we sign in the same order that we send on this socket 628 /* make sure that we sign in the same order that we send on this socket
624 and avoid races inside tcp sendmsg code that could cause corruption 629 and avoid races inside tcp sendmsg code that could cause corruption
625 of smb data */ 630 of smb data */
626 631
627 down(&ses->server->tcpSem); 632 down(&ses->server->tcpSem);
628 633
629 if (ses->server->tcpStatus == CifsExiting) { 634 rc = allocate_mid(ses, in_buf, &midQ);
630 rc = -ENOENT; 635 if (rc) {
631 goto out_unlock;
632 } else if (ses->server->tcpStatus == CifsNeedReconnect) {
633 cFYI(1,("tcp session dead - return to caller to retry"));
634 rc = -EAGAIN;
635 goto out_unlock;
636 } else if (ses->status != CifsGood) {
637 /* check if SMB session is bad because we are setting it up */
638 if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
639 (in_buf->Command != SMB_COM_NEGOTIATE)) {
640 rc = -EAGAIN;
641 goto out_unlock;
642 } /* else ok - we are setting up session */
643 }
644 midQ = AllocMidQEntry(in_buf, ses);
645 if (midQ == NULL) {
646 up(&ses->server->tcpSem); 636 up(&ses->server->tcpSem);
647 /* If not lock req, update # of requests on wire to server */ 637 /* Update # of requests on wire to server */
648 if(long_op < 3) { 638 atomic_dec(&ses->server->inFlight);
649 atomic_dec(&ses->server->inFlight); 639 wake_up(&ses->server->request_q);
650 wake_up(&ses->server->request_q); 640 return rc;
651 }
652 return -ENOMEM;
653 } 641 }
654 642
655 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { 643 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
656 up(&ses->server->tcpSem);
657 cERROR(1, ("Illegal length, greater than maximum frame, %d", 644 cERROR(1, ("Illegal length, greater than maximum frame, %d",
658 in_buf->smb_buf_length)); 645 in_buf->smb_buf_length));
659 DeleteMidQEntry(midQ); 646 DeleteMidQEntry(midQ);
660 /* If not lock req, update # of requests on wire to server */ 647 up(&ses->server->tcpSem);
661 if(long_op < 3) { 648 /* Update # of requests on wire to server */
662 atomic_dec(&ses->server->inFlight); 649 atomic_dec(&ses->server->inFlight);
663 wake_up(&ses->server->request_q); 650 wake_up(&ses->server->request_q);
664 }
665 return -EIO; 651 return -EIO;
666 } 652 }
667 653
@@ -677,27 +663,19 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
677 atomic_dec(&ses->server->inSend); 663 atomic_dec(&ses->server->inSend);
678 midQ->when_sent = jiffies; 664 midQ->when_sent = jiffies;
679#endif 665#endif
680 if(rc < 0) { 666 up(&ses->server->tcpSem);
681 DeleteMidQEntry(midQ); 667
682 up(&ses->server->tcpSem); 668 if(rc < 0)
683 /* If not lock req, update # of requests on wire to server */ 669 goto out;
684 if(long_op < 3) { 670
685 atomic_dec(&ses->server->inFlight);
686 wake_up(&ses->server->request_q);
687 }
688 return rc;
689 } else
690 up(&ses->server->tcpSem);
691 if (long_op == -1) 671 if (long_op == -1)
692 goto cifs_no_response_exit; 672 goto out;
693 else if (long_op == 2) /* writes past end of file can take loong time */ 673 else if (long_op == 2) /* writes past end of file can take loong time */
694 timeout = 180 * HZ; 674 timeout = 180 * HZ;
695 else if (long_op == 1) 675 else if (long_op == 1)
696 timeout = 45 * HZ; /* should be greater than 676 timeout = 45 * HZ; /* should be greater than
697 servers oplock break timeout (about 43 seconds) */ 677 servers oplock break timeout (about 43 seconds) */
698 else if (long_op > 2) { 678 else
699 timeout = MAX_SCHEDULE_TIMEOUT;
700 } else
701 timeout = 15 * HZ; 679 timeout = 15 * HZ;
702 /* wait for 15 seconds or until woken up due to response arriving or 680 /* wait for 15 seconds or until woken up due to response arriving or
703 due to last connection to this server being unmounted */ 681 due to last connection to this server being unmounted */
@@ -708,19 +686,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
708 } 686 }
709 687
710 /* No user interrupts in wait - wreaks havoc with performance */ 688 /* No user interrupts in wait - wreaks havoc with performance */
711 if(timeout != MAX_SCHEDULE_TIMEOUT) { 689 wait_for_response(ses, midQ, timeout, 10 * HZ);
712 timeout += jiffies;
713 wait_event(ses->server->response_q,
714 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
715 time_after(jiffies, timeout) ||
716 ((ses->server->tcpStatus != CifsGood) &&
717 (ses->server->tcpStatus != CifsNew)));
718 } else {
719 wait_event(ses->server->response_q,
720 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
721 ((ses->server->tcpStatus != CifsGood) &&
722 (ses->server->tcpStatus != CifsNew)));
723 }
724 690
725 spin_lock(&GlobalMid_Lock); 691 spin_lock(&GlobalMid_Lock);
726 if (midQ->resp_buf) { 692 if (midQ->resp_buf) {
@@ -748,11 +714,9 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
748 } 714 }
749 spin_unlock(&GlobalMid_Lock); 715 spin_unlock(&GlobalMid_Lock);
750 DeleteMidQEntry(midQ); 716 DeleteMidQEntry(midQ);
751 /* If not lock req, update # of requests on wire to server */ 717 /* Update # of requests on wire to server */
752 if(long_op < 3) { 718 atomic_dec(&ses->server->inFlight);
753 atomic_dec(&ses->server->inFlight); 719 wake_up(&ses->server->request_q);
754 wake_up(&ses->server->request_q);
755 }
756 return rc; 720 return rc;
757 } 721 }
758 722
@@ -799,23 +763,253 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
799 cERROR(1,("Bad MID state?")); 763 cERROR(1,("Bad MID state?"));
800 } 764 }
801 } 765 }
802cifs_no_response_exit: 766
767out:
768
803 DeleteMidQEntry(midQ); 769 DeleteMidQEntry(midQ);
770 atomic_dec(&ses->server->inFlight);
771 wake_up(&ses->server->request_q);
804 772
805 if(long_op < 3) { 773 return rc;
806 atomic_dec(&ses->server->inFlight); 774}
807 wake_up(&ses->server->request_q); 775
808 } 776/* Send an NT_CANCEL SMB to cause the POSIX blocking lock to return. */
777
778static int
779send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf,
780 struct mid_q_entry *midQ)
781{
782 int rc = 0;
783 struct cifsSesInfo *ses = tcon->ses;
784 __u16 mid = in_buf->Mid;
809 785
786 header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0);
787 in_buf->Mid = mid;
788 down(&ses->server->tcpSem);
789 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
790 if (rc) {
791 up(&ses->server->tcpSem);
792 return rc;
793 }
794 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
795 (struct sockaddr *) &(ses->server->addr.sockAddr));
796 up(&ses->server->tcpSem);
810 return rc; 797 return rc;
798}
799
800/* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
801 blocking lock to return. */
802
803static int
804send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon,
805 struct smb_hdr *in_buf,
806 struct smb_hdr *out_buf)
807{
808 int bytes_returned;
809 struct cifsSesInfo *ses = tcon->ses;
810 LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
811
812 /* We just modify the current in_buf to change
813 the type of lock from LOCKING_ANDX_SHARED_LOCK
814 or LOCKING_ANDX_EXCLUSIVE_LOCK to
815 LOCKING_ANDX_CANCEL_LOCK. */
816
817 pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
818 pSMB->Timeout = 0;
819 pSMB->hdr.Mid = GetNextMid(ses->server);
820
821 return SendReceive(xid, ses, in_buf, out_buf,
822 &bytes_returned, 0);
823}
811 824
812out_unlock: 825int
826SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
827 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
828 int *pbytes_returned)
829{
830 int rc = 0;
831 int rstart = 0;
832 unsigned int receive_len;
833 struct mid_q_entry *midQ;
834 struct cifsSesInfo *ses;
835
836 if (tcon == NULL || tcon->ses == NULL) {
837 cERROR(1,("Null smb session"));
838 return -EIO;
839 }
840 ses = tcon->ses;
841
842 if(ses->server == NULL) {
843 cERROR(1,("Null tcp session"));
844 return -EIO;
845 }
846
847 if(ses->server->tcpStatus == CifsExiting)
848 return -ENOENT;
849
850 /* Ensure that we do not send more than 50 overlapping requests
851 to the same server. We may make this configurable later or
852 use ses->maxReq */
853
854 rc = wait_for_free_request(ses, 3);
855 if (rc)
856 return rc;
857
858 /* make sure that we sign in the same order that we send on this socket
859 and avoid races inside tcp sendmsg code that could cause corruption
860 of smb data */
861
862 down(&ses->server->tcpSem);
863
864 rc = allocate_mid(ses, in_buf, &midQ);
865 if (rc) {
866 up(&ses->server->tcpSem);
867 return rc;
868 }
869
870 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
871 up(&ses->server->tcpSem);
872 cERROR(1, ("Illegal length, greater than maximum frame, %d",
873 in_buf->smb_buf_length));
874 DeleteMidQEntry(midQ);
875 return -EIO;
876 }
877
878 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
879
880 midQ->midState = MID_REQUEST_SUBMITTED;
881#ifdef CONFIG_CIFS_STATS2
882 atomic_inc(&ses->server->inSend);
883#endif
884 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
885 (struct sockaddr *) &(ses->server->addr.sockAddr));
886#ifdef CONFIG_CIFS_STATS2
887 atomic_dec(&ses->server->inSend);
888 midQ->when_sent = jiffies;
889#endif
813 up(&ses->server->tcpSem); 890 up(&ses->server->tcpSem);
814 /* If not lock req, update # of requests on wire to server */ 891
815 if(long_op < 3) { 892 if(rc < 0) {
816 atomic_dec(&ses->server->inFlight); 893 DeleteMidQEntry(midQ);
817 wake_up(&ses->server->request_q); 894 return rc;
895 }
896
897 /* Wait for a reply - allow signals to interrupt. */
898 rc = wait_event_interruptible(ses->server->response_q,
899 (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
900 ((ses->server->tcpStatus != CifsGood) &&
901 (ses->server->tcpStatus != CifsNew)));
902
903 /* Were we interrupted by a signal ? */
904 if ((rc == -ERESTARTSYS) &&
905 (midQ->midState == MID_REQUEST_SUBMITTED) &&
906 ((ses->server->tcpStatus == CifsGood) ||
907 (ses->server->tcpStatus == CifsNew))) {
908
909 if (in_buf->Command == SMB_COM_TRANSACTION2) {
910 /* POSIX lock. We send a NT_CANCEL SMB to cause the
911 blocking lock to return. */
912
913 rc = send_nt_cancel(tcon, in_buf, midQ);
914 if (rc) {
915 DeleteMidQEntry(midQ);
916 return rc;
917 }
918 } else {
919 /* Windows lock. We send a LOCKINGX_CANCEL_LOCK
920 to cause the blocking lock to return. */
921
922 rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
923
924 /* If we get -ENOLCK back the lock may have
925 already been removed. Don't exit in this case. */
926 if (rc && rc != -ENOLCK) {
927 DeleteMidQEntry(midQ);
928 return rc;
929 }
930 }
931
932 /* Wait 5 seconds for the response. */
933 if (wait_for_response(ses, midQ, 5 * HZ, 5 * HZ)==0) {
934 /* We got the response - restart system call. */
935 rstart = 1;
936 }
937 }
938
939 spin_lock(&GlobalMid_Lock);
940 if (midQ->resp_buf) {
941 spin_unlock(&GlobalMid_Lock);
942 receive_len = midQ->resp_buf->smb_buf_length;
943 } else {
944 cERROR(1,("No response for cmd %d mid %d",
945 midQ->command, midQ->mid));
946 if(midQ->midState == MID_REQUEST_SUBMITTED) {
947 if(ses->server->tcpStatus == CifsExiting)
948 rc = -EHOSTDOWN;
949 else {
950 ses->server->tcpStatus = CifsNeedReconnect;
951 midQ->midState = MID_RETRY_NEEDED;
952 }
953 }
954
955 if (rc != -EHOSTDOWN) {
956 if(midQ->midState == MID_RETRY_NEEDED) {
957 rc = -EAGAIN;
958 cFYI(1,("marking request for retry"));
959 } else {
960 rc = -EIO;
961 }
962 }
963 spin_unlock(&GlobalMid_Lock);
964 DeleteMidQEntry(midQ);
965 return rc;
818 } 966 }
967
968 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
969 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
970 receive_len, xid));
971 rc = -EIO;
972 } else { /* rcvd frame is ok */
973
974 if (midQ->resp_buf && out_buf
975 && (midQ->midState == MID_RESPONSE_RECEIVED)) {
976 out_buf->smb_buf_length = receive_len;
977 memcpy((char *)out_buf + 4,
978 (char *)midQ->resp_buf + 4,
979 receive_len);
980
981 dump_smb(out_buf, 92);
982 /* convert the length into a more usable form */
983 if((receive_len > 24) &&
984 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
985 SECMODE_SIGN_ENABLED))) {
986 rc = cifs_verify_signature(out_buf,
987 ses->server->mac_signing_key,
988 midQ->sequence_number+1);
989 if(rc) {
990 cERROR(1,("Unexpected SMB signature"));
991 /* BB FIXME add code to kill session */
992 }
993 }
994
995 *pbytes_returned = out_buf->smb_buf_length;
996
997 /* BB special case reconnect tid and uid here? */
998 rc = map_smb_to_linux_error(out_buf);
819 999
1000 /* convert ByteCount if necessary */
1001 if (receive_len >=
1002 sizeof (struct smb_hdr) -
1003 4 /* do not count RFC1001 header */ +
1004 (2 * out_buf->WordCount) + 2 /* bcc */ )
1005 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
1006 } else {
1007 rc = -EIO;
1008 cERROR(1,("Bad MID state?"));
1009 }
1010 }
1011 DeleteMidQEntry(midQ);
1012 if (rstart && rc == -EACCES)
1013 return -ERESTARTSYS;
820 return rc; 1014 return rc;
821} 1015}
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index 7754d641775e..067648b7179b 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -330,11 +330,15 @@ ssize_t cifs_listxattr(struct dentry * direntry, char * data, size_t buf_size)
330 sb = direntry->d_inode->i_sb; 330 sb = direntry->d_inode->i_sb;
331 if(sb == NULL) 331 if(sb == NULL)
332 return -EIO; 332 return -EIO;
333 xid = GetXid();
334 333
335 cifs_sb = CIFS_SB(sb); 334 cifs_sb = CIFS_SB(sb);
336 pTcon = cifs_sb->tcon; 335 pTcon = cifs_sb->tcon;
337 336
337 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
338 return -EOPNOTSUPP;
339
340 xid = GetXid();
341
338 full_path = build_path_from_dentry(direntry); 342 full_path = build_path_from_dentry(direntry);
339 if(full_path == NULL) { 343 if(full_path == NULL) {
340 FreeXid(xid); 344 FreeXid(xid);