bk://cifs.bkbits.net/linux-2.5cifs
cifs.adm@hostme.bitkeeper.com|ChangeSet|20040526013611|10092 cifs.adm

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/05/25 21:18:56-07:00 akpm@bix.(none) 
#   Merge bk://cifs.bkbits.net/linux-2.5cifs
#   into bix.(none):/usr/src/bk-cifs
# 
# fs/cifs/cifssmb.c
#   2004/05/25 21:18:53-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/25 17:37:38-05:00 stevef@stevef95.austin.ibm.com 
#   Merge bk://cifs.bkbits.net/linux-2.5cifs
#   into stevef95.austin.ibm.com:/home/stevef/linux-2.5cifs
# 
# fs/cifs/cifssmb.c
#   2004/05/25 17:37:26-05:00 stevef@stevef95.austin.ibm.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/25 17:36:24-05:00 stevef@stevef95.austin.ibm.com 
#   do not log errors on write failures unless debug is on
# 
# fs/cifs/cifssmb.c
#   2004/05/25 17:36:16-05:00 stevef@stevef95.austin.ibm.com +2 -2
#   do not log errors on write failures unless debug is on
# 
# ChangeSet
#   2004/05/25 00:13:22-05:00 stevef@smfhome.smfdom 
#   Retry build_path_from_dentry if parent path changes in flight
# 
# fs/cifs/dir.c
#   2004/05/25 00:13:15-05:00 stevef@smfhome.smfdom +18 -1
#   Retry build_path_from_dentry if parent path changes in flight
# 
# ChangeSet
#   2004/05/24 23:58:35-05:00 stevef@smfhome.smfdom 
#   check for close pending and invalid file struct on writing out page
# 
# fs/cifs/file.c
#   2004/05/24 23:58:29-05:00 stevef@smfhome.smfdom +14 -1
#   check for close pending and invalid file struct on writing out page
# 
# fs/cifs/CHANGES
#   2004/05/24 23:58:29-05:00 stevef@smfhome.smfdom +2 -1
#   update cifs change log
# 
# ChangeSet
#   2004/05/24 18:04:01-07:00 akpm@bix.(none) 
#   Merge bk://cifs.bkbits.net/linux-2.5cifs
#   into bix.(none):/usr/src/bk-cifs
# 
# fs/cifs/cifssmb.c
#   2004/05/24 18:03:57-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/24 19:51:38-05:00 stevef@smfhome1.smfsambadom 
#   Fix incorrect file size on handle based setattr (for big endian hardware)
# 
# fs/cifs/cifssmb.c
#   2004/05/24 19:51:31-05:00 stevef@smfhome1.smfsambadom +1 -1
#   Fix incorrect file size on handle based setattr (for big endian hardware)
# 
# fs/cifs/cifsfs.h
#   2004/05/24 19:51:31-05:00 stevef@smfhome1.smfsambadom +1 -1
#   Update cifs version to 1.16
# 
# fs/cifs/CHANGES
#   2004/05/24 19:51:30-05:00 stevef@smfhome1.smfsambadom +5 -0
#   Update cifs version to 1.16
# 
# ChangeSet
#   2004/05/22 23:28:34-07:00 akpm@bix.(none) 
#   Merge bk://cifs.bkbits.net/linux-2.5cifs
#   into bix.(none):/usr/src/bk-cifs
# 
# fs/cifs/cifssmb.c
#   2004/05/22 23:28:31-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/22 23:20:38-05:00 stevef@smfhome1.smfsambadom 
#   fix oops in heavy stress test caused by lack of check for bad dentry being passed in on reconnect
# 
# fs/cifs/file.c
#   2004/05/22 23:20:31-05:00 stevef@smfhome1.smfsambadom +6 -1
#   fix oops in heavy stress test caused by lack of check for bad dentry being passed in on reconnect
# 
# fs/cifs/dir.c
#   2004/05/22 23:20:31-05:00 stevef@smfhome1.smfsambadom +6 -1
#   fix oops in heavy stress test caused by lack of check for bad dentry being passed in on reconnect
# 
# ChangeSet
#   2004/05/22 05:47:17-05:00 stevef@steveft21.ltcsamba 
#   Check for kmalloc failure on building full path
# 
# fs/cifs/link.c
#   2004/05/22 05:28:46-05:00 stevef@steveft21.ltcsamba +20 -0
#   Check for kmalloc failure on building full path
# 
# fs/cifs/inode.c
#   2004/05/22 05:28:46-05:00 stevef@steveft21.ltcsamba +26 -1
#   Check for kmalloc failure on building full path
# 
# fs/cifs/file.c
#   2004/05/22 05:28:46-05:00 stevef@steveft21.ltcsamba +9 -0
#   Check for kmalloc failure on building full path
# 
# fs/cifs/fcntl.c
#   2004/05/22 05:28:46-05:00 stevef@steveft21.ltcsamba +7 -2
#   Check for kmalloc failure on building full path
# 
# fs/cifs/dir.c
#   2004/05/22 05:28:46-05:00 stevef@steveft21.ltcsamba +27 -7
#   Check for kmalloc failure on building full path
# 
# fs/cifs/file.c
#   2004/05/21 20:32:52-05:00 stevef@steveft21.ltcsamba +5 -11
#   reorder check for bad pointer
# 
# fs/cifs/dir.c
#   2004/05/21 20:32:52-05:00 stevef@steveft21.ltcsamba +4 -6
#   cleanup ugly code
# 
# fs/cifs/transport.c
#   2004/05/21 05:45:32-05:00 stevef@steveft21.ltcsamba +15 -8
#   check session status in the right order, after getting ses semaphore
# 
# ChangeSet
#   2004/05/20 03:26:15-05:00 stevef@steveft21.ltcsamba 
#   POSIX protocol extensions part 1
# 
# fs/cifs/cifssmb.c
#   2004/05/20 03:25:20-05:00 stevef@steveft21.ltcsamba +54 -44
#   POSIX protocol extensions part 1
# 
# fs/cifs/cifspdu.h
#   2004/05/20 03:25:19-05:00 stevef@steveft21.ltcsamba +77 -0
#   POSIX protocol extensions part 1
# 
# ChangeSet
#   2004/05/18 14:31:25-07:00 akpm@bix.(none) 
#   Merge bk://cifs.bkbits.net/linux-2.5cifs
#   into bix.(none):/usr/src/bk-cifs
# 
# fs/cifs/cifsfs.c
#   2004/05/18 14:31:22-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/11 16:37:09-07:00 akpm@bix.(none) 
#   Merge bk://cifs.bkbits.net/linux-2.5cifs
#   into bix.(none):/usr/src/bk-cifs
# 
# fs/cifs/cifssmb.c
#   2004/05/11 16:37:06-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/04 13:51:19-07:00 akpm@bix.(none) 
#   Merge bk://cifs.bkbits.net/linux-2.5cifs
#   into bix.(none):/usr/src/bk-cifs
# 
# fs/cifs/cifssmb.c
#   2004/05/04 13:51:17-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/02 21:56:11-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-cifs
# 
# fs/cifs/cifssmb.c
#   2004/05/02 21:56:09-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# fs/cifs/cifsfs.c
#   2004/05/02 21:56:08-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/01 15:05:17-07:00 akpm@bix.(none) 
#   Merge bk://cifs.bkbits.net/linux-2.5cifs
#   into bix.(none):/usr/src/bk-cifs
# 
# fs/cifs/cifssmb.c
#   2004/05/01 15:05:14-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/04/29 15:41:50-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-cifs
# 
# fs/cifs/cifssmb.c
#   2004/04/29 15:41:48-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/04/26 18:11:55-07:00 akpm@bix.(none) 
#   Merge bk://cifs.bkbits.net/linux-2.5cifs
#   into bix.(none):/usr/src/bk-cifs
# 
# fs/cifs/cifsfs.c
#   2004/04/26 18:11:52-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/04/23 12:36:52-07:00 akpm@bix.(none) 
#   Merge bk://cifs.bkbits.net/linux-2.5cifs
#   into bix.(none):/usr/src/bk-cifs
# 
# fs/cifs/cifsfs.c
#   2004/04/23 12:36:49-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/04/19 19:23:58-07:00 akpm@bix.(none) 
#   Merge bk://cifs.bkbits.net/linux-2.5cifs
#   into bix.(none):/usr/src/bk-cifs
# 
# fs/cifs/cifsfs.c
#   2004/04/19 19:23:56-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/04/16 20:19:53-07:00 akpm@bix.(none) 
#   Merge bk://cifs.bkbits.net/linux-2.5cifs
#   into bix.(none):/usr/src/bk-cifs
# 
# fs/cifs/cifsfs.c
#   2004/04/16 20:19:51-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/04/16 20:18:59-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-cifs
# 
# fs/cifs/cifsfs.c
#   2004/04/16 20:18:56-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
diff -Nru a/fs/cifs/CHANGES b/fs/cifs/CHANGES
--- a/fs/cifs/CHANGES	2004-05-25 21:19:51 -07:00
+++ b/fs/cifs/CHANGES	2004-05-25 21:19:51 -07:00
@@ -1,3 +1,9 @@
+Version 1.16
+------------
+Fix incorrect file size in file handle based setattr on big endian hardware.
+Fix oops in build_path_from_dentry when out of memory.  Add checks for invalid
+and closing file structs in writepage/partialpagewrite
+
 Version 1.15
 ------------
 Change to mempools for alloc smb request buffers and multiplex structs
