*
* For licensing information, see the file 'LICENCE' in this directory.
*
- * $Id: readinode.c,v 1.113 2003/11/03 13:20:33 dwmw2 Exp $
+ * $Id: readinode.c,v 1.107 2003/10/04 08:33:06 dwmw2 Exp $
*
*/
printk(KERN_DEBUG "metadata at 0x%08x\n", ref_offset(f->metadata->raw));
}
}
-
-static int jffs2_sanitycheck_fragtree(struct jffs2_inode_info *f)
-{
- struct jffs2_node_frag *frag;
- int bitched = 0;
-
- for (frag = frag_first(&f->fragtree); frag; frag = frag_next(frag)) {
-
- struct jffs2_full_dnode *fn = frag->node;
- if (!fn || !fn->raw)
- continue;
-
- if (ref_flags(fn->raw) == REF_PRISTINE) {
-
- if (fn->frags > 1) {
- printk(KERN_WARNING "REF_PRISTINE node at 0x%08x had %d frags. Tell dwmw2\n", ref_offset(fn->raw), fn->frags);
- bitched = 1;
- }
- /* A hole node which isn't multi-page should be garbage-collected
- and merged anyway, so we just check for the frag size here,
- rather than mucking around with actually reading the node
- and checking the compression type, which is the real way
- to tell a hole node. */
- if (frag->ofs & (PAGE_CACHE_SIZE-1) && frag_prev(frag) && frag_prev(frag)->size < PAGE_CACHE_SIZE && frag_prev(frag)->node) {
- printk(KERN_WARNING "REF_PRISTINE node at 0x%08x had a previous non-hole frag in the same page. Tell dwmw2\n",
- ref_offset(fn->raw));
- bitched = 1;
- }
-
- if ((frag->ofs+frag->size) & (PAGE_CACHE_SIZE-1) && frag_next(frag) && frag_next(frag)->size < PAGE_CACHE_SIZE && frag_next(frag)->node) {
- printk(KERN_WARNING "REF_PRISTINE node at 0x%08x (%08x-%08x) had a following non-hole frag in the same page. Tell dwmw2\n",
- ref_offset(fn->raw), frag->ofs, frag->ofs+frag->size);
- bitched = 1;
- }
- }
- }
-
- if (bitched) {
- struct jffs2_node_frag *thisfrag;
-
- printk(KERN_WARNING "Inode is #%u\n", f->inocache->ino);
- thisfrag = frag_first(&f->fragtree);
- while (thisfrag) {
- if (!thisfrag->node) {
- printk("Frag @0x%x-0x%x; node-less hole\n",
- thisfrag->ofs, thisfrag->size + thisfrag->ofs);
- } else if (!thisfrag->node->raw) {
- printk("Frag @0x%x-0x%x; raw-less hole\n",
- thisfrag->ofs, thisfrag->size + thisfrag->ofs);
- } else {
- printk("Frag @0x%x-0x%x; raw at 0x%08x(%d) (0x%x-0x%x)\n",
- thisfrag->ofs, thisfrag->size + thisfrag->ofs,
- ref_offset(thisfrag->node->raw), ref_flags(thisfrag->node->raw),
- thisfrag->node->ofs, thisfrag->node->ofs+thisfrag->node->size);
- }
- thisfrag = frag_next(thisfrag);
- }
- }
- return bitched;
-}
#endif /* D1 */
static void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *this)
mark_ref_normal(next->node->raw);
}
}
- D2(if (jffs2_sanitycheck_fragtree(f)) {
- printk(KERN_WARNING "Just added node %04x-%04x @0x%08x on flash, newfrag *%p\n",
- fn->ofs, fn->ofs+fn->size, ref_offset(fn->raw), newfrag);
- return 0;
- })
D2(jffs2_print_frag_list(f));
return 0;
}
}
}
spin_unlock(&c->inocache_lock);
-
if (!f->inocache && ino == 1) {
/* Special case - no root inode on medium */
f->inocache = jffs2_alloc_inode_cache();
fn = tn->fn;
if (f->metadata) {
- if (likely(tn->version >= mdata_ver)) {
+ if (tn->version > mdata_ver) {
D1(printk(KERN_DEBUG "Obsoleting old metadata at 0x%08x\n", ref_offset(f->metadata->raw)));
jffs2_mark_node_obsolete(c, f->metadata->raw);
jffs2_free_full_dnode(f->metadata);
mdata_ver = 0;
} else {
- /* This should never happen. */
- printk(KERN_WARNING "Er. New metadata at 0x%08x with ver %d is actually older than previous ver %d at 0x%08x\n",
- ref_offset(fn->raw), tn->version, mdata_ver, ref_offset(f->metadata->raw));
+ D1(printk(KERN_DEBUG "Er. New metadata at 0x%08x with ver %d is actually older than previous %d\n",
+ ref_offset(f->metadata->raw), tn->version, mdata_ver));
jffs2_mark_node_obsolete(c, fn->raw);
jffs2_free_full_dnode(fn);
- /* Fill in latest_node from the metadata, not this one we're about to free... */
- fn = f->metadata;
goto next_tn;
}
}
tn_list = tn->next;
jffs2_free_tmp_dnode_info(tn);
}
- D1(jffs2_sanitycheck_fragtree(f));
-
if (!fn) {
/* No data nodes for this inode. */
if (f->inocache->ino != 1) {
void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
{
struct jffs2_full_dirent *fd, *fds;
- int deleted;
+ /* I don't think we care about the potential race due to reading this
+ without f->sem. It can never get undeleted. */
+ int deleted = f->inocache && !f->inocache->nlink;
+
+ /* If it's a deleted inode, grab the alloc_sem. This prevents
+ jffs2_garbage_collect_pass() from deciding that it wants to
+ garbage collect one of the nodes we're just about to mark
+ obsolete -- by the time we drop alloc_sem and return, all
+ the nodes are marked obsolete, and jffs2_g_c_pass() won't
+ call iget() for the inode in question.
+
+ We also used to do this to keep the temporary BUG() in
+ jffs2_mark_node_obsolete() from triggering.
+ */
+ if(deleted)
+ down(&c->alloc_sem);
down(&f->sem);
- deleted = f->inocache && !f->inocache->nlink;
if (f->metadata) {
if (deleted)
jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
up(&f->sem);
+
+ if(deleted)
+ up(&c->alloc_sem);
}