[JFFS2] Deletion dirents should be REF_NORMAL, not REF_PRISTINE. Otherwise they'll never actually get garbage-collected. Noted by Jonathan Larmour. Signed-off-by: David Woodhouse <dwmw2@infradead.org>
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index 25126a0..bc5509f 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h
@@ -139,6 +139,11 @@ #define ref_obsolete(ref) (((ref)->flash_offset & 3) == REF_OBSOLETE) #define mark_ref_normal(ref) do { (ref)->flash_offset = ref_offset(ref) | REF_NORMAL; } while(0) +/* Dirent nodes should be REF_PRISTINE only if they are not a deletion + dirent. Deletion dirents should be REF_NORMAL so that GC gets to + throw them away when appropriate */ +#define dirent_node_state(rd) ( (je32_to_cpu((rd)->ino)?REF_PRISTINE:REF_NORMAL) ) + /* NB: REF_PRISTINE for an inode-less node (ref->next_in_ino == NULL) indicates it is an unknown node of type JFFS2_NODETYPE_RWCOMPAT_COPY, so it'll get copied. If you need to do anything different to GC inode-less nodes, then
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 7b36378..170da20 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c
@@ -613,7 +613,7 @@ jeb->unchecked_size -= len; c->used_size += len; c->unchecked_size -= len; - ref->flash_offset = ref_offset(ref) | REF_PRISTINE; + ref->flash_offset = ref_offset(ref) | dirent_node_state(rd); spin_unlock(&c->erase_completion_lock); }
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index 2a1c976..6c75cd4 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c
@@ -1049,7 +1049,8 @@ return -ENOMEM; } - fd->raw = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rd->totlen)), ic); + fd->raw = jffs2_link_node_ref(c, jeb, ofs | dirent_node_state(rd), + PAD(je32_to_cpu(rd->totlen)), ic); fd->next = NULL; fd->version = je32_to_cpu(rd->version);
diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c index 1406f2ce..bc61859 100644 --- a/fs/jffs2/write.c +++ b/fs/jffs2/write.c
@@ -296,7 +296,8 @@ return ERR_PTR(ret?ret:-EIO); } /* Mark the space used */ - fd->raw = jffs2_add_physical_node_ref(c, flash_ofs | REF_PRISTINE, PAD(sizeof(*rd)+namelen), f->inocache); + fd->raw = jffs2_add_physical_node_ref(c, flash_ofs | dirent_node_state(rd), + PAD(sizeof(*rd)+namelen), f->inocache); if (IS_ERR(fd->raw)) { void *hold_err = fd->raw; /* Release the full_dirent which is now useless, and return */