diff -Nru a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
--- a/fs/cifs/cifsfs.h	2004-05-25 21:19:51 -07:00
+++ b/fs/cifs/cifsfs.h	2004-05-25 21:19:51 -07:00
@@ -93,5 +93,5 @@
 			 size_t, int);
 extern ssize_t	cifs_getxattr(struct dentry *, const char *, void *, size_t);
 extern ssize_t	cifs_listxattr(struct dentry *, char *, size_t);
-#define CIFS_VERSION   "1.15"
+#define CIFS_VERSION   "1.16"
 #endif				/* _CIFSFS_H */
diff -Nru a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
--- a/fs/cifs/cifspdu.h	2004-05-25 21:19:51 -07:00
+++ b/fs/cifs/cifspdu.h	2004-05-25 21:19:51 -07:00
@@ -1687,6 +1687,83 @@
 	void (*free) (struct data_blob * data_blob);
 };
 
+#ifdef CIFS_POSIX
+/* 
+	For better POSIX semantics from Linux client, (even better
+	than the existing CIFS Unix Extensions) we need updated PDUs for:
+	
+	1) PosixCreateX - to set and return the mode, inode#, device info and
+	perhaps add a CreateDevice - to create Pipes and other special .inodes
+	Also note POSIX open flags
+	2) Close - to return the last write time to do cache across close more safely
+	3) PosixQFSInfo - to return statfs info
+	4) FindFirst return unique inode number - what about resume key, two forms short (matches readdir) and full (enough info to cache inodes)
+	5) Mkdir - set mode
+	
+	And under consideration: 
+	6) FindClose2 (return nanosecond timestamp ??)
+	7) Use nanosecond timestamps throughout all time fields if 
+	   corresponding attribute flag is set
+	8) sendfile - handle based copy
+	9) Direct i/o
+	10) "POSIX ACL" support
+	11) Misc fcntls?
+	
+	what about fixing 64 bit alignment
+	
+	There are also various legacy SMB/CIFS requests used as is
+	
+	From existing Lanman and NTLM dialects:
+	--------------------------------------
+	NEGOTIATE
+	SESSION_SETUP_ANDX (BB which?)
+	TREE_CONNECT_ANDX (BB which wct?)
+	TREE_DISCONNECT (BB add volume timestamp on response)
+	LOGOFF_ANDX
+	DELETE (note delete open file behavior)
+	DELETE_DIRECTORY
+	READ_AND_X
+	WRITE_AND_X
+	LOCKING_AND_X (note posix lock semantics)
+	RENAME (note rename across dirs and open file rename posix behaviors)
+	NT_RENAME (for hardlinks) Is this good enough for all features?
+	FIND_CLOSE2
+	TRANSACTION2 (18 cases)
+		SMB_SET_FILE_END_OF_FILE_INFO2 SMB_SET_PATH_END_OF_FILE_INFO2
+		(BB verify that never need to set allocation size)
+		SMB_SET_FILE_BASIC_INFO2 (setting times - BB can it be done via Unix ext?)
+	
+	COPY (note support for copy across directories) - FUTURE, OPTIONAL
+	setting/getting OS/2 EAs - FUTURE (BB can this handle
+	        setting Linux xattrs perfectly)         - OPTIONAL
+    dnotify                                         - FUTURE, OPTIONAL
+    quota                                           - FUTURE, OPTIONAL
+			
+	Note that various requests implemented for NT interop such as 
+		NT_TRANSACT (IOCTL) QueryReparseInfo
+	are unneeded to servers compliant with the CIFS POSIX extensions
+	
+	From CIFS Unix Extensions:
+	-------------------------
+	T2 SET_PATH_INFO (SMB_SET_FILE_UNIX_LINK) for symlinks
+	T2 SET_PATH_INFO (SMB_SET_FILE_BASIC_INFO2)
+	T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_LINK)
+	T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_BASIC) - BB check for missing inode fields
+					Actually need QUERY_FILE_UNIX_INFO since has inode num
+					BB what about a) blksize/blkbits/blocks
+								  b) i_version
+								  c) i_rdev
+								  d) notify mask?
+								  e) generation
+								  f) size_seqcount
+	T2 FIND_FIRST/FIND_NEXT FIND_FILE_UNIX
+	TRANS2_GET_DFS_REFERRAL				  - OPTIONAL but recommended
+	T2_QFS_INFO QueryDevice/AttributeInfo - OPTIONAL
+	
+	
+ */
+#endif 
+
 #pragma pack()			/* resume default structure packing */
 
 #endif				/* _CIFSPDU_H */
