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