mtd/fs/jffs2 build.c,1.39,1.40 gc.c,1.81,1.82 nodelist.c,1.49,1.50 nodelist.h,1.77,1.78 read.c,1.25,1.26 readinode.c,1.76,1.77
David Woodhouse
dwmw2 at infradead.org
Mon Sep 2 20:08:54 EDT 2002
- Previous message: mtd/fs/jffs2 build.c,1.38,1.39 file.c,1.77,1.78 gc.c,1.80,1.81 nodelist.c,1.48,1.49 nodelist.h,1.76,1.77 read.c,1.24,1.25 readinode.c,1.75,1.76
- Next message: mtd/drivers/mtd/chips cfi_cmdset_0020.c,NONE,1.1 Config.in,1.15,1.16 gen_probe.c,1.7,1.8
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /home/cvs/mtd/fs/jffs2
In directory phoenix.infradead.org:/tmp/cvs-serv20956
Modified Files:
build.c gc.c nodelist.c nodelist.h read.c readinode.c
Log Message:
Wheee. The code use Red/Black trees for inode fragment lists finally
compiles. NFC if it works yet, of course -- Thomas will probably tell me
in the morning.
Index: build.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/build.c,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -r1.39 -r1.40
--- build.c 1 Sep 2002 15:47:04 -0000 1.39
+++ build.c 3 Sep 2002 00:08:51 -0000 1.40
@@ -121,7 +121,7 @@
{
struct jffs2_tmp_dnode_info *tn;
struct jffs2_full_dirent *fd;
- struct jffs2_node_frag *fraglist = NULL;
+ rb_root_t fragtree = RB_ROOT;
struct jffs2_tmp_dnode_info *metadata = NULL;
D1(printk(KERN_DEBUG "jffs2_build_inode building inode #%u\n", ic->ino));
@@ -147,7 +147,7 @@
}
if (tn->fn->size) {
- jffs2_add_full_dnode_to_fraglist (c, &fraglist, tn->fn);
+ jffs2_add_full_dnode_to_fraglist (c, &fragtree, tn->fn);
jffs2_free_tmp_dnode_info(tn);
} else {
if (!metadata) {
@@ -169,7 +169,7 @@
/* It's a regular file, so truncate it to the last known
i_size, if necessary */
D1(printk(KERN_DEBUG "jffs2_build_inode_pass1 truncating fraglist to 0x%08x\n", ic->scan->isize));
- jffs2_truncate_fraglist(c, &fraglist, ic->scan->isize);
+ jffs2_truncate_fraglist(c, &fragtree, ic->scan->isize);
}
/* OK. Now clear up */
@@ -179,17 +179,7 @@
}
metadata = NULL;
- /* RBTREE */
- while (fraglist) {
- struct jffs2_node_frag *frag;
- frag = fraglist;
- fraglist = fraglist->fnext;
-
- if (frag->node && !(--frag->node->frags)) {
- jffs2_free_full_dnode(frag->node);
- }
- jffs2_free_node_frag(frag);
- }
+ jffs2_kill_fragtree(&fragtree, NULL);
/* Now for each child, increase nlink */
for(fd=ic->scan->dents; fd; fd = fd->next) {
Index: gc.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/gc.c,v
retrieving revision 1.81
retrieving revision 1.82
diff -u -r1.81 -r1.82
--- gc.c 1 Sep 2002 15:47:04 -0000 1.81
+++ gc.c 3 Sep 2002 00:08:51 -0000 1.82
@@ -202,7 +202,7 @@
}
/* FIXME. Read node and do lookup? */
- for (frag = frag_first(f->fragtree); frag; frag = frag_next(frag)) {
+ for (frag = frag_first(&f->fragtree); frag; frag = frag_next(frag)) {
if (frag->node && frag->node->raw == raw) {
fn = frag->node;
end = frag->ofs + frag->size;
@@ -626,7 +626,7 @@
je32_to_cpu(ri.ino));
});
- for (frag = jffs2_lookup_node_frag(f->fragtree, fn->ofs);
+ for (frag = jffs2_lookup_node_frag(&f->fragtree, fn->ofs);
frag; frag = frag_next(frag)) {
if (frag->ofs > fn->size + fn->ofs)
break;
Index: nodelist.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/nodelist.c,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -r1.49 -r1.50
--- nodelist.c 1 Sep 2002 15:47:04 -0000 1.49
+++ nodelist.c 3 Sep 2002 00:08:51 -0000 1.50
@@ -15,6 +15,7 @@
#include <linux/fs.h>
#include <linux/mtd/mtd.h>
#include <linux/interrupt.h>
+#include <linux/rbtree.h>
#include "nodelist.h"
void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list)
@@ -371,13 +372,136 @@
}
}
-struct jffs2_node_frag *jffs2_lookup_node_frag(struct jffs2_node_frag *fragtree, uint32_t offset)
+struct jffs2_node_frag *jffs2_lookup_node_frag(rb_root_t *fragtree, uint32_t offset)
{
- struct jffs2_node_frag *frag = fragtree;
+ /* The common case in lookup is that there will be a node
+ which precisely matches. So we go looking for that first */
+ rb_node_t *next = &(frag_first(fragtree))->rb;
+ struct jffs2_node_frag *ret;
+ struct jffs2_node_frag *frag;
+
+ D1(printk(KERN_DEBUG "jffs2_lookup_node_frag(%d)\n", offset));
+
+ do {
+ frag = rb_entry(next, struct jffs2_node_frag, rb);
+
+ if (frag->ofs + frag->size <= offset) {
+ D1(printk(KERN_DEBUG "Going right from frag %d-%d, before the region we care about\n",
+ frag->ofs, frag->ofs+frag->size));
+ next = frag->rb.rb_right;
+ } else if (frag->ofs > offset) {
+ D1(printk(KERN_DEBUG "Going left from frag %d-%d, after the region we care about\n",
+ frag->ofs, frag->ofs+frag->size));
+ next = frag->rb.rb_left;
+ } else {
+ D1(printk(KERN_DEBUG "Returning frag %d,%d, matched\n",
+ frag->ofs, frag->ofs+frag->size));
+ return frag;
+ }
+ } while(next);
+
+ /* Exact match not found. Go back up looking at each parent,
+ and return the closest smaller one */
+
+ D1(printk(KERN_DEBUG "No match. Looking for closest previous frag\n"));
+
+ ret = frag;
- while(frag && frag->ofs + frag->size <= offset) {
- D2(printk(KERN_DEBUG "skipping frag %d-%d; before the region we care about\n", frag->ofs, frag->ofs + frag->size));
- frag = frag_next(frag);
+ while (frag) {
+ D1(printk(KERN_DEBUG "Considering frag %d-%d.\n",
+ frag->ofs, frag->ofs+frag->size));
+ if (frag->ofs < offset && frag->ofs > ret->ofs)
+ ret = frag;
+
+ frag = frag_parent(frag);
}
- return frag;
+ D1(printk(KERN_DEBUG "Returning frag %d,%d, closest previous\n",
+ frag->ofs, frag->ofs+frag->size));
+
+ return ret;
+}
+
+/* Pass 'c' argument to indicate that nodes should be marked obsolete as
+ they're killed. */
+void jffs2_kill_fragtree(rb_root_t *root, struct jffs2_sb_info *c)
+{
+ struct jffs2_node_frag *frag = (rb_entry(root->rb_node, struct jffs2_node_frag, rb));
+ struct jffs2_node_frag *parent;
+
+ while(frag) {
+ if (frag_left(frag)) {
+ frag = frag_left(frag);
+ continue;
+ }
+ if (frag_right(frag)) {
+ frag = frag_right(frag);
+ continue;
+ }
+
+ D2(printk(KERN_DEBUG "jffs2_kill_fragtree: frag at 0x%x-0x%x: node %p, frags %d--\n",
+ frag->ofs, frag->ofs+frag->size, frag->node,
+ frag->node?frag->node->frags:0));
+
+ if (frag->node && !(--frag->node->frags)) {
+ /* Not a hole, and it's the final remaining frag
+ of this node. Free the node */
+ if (c)
+ jffs2_mark_node_obsolete(c, frag->node->raw);
+
+ jffs2_free_full_dnode(frag->node);
+ }
+ parent = frag_parent(frag);
+ if (frag_left(parent) == frag)
+ parent->rb.rb_left = NULL;
+ else
+ parent->rb.rb_right = NULL;
+
+ jffs2_free_node_frag(frag);
+ frag = parent;
+ }
+}
+
+void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_node_frag *base)
+{
+ rb_node_t *parent = &base->rb;
+ rb_node_t **link = &parent;
+
+ while (*link) {
+ parent = *link;
+ base = rb_entry(parent, struct jffs2_node_frag, rb);
+
+ if (newfrag->ofs > base->ofs)
+ link = &base->rb.rb_right;
+ else if (newfrag->ofs > base->ofs)
+ link = &base->rb.rb_left;
+ else {
+ printk(KERN_CRIT "Duplicate frag at %08x (%p,%p)\n", newfrag->ofs, newfrag, base);
+ BUG();
+ }
+ }
+
+ rb_link_node(&newfrag->rb, &base->rb, link);
+}
+
+rb_node_t *rb_next(rb_node_t *node)
+{
+ /* If we have a right-hand child, go down and then left as far
+ as we can. */
+ if (node->rb_right) {
+ node = node->rb_right;
+ while (node->rb_left)
+ node=node->rb_left;
+ return node;
+ }
+
+ /* No right-hand children. Everything down and left is
+ smaller than us, so any 'next' node must be in the general
+ direction of our parent. Go up the tree; any time the
+ ancestor is a right-hand child of its parent, keep going
+ up. First time it's a left-hand child of its parent, said
+ parent is our 'next' node. */
+ while (node->rb_parent && node == node->rb_parent->rb_right)
+ node = node->rb_parent;
+
+ return node->rb_parent;
}
Index: nodelist.h
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/nodelist.h,v
retrieving revision 1.77
retrieving revision 1.78
diff -u -r1.77 -r1.78
--- nodelist.h 1 Sep 2002 15:47:04 -0000 1.77
+++ nodelist.h 3 Sep 2002 00:08:51 -0000 1.78
@@ -146,15 +146,12 @@
*/
struct jffs2_node_frag
{
- struct jffs2_node_frag *fnext;
+ rb_node_t rb;
struct jffs2_full_dnode *node; /* NULL for holes */
uint32_t size;
uint32_t ofs; /* Don't really need this, but optimisation */
};
-#define frag_next(f) ((f)->fnext)
-#define frag_first(f) (f)
-
struct jffs2_eraseblock
{
struct list_head list;
@@ -238,6 +235,23 @@
return ((struct jffs2_inode_cache *)raw)->ino;
}
+static inline struct jffs2_node_frag *frag_first(rb_root_t *root)
+{
+ rb_node_t *node = root->rb_node;
+
+ if (!node)
+ return NULL;
+ while(node->rb_left)
+ node = node->rb_left;
+ return rb_entry(node, struct jffs2_node_frag, rb);
+}
+#define rb_parent(rb) ((rb)->rb_parent)
+#define frag_next(frag) rb_entry(rb_next(&(frag)->rb), struct jffs2_node_frag, rb)
+#define frag_parent(frag) rb_entry(rb_parent(&(frag)->rb), struct jffs2_node_frag, rb)
+#define frag_left(frag) rb_entry(&(frag)->rb.rb_left, struct jffs2_node_frag, rb)
+#define frag_right(frag) rb_entry(&(frag)->rb.rb_right, struct jffs2_node_frag, rb)
+#define frag_erase(frag, list) rb_erase(&frag->rb, list);
+
/* nodelist.c */
D1(void jffs2_print_frag_list(struct jffs2_inode_info *f));
void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list);
@@ -251,7 +265,10 @@
void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old);
void jffs2_free_ino_caches(struct jffs2_sb_info *c);
void jffs2_free_raw_node_refs(struct jffs2_sb_info *c);
-struct jffs2_node_frag *jffs2_lookup_node_frag(struct jffs2_node_frag *fragtree, uint32_t offset);
+struct jffs2_node_frag *jffs2_lookup_node_frag(rb_root_t *fragtree, uint32_t offset);
+void jffs2_kill_fragtree(rb_root_t *root, struct jffs2_sb_info *c_delete);
+void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_node_frag *base);
+rb_node_t *rb_next(rb_node_t *);
/* nodemgmt.c */
int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len, int prio);
@@ -274,8 +291,8 @@
/* readinode.c */
-void jffs2_truncate_fraglist (struct jffs2_sb_info *c, struct jffs2_node_frag **list, uint32_t size);
-int jffs2_add_full_dnode_to_fraglist(struct jffs2_sb_info *c, struct jffs2_node_frag **list, struct jffs2_full_dnode *fn);
+void jffs2_truncate_fraglist (struct jffs2_sb_info *c, rb_root_t *list, uint32_t size);
+int jffs2_add_full_dnode_to_fraglist(struct jffs2_sb_info *c, rb_root_t *list, struct jffs2_full_dnode *fn);
int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn);
int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
uint32_t ino, struct jffs2_raw_inode *latest_node);
Index: read.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/read.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -r1.25 -r1.26
--- read.c 1 Sep 2002 15:47:04 -0000 1.25
+++ read.c 3 Sep 2002 00:08:51 -0000 1.26
@@ -157,7 +157,7 @@
D1(printk(KERN_DEBUG "jffs2_read_inode_range: ino #%u, range 0x%08x-0x%08x\n",
f->inocache->ino, offset, offset+len));
- frag = jffs2_lookup_node_frag(f->fragtree, offset);
+ frag = jffs2_lookup_node_frag(&f->fragtree, offset);
/* XXX FIXME: Where a single physical node actually shows up in two
frags, we read it twice. Don't do that. */
Index: readinode.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/readinode.c,v
retrieving revision 1.76
retrieving revision 1.77
diff -u -r1.76 -r1.77
--- readinode.c 1 Sep 2002 15:47:04 -0000 1.76
+++ readinode.c 3 Sep 2002 00:08:52 -0000 1.77
@@ -22,7 +22,7 @@
D1(void jffs2_print_frag_list(struct jffs2_inode_info *f)
{
- struct jffs2_node_frag *this = frag_first(f->fragtree);
+ struct jffs2_node_frag *this = frag_first(&f->fragtree);
while(this) {
if (this->node)
@@ -72,14 +72,12 @@
}
/* Doesn't set inode->i_size */
-int jffs2_add_full_dnode_to_fraglist(struct jffs2_sb_info *c, struct jffs2_node_frag **list, struct jffs2_full_dnode *fn)
+int jffs2_add_full_dnode_to_fraglist(struct jffs2_sb_info *c, rb_root_t *list, struct jffs2_full_dnode *fn)
{
-
- struct jffs2_node_frag *this, **prev, *old;
- struct jffs2_node_frag *newfrag, *newfrag2;
+ struct jffs2_node_frag *this;
+ struct jffs2_node_frag *newfrag;
uint32_t lastend = 0;
-
newfrag = jffs2_alloc_node_frag();
if (!newfrag) {
return -ENOMEM;
@@ -90,33 +88,27 @@
else
printk(KERN_DEBUG "adding hole node %04x-%04x on flash, newfrag *%p\n", fn->ofs, fn->ofs+fn->size, newfrag));
- prev = list;
- this = *list;
-
if (!fn->size) {
jffs2_free_node_frag(newfrag);
return 0;
}
- /* RBTREE */
newfrag->ofs = fn->ofs;
newfrag->size = fn->size;
newfrag->node = fn;
newfrag->node->frags = 1;
- newfrag->fnext = (void *)0xdeadbeef;
/* Skip all the nodes which are completed before this one starts */
- while(this && fn->ofs >= this->ofs+this->size) {
- lastend = this->ofs + this->size;
+ this = jffs2_lookup_node_frag(list, fn->ofs);
+
+ D1(printk(KERN_DEBUG "j_a_f_d_t_f: Lookup gave frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n",
+ this->ofs, this->ofs+this->size, this->node?(this->node->raw->flash_offset &~3):0xffffffff, this));
- D2(printk(KERN_DEBUG "j_a_f_d_t_f: skipping frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n",
- this->ofs, this->ofs+this->size, this->node?(this->node->raw->flash_offset &~3):0xffffffff, this));
- prev = &this->fnext;
- this = this->fnext;
- }
+
+ lastend = this->ofs + this->size;
/* See if we ran off the end of the list */
- if (!this) {
+ if (lastend <= newfrag->ofs) {
/* We did */
if (lastend < fn->ofs) {
/* ... and we need to put a hole in before the new node */
@@ -125,27 +117,31 @@
return -ENOMEM;
holefrag->ofs = lastend;
holefrag->size = fn->ofs - lastend;
- holefrag->fnext = NULL;
holefrag->node = NULL;
- *prev = holefrag;
- prev = &holefrag->fnext;
- }
- newfrag->fnext = NULL;
- *prev = newfrag;
+ /* By definition, the 'this' node has no right-hand child.
+ And that's where we want to put the hole */
+ rb_link_node(&holefrag->rb, &this->rb, &this->rb.rb_right);
+ rb_insert_color(&holefrag->rb, list);
+ this = holefrag;
+ }
+ /* By definition, the 'this' node has no right-hand child.
+ And that's where we want to put the new node */
+ rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right);
+ rb_insert_color(&newfrag->rb, list);
return 0;
}
D2(printk(KERN_DEBUG "j_a_f_d_t_f: dealing with frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n",
this->ofs, this->ofs+this->size, this->node?(this->node->raw->flash_offset &~3):0xffffffff, this));
- /* OK. 'this' is pointing at the first frag that fn->ofs at least partially obsoletes,
- * - i.e. fn->ofs < this->ofs+this->size && fn->ofs >= this->ofs
+ /* OK. 'this' is pointing at the first frag that newfrag->ofs at least partially obsoletes,
+ * - i.e. newfrag->ofs < this->ofs+this->size && newfrag->ofs >= this->ofs
*/
- if (fn->ofs > this->ofs) {
+ if (newfrag->ofs > this->ofs) {
/* This node isn't completely obsoleted. The start of it remains valid */
- if (this->ofs + this->size > fn->ofs + fn->size) {
+ if (this->ofs + this->size > newfrag->ofs + newfrag->size) {
/* The new node splits 'this' frag into two */
- newfrag2 = jffs2_alloc_node_frag();
+ struct jffs2_node_frag *newfrag2 = jffs2_alloc_node_frag();
if (!newfrag2) {
jffs2_free_node_frag(newfrag);
return -ENOMEM;
@@ -156,39 +152,55 @@
else
printk("hole\n");
)
- newfrag2->ofs = fn->ofs + fn->size;
+ /* Adjust size of original 'this' */
+ this->size = newfrag->ofs - this->ofs;
+
+ /* New second frag pointing to 'this's node */
+ newfrag2->ofs = newfrag->ofs + newfrag->size;
newfrag2->size = (this->ofs+this->size) - newfrag2->ofs;
- newfrag2->fnext = this->fnext;
newfrag2->node = this->node;
if (this->node)
this->node->frags++;
- newfrag->fnext = newfrag2;
- this->fnext = newfrag;
- this->size = newfrag->ofs - this->ofs;
+
+ /* Now, we know there's no node with offset greater than newfrag2->ofs, for
+ obvious reasons. So we can do a tree insert from this to insert newfrag,
+ and a tree insert from newfrag to insert newfrag2. */
+ jffs2_fragtree_insert(newfrag, this);
+ rb_insert_color(&newfrag->rb, list);
+
+ jffs2_fragtree_insert(newfrag2, this);
+ rb_insert_color(&newfrag2->rb, list);
+
return 0;
}
/* New node just reduces 'this' frag in size, doesn't split it */
- this->size = fn->ofs - this->ofs;
- newfrag->fnext = this->fnext;
- this->fnext = newfrag;
- this = newfrag->fnext;
+ this->size = newfrag->ofs - this->ofs;
+
+ /* Again, we know it lives down here in the tree */
+ jffs2_fragtree_insert(newfrag, this);
+ rb_insert_color(&newfrag->rb, list);
} else {
D2(printk(KERN_DEBUG "Inserting newfrag (*%p) in before 'this' (*%p)\n", newfrag, this));
- *prev = newfrag;
- newfrag->fnext = this;
+ struct jffs2_node_frag *parent = frag_parent(this);
+
+ if (this == frag_left(parent))
+ parent->rb.rb_left = &newfrag->rb;
+ else
+ parent->rb.rb_right = &newfrag->rb;
+
+ newfrag->rb = this->rb;
+ jffs2_obsolete_node_frag(c, this);
}
- /* OK, now we have newfrag added in the correct place in the list, but
- newfrag->fnext points to a fragment which may be overlapping it
+ /* OK, now we have newfrag added in the correct place in the tree, but
+ frag_next(newfrag) may be a fragment which is overlapped by it
*/
- while (this && newfrag->ofs + newfrag->size >= this->ofs + this->size) {
- /* 'this' frag is obsoleted. */
- old = this;
- this = old->fnext;
- jffs2_obsolete_node_frag(c, old);
+ while ((this = frag_next(newfrag)) && newfrag->ofs + newfrag->size >= this->ofs + this->size) {
+ /* 'this' frag is obsoleted completely. */
+ rb_erase(&this->rb, list);
+ jffs2_obsolete_node_frag(c, this);
}
/* Now we're pointing at the first frag which isn't totally obsoleted by
the new frag */
- newfrag->fnext = this;
if (!this || newfrag->ofs + newfrag->size == this->ofs) {
return 0;
@@ -196,25 +208,29 @@
/* Still some overlap */
this->size = (this->ofs + this->size) - (newfrag->ofs + newfrag->size);
this->ofs = newfrag->ofs + newfrag->size;
+
return 0;
}
-void jffs2_truncate_fraglist (struct jffs2_sb_info *c, struct jffs2_node_frag **list, uint32_t size)
+void jffs2_truncate_fraglist (struct jffs2_sb_info *c, rb_root_t *list, uint32_t size)
{
+ struct jffs2_node_frag *frag = jffs2_lookup_node_frag(list, size);
+
D1(printk(KERN_DEBUG "Truncating fraglist to 0x%08x bytes\n", size));
- while (*list) {
- if ((*list)->ofs >= size) {
- struct jffs2_node_frag *this = *list;
- *list = this->fnext;
- D1(printk(KERN_DEBUG "Removing frag 0x%08x-0x%08x\n", this->ofs, this->ofs+this->size));
- jffs2_obsolete_node_frag(c, this);
- continue;
- } else if ((*list)->ofs + (*list)->size > size) {
- D1(printk(KERN_DEBUG "Truncating frag 0x%08x-0x%08x\n", (*list)->ofs, (*list)->ofs + (*list)->size));
- (*list)->size = size - (*list)->ofs;
- }
- list = &(*list)->fnext;
+ /* We know frag->ofs <= size. That's what lookup does for us */
+ if (frag && frag->ofs != size && frag->ofs+frag->size > size) {
+ D1(printk(KERN_DEBUG "Truncating frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size));
+ frag->size = size - frag->ofs;
+ frag = frag_next(frag);
+ }
+ while (frag) {
+ struct jffs2_node_frag *next = frag_next(frag);
+
+ D1(printk(KERN_DEBUG "Removing frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size));
+ frag_erase(frag, list);
+ jffs2_obsolete_node_frag(c, frag);
+ frag = next;
}
}
@@ -361,14 +377,14 @@
jffs2_do_clear_inode(c, f);
return -EIO;
}
- if (!frag_first(f->fragtree)) {
+ if (!frag_first(&f->fragtree)) {
printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o has no fragments\n", ino, je32_to_cpu(latest_node->mode));
up(&f->sem);
jffs2_do_clear_inode(c, f);
return -EIO;
}
/* ASSERT: f->fraglist != NULL */
- if (frag_next(frag_first(f->fragtree))) {
+ if (frag_next(frag_first(&f->fragtree))) {
printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o had more than one node\n", ino, je32_to_cpu(latest_node->mode));
/* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */
up(&f->sem);
@@ -376,52 +392,37 @@
return -EIO;
}
/* OK. We're happy */
- f->metadata = frag_first(f->fragtree)->node;
- jffs2_free_node_frag(frag_first(f->fragtree));
- f->fragtree = NULL;
+ f->metadata = frag_first(&f->fragtree)->node;
+ jffs2_free_node_frag(frag_first(&f->fragtree));
+ f->fragtree = RB_ROOT;
break;
}
return 0;
}
-
void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
{
- struct jffs2_node_frag *frag, *frags;
struct jffs2_full_dirent *fd, *fds;
+ /* 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 to keep the
(maybe temporary) BUG() in jffs2_mark_node_obsolete()
from triggering */
- if(f->inocache && !f->inocache->nlink)
+ if(deleted)
down(&c->alloc_sem);
down(&f->sem);
if (f->metadata) {
- if (f->inocache && !f->inocache->nlink)
+ if (deleted)
jffs2_mark_node_obsolete(c, f->metadata->raw);
jffs2_free_full_dnode(f->metadata);
}
- /* RBTREE */
- frags = frag_first(f->fragtree);
-
- while (frags) {
- frag = frags;
- frags = frag_next(frag);
- D2(printk(KERN_DEBUG "jffs2_do_clear_inode: frag at 0x%x-0x%x: node %p, frags %d--\n", frag->ofs, frag->ofs+frag->size, frag->node, frag->node?frag->node->frags:0));
-
- if (frag->node && !(--frag->node->frags)) {
- /* Not a hole, and it's the final remaining frag of this node. Free the node */
- if (f->inocache && !f->inocache->nlink)
- jffs2_mark_node_obsolete(c, frag->node->raw);
-
- jffs2_free_full_dnode(frag->node);
- }
- jffs2_free_node_frag(frag);
- }
+ jffs2_kill_fragtree(&f->fragtree, deleted?c:NULL);
fds = f->dents;
@@ -431,11 +432,8 @@
jffs2_free_full_dirent(fd);
}
- /* Urgh. Is there a nicer way to do this? */
- if(f->inocache && !f->inocache->nlink) {
- up(&f->sem);
+ up(&f->sem);
+
+ if(deleted)
up(&c->alloc_sem);
- } else {
- up(&f->sem);
- }
}
- Previous message: mtd/fs/jffs2 build.c,1.38,1.39 file.c,1.77,1.78 gc.c,1.80,1.81 nodelist.c,1.48,1.49 nodelist.h,1.76,1.77 read.c,1.24,1.25 readinode.c,1.75,1.76
- Next message: mtd/drivers/mtd/chips cfi_cmdset_0020.c,NONE,1.1 Config.in,1.15,1.16 gen_probe.c,1.7,1.8
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the linux-mtd-cvs
mailing list