patch-2.4.23 linux-2.4.23/fs/jffs2/gc.c
Next file: linux-2.4.23/fs/jffs2/nodelist.h
Previous file: linux-2.4.23/fs/jffs2/file.c
Back to the patch index
Back to the overall index
- Lines: 73
- Date:
2003-11-28 10:26:21.000000000 -0800
- Orig file:
linux-2.4.22/fs/jffs2/gc.c
- Orig date:
2003-08-25 04:44:43.000000000 -0700
diff -urN linux-2.4.22/fs/jffs2/gc.c linux-2.4.23/fs/jffs2/gc.c
@@ -31,7 +31,7 @@
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
- * $Id: gc.c,v 1.52.2.5 2002/10/10 13:18:38 dwmw2 Exp $
+ * $Id: gc.c,v 1.52.2.7 2003/11/02 13:54:20 dwmw2 Exp $
*
*/
@@ -109,8 +109,8 @@
struct jffs2_node_frag *frag;
struct jffs2_full_dnode *fn = NULL;
struct jffs2_full_dirent *fd;
+ struct jffs2_inode_cache *ic;
__u32 start = 0, end = 0, nrfrags = 0;
- __u32 inum;
struct inode *inode;
int ret = 0;
@@ -162,16 +162,47 @@
goto eraseit_lock;
}
- inum = jffs2_raw_ref_to_inum(raw);
- D1(printk(KERN_DEBUG "Inode number is #%u\n", inum));
+ ic = jffs2_raw_ref_to_ic(raw);
+ D1(printk(KERN_DEBUG "Inode number is #%u\n", ic->ino));
spin_unlock_bh(&c->erase_completion_lock);
- D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass collecting from block @0x%08x. Node @0x%08x, ino #%u\n", jeb->offset, raw->flash_offset&~3, inum));
-
- inode = iget(OFNI_BS_2SFFJ(c), inum);
+ D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass collecting from block @0x%08x. Node @0x%08x, ino #%u\n", jeb->offset, raw->flash_offset&~3, ic->ino));
+ if (!ic->nlink) {
+ /* 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_DEBUG "ilookup() failed for ino #%u; inode is probably deleted.\n",
+ ic->ino));
+ up(&c->alloc_sem);
+ return 0;
+ }
+ } 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) {
+ up(&c->alloc_sem);
+ return -ENOMEM;
+ }
+ }
if (is_bad_inode(inode)) {
- printk(KERN_NOTICE "Eep. read_inode() failed for ino #%u\n", inum);
+ printk(KERN_NOTICE "Eep. read_inode() failed for ino #%u\n", ic->ino);
/* NB. This will happen again. We need to do something appropriate here. */
up(&c->alloc_sem);
iput(inode);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)