From b2aeb9d565be5ef00fb9f921c6d2459c74d90cdf Mon Sep 17 00:00:00 2001
From: Steve French <stevef@stevef95>
Date: Tue, 17 May 2005 13:16:18 -0500
Subject: [PATCH] [CIFS] Fix oops in cifs_unlink.  Caused in some cases when
 renaming over existing, newly created, file.

Samba bugzilla: 2697

Signed-off-by: Steve French (sfrench@us.ibm.com)
---
 fs/cifs/dir.c   |  3 ++-
 fs/cifs/inode.c | 24 +++++++++++++++---------
 2 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index e3137aa48cdd..3f3538d4a1fa 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -392,7 +392,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
 		rc = 0;
 		d_add(direntry, NULL);
 	} else {
-		cERROR(1,("Error 0x%x or on cifs_get_inode_info in lookup",rc));
+		cERROR(1,("Error 0x%x on cifs_get_inode_info in lookup of %s",
+			   rc,full_path));
 		/* 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 */
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 670947288262..b8b78cbb34c9 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -422,7 +422,8 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
 			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 
 	if (!rc) {
-		direntry->d_inode->i_nlink--;
+		if(direntry->d_inode)
+			direntry->d_inode->i_nlink--;
 	} else if (rc == -ENOENT) {
 		d_drop(direntry);
 	} else if (rc == -ETXTBSY) {
@@ -440,7 +441,8 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
 					      cifs_sb->mnt_cifs_flags & 
 						CIFS_MOUNT_MAP_SPECIAL_CHR);
 			CIFSSMBClose(xid, pTcon, netfid);
-			direntry->d_inode->i_nlink--;
+			if(direntry->d_inode)
+				direntry->d_inode->i_nlink--;
 		}
 	} else if (rc == -EACCES) {
 		/* try only if r/o attribute set in local lookup data? */
@@ -494,7 +496,8 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
 					    cifs_sb->mnt_cifs_flags & 
 						CIFS_MOUNT_MAP_SPECIAL_CHR);
 			if (!rc) {
-				direntry->d_inode->i_nlink--;
+				if(direntry->d_inode)
+					direntry->d_inode->i_nlink--;
 			} else if (rc == -ETXTBSY) {
 				int oplock = FALSE;
 				__u16 netfid;
@@ -514,17 +517,20 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
 						cifs_sb->mnt_cifs_flags &
 						    CIFS_MOUNT_MAP_SPECIAL_CHR);
 					CIFSSMBClose(xid, pTcon, netfid);
-		                        direntry->d_inode->i_nlink--;
+					if(direntry->d_inode)
+			                        direntry->d_inode->i_nlink--;
 				}
 			/* BB if rc = -ETXTBUSY goto the rename logic BB */
 			}
 		}
 	}
-	cifsInode = CIFS_I(direntry->d_inode);
-	cifsInode->time = 0;	/* will force revalidate to get info when
-				   needed */
-	direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
-		current_fs_time(inode->i_sb);
+	if(direntry->d_inode) {
+		cifsInode = CIFS_I(direntry->d_inode);
+		cifsInode->time = 0;	/* will force revalidate to get info
+					   when needed */
+		direntry->d_inode->i_ctime = current_fs_time(inode->i_sb);
+	}
+	inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb);
 	cifsInode = CIFS_I(inode);
 	cifsInode->time = 0;	/* force revalidate of dir as well */