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