mtd/fs/jffs2 build.c,1.53,1.54
David Woodhouse
dwmw2 at infradead.org
Fri Oct 24 13:31:13 EDT 2003
Update of /home/cvs/mtd/fs/jffs2
In directory phoenix.infradead.org:/tmp/cvs-serv13203
Modified Files:
build.c
Log Message:
Better optimisation for NAND: Don't restart pass 2 if a child of a zero-nlink
directory ends up with nlink zero, just add it to a list to be cleaned up
afterwards
Index: build.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/build.c,v
retrieving revision 1.53
retrieving revision 1.54
diff -u -r1.53 -r1.54
--- build.c 24 Oct 2003 11:32:59 -0000 1.53
+++ build.c 24 Oct 2003 17:31:11 -0000 1.54
@@ -16,8 +16,8 @@
#include <linux/slab.h>
#include "nodelist.h"
-int jffs2_build_inode_pass1(struct jffs2_sb_info *, struct jffs2_inode_cache *);
-int jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *, struct jffs2_inode_cache *);
+static int jffs2_build_inode_pass1(struct jffs2_sb_info *, struct jffs2_inode_cache *);
+static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *, struct jffs2_inode_cache *, struct jffs2_full_dirent **);
static inline struct jffs2_inode_cache *
first_inode_chain(int *i, struct jffs2_sb_info *c)
@@ -54,6 +54,7 @@
int ret;
int i;
struct jffs2_inode_cache *ic;
+ struct jffs2_full_dirent *dead_fds = NULL;
/* First, scan the medium and build all the inode caches with
lists of physical nodes */
@@ -86,30 +87,35 @@
children too, and repeat the scan. As that's going to be
a fairly uncommon occurrence, it's not so evil to do it this
way. Recursion bad. */
- do {
- D1(printk(KERN_DEBUG "Pass 2 (re)starting\n"));
- ret = 0;
- for_each_inode(i, c, ic) {
- D1(printk(KERN_DEBUG "Pass 2: ino #%u, nlink %d, ic %p, nodes %p\n", ic->ino, ic->nlink, ic, ic->nodes));
- if (ic->nlink)
- continue;
+ D1(printk(KERN_DEBUG "Pass 2 starting\n"));
+
+ for_each_inode(i, c, ic) {
+ D1(printk(KERN_DEBUG "Pass 2: ino #%u, nlink %d, ic %p, nodes %p\n", ic->ino, ic->nlink, ic, ic->nodes));
+ if (ic->nlink)
+ continue;
- /* XXX: Can get high latency here. Move the cond_resched() from the end of the loop? */
+ jffs2_build_remove_unlinked_inode(c, ic, &dead_fds);
+ cond_resched();
+ }
- ret = jffs2_build_remove_unlinked_inode(c, ic);
- if (ret)
- break;
- /* -EAGAIN means the inode's nlink was zero, so we deleted it,
- and furthermore that it had children and their nlink has now
- gone to zero too. So we have to restart the scan. */
- }
- D1(jffs2_dump_block_lists(c));
+ D1(printk(KERN_DEBUG "Pass 2a starting\n"));
- cond_resched();
-
- } while(ret == -EAGAIN);
+ while (dead_fds) {
+ struct jffs2_inode_cache *ic;
+ struct jffs2_full_dirent *fd = dead_fds;
+
+ dead_fds = fd->next;
+
+ ic = jffs2_get_ino_cache(c, fd->ino);
+ D1(printk(KERN_DEBUG "Removing dead_fd ino #%u (\"%s\"), ic at %p\n", fd->ino, fd->name, ic));
+
+ if (ic)
+ jffs2_build_remove_unlinked_inode(c, ic, &dead_fds);
+ jffs2_free_full_dirent(fd);
+ }
D1(printk(KERN_DEBUG "Pass 2 complete\n"));
+ D1(jffs2_dump_block_lists(c));
/* Finally, we can scan again and free the dirent nodes and scan_info structs */
for_each_inode(i, c, ic) {
@@ -133,7 +139,7 @@
return ret;
}
-int jffs2_build_inode_pass1(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
+static int jffs2_build_inode_pass1(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
{
struct jffs2_full_dirent *fd;
@@ -171,11 +177,10 @@
return 0;
}
-int jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
+static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, struct jffs2_full_dirent **dead_fds)
{
struct jffs2_raw_node_ref *raw;
struct jffs2_full_dirent *fd;
- int ret = 0;
D1(printk(KERN_DEBUG "JFFS2: Removing ino #%u with nlink == zero.\n", ic->ino));
@@ -214,9 +219,22 @@
jffs2_free_full_dirent(fd);
continue;
}
- jffs2_free_full_dirent(fd);
+
+ /* Reduce nlink of the child. If it's now zero, stick it on the
+ dead_fds list to be cleaned up later. Else just free the fd */
+
child_ic->nlink--;
- ret = -EAGAIN;
+
+ if (!child_ic->nlink) {
+ D1(printk(KERN_DEBUG "Inode #%u (\"%s\") has now got zero nlink. Adding to dead_fds list.\n",
+ fd->ino, fd->name));
+ fd->next = *dead_fds;
+ *dead_fds = fd;
+ } else {
+ D1(printk(KERN_DEBUG "Inode #%u (\"%s\") has now got nlink %d. Ignoring.\n",
+ fd->ino, fd->name, child_ic->nlink));
+ jffs2_free_full_dirent(fd);
+ }
}
}
@@ -224,8 +242,6 @@
We don't delete the inocache from the hash list and free it yet.
The erase code will do that, when all the nodes are completely gone.
*/
-
- return ret;
}
static void jffs2_calc_trigger_levels(struct jffs2_sb_info *c)
More information about the linux-mtd-cvs
mailing list