diff -Nru a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
--- a/fs/cifs/cifssmb.c	2004-05-25 21:19:51 -07:00
+++ b/fs/cifs/cifssmb.c	2004-05-25 21:19:51 -07:00
@@ -37,13 +37,24 @@
 #include "cifs_unicode.h"
 #include "cifs_debug.h"
 
+#ifdef CIFS_POSIX
 static struct {
 	int index;
 	char *name;
 } protocols[] = {
 	{CIFS_PROT, "\2NT LM 0.12"}, 
+	{CIFS_PROT, "\2POSIX 2"},
 	{BAD_PROT, "\2"}
 };
+#else
+static struct {
+	int index;
+	char *name;
+} protocols[] = {
+	{CIFS_PROT, "\2NT LM 0.12"}, 
+	{BAD_PROT, "\2"}
+};
+#endif
 
 
 /* Mark as invalid, all open files on tree connections since they
@@ -728,7 +739,7 @@
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
 	if (rc) {
-		cERROR(1, ("Send error in write = %d", rc));
+		cFYI(1, ("Send error in write = %d", rc));
 		*nbytes = 0;
 	} else
 		*nbytes = le16_to_cpu(pSMBr->Count);
@@ -792,7 +803,7 @@
 			 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
 
 	if (rc) {
-		cERROR(1, ("Send error in Lock = %d", rc));
+		cFYI(1, ("Send error in Lock = %d", rc));
 	}
 	if (pSMB)
 		cifs_buf_release(pSMB);
@@ -987,60 +998,59 @@
 
 int
 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName, 
-              const __u16 target_tid, const char *toName, const int flags,
-              const struct nls_table *nls_codepage)
+            const __u16 target_tid, const char *toName, const int flags,
+            const struct nls_table *nls_codepage)
 {
-        int rc = 0;
-        COPY_REQ *pSMB = NULL;
-        COPY_RSP *pSMBr = NULL;
-        int bytes_returned;
-        int name_len, name_len2;
+	int rc = 0;
+	COPY_REQ *pSMB = NULL;
+	COPY_RSP *pSMBr = NULL;
+	int bytes_returned;
+	int name_len, name_len2;
 
-        cFYI(1, ("In CIFSSMBCopy"));
+	cFYI(1, ("In CIFSSMBCopy"));
 copyRetry:
-        rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
-                      (void **) &pSMBr);
-        if (rc)
-                return rc;
+	rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
+			(void **) &pSMBr);
+	if (rc)
+		return rc;
 
-        pSMB->BufferFormat = 0x04;
+	pSMB->BufferFormat = 0x04;
 	pSMB->Tid2 = target_tid;
 
 	if(flags & COPY_TREE)
 		pSMB->Flags |= COPY_TREE;
 	pSMB->Flags = cpu_to_le16(pSMB->Flags);
 
-        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
-                name_len =
-                    cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
-                                  /* find define for this maxpathcomponent */
-                                  , nls_codepage);
-                name_len++;     /* trailing null */
-                name_len *= 2;
-                pSMB->OldFileName[name_len] = 0x04;     /* pad */
-        /* protocol requires ASCII signature byte on Unicode string */
-                pSMB->OldFileName[name_len + 1] = 0x00;
-                name_len2 =
-                    cifs_strtoUCS((wchar_t *) & pSMB->
-                                  OldFileName[name_len + 2], toName, 530,
-                                  nls_codepage);
-                name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
-                name_len2 *= 2; /* convert to bytes */
-        } else {                /* BB improve the check for buffer overruns BB */
-                name_len = strnlen(fromName, 530);
-                name_len++;     /* trailing null */
-                strncpy(pSMB->OldFileName, fromName, name_len);
-                name_len2 = strnlen(toName, 530);
-                name_len2++;    /* trailing null */
-                pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
-                strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
-                name_len2++;    /* trailing null */
-                name_len2++;    /* signature byte */
-        }
-
-        pSMB->ByteCount = 1 /* 1st signature byte */  + name_len + name_len2;
-        pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-        pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len = cifs_strtoUCS((wchar_t *) pSMB->OldFileName, 
+				fromName, 
+				530 /* find define for this maxpathcomponent */,
+				nls_codepage);
+		name_len++;     /* trailing null */
+		name_len *= 2;
+		pSMB->OldFileName[name_len] = 0x04;     /* pad */
+		/* protocol requires ASCII signature byte on Unicode string */
+		pSMB->OldFileName[name_len + 1] = 0x00;
+		name_len2 = cifs_strtoUCS((wchar_t *) & pSMB->
+				OldFileName[name_len + 2], toName, 530,
+				nls_codepage);
+		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
+		name_len2 *= 2; /* convert to bytes */
+	} else {                /* BB improve the check for buffer overruns BB */
+		name_len = strnlen(fromName, 530);
+		name_len++;     /* trailing null */
+		strncpy(pSMB->OldFileName, fromName, name_len);
+		name_len2 = strnlen(toName, 530);
+		name_len2++;    /* trailing null */
+		pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
+		strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
+		name_len2++;    /* trailing null */
+		name_len2++;    /* signature byte */
+	}
+
+	pSMB->ByteCount = 1 /* 1st signature byte */  + name_len + name_len2;
+	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
@@ -2581,7 +2591,7 @@
 		(struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
 			pSMB->DataOffset);
 	pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset); /* now safe to change to le */
