summaryrefslogtreecommitdiff
path: root/fs/jffs2/nodelist.c
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2007-11-01 16:25:56 -0400
committerDavid Woodhouse <dwmw2@infradead.org>2007-11-01 16:25:56 -0400
commit15953580e79b58caefb107e77f218e009b9992e6 (patch)
treee2c51dacd42f4e575ed2e824a295f19df177649d /fs/jffs2/nodelist.c
parentd10a39d1a580db005d206fb6527a60fd9800c9fd (diff)
downloadlwn-15953580e79b58caefb107e77f218e009b9992e6.tar.gz
lwn-15953580e79b58caefb107e77f218e009b9992e6.zip
[JFFS2] Improve getdents vs. f_pos handling on NOR flash.
Commit a491486a2087ac3dfc00efb4f838c8d684afaf54 started obliterating dirents directly on the medium, when jffs2_can_mark_obsolete(). Removing them immediately from the f->dents list, however, screws up handling of f_pos within a directory -- because the offset is equivalent to the number of entries through the list we are, and the existence of deletion dirents served to provide 'placeholders' for unlinked entries. Now, 'rm -r' doesn't even manage to unlink everything in the directory. Revert to keeping 'deletion' dirents in the list, at least in memory even though we no longer write anything to the medium. Spotted, debugged and mostly fixed by Joakim Tjernlund Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'fs/jffs2/nodelist.c')
-rw-r--r--fs/jffs2/nodelist.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c
index 4bf86088b3ae..87c6f555e1a0 100644
--- a/fs/jffs2/nodelist.c
+++ b/fs/jffs2/nodelist.c
@@ -32,15 +32,18 @@ void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new
if ((*prev)->nhash == new->nhash && !strcmp((*prev)->name, new->name)) {
/* Duplicate. Free one */
if (new->version < (*prev)->version) {
- dbg_dentlist("Eep! Marking new dirent node is obsolete, old is \"%s\", ino #%u\n",
+ dbg_dentlist("Eep! Marking new dirent node obsolete, old is \"%s\", ino #%u\n",
(*prev)->name, (*prev)->ino);
jffs2_mark_node_obsolete(c, new->raw);
jffs2_free_full_dirent(new);
} else {
- dbg_dentlist("marking old dirent \"%s\", ino #%u bsolete\n",
+ dbg_dentlist("marking old dirent \"%s\", ino #%u obsolete\n",
(*prev)->name, (*prev)->ino);
new->next = (*prev)->next;
- jffs2_mark_node_obsolete(c, ((*prev)->raw));
+ /* It may have been a 'placeholder' deletion dirent,
+ if jffs2_can_mark_obsolete() (see jffs2_do_unlink()) */
+ if ((*prev)->raw)
+ jffs2_mark_node_obsolete(c, ((*prev)->raw));
jffs2_free_full_dirent(*prev);
*prev = new;
}