mtd/fs/jffs2 wbuf.c,1.38,1.39
David Woodhouse
dwmw2 at infradead.org
Mon Aug 25 08:03:22 EDT 2003
Update of /home/cvs/mtd/fs/jffs2
In directory phoenix.infradead.org:/tmp/cvs-serv4228/fs/jffs2
Modified Files:
wbuf.c
Log Message:
Make wbuf code actually keep track of which inodes are dirty.
Index: wbuf.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/wbuf.c,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -r1.38 -r1.39
--- wbuf.c 25 Aug 2003 11:38:05 -0000 1.38
+++ wbuf.c 25 Aug 2003 12:03:20 -0000 1.39
@@ -24,6 +24,70 @@
/* two seconds timeout for timed wbuf-flushing */
#define WBUF_FLUSH_TIMEOUT 2 * HZ
+struct jffs2_inodirty {
+ uint32_t ino;
+ struct jffs2_inodirty *next;
+};
+
+static struct jffs2_inodirty inodirty_nomem;
+
+static int jffs2_wbuf_pending_for_ino(struct jffs2_sb_info *c, uint32_t ino)
+{
+ struct jffs2_inodirty *this = c->wbuf_inodes;
+
+ /* If a malloc failed, consider _everything_ dirty */
+ if (this == &inodirty_nomem)
+ return 1;
+
+ /* If ino == 0, _any_ non-GC writes mean 'yes' */
+ if (this && !ino)
+ return 1;
+
+ /* Look to see if the inode in question is pending in the wbuf */
+ while (this) {
+ if (this->ino == ino)
+ return 1;
+ this = this->next;
+ }
+ return 0;
+}
+
+static void jffs2_clear_wbuf_ino_list(struct jffs2_sb_info *c)
+{
+ struct jffs2_inodirty *this;
+
+ this = c->wbuf_inodes;
+
+ if (this != &inodirty_nomem) {
+ while (this) {
+ struct jffs2_inodirty *next = this->next;
+ kfree(this);
+ this = next;
+ }
+ }
+ c->wbuf_inodes = NULL;
+}
+
+static void jffs2_wbuf_dirties_inode(struct jffs2_sb_info *c, uint32_t ino)
+{
+ struct jffs2_inodirty *new;
+
+ if (jffs2_wbuf_pending_for_ino(c, ino))
+ return;
+
+ new = kmalloc(sizeof(*new), GFP_KERNEL);
+ if (!new) {
+ D1(printk(KERN_DEBUG "No memory to allocate inodirty. Fallback to all considered dirty\n"));
+ jffs2_clear_wbuf_ino_list(c);
+ c->wbuf_inodes = &inodirty_nomem;
+ return;
+ }
+ new->ino = ino;
+ new->next = c->wbuf_inodes;
+ c->wbuf_inodes = new;
+ return;
+}
+
static inline void jffs2_refile_wbuf_blocks(struct jffs2_sb_info *c)
{
struct list_head *this, *next;
@@ -210,6 +274,7 @@
/* Stick any now-obsoleted blocks on the erase_pending_list */
spin_lock(&c->erase_completion_lock);
jffs2_refile_wbuf_blocks(c);
+ jffs2_clear_wbuf_ino_list(c);
spin_unlock(&c->erase_completion_lock);
memset(c->wbuf,0xff,c->wbuf_pagesize);
@@ -233,6 +298,12 @@
D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() called for ino #%u...\n", ino));
down(&c->alloc_sem);
+ if (!jffs2_wbuf_pending_for_ino(c, ino)) {
+ D1(printk(KERN_DEBUG "Ino #%d not pending in wbuf. Returning\n", ino));
+ up(&c->alloc_sem);
+ return 0;
+ }
+
old_wbuf_ofs = c->wbuf_ofs;
old_wbuf_len = c->wbuf_len;
@@ -462,7 +533,11 @@
}
c->wbuf_len = wbuf_ptr - c->wbuf;
-alldone:
+ /* If there's a remainder in the wbuf and it's a non-GC write,
+ remember that the wbuf affects this ino */
+ if (c->wbuf_len && ino)
+ jffs2_wbuf_dirties_inode(c, ino);
+alldone:
*retlen = donelen;
/* Setup timed wbuf flush, if buffer len != 0 */
if (c->wbuf_len) {
More information about the linux-mtd-cvs
mailing list