-	parm_data->FileSize = size;
+	parm_data->FileSize = cpu_to_le64(size);
 	pSMB->Fid = fid;
 	if(SetAllocation) {
 		if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
diff -Nru a/fs/cifs/dir.c b/fs/cifs/dir.c
--- a/fs/cifs/dir.c	2004-05-25 21:19:51 -07:00
+++ b/fs/cifs/dir.c	2004-05-25 21:19:51 -07:00
@@ -38,7 +38,7 @@
 	do {
 		direntry->d_time = jiffies;
 		direntry = direntry->d_parent;
-	} while (!IS_ROOT(direntry));	/* BB for DFS case should stop at the root of share which could be lower than root of this mount due to implicit dfs connections */
+	} while (!IS_ROOT(direntry));	
 }
 
 /* Note: caller must free return buffer */
@@ -49,14 +49,26 @@
 	int namelen = 0;
 	char *full_path;
 
+	if(direntry == NULL)
+		return NULL;  /* not much we can do if dentry is freed and
+		we need to reopen the file after it was closed implicitly
+		when the server crashed */
+
+cifs_bp_rename_retry:
 	for (temp = direntry; !IS_ROOT(temp);) {
 		namelen += (1 + temp->d_name.len);
 		temp = temp->d_parent;
+		if(temp == NULL) {
+			cERROR(1,("corrupt dentry"));
+			return NULL;
+		}
 	}
