Is JFFS a full featured filesystem?
David Woodhouse
dwmw2 at infradead.org
Wed Aug 2 08:11:09 EDT 2000
alex at cendio.se said:
> This could cause consistancy problems though, because we're not using
> the (possibly modified) mmaped data when writing directly to a file,
> we also in some way guarantee that all writes are done to the log in
> the correct order. It will also be an inefficient way to write data to
> jffs, since we have to rewrite whole pages instead of only the written
> part.
I believe that we can address both of those problems - we can write data
directly from the page cache and we can also work out which ranges within
a page have actually been dirtied.
alex at cendio.se said:
> All this, and the fact that the missing needed mutex around the
> writing to the log makes the jffs filesystem quite seriously borked.
This compiles. Wonder if it works...
Index: fs/jffs/intrep.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs/intrep.c,v
retrieving revision 1.25
diff -u -w -r1.25 intrep.c
--- fs/jffs/intrep.c 2000/07/27 19:45:35 1.25
+++ fs/jffs/intrep.c 2000/08/02 12:08:55
@@ -377,6 +377,17 @@
return sum;
}
+static __inline__ void jffs_fm_write_lock(struct jffs_fmcontrol *fmc)
+{
+ down(&fmc->wlock);
+}
+
+static __inline__ void jffs_fm_write_unlock(struct jffs_fmcontrol *fmc)
+{
+ up(&fmc->wlock);
+}
+
+
/* Create and initialize a new struct jffs_file. */
static struct jffs_file *
jffs_create_file(struct jffs_control *c,
@@ -1373,8 +1384,11 @@
(name ? name : ""), raw_inode->ino,
raw_inode->version, total_size));
+ jffs_fm_write_lock(fmc);
+
/* First try to allocate some flash memory. */
if ((err = jffs_fmalloc(fmc, total_size, node, &fm)) < 0) {
+ jffs_fm_write_unlock(fmc);
D(printk("jffs_write_node(): jffs_fmalloc(0x%p, %u) "
"failed!\n", fmc, total_size));
return err;
@@ -1383,14 +1397,16 @@
/* The jffs_fm struct that we got is not good enough.
Make that space dirty. */
if ((err = jffs_write_dummy_node(c, fm)) < 0) {
- D(printk("jffs_write_node(): "
- "jffs_write_dummy_node(): Failed!\n"));
kfree(fm);
DJM(no_jffs_fm--);
+ jffs_fm_write_unlock(fmc);
+ D(printk("jffs_write_node(): "
+ "jffs_write_dummy_node(): Failed!\n"));
return err;
}
/* Get a new one. */
if ((err = jffs_fmalloc(fmc, total_size, node, &fm)) < 0) {
+ jffs_fm_write_unlock(fmc);
D(printk("jffs_write_node(): Second "
"jffs_fmalloc(0x%p, %u) failed!\n",
fmc, total_size));
@@ -1427,6 +1443,7 @@
sizeof(struct jffs_raw_inode))) < 0) {
jffs_fmfree_partly(fmc, fm,
total_name_size + total_data_size);
+ jffs_fm_write_unlock(fmc);
printk(KERN_ERR "JFFS: jffs_write_node: Failed to write "
"raw_inode.\n");
return err;
@@ -1439,6 +1456,7 @@
(u_char *)name,
raw_inode->nsize)) < 0) {
jffs_fmfree_partly(fmc, fm, total_data_size);
+ jffs_fm_write_unlock(fmc);
printk(KERN_ERR "JFFS: jffs_write_node: Failed to "
"write the name.\n");
return err;
@@ -1451,12 +1469,13 @@
if ((err = flash_safe_write(fmc->mtd, pos, data,
raw_inode->dsize)) < 0) {
jffs_fmfree_partly(fmc, fm, 0);
+ jffs_fm_write_unlock(fmc);
printk(KERN_ERR "JFFS: jffs_write_node: Failed to "
"write the data.\n");
return err;
}
}
-
+ jffs_fm_write_unlock(fmc);
D3(printk("jffs_write_node(): Leaving...\n"));
return raw_inode->dsize;
} /* jffs_write_node() */
@@ -2211,23 +2230,28 @@
new_node->fm_offset = sizeof(struct jffs_raw_inode)
+ total_name_size;
+ jffs_fm_write_lock(fmc);
+
if ((err = jffs_fmalloc(fmc, total_size, new_node, &fm)) < 0) {
+ DJM(no_jffs_node--);
+ jffs_fm_write_unlock(fmc);
D(printk("jffs_rewrite_data(): Failed to allocate fm.\n"));
kfree(new_node);
- DJM(no_jffs_node--);
return err;
}
else if (!fm->nodes) {
/* The jffs_fm struct that we got is not good enough. */
if ((err = jffs_write_dummy_node(c, fm)) < 0) {
+ DJM(no_jffs_fm--);
+ jffs_fm_write_unlock(fmc);
D(printk("jffs_rewrite_data(): "
"jffs_write_dummy_node() Failed!\n"));
kfree(fm);
- DJM(no_jffs_fm--);
return err;
}
/* Get a new one. */
if ((err = jffs_fmalloc(fmc, total_size, node, &fm)) < 0) {
+ jffs_fm_write_unlock(fmc);
D(printk("jffs_rewrite_data(): Second "
"jffs_fmalloc(0x%p, %u) failed!\n",
fmc, total_size));
@@ -2276,10 +2300,11 @@
sizeof(struct jffs_raw_inode)
- sizeof(__u32)
- sizeof(__u16) - sizeof(__u16))) < 0) {
- printk(KERN_ERR "JFFS: jffs_rewrite_data: Write error during "
- "rewrite. (raw inode)\n");
jffs_fmfree_partly(fmc, fm,
total_name_size + total_data_size);
+ jffs_fm_write_unlock(fmc);
+ printk(KERN_ERR "JFFS: jffs_rewrite_data: Write error during "
+ "rewrite. (raw inode)\n");
return err;
}
pos += sizeof(struct jffs_raw_inode);
@@ -2291,9 +2316,10 @@
if ((err = flash_safe_write(fmc->mtd, pos,
(u_char *)f->name,
f->nsize)) < 0) {
+ jffs_fmfree_partly(fmc, fm, total_data_size);
+ jffs_fm_write_unlock(fmc);
printk(KERN_ERR "JFFS: jffs_rewrite_data: Write "
"error during rewrite. (name)\n");
- jffs_fmfree_partly(fmc, fm, total_data_size);
return err;
}
pos += total_name_size;
@@ -2315,20 +2341,22 @@
__u32 s = jffs_min(size, PAGE_SIZE);
if ((r = jffs_read_data(f, (char *)page,
offset, s)) < s) {
+ free_page((unsigned long)page);
+ jffs_fmfree_partly(fmc, fm, 0);
+ jffs_fm_write_unlock(fmc);
printk(KERN_ERR "JFFS: jffs_rewrite_data: "
"jffs_read_data() "
"failed! (r = %d)\n", r);
- free_page((unsigned long)page);
- jffs_fmfree_partly(fmc, fm, 0);
return -1;
}
if ((err = flash_safe_write(fmc->mtd,
pos, page, r)) < 0) {
+ free_page((unsigned long)page);
+ jffs_fmfree_partly(fmc, fm, 0);
+ jffs_fm_write_unlock(fmc);
printk(KERN_ERR "JFFS: jffs_rewrite_data: "
"Write error during rewrite. "
"(data)\n");
- free_page((unsigned long)page);
- jffs_fmfree_partly(fmc, fm, 0);
return err;
}
pos += r;
@@ -2352,14 +2380,16 @@
&raw_inode)[JFFS_RAW_INODE_DCHKSUM_OFFSET],
sizeof(__u32) + sizeof(__u16)
+ sizeof(__u16))) < 0) {
+ jffs_fmfree_partly(fmc, fm, 0);
+ jffs_fm_write_unlock(fmc);
printk(KERN_ERR "JFFS: jffs_rewrite_data: Write error during "
"rewrite. (checksum)\n");
- jffs_fmfree_partly(fmc, fm, 0);
return err;
}
/* Now make the file system aware of the newly written node. */
jffs_insert_node(c, f, &raw_inode, f->name, new_node);
+ jffs_fm_write_unlock(fmc);
D3(printk("jffs_rewrite_data(): Leaving...\n"));
return 0;
Index: fs/jffs/jffs_fm.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs/jffs_fm.c,v
retrieving revision 1.8
diff -u -w -r1.8 jffs_fm.c
--- fs/jffs/jffs_fm.c 2000/07/13 13:15:33 1.8
+++ fs/jffs/jffs_fm.c 2000/08/02 12:08:55
@@ -77,6 +77,7 @@
fmc->tail = 0;
fmc->head_extra = 0;
fmc->tail_extra = 0;
+ init_MUTEX(&fmc->wlock);
return fmc;
}
Index: fs/jffs/jffs_fm.h
===================================================================
RCS file: /home/cvs/mtd/fs/jffs/jffs_fm.h,v
retrieving revision 1.3
diff -u -w -r1.3 jffs_fm.h
--- fs/jffs/jffs_fm.h 2000/07/04 16:15:42 1.3
+++ fs/jffs/jffs_fm.h 2000/08/02 12:08:55
@@ -30,7 +30,9 @@
/* Mark the on-flash space as obsolete when appropriate. */
#define JFFS_MARK_OBSOLETE 0
-#define CONFIG_JFFS_FS_VERBOSE 0
+#if !defined(CONFIG_JFFS_FS) && !defined(CONFIG_JFFS_FS_MODULE)
+#define CONFIG_JFFS_FS_VERBOSE 1
+#endif
/* How many padding bytes should be inserted between two chunks of data
on the flash? */
@@ -77,6 +79,7 @@
struct jffs_fm *tail;
struct jffs_fm *head_extra;
struct jffs_fm *tail_extra;
+ struct semaphore wlock;
};
/* Notice the two members head_extra and tail_extra in the jffs_control
--
dwmw2
To unsubscribe, send "unsubscribe mtd" to majordomo at infradead.org
More information about the linux-mtd
mailing list