mtd/fs/jffs2 gc.c,1.118,1.119 readinode.c,1.109,1.110

David Woodhouse dwmw2 at infradead.org
Thu Oct 30 10:22:01 EST 2003


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

Modified Files:
	gc.c readinode.c 
Log Message:
work around VFS race

Index: gc.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/gc.c,v
retrieving revision 1.118
retrieving revision 1.119
diff -u -r1.118 -r1.119
--- gc.c	28 Oct 2003 17:13:09 -0000	1.118
+++ gc.c	30 Oct 2003 15:21:58 -0000	1.119
@@ -376,11 +376,16 @@
 
 	inode = iget(OFNI_BS_2SFFJ(c), ic->ino);
 	if (is_bad_inode(inode)) {
-		printk(KERN_NOTICE "Eep. read_inode() failed for ino #%u\n", ic->ino);
+		if (!ic->nlink && ic->state == INO_STATE_PRESENT) {
+			/* It _did_ exist but doesn't any more -- it was being deleted
+			   while we tried to iget() it. */
+			D1(printk(KERN_NOTICE "Ino #%u was present but iget() failed. VFS race blamed; retrying...\n", ic->ino));
+			goto put_out;
+		}
+		printk(KERN_NOTICE "Eep. read_inode() failed for ino #%u. nlink %d, state %d\n", ic->ino, ic->nlink, ic->state);
 		/* NB. This will happen again. We need to do something appropriate here. */
-		up(&c->alloc_sem);
-		iput(inode);
-		return -EIO;
+		ret = -EIO;
+		goto put_out;
 	}
 
 	f = JFFS2_INODE_INFO(inode);
@@ -502,6 +507,7 @@
 	}
  upnout:
 	up(&f->sem);
+ put_out:
 	iput(inode);
 
 	return ret;

Index: readinode.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/readinode.c,v
retrieving revision 1.109
retrieving revision 1.110
diff -u -r1.109 -r1.110
--- readinode.c	28 Oct 2003 17:10:44 -0000	1.109
+++ readinode.c	30 Oct 2003 15:21:58 -0000	1.110
@@ -408,6 +408,8 @@
 int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, 
 			uint32_t ino, struct jffs2_raw_inode *latest_node)
 {
+	int ret = 0;
+
 	D2(printk(KERN_DEBUG "jffs2_do_read_inode(): getting inocache\n"));
 
  retry_inocache:
@@ -434,14 +436,23 @@
 			sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
 			goto retry_inocache;
 
-		case INO_STATE_READING:
 		case INO_STATE_PRESENT:
+			if (!f->inocache->nlink) {
+				D1(printk(KERN_WARNING "Kernel VFS BUG: read_inode() called for inode #%u not yet cleared\n",
+					  ino));
+				f->inocache = NULL;
+				ret = -EAGAIN;
+				break;
+			}
+
+		case INO_STATE_READING:
 			/* Eep. This should never happen. It can
 			happen if Linux calls read_inode() again
 			before clear_inode() has finished though. */
 			printk(KERN_WARNING "Eep. Trying to read_inode #%u when it's already in state %d!\n", ino, f->inocache->state);
 			/* Fail. That's probably better than allowing it to succeed */
 			f->inocache = NULL;
+			ret = -EIO;
 			break;
 
 		default:
@@ -449,6 +460,7 @@
 		}
 	}
 	spin_unlock(&c->inocache_lock);
+
 	if (!f->inocache && ino == 1) {
 		/* Special case - no root inode on medium */
 		f->inocache = jffs2_alloc_inode_cache();
@@ -464,8 +476,11 @@
 		jffs2_add_ino_cache(c, f->inocache);
 	}
 	if (!f->inocache) {
-		printk(KERN_WARNING "jffs2_do_read_inode() on nonexistent ino %u\n", ino);
-		return -ENOENT;
+		if (!ret) {
+			printk(KERN_WARNING "jffs2_do_read_inode() on nonexistent ino %u\n", ino);
+			ret = -ENOENT;
+		}
+		return ret;
 	}
 
 	return jffs2_do_read_inode_internal(c, f, latest_node);




More information about the linux-mtd-cvs mailing list