-	namelen += 1;		/* allow for trailing null */
-	full_path = kmalloc(namelen, GFP_KERNEL);
-	namelen--;
+
+	full_path = kmalloc(namelen+1, GFP_KERNEL);
+	if(full_path == NULL)
+		return full_path;
 	full_path[namelen] = 0;	/* trailing null */
+
 	for (temp = direntry; !IS_ROOT(temp);) {
 		namelen -= 1 + temp->d_name.len;
 		if (namelen < 0) {
@@ -68,11 +80,23 @@
 			cFYI(0, (" name: %s ", full_path + namelen));
 		}
 		temp = temp->d_parent;
+		if(temp == NULL) {
+			cERROR(1,("corrupt dentry"));
+			kfree(full_path);
+			return NULL;
+		}
 	}
-	if (namelen != 0)
+	if (namelen != 0) {
 		cERROR(1,
 		       ("We did not end path lookup where we expected namelen is %d",
 			namelen));
+		/* presumably this is only possible if we were racing with a rename 
+		of one of the parent directories  (we can not lock the dentries
+		above us to prevent this, but retrying should be harmless) */
+		kfree(full_path);
+		namelen = 0;
+		goto cifs_bp_rename_retry;
+	}
 
 	return full_path;
 }
@@ -142,10 +166,12 @@
 	pTcon = cifs_sb->tcon;
 
 	full_path = build_path_from_dentry(direntry);
+	if(full_path == NULL) {
+		FreeXid(xid);
+		return -ENOMEM;
+	}
 
