[PATCH] [CHECKER] if txCommit fails, don't call d_instantiate (6 of 6)

[email protected] Thu, 20 May 2004 16:50:26 -0500
Newsgroups gmane.comp.file-systems.jfs.patches
Message-ID <[email protected]>
# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/05/20 15:46:12-05:00 [email protected] 
#   JFS: [CHECKER] if txCommit fails, don't call d_instantiate
#   
#   In several functions, d_instantiate is called before the transaction
#   is committed.  Under the rare condition that txCommit fails, the new
#   inode is released, but the dentry continues to point to it.  This
#   can lead to a seg fault.  The fix is to call d_instantiate after
#   txCommit has run successfully.
# 
diff -Nru a/fs/jfs/namei.c b/fs/jfs/namei.c
--- a/fs/jfs/namei.c	2004-05-20 16:47:47 -05:00
+++ b/fs/jfs/namei.c	2004-05-20 16:47:47 -05:00
@@ -135,7 +135,6 @@
 
 	insert_inode_hash(ip);
 	mark_inode_dirty(ip);
-	d_instantiate(dentry, ip);
 
 	dip->i_ctime = dip->i_mtime = CURRENT_TIME;
 
@@ -150,7 +149,8 @@
 	if (rc) {
 		ip->i_nlink = 0;
 		iput(ip);
-	}
+	} else
+		d_instantiate(dentry, ip);
 
       out2:
 	free_UCSname(&dname);
@@ -265,7 +265,6 @@
 
 	insert_inode_hash(ip);
 	mark_inode_dirty(ip);
-	d_instantiate(dentry, ip);
 
 	/* update parent directory inode */
 	dip->i_nlink++;		/* for '..' from child directory */
@@ -281,7 +280,8 @@
 	if (rc) {
 		ip->i_nlink = 0;
 		iput(ip);
-	}
+	} else
+		d_instantiate(dentry, ip);
 
       out2:
 	free_UCSname(&dname);
@@ -806,12 +806,14 @@
 	ip->i_ctime = CURRENT_TIME;
 	mark_inode_dirty(dir);
 	atomic_inc(&ip->i_count);
-	d_instantiate(dentry, ip);
 
 	iplist[0] = ip;
 	iplist[1] = dir;
 	rc = txCommit(tid, 2, &iplist[0], 0);
 
+	if (!rc)
+		d_instantiate(dentry, ip);
+
       free_dname:
 	free_UCSname(&dname);
 
@@ -999,7 +1001,6 @@
 
 	insert_inode_hash(ip);
 	mark_inode_dirty(ip);
-	d_instantiate(dentry, ip);
 
 	/*
 	 * commit update of parent directory and link object
@@ -1028,7 +1029,8 @@
 	if (rc) {
 		ip->i_nlink = 0;
 		iput(ip);
-	}
+	} else
+		d_instantiate(dentry, ip);
 
       out2:
 	free_UCSname(&dname);
@@ -1368,7 +1370,6 @@
 
 	insert_inode_hash(ip);
 	mark_inode_dirty(ip);
-	d_instantiate(dentry, ip);
 
 	dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 
@@ -1385,7 +1386,8 @@
 	if (rc) {
 		ip->i_nlink = 0;
 		iput(ip);
-	}
+	} else
+		d_instantiate(dentry, ip);
 
       out1:
 	free_UCSname(&dname);