mtd/fs/jffs2 nodelist.c,1.89,1.90
David Woodhouse
dwmw2 at infradead.org
Wed Dec 8 12:59:23 EST 2004
Update of /home/cvs/mtd/fs/jffs2
In directory phoenix.infradead.org:/tmp/cvs-serv12308
Modified Files:
nodelist.c
Log Message:
Adjust jffs2_get_inode_nodes() so we don't use node refs after they're obsoleted.
Index: nodelist.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/nodelist.c,v
retrieving revision 1.89
retrieving revision 1.90
diff -u -r1.89 -r1.90
--- nodelist.c 28 Nov 2004 12:20:35 -0000 1.89
+++ nodelist.c 8 Dec 2004 17:59:20 -0000 1.90
@@ -92,6 +92,17 @@
}
}
+/* Returns first valid node after 'ref'. May return 'ref' */
+static struct jffs2_raw_node_ref *jffs2_first_valid_node(struct jffs2_raw_node_ref *ref)
+{
+ while (ref && ref->next_in_ino) {
+ if (!ref_obsolete(ref))
+ return ref;
+ D1(printk(KERN_DEBUG "node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref)));
+ ref = ref->next_in_ino;
+ }
+ return NULL;
+}
/* Get tmp_dnode_info and full_dirent for all non-obsolete nodes associated
with this ino, returning the former in order of version */
@@ -101,7 +112,7 @@
uint32_t *highest_version, uint32_t *latest_mctime,
uint32_t *mctime_ver)
{
- struct jffs2_raw_node_ref *ref = f->inocache->nodes;
+ struct jffs2_raw_node_ref *ref, *valid_ref;
struct jffs2_tmp_dnode_info *tn, *ret_tn = NULL;
struct jffs2_full_dirent *fd, *ret_fd = NULL;
union jffs2_node_union node;
@@ -111,22 +122,23 @@
*mctime_ver = 0;
D1(printk(KERN_DEBUG "jffs2_get_inode_nodes(): ino #%u\n", f->inocache->ino));
- if (!f->inocache->nodes) {
- printk(KERN_WARNING "Eep. no nodes for ino #%u\n", f->inocache->ino);
- }
spin_lock(&c->erase_completion_lock);
- for (ref = f->inocache->nodes; ref && ref->next_in_ino; ref = ref->next_in_ino) {
- /* Work out whether it's a data node or a dirent node */
- if (ref_obsolete(ref)) {
- /* FIXME: On NAND flash we may need to read these */
- D1(printk(KERN_DEBUG "node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref)));
- continue;
- }
+ valid_ref = jffs2_first_valid_node(f->inocache->nodes);
+
+ if (!valid_ref)
+ printk(KERN_WARNING "Eep. No valid nodes for ino #%u\n", f->inocache->ino);
+
+ while (valid_ref) {
/* We can hold a pointer to a non-obsolete node without the spinlock,
but _obsolete_ nodes may disappear at any time, if the block
- they're in gets erased */
+ they're in gets erased. So if we mark 'ref' obsolete while we're
+ not holding the lock, it can go away immediately. For that reason,
+ we find the next valid node first, before processing 'ref'.
+ */
+ ref = valid_ref;
+ valid_ref = jffs2_first_valid_node(ref->next_in_ino);
spin_unlock(&c->erase_completion_lock);
cond_resched();
More information about the linux-mtd-cvs
mailing list