diff options
Diffstat (limited to 'fs/jffs2/write.c')
| -rw-r--r-- | fs/jffs2/write.c | 28 |
1 files changed, 15 insertions, 13 deletions
diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c index 1b88e6e734ef..776f13cbf2b5 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,21 +590,22 @@ 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); | ||
| 608 | } | 609 | } |
| 609 | up(&dir_f->sem); | 610 | up(&dir_f->sem); |
| 610 | } | 611 | } |
| @@ -630,7 +631,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", | 631 | D1(printk(KERN_DEBUG "Removing deletion dirent for \"%s\" from dir ino #%u\n", |
| 631 | fd->name, dead_f->inocache->ino)); | 632 | fd->name, dead_f->inocache->ino)); |
| 632 | } | 633 | } |
| 633 | jffs2_mark_node_obsolete(c, fd->raw); | 634 | if (fd->raw) |
| 635 | jffs2_mark_node_obsolete(c, fd->raw); | ||
| 634 | jffs2_free_full_dirent(fd); | 636 | jffs2_free_full_dirent(fd); |
| 635 | } | 637 | } |
| 636 | } | 638 | } |