-	if(nd) { 
-		cFYI(1,("In create for inode %p dentry->inode %p nd flags = 0x%x for %s",inode, direntry->d_inode, nd->flags,full_path));
-
+	if(nd) {
 		if ((nd->intent.open.flags & O_ACCMODE) == O_RDONLY)
 			desiredAccess = GENERIC_READ;
 		else if ((nd->intent.open.flags & O_ACCMODE) == O_WRONLY)
@@ -173,6 +199,12 @@
 		oplock = REQ_OPLOCK;
 
 	buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
+	if(buf == NULL) {
+		kfree(full_path);
+		FreeXid(xid);
+		return -ENOMEM;
+	}
+
 	rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
 			 desiredAccess, CREATE_NOT_DIR,
 			 &fileHandle, &oplock, buf, cifs_sb->local_nls);
@@ -273,8 +305,10 @@
 	pTcon = cifs_sb->tcon;
 
 	full_path = build_path_from_dentry(direntry);
-
-	if (pTcon->ses->capabilities & CAP_UNIX) {
+	if(full_path == NULL)
+		rc = -ENOMEM;
+	
+	if (full_path && (pTcon->ses->capabilities & CAP_UNIX)) {
 		rc = CIFSSMBUnixSetPerms(xid, pTcon,
 			full_path, mode, current->euid, current->egid,
 			device_number, cifs_sb->local_nls);
@@ -298,7 +332,8 @@
 struct dentry *
 cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct nameidata *nd)
 {
-	int rc, xid;
+	int xid;
+	int rc = 0; /* to get around spurious gcc warning, set to zero here */
 	struct cifs_sb_info *cifs_sb;
 	struct cifsTconInfo *pTcon;
 	struct inode *newInode = NULL;
@@ -321,6 +356,11 @@
 	pTcon = cifs_sb->tcon;
 
 	full_path = build_path_from_dentry(direntry);
+	if(full_path == NULL) {
+		FreeXid(xid);
+		return ERR_PTR(-ENOMEM);
+	}
+
 	if (direntry->d_inode != NULL) {
 		cFYI(1, (" non-NULL inode in lookup"));
 	} else {
@@ -347,10 +387,10 @@
 		rc = 0;
 		d_add(direntry, NULL);
 	} else {
-		cERROR(1,
-		       ("Error 0x%x or (%d decimal) on cifs_get_inode_info in lookup",
-			rc, rc));
-		/* BB special case check for Access Denied - watch security exposure of returning dir info implicitly via different rc if file exists or not but no access BB */
+		cERROR(1,("Error 0x%x or on cifs_get_inode_info in lookup",rc));
+		/* BB special case check for Access Denied - watch security 
+		exposure of returning dir info implicitly via different rc 
+		if file exists or not but no access BB */
 	}
 
 	if (full_path)
diff -Nru a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c
--- a/fs/cifs/fcntl.c	2004-05-25 21:19:51 -07:00
+++ b/fs/cifs/fcntl.c	2004-05-25 21:19:51 -07:00
@@ -40,8 +40,13 @@
 	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
 	pTcon = cifs_sb->tcon;
 	full_path = build_path_from_dentry(file->f_dentry);
-	cFYI(1,("cifs dir notify on file %s",full_path));
-	/* CIFSSMBNotify */
+	if(full_path == NULL) {
+		rc = -ENOMEM;
+	} else {
+		cFYI(1,("cifs dir notify on file %s",full_path));
+		/* CIFSSMBNotify(xid, pTcon, full_path, cifs_sb->local_nls);*/
+	}
+	
 	FreeXid(xid);
 	return rc;
 }
diff -Nru a/fs/cifs/file.c b/fs/cifs/file.c
--- a/fs/cifs/file.c	2004-05-25 21:19:51 -07:00
+++ b/fs/cifs/file.c	2004-05-25 21:19:51 -07:00
@@ -81,6 +81,10 @@
 	}
 
 	full_path = build_path_from_dentry(file->f_dentry);
+	if(full_path == NULL) {
+		FreeXid(xid);
+		return -ENOMEM;
+	}
 
 	cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path));
 	if ((file->f_flags & O_ACCMODE) == O_RDONLY)
@@ -150,8 +154,6 @@
 		cFYI(1, ("cifs_open returned 0x%x ", rc));
 		cFYI(1, ("oplock: %d ", oplock));	
 	} else {
-		if(file->private_data)
-			kfree(file->private_data);
 		file->private_data =
 			kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
 		if (file->private_data) {
@@ -281,11 +283,21 @@
 		return 0;
 	}
 
-
+	if(file->f_dentry == NULL) {
+		up(&pCifsFile->fh_sem);
+		cFYI(1,("failed file reopen, no valid name if dentry freed"));
+		FreeXid(xid);
+		return -EBADF;
+	}
 	cifs_sb = CIFS_SB(inode->i_sb);
 	pTcon = cifs_sb->tcon;
 
 	full_path = build_path_from_dentry(file->f_dentry);
+	if(full_path == NULL) {
+		up(&pCifsFile->fh_sem);
+		FreeXid(xid);
+		return -ENOMEM;
+	}
 
 	cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path));
 	if ((file->f_flags & O_ACCMODE) == O_RDONLY)
