[Ocfs2-commits] mfasheh commits r2377 - trunk/fs/ocfs2

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Tue Jun 7 19:51:12 CDT 2005


Author: mfasheh
Signed-off-by: jlbec
Date: 2005-06-07 19:51:11 -0500 (Tue, 07 Jun 2005)
New Revision: 2377

Modified:
   trunk/fs/ocfs2/inode.c
Log:
* don't wait on freeing inodes during ilookup which comes from the vote
  thread. this fixes a deadlock where ocfs2 gets a vote for the inode while
  another process on the system is in delete_inode waiting on the lock.

Signed-off-by: jlbec



Modified: trunk/fs/ocfs2/inode.c
===================================================================
--- trunk/fs/ocfs2/inode.c	2005-06-08 00:25:15 UTC (rev 2376)
+++ trunk/fs/ocfs2/inode.c	2005-06-08 00:51:11 UTC (rev 2377)
@@ -54,11 +54,12 @@
 
 extern struct address_space_operations ocfs2_aops;
 
+#define OCFS2_FI_FLAG_NOWAIT	0x1
 struct ocfs2_find_inode_args
 {
-	u64 blkno;
-	unsigned long ino;
-	u32 flags;
+	u64		fi_blkno;
+	unsigned long	fi_ino;
+	unsigned int	fi_flags;
 };
 
 static int ocfs2_read_locked_inode(struct inode *inode,
@@ -73,10 +74,15 @@
 {
 	struct ocfs2_find_inode_args args;
 
-	args.blkno = blkno;
-	args.flags = 0;
-	args.ino = ino_from_blkno(osb->sb, blkno);
-	return ilookup5(osb->sb, args.ino, ocfs2_find_actor, &args);
+	/* ocfs2_ilookup should *only* be called from the vote thread,
+	 * unless modified to conditionally set
+	 * OCFS2_FI_FLAG_NOWAIT */
+	BUG_ON(current != osb->vote_task);
+
+	args.fi_blkno = blkno;
+	args.fi_flags = OCFS2_FI_FLAG_NOWAIT;
+	args.fi_ino = ino_from_blkno(osb->sb, blkno);
+	return ilookup5(osb->sb, args.fi_ino, ocfs2_find_actor, &args);
 }
 
 struct inode *ocfs2_iget(ocfs2_super *osb, u64 blkno)
@@ -84,7 +90,6 @@
 	struct inode *inode = NULL;
 	struct super_block *sb = osb->sb;
 	struct ocfs2_find_inode_args args;
-	u32 flags = 0;
 
 	mlog_entry("(blkno = %"MLFu64")\n", blkno);
 
@@ -96,11 +101,11 @@
 		goto bail;
 	}
 
-	args.blkno = blkno;
-	args.flags = flags;
-	args.ino = ino_from_blkno(sb, blkno);
+	args.fi_blkno = blkno;
+	args.fi_flags = 0;
+	args.fi_ino = ino_from_blkno(sb, blkno);
 
-	inode = iget5_locked(sb, args.ino, ocfs2_find_actor, 
+	inode = iget5_locked(sb, args.fi_ino, ocfs2_find_actor, 
 			     ocfs2_init_locked_inode, &args);
 	/* inode was *not* in the inode cache. 2.6.x requires
 	 * us to do our own read_inode call and unlock it
@@ -151,9 +156,21 @@
 
 	mlog_bug_on_msg(!inode, "No inode in find actor!\n");
 
-	if (OCFS2_I(inode)->ip_blkno != args->blkno)
+	if (OCFS2_I(inode)->ip_blkno != args->fi_blkno)
 		goto bail;
 
+	/* OCFS2_FI_FLAG_NOWAIT is *only* set from ocfs2_ilookup which
+	 * won't create an inode for one that isn't
+	 * found. ocfs2_ilookup is called from the vote thread which
+	 * doesn't want to get an inode which is in the process of
+	 * going away - otherwise the call to __wait_on_freeing_inode
+	 * in find_inode_fast will cause it to deadlock on an inode
+	 * which may be waiting on a vote (or lock release) in
+	 * delete_inode */
+	if ((args->fi_flags & OCFS2_FI_FLAG_NOWAIT) &&
+	    (inode->i_state & (I_FREEING|I_CLEAR)))
+		goto bail;
+
 	ret = 1;
 bail:
 	mlog_exit(ret);
@@ -171,8 +188,8 @@
 
 	mlog_entry("inode = %p, opaque = %p\n", inode, opaque);
 
-	inode->i_ino = args->ino;
-	OCFS2_I(inode)->ip_blkno = args->blkno;
+	inode->i_ino = args->fi_ino;
+	OCFS2_I(inode)->ip_blkno = args->fi_blkno;
 
 	mlog_exit(0);
 	return 0;
@@ -330,7 +347,7 @@
 	/* Read the FE off disk. This is safe because the kernel only
 	 * does one read_inode2 for a new inode, and if it doesn't
 	 * exist yet then nobody can be working on it! */
-	status = ocfs2_read_block(osb, args->blkno, &bh, 0, NULL);
+	status = ocfs2_read_block(osb, args->fi_blkno, &bh, 0, NULL);
 	if (status < 0) {
 		mlog_errno(status);
 		make_bad_inode(inode);
@@ -357,8 +374,7 @@
 		goto bail;
 	}
 
-	if (args->blkno != fe->i_blkno)
-		BUG();
+	BUG_ON(args->fi_blkno != fe->i_blkno);
 
 	if (sysfile)
 	       OCFS2_I(inode)->ip_flags |= OCFS2_INODE_SYSTEM_FILE;



More information about the Ocfs2-commits mailing list