aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jffs2
diff options
context:
space:
mode:
Diffstat (limited to 'fs/jffs2')
-rw-r--r--fs/jffs2/nodelist.c9
-rw-r--r--fs/jffs2/write.c27
2 files changed, 21 insertions, 15 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
32 if ((*prev)->nhash == new->nhash && !strcmp((*prev)->name, new->name)) { 32 if ((*prev)->nhash == new->nhash && !strcmp((*prev)->name, new->name)) {
33 /* Duplicate. Free one */ 33 /* Duplicate. Free one */
34 if (new->version < (*prev)->version) { 34 if (new->version < (*prev)->version) {
35 dbg_dentlist("Eep! Marking new dirent node is obsolete, old is \"%s\", ino #%u\n", 35 dbg_dentlist("Eep! Marking new dirent node obsolete, old is \"%s\", ino #%u\n",
36 (*prev)->name, (*prev)->ino); 36 (*prev)->name, (*prev)->ino);
37 jffs2_mark_node_obsolete(c, new->raw); 37 jffs2_mark_node_obsolete(c, new->raw);
38 jffs2_free_full_dirent(new); 38 jffs2_free_full_dirent(new);
39 } else { 39 } else {
40 dbg_dentlist("marking old dirent \"%s\", ino #%u bsolete\n", 40 dbg_dentlist("marking old dirent \"%s\", ino #%u obsolete\n",
41 (*prev)->name, (*prev)->ino); 41 (*prev)->name, (*prev)->ino);
42 new->next = (*prev)->next; 42 new->next = (*prev)->next;
43 jffs2_mark_node_obsolete(c, ((*prev)->raw)); 43 /* It may have been a 'placeholder' deletion dirent,
44 if jffs2_can_mark_obsolete() (see jffs2_do_unlink()) */
45 if ((*prev)->raw)
46 jffs2_mark_node_obsolete(c, ((*prev)->raw));
44 jffs2_free_full_dirent(*prev); 47 jffs2_free_full_dirent(*prev);
45 *prev = new; 48 *prev = new;
46 } 49 }
diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c
index 147e2cbee9e4..611012f7c8ae 100644
--- a/fs/jffs2/write.c
+++ b/fs/jffs2/write.c
@@ -582,7 +582,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
582 jffs2_add_fd_to_list(c, fd, &dir_f->dents); 582 jffs2_add_fd_to_list(c, fd, &dir_f->dents);
583 up(&dir_f->sem); 583 up(&dir_f->sem);
584 } else { 584 } else {
585 struct jffs2_full_dirent **prev = &dir_f->dents; 585 struct jffs2_full_dirent *fd = dir_f->dents;
586 uint32_t nhash = full_name_hash(name, namelen); 586 uint32_t nhash = full_name_hash(name, namelen);
587 587
588 /* We don't actually want to reserve any space, but we do 588 /* We don't actually want to reserve any space, but we do
@@ -590,18 +590,20 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
590 down(&c->alloc_sem); 590 down(&c->alloc_sem);
591 down(&dir_f->sem); 591 down(&dir_f->sem);
592 592
593 while ((*prev) && (*prev)->nhash <= nhash) { 593 for (fd = dir_f->dents; fd; fd = fd->next) {
594 if ((*prev)->nhash == nhash && 594 if (fd->nhash == nhash &&
595 !memcmp((*prev)->name, name, namelen) && 595 !memcmp(fd->name, name, namelen) &&
596 !(*prev)->name[namelen]) { 596 !fd->name[namelen]) {
597 struct jffs2_full_dirent *this = *prev;
598 597
599 D1(printk(KERN_DEBUG "Marking old dirent node (ino #%u) @%08x obsolete\n", 598 D1(printk(KERN_DEBUG "Marking old dirent node (ino #%u) @%08x obsolete\n",
600 this->ino, ref_offset(this->raw))); 599 fd->ino, ref_offset(fd->raw)));
601 600 jffs2_mark_node_obsolete(c, fd->raw);
602 *prev = this->next; 601 /* We don't want to remove it from the list immediately,
603 jffs2_mark_node_obsolete(c, (this->raw)); 602 because that screws up getdents()/seek() semantics even
604 jffs2_free_full_dirent(this); 603 more than they're screwed already. Turn it into a
604 node-less deletion dirent instead -- a placeholder */
605 fd->raw = NULL;
606 fd->ino = 0;
605 break; 607 break;
606 } 608 }
607 prev = &((*prev)->next); 609 prev = &((*prev)->next);
@@ -630,7 +632,8 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
630 D1(printk(KERN_DEBUG "Removing deletion dirent for \"%s\" from dir ino #%u\n", 632 D1(printk(KERN_DEBUG "Removing deletion dirent for \"%s\" from dir ino #%u\n",
631 fd->name, dead_f->inocache->ino)); 633 fd->name, dead_f->inocache->ino));
632 } 634 }
633 jffs2_mark_node_obsolete(c, fd->raw); 635 if (fd->raw)
636 jffs2_mark_node_obsolete(c, fd->raw);
634 jffs2_free_full_dirent(fd); 637 jffs2_free_full_dirent(fd);
635 } 638 }
636 } 639 }