mtd/fs/jffs2 gc.c,1.122,1.123

David Woodhouse dwmw2 at infradead.org
Sun Nov 2 07:30:18 EST 2003


Update of /home/cvs/mtd/fs/jffs2
In directory phoenix.infradead.org:/tmp/cvs-serv16700

Modified Files:
	gc.c 
Log Message:
Comment to Al's liking, wait for progress

Index: gc.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/gc.c,v
retrieving revision 1.122
retrieving revision 1.123
diff -u -r1.122 -r1.123
--- gc.c	2 Nov 2003 08:47:37 -0000	1.122
+++ gc.c	2 Nov 2003 12:30:16 -0000	1.123
@@ -361,7 +361,6 @@
 	return ret;
 }
 
-
 static int jffs2_garbage_collect_live(struct jffs2_sb_info *c,  struct jffs2_eraseblock *jeb,
 				      struct jffs2_raw_node_ref *raw, struct jffs2_inode_cache *ic)
 {
@@ -374,16 +373,41 @@
 	int ret = 0;
 
 	if (!ic->nlink) {
-		/* Only GC from it if it's still actually in the
-		   icache and hasn't been deleted while we were
-		   pondering it. */
+		/* The inode has zero nlink but its nodes weren't yet marked
+		   obsolete. This has to be because we're still waiting for 
+		   the final (close() and) iput() to happen.
+
+		   There's a possibility that the final iput() could have 
+		   happened while we were contemplating. In order to ensure
+		   that we don't cause a new read_inode() (which would fail)
+		   for the inode in question, we use ilookup() in this case
+		   instead of iget().
+
+		   The nlink can't _become_ zero at this point because we're 
+		   holding the alloc_sem, and jffs2_do_unlink() would also
+		   need that while decrementing nlink on any inode.
+		*/
 		inode = ilookup(OFNI_BS_2SFFJ(c), ic->ino);
 		if (!inode) {
-			D1(printk(KERN_WARNING "ilookup() failed for ino #%u; inode is probably deleted. Skipping.\n",
+			D1(printk(KERN_DEBUG "ilookup() failed for ino #%u; inode is probably deleted.\n",
 				  ic->ino));
+
+			spin_lock(c->inocache_lock);
+			if (ic->state != INO_STATE_CHECKEDABSENT) {
+				/* Wait for progress. Don't just loop */
+				D1(printk(KERN_DEBUG "Waiting for ino #%u in state %d\n",
+					  ic->ino, ic->state));
+				sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
+				D1(printk(KERN_DEBUG "Waited for ino #%u. State now %d\n",
+					  ic->ino, ic->state));
+			}
 			return 0;
 		}
-	else {
+	} else {
+		/* Inode has links to it still; they're not going away because
+		   jffs2_do_unlink() would need the alloc_sem and we have it.
+		   Just iget() it, and if read_inode() is necessary that's OK.
+		*/
 		inode = iget(OFNI_BS_2SFFJ(c), ic->ino);
 		if (!inode)
 			return -ENOMEM;




More information about the linux-mtd-cvs mailing list