@@ -546,6 +558,9 @@
 	int xid, long_op;
 	struct cifsFileInfo * open_file;
 
+	if(file->f_dentry == NULL)
+		return -EBADF;
+
 	xid = GetXid();
 
 	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
@@ -634,26 +649,22 @@
 	int bytes_written = 0;
 	struct cifs_sb_info *cifs_sb;
 	struct cifsTconInfo *pTcon;
-	struct inode *inode = page->mapping->host;
+	struct inode *inode;
 	struct cifsInodeInfo *cifsInode;
 	struct cifsFileInfo *open_file = NULL;
 	struct list_head *tmp;
 	struct list_head *tmp1;
 
-	cifs_sb = CIFS_SB(inode->i_sb);
-	pTcon = cifs_sb->tcon;
-
-	/* figure out which file struct to use 
-	if (file->private_data == NULL) {
-		return -EBADF;
-	}     
-	 */
 	if (!mapping) {
 		return -EFAULT;
 	} else if(!mapping->host) {
 		return -EFAULT;
 	}
 
+	inode = page->mapping->host;
+	cifs_sb = CIFS_SB(inode->i_sb);
+	pTcon = cifs_sb->tcon;
+
 	offset += (loff_t)from;
 	write_data = kmap(page);
 	write_data += from;
@@ -678,6 +689,8 @@
 	read_lock(&GlobalSMBSeslock); 
 	list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {            
 		open_file = list_entry(tmp,struct cifsFileInfo, flist);
+		if(open_file->closePend)
+			continue;
 		/* We check if file is open for writing first */
 		if((open_file->pfile) && 
 		   ((open_file->pfile->f_flags & O_RDWR) || 
@@ -691,7 +704,15 @@
 			if ((bytes_written > 0) && (offset)) {
 				rc = 0;
 			} else if(bytes_written < 0) {
-				rc = bytes_written;
+				if(rc == -EBADF) {
+				/* have seen a case in which
+				kernel seemed to have closed/freed a file
+				even with writes active so we might as well
+				see if there are other file structs to try
+				for the same inode before giving up */
+					continue;
+				} else
+					rc = bytes_written;
 			}
 			break;  /* now that we found a valid file handle
 				and tried to write to it we are done, no
diff -Nru a/fs/cifs/inode.c b/fs/cifs/inode.c
--- a/fs/cifs/inode.c	2004-05-25 21:19:51 -07:00
+++ b/fs/cifs/inode.c	2004-05-25 21:19:51 -07:00
@@ -346,7 +346,10 @@
 	pTcon = cifs_sb->tcon;
 
 	full_path = build_path_from_dentry(direntry);
-
+	if(full_path == NULL) {
+		FreeXid(xid);
+		return -ENOMEM;
+	}
 	rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls);
 
 	if (!rc) {
@@ -428,6 +431,10 @@
 	pTcon = cifs_sb->tcon;
 
 	full_path = build_path_from_dentry(direntry);
+	if(full_path == NULL) {
+		FreeXid(xid);
+		return -ENOMEM;
+	}
 	/* BB add setting the equivalent of mode via CreateX w/ACLs */
 	rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls);
 	if (rc) {
@@ -481,6 +488,10 @@
 	pTcon = cifs_sb->tcon;
 
 	full_path = build_path_from_dentry(direntry);
+	if(full_path == NULL) {
+		FreeXid(xid);
+		return -ENOMEM;
+	}
 
 	rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls);
 
@@ -527,6 +538,10 @@
 
 	fromName = build_path_from_dentry(source_direntry);
 	toName = build_path_from_dentry(target_direntry);
+	if((fromName == NULL) || (toName == NULL)) {
+		rc = -ENOMEM;
+		goto cifs_rename_exit;
+	}
 
 	rc = CIFSSMBRename(xid, pTcon, fromName, toName,
 			   cifs_sb_source->local_nls);
@@ -549,6 +564,8 @@
 			CIFSSMBClose(xid, pTcon, netfid);
 		}
 	}
+
+cifs_rename_exit:
 	if (fromName)
 		kfree(fromName);
 	if (toName)
@@ -587,6 +604,10 @@
 	cifs_sb = CIFS_SB(direntry->d_sb);
 
 	full_path = build_path_from_dentry(direntry);
