diff options
Diffstat (limited to 'fs/jffs2/write.c')
-rw-r--r-- | fs/jffs2/write.c | 27 |
1 files changed, 15 insertions, 12 deletions
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 | } |