getdents64 problem in 2.6.23
Joakim Tjernlund
joakim.tjernlund at transmode.se
Sat Oct 27 07:02:40 EDT 2007
On Fri, 2007-10-26 at 19:17 -0400, David Woodhouse wrote:
> On Sat, 2007-10-27 at 01:03 +0200, Joakim Tjernlund wrote:
> > Is this what you mean(just a stupid hack for now)?
> > //*prev = this->next;
> > jffs2_mark_node_obsolete(c, (this->raw));
> > this->raw = NULL;
> > //jffs2_free_full_dirent(this);
>
> Yeah, something like that. And we also need to modify
> jffs2_add_fd_to_list() so that if we later add a new dirent which
> _replaces_ this one, it doesn't oops after calling
> jffs2_mark_node_obsolete(c, fd->raw);
>
> > Perhaps add a jffs2_add_fd_to_list(c, this, &dir_f->dents)?
>
> Nah, no need for that. It's already _in_ the list.
>
> > How do I find where the filedescriptor is closed?
>
> We probably need to implement a release() operation in the
> jffs2_dir_operations (top of dir.c), which will remove the fake
> 'deletion' dirents if !atomic_read(&inode->i_count). Or something like
> that.
>
Next iteration. I am rather lost in the release function.
Some hints would be great.
Jocke
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index 8353eb9..a658bcb 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -20,6 +20,7 @@
#include "nodelist.h"
static int jffs2_readdir (struct file *, void *, filldir_t);
+static int jffs2_release (struct inode *, struct file *);
static int jffs2_create (struct inode *,struct dentry *,int,
struct nameidata *);
@@ -39,7 +40,8 @@ const struct file_operations jffs2_dir_operations =
.read = generic_read_dir,
.readdir = jffs2_readdir,
.ioctl = jffs2_ioctl,
- .fsync = jffs2_fsync
+ .fsync = jffs2_fsync,
+ .release = jffs2_release,
};
@@ -174,6 +176,25 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir)
/***********************************************************************/
+static int jffs2_release(struct inode *dir_i, struct file *file)
+{
+ //struct jffs2_sb_info *c = JFFS2_SB_INFO(dir_i->i_sb);
+ struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i);
+ struct jffs2_full_dirent **prev = &dir_f->dents;
+
+ if (atomic_read(&dir_i->i_count))
+ return 0;
+
+ while (*prev) {
+ D1(printk(KERN_DEBUG "Releasing directory inode:%d\n", (*prev)->ino));
+
+ jffs2_free_full_dirent(*prev);
+ prev = &((*prev)->next);
+ }
+ return 0;
+}
+
+/***********************************************************************/
static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode,
struct nameidata *nd)
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c
index 4bf8608..5419023 100644
--- a/fs/jffs2/nodelist.c
+++ b/fs/jffs2/nodelist.c
@@ -34,13 +34,15 @@ void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new
if (new->version < (*prev)->version) {
dbg_dentlist("Eep! Marking new dirent node is obsolete, old is \"%s\", ino #%u\n",
(*prev)->name, (*prev)->ino);
- jffs2_mark_node_obsolete(c, new->raw);
+ if (new->raw)
+ jffs2_mark_node_obsolete(c, new->raw);
jffs2_free_full_dirent(new);
} else {
dbg_dentlist("marking old dirent \"%s\", ino #%u bsolete\n",
(*prev)->name, (*prev)->ino);
new->next = (*prev)->next;
- jffs2_mark_node_obsolete(c, ((*prev)->raw));
+ if ((*prev)->raw)
+ jffs2_mark_node_obsolete(c, ((*prev)->raw));
jffs2_free_full_dirent(*prev);
*prev = new;
}
diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c
index 2f56954..11e8b5f 100644
--- a/fs/jffs2/write.c
+++ b/fs/jffs2/write.c
@@ -591,9 +591,8 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
D1(printk(KERN_DEBUG "Marking old dirent node (ino #%u) @%08x obsolete\n",
this->ino, ref_offset(this->raw)));
- *prev = this->next;
jffs2_mark_node_obsolete(c, (this->raw));
- jffs2_free_full_dirent(this);
+ this->raw = NULL;
break;
}
prev = &((*prev)->next);
More information about the linux-mtd
mailing list