+	if(full_path == NULL) {
+		FreeXid(xid);
+		return -ENOMEM;
+	}
 	cFYI(1,
 	     ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld",
 	      full_path, direntry->d_inode,
@@ -731,6 +752,10 @@
 	pTcon = cifs_sb->tcon;
 
 	full_path = build_path_from_dentry(direntry);
+	if(full_path == NULL) {
+		FreeXid(xid);
+		return -ENOMEM;
+	}
 	cifsInode = CIFS_I(direntry->d_inode);
 
 	/* BB check if we need to refresh inode from server now ? BB */
diff -Nru a/fs/cifs/link.c b/fs/cifs/link.c
--- a/fs/cifs/link.c	2004-05-25 21:19:51 -07:00
+++ b/fs/cifs/link.c	2004-05-25 21:19:51 -07:00
@@ -48,6 +48,11 @@
 
 	fromName = build_path_from_dentry(old_file);
 	toName = build_path_from_dentry(direntry);
+	if((fromName == NULL) || (toName == NULL)) {
+		rc = -ENOMEM;
+		goto cifs_hl_exit;
+	}
+
 	if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)
 		rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName,
 					    cifs_sb_target->local_nls);
@@ -70,6 +75,7 @@
 	cifsInode = CIFS_I(old_file->d_inode);
 	cifsInode->time = 0;	/* will force revalidate to go get info when needed */
 
+cifs_hl_exit:
 	if (fromName)
 		kfree(fromName);
 	if (toName)
@@ -91,6 +97,10 @@
 
 	xid = GetXid();
 	full_path = build_path_from_dentry(direntry);
+	if(full_path == NULL) {
+		FreeXid(xid);
+		return -ENOMEM;
+	}
 	cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode));
 	cifs_sb = CIFS_SB(inode->i_sb);
 	pTcon = cifs_sb->tcon;
@@ -150,6 +160,11 @@
 	pTcon = cifs_sb->tcon;
 
 	full_path = build_path_from_dentry(direntry);
+	if(full_path == NULL) {
+		FreeXid(xid);
+		return -ENOMEM;
+	}
+
 	cFYI(1, ("Full path: %s ", full_path));
 	cFYI(1, ("symname is %s", symname));
 
@@ -205,6 +220,11 @@
 	cifs_sb = CIFS_SB(inode->i_sb);
 	pTcon = cifs_sb->tcon;
 	full_path = build_path_from_dentry(direntry);
+	if(full_path == NULL) {
+		FreeXid(xid);
+		return -ENOMEM;
+	}
+
 	cFYI(1,
 	     ("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d",
 	      full_path, inode, pBuffer, buflen));
diff -Nru a/fs/cifs/transport.c b/fs/cifs/transport.c
--- a/fs/cifs/transport.c	2004-05-25 21:19:51 -07:00
+++ b/fs/cifs/transport.c	2004-05-25 21:19:51 -07:00
@@ -187,22 +187,26 @@
 		return -EIO;
 	}
 
+	/* make sure that we sign in the same order that we send on this socket 
+		and avoid races inside tcp sendmsg code that could cause corruption
+		of smb data */
+	down(&ses->server->tcpSem); 
+
 	if (ses->server->tcpStatus == CifsExiting) {
-		return -ENOENT;
+		rc = -ENOENT;
+		goto out_unlock;
 	} else if (ses->server->tcpStatus == CifsNeedReconnect) {
 		cFYI(1,("tcp session dead - return to caller to retry"));
-		return -EAGAIN;
+		rc = -EAGAIN;
+		goto out_unlock;
 	} else if (ses->status != CifsGood) {
 		/* check if SMB session is bad because we are setting it up */
 		if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && 
 			(in_buf->Command != SMB_COM_NEGOTIATE)) {
-			return -EAGAIN;
+			rc = -EAGAIN;
+			goto out_unlock;
 		} /* else ok - we are setting up session */
 	}
-	/* make sure that we sign in the same order that we send on this socket 
-		and avoid races inside tcp sendmsg code that could cause corruption
-		of smb data */
-	down(&ses->server->tcpSem); 
 	midQ = AllocMidQEntry(in_buf, ses);
 	if (midQ == NULL) {
 		up(&ses->server->tcpSem);
@@ -288,7 +292,6 @@
 		return rc;
 	}
   
-
 	if (receive_len > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE) {
 		cERROR(1,
 		       ("Frame too large received.  Length: %d  Xid: %d",
@@ -341,5 +344,9 @@
 	DeleteMidQEntry(midQ);	/* BB what if process is killed?
 			 - BB add background daemon to clean up Mid entries from
 			 killed processes & test killing process with active mid */
+	return rc;
+
+out_unlock:
+	up(&ses->server->tcpSem);
 	return rc;
 }
