aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jffs2
diff options
context:
space:
mode:
authorAndrew Victor <andrew@sanpeople.com>2005-02-09 04:17:45 -0500
committerThomas Gleixner <tglx@mtd.linutronix.de>2005-05-23 06:28:03 -0400
commit8f15fd55f9bf266139b10850947e19c4e3f4e9b7 (patch)
tree3df936efbffbbd6c20dd75f51780ac37458285ff /fs/jffs2
parent3be36675d41a30ed3b192f92684f1417aa0f8bfe (diff)
[JFFS2] Add support for JFFS2-on-Dataflash devices.
For Dataflash, can_mark_obsolete = false and the NAND write buffering code (wbuf.c) is used. Since the DataFlash chip will automatically erase pages when writing, the cleanmarkers are not needed - so cleanmarker_oob = false and cleanmarker_size = 0 DataFlash page-sizes are not a power of two (they're multiples of 528 bytes). The SECTOR_ADDR macro (added in the previous core patch) is replaced with a (slower) div/mod version if CONFIG_JFFS2_FS_DATAFLASH is selected. Signed-off-by: Andrew Victor <andrew@sanpeople.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'fs/jffs2')
-rw-r--r--fs/jffs2/Makefile3
-rw-r--r--fs/jffs2/erase.c13
-rw-r--r--fs/jffs2/fs.c21
-rw-r--r--fs/jffs2/os-linux.h18
-rw-r--r--fs/jffs2/scan.c11
-rw-r--r--fs/jffs2/wbuf.c35
6 files changed, 87 insertions, 14 deletions
diff --git a/fs/jffs2/Makefile b/fs/jffs2/Makefile
index e3c38ccf9c7d..6c2ebe176b40 100644
--- a/fs/jffs2/Makefile
+++ b/fs/jffs2/Makefile
@@ -1,7 +1,7 @@
1# 1#
2# Makefile for the Linux Journalling Flash File System v2 (JFFS2) 2# Makefile for the Linux Journalling Flash File System v2 (JFFS2)
3# 3#
4# $Id: Makefile.common,v 1.7 2004/11/03 12:57:38 jwboyer Exp $ 4# $Id: Makefile.common,v 1.8 2005/02/09 09:17:40 pavlov Exp $
5# 5#
6 6
7obj-$(CONFIG_JFFS2_FS) += jffs2.o 7obj-$(CONFIG_JFFS2_FS) += jffs2.o
@@ -13,6 +13,7 @@ jffs2-y += super.o
13 13
14jffs2-$(CONFIG_JFFS2_FS_NAND) += wbuf.o 14jffs2-$(CONFIG_JFFS2_FS_NAND) += wbuf.o
15jffs2-$(CONFIG_JFFS2_FS_NOR_ECC) += wbuf.o 15jffs2-$(CONFIG_JFFS2_FS_NOR_ECC) += wbuf.o
16jffs2-$(CONFIG_JFFS2_FS_DATAFLASH) += wbuf.o
16jffs2-$(CONFIG_JFFS2_RUBIN) += compr_rubin.o 17jffs2-$(CONFIG_JFFS2_RUBIN) += compr_rubin.o
17jffs2-$(CONFIG_JFFS2_RTIME) += compr_rtime.o 18jffs2-$(CONFIG_JFFS2_RTIME) += compr_rtime.o
18jffs2-$(CONFIG_JFFS2_ZLIB) += compr_zlib.o 19jffs2-$(CONFIG_JFFS2_ZLIB) += compr_zlib.o
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
index ae858f878875..a3c6cc150497 100644
--- a/fs/jffs2/erase.c
+++ b/fs/jffs2/erase.c
@@ -7,7 +7,7 @@
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: erase.c,v 1.70 2005/02/09 09:09:01 pavlov Exp $ 10 * $Id: erase.c,v 1.71 2005/02/09 09:17:40 pavlov Exp $
11 * 11 *
12 */ 12 */
13 13
@@ -310,7 +310,7 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
310 int ret; 310 int ret;
311 uint32_t bad_offset; 311 uint32_t bad_offset;
312 312
313 if (!jffs2_cleanmarker_oob(c)) { 313 if ((!jffs2_cleanmarker_oob(c)) && (c->cleanmarker_size > 0)) {
314 marker_ref = jffs2_alloc_raw_node_ref(); 314 marker_ref = jffs2_alloc_raw_node_ref();
315 if (!marker_ref) { 315 if (!marker_ref) {
316 printk(KERN_WARNING "Failed to allocate raw node ref for clean marker\n"); 316 printk(KERN_WARNING "Failed to allocate raw node ref for clean marker\n");
@@ -351,7 +351,7 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
351 bad_offset += i; 351 bad_offset += i;
352 printk(KERN_WARNING "Newly-erased block contained word 0x%lx at offset 0x%08x\n", datum, bad_offset); 352 printk(KERN_WARNING "Newly-erased block contained word 0x%lx at offset 0x%08x\n", datum, bad_offset);
353 bad: 353 bad:
354 if (!jffs2_cleanmarker_oob(c)) 354 if ((!jffs2_cleanmarker_oob(c)) && (c->cleanmarker_size > 0))
355 jffs2_free_raw_node_ref(marker_ref); 355 jffs2_free_raw_node_ref(marker_ref);
356 kfree(ebuf); 356 kfree(ebuf);
357 bad2: 357 bad2:
@@ -387,6 +387,13 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
387 jeb->used_size = 0; 387 jeb->used_size = 0;
388 jeb->dirty_size = 0; 388 jeb->dirty_size = 0;
389 jeb->wasted_size = 0; 389 jeb->wasted_size = 0;
390 } else if (c->cleanmarker_size == 0) {
391 jeb->first_node = jeb->last_node = NULL;
392
393 jeb->free_size = c->sector_size;
394 jeb->used_size = 0;
395 jeb->dirty_size = 0;
396 jeb->wasted_size = 0;
390 } else { 397 } else {
391 struct kvec vecs[1]; 398 struct kvec vecs[1];
392 struct jffs2_unknown_node marker = { 399 struct jffs2_unknown_node marker = {
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index 30ab233fe423..5b7c960a0475 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -7,7 +7,7 @@
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: fs.c,v 1.51 2004/11/28 12:19:37 dedekind Exp $ 10 * $Id: fs.c,v 1.52 2005/02/09 09:17:40 pavlov Exp $
11 * 11 *
12 */ 12 */
13 13
@@ -456,6 +456,12 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent)
456 return -EINVAL; 456 return -EINVAL;
457 } 457 }
458#endif 458#endif
459#ifndef CONFIG_JFFS2_FS_DATAFLASH
460 if (c->mtd->type == MTD_DATAFLASH) {
461 printk(KERN_ERR "jffs2: Cannot operate on DataFlash unless jffs2 DataFlash support is compiled in.\n");
462 return -EINVAL;
463 }
464#endif
459 465
460 c->flash_size = c->mtd->size; 466 c->flash_size = c->mtd->size;
461 467
@@ -661,6 +667,14 @@ static int jffs2_flash_setup(struct jffs2_sb_info *c) {
661 if (ret) 667 if (ret)
662 return ret; 668 return ret;
663 } 669 }
670
671 /* and Dataflash */
672 if (jffs2_dataflash(c)) {
673 ret = jffs2_dataflash_setup(c);
674 if (ret)
675 return ret;
676 }
677
664 return ret; 678 return ret;
665} 679}
666 680
@@ -674,4 +688,9 @@ void jffs2_flash_cleanup(struct jffs2_sb_info *c) {
674 if (jffs2_nor_ecc(c)) { 688 if (jffs2_nor_ecc(c)) {
675 jffs2_nor_ecc_flash_cleanup(c); 689 jffs2_nor_ecc_flash_cleanup(c);
676 } 690 }
691
692 /* and DataFlash */
693 if (jffs2_dataflash(c)) {
694 jffs2_dataflash_cleanup(c);
695 }
677} 696}
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index 0412416d1f2d..af27b84007a1 100644
--- a/fs/jffs2/os-linux.h
+++ b/fs/jffs2/os-linux.h
@@ -7,7 +7,7 @@
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: os-linux.h,v 1.52 2005/02/09 09:09:01 pavlov Exp $ 10 * $Id: os-linux.h,v 1.53 2005/02/09 09:17:41 pavlov Exp $
11 * 11 *
12 */ 12 */
13 13
@@ -97,12 +97,16 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f)
97#endif 97#endif
98} 98}
99 99
100#ifdef CONFIG_JFFS2_FS_DATAFLASH
101#define SECTOR_ADDR(x) ( ((unsigned long)(x) / (unsigned long)(c->sector_size)) * c->sector_size )
102#else
100#define SECTOR_ADDR(x) ( ((unsigned long)(x) & ~(c->sector_size-1)) ) 103#define SECTOR_ADDR(x) ( ((unsigned long)(x) & ~(c->sector_size-1)) )
104#endif
101 105
102#define jffs2_is_readonly(c) (OFNI_BS_2SFFJ(c)->s_flags & MS_RDONLY) 106#define jffs2_is_readonly(c) (OFNI_BS_2SFFJ(c)->s_flags & MS_RDONLY)
103#define jffs2_is_writebuffered(c) (c->wbuf != NULL) 107#define jffs2_is_writebuffered(c) (c->wbuf != NULL)
104 108
105#if (!defined CONFIG_JFFS2_FS_NAND && !defined CONFIG_JFFS2_FS_NOR_ECC) 109#if (!defined CONFIG_JFFS2_FS_NAND && !defined CONFIG_JFFS2_FS_NOR_ECC && !defined CONFIG_JFFS2_FS_DATAFLASH)
106#define jffs2_can_mark_obsolete(c) (1) 110#define jffs2_can_mark_obsolete(c) (1)
107#define jffs2_cleanmarker_oob(c) (0) 111#define jffs2_cleanmarker_oob(c) (0)
108#define jffs2_write_nand_cleanmarker(c,jeb) (-EIO) 112#define jffs2_write_nand_cleanmarker(c,jeb) (-EIO)
@@ -119,6 +123,7 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f)
119#define jffs2_wbuf_timeout NULL 123#define jffs2_wbuf_timeout NULL
120#define jffs2_wbuf_process NULL 124#define jffs2_wbuf_process NULL
121#define jffs2_nor_ecc(c) (0) 125#define jffs2_nor_ecc(c) (0)
126#define jffs2_dataflash(c) (0)
122#define jffs2_nor_ecc_flash_setup(c) (0) 127#define jffs2_nor_ecc_flash_setup(c) (0)
123#define jffs2_nor_ecc_flash_cleanup(c) do {} while (0) 128#define jffs2_nor_ecc_flash_cleanup(c) do {} while (0)
124 129
@@ -154,6 +159,15 @@ void jffs2_nor_ecc_flash_cleanup(struct jffs2_sb_info *c);
154#define jffs2_nor_ecc_flash_setup(c) (0) 159#define jffs2_nor_ecc_flash_setup(c) (0)
155#define jffs2_nor_ecc_flash_cleanup(c) do {} while (0) 160#define jffs2_nor_ecc_flash_cleanup(c) do {} while (0)
156#endif /* NOR ECC */ 161#endif /* NOR ECC */
162#ifdef CONFIG_JFFS2_FS_DATAFLASH
163#define jffs2_dataflash(c) (c->mtd->type == MTD_DATAFLASH)
164int jffs2_dataflash_setup(struct jffs2_sb_info *c);
165void jffs2_dataflash_cleanup(struct jffs2_sb_info *c);
166#else
167#define jffs2_dataflash(c) (0)
168#define jffs2_dataflash_setup(c) (0)
169#define jffs2_dataflash_cleanup(c) do {} while (0)
170#endif /* DATAFLASH */
157#endif /* NAND */ 171#endif /* NAND */
158 172
159/* erase.c */ 173/* erase.c */
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index 76859ff53437..e8c43746c82e 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -7,7 +7,7 @@
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: scan.c,v 1.116 2005/02/09 09:09:02 pavlov Exp $ 10 * $Id: scan.c,v 1.117 2005/02/09 09:17:41 pavlov Exp $
11 * 11 *
12 */ 12 */
13#include <linux/kernel.h> 13#include <linux/kernel.h>
@@ -68,7 +68,7 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo
68static inline int min_free(struct jffs2_sb_info *c) 68static inline int min_free(struct jffs2_sb_info *c)
69{ 69{
70 uint32_t min = 2 * sizeof(struct jffs2_raw_inode); 70 uint32_t min = 2 * sizeof(struct jffs2_raw_inode);
71#if defined CONFIG_JFFS2_FS_NAND || defined CONFIG_JFFS2_FS_NOR_ECC 71#if defined CONFIG_JFFS2_FS_NAND || defined CONFIG_JFFS2_FS_NOR_ECC || defined CONFIG_JFFS2_FS_DATAFLASH
72 if (!jffs2_can_mark_obsolete(c) && min < c->wbuf_pagesize) 72 if (!jffs2_can_mark_obsolete(c) && min < c->wbuf_pagesize)
73 return c->wbuf_pagesize; 73 return c->wbuf_pagesize;
74#endif 74#endif
@@ -228,7 +228,7 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
228 c->dirty_size -= c->nextblock->dirty_size; 228 c->dirty_size -= c->nextblock->dirty_size;
229 c->nextblock->dirty_size = 0; 229 c->nextblock->dirty_size = 0;
230 } 230 }
231#if defined CONFIG_JFFS2_FS_NAND || defined CONFIG_JFFS2_FS_NOR_ECC 231#if defined CONFIG_JFFS2_FS_NAND || defined CONFIG_JFFS2_FS_NOR_ECC || defined CONFIG_JFFS2_FS_DATAFLASH
232 if (!jffs2_can_mark_obsolete(c) && c->nextblock && (c->nextblock->free_size & (c->wbuf_pagesize-1))) { 232 if (!jffs2_can_mark_obsolete(c) && c->nextblock && (c->nextblock->free_size & (c->wbuf_pagesize-1))) {
233 /* If we're going to start writing into a block which already 233 /* If we're going to start writing into a block which already
234 contains data, and the end of the data isn't page-aligned, 234 contains data, and the end of the data isn't page-aligned,
@@ -351,7 +351,10 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo
351 } 351 }
352#endif 352#endif
353 D1(printk(KERN_DEBUG "Block at 0x%08x is empty (erased)\n", jeb->offset)); 353 D1(printk(KERN_DEBUG "Block at 0x%08x is empty (erased)\n", jeb->offset));
354 return BLK_STATE_ALLFF; /* OK to erase if all blocks are like this */ 354 if (c->cleanmarker_size == 0)
355 return BLK_STATE_CLEANMARKER; /* don't bother with re-erase */
356 else
357 return BLK_STATE_ALLFF; /* OK to erase if all blocks are like this */
355 } 358 }
356 if (ofs) { 359 if (ofs) {
357 D1(printk(KERN_DEBUG "Free space at %08x ends at %08x\n", jeb->offset, 360 D1(printk(KERN_DEBUG "Free space at %08x ends at %08x\n", jeb->offset,
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
index 894dea88678d..a35e007e5bf8 100644
--- a/fs/jffs2/wbuf.c
+++ b/fs/jffs2/wbuf.c
@@ -9,7 +9,7 @@
9 * 9 *
10 * For licensing information, see the file 'LICENCE' in this directory. 10 * For licensing information, see the file 'LICENCE' in this directory.
11 * 11 *
12 * $Id: wbuf.c,v 1.87 2005/02/09 09:09:02 pavlov Exp $ 12 * $Id: wbuf.c,v 1.88 2005/02/09 09:17:41 pavlov Exp $
13 * 13 *
14 */ 14 */
15 15
@@ -435,7 +435,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
435 if we have a switch to next page, we will not have 435 if we have a switch to next page, we will not have
436 enough remaining space for this. 436 enough remaining space for this.
437 */ 437 */
438 if (pad) { 438 if (pad && !jffs2_dataflash(c)) {
439 c->wbuf_len = PAD(c->wbuf_len); 439 c->wbuf_len = PAD(c->wbuf_len);
440 440
441 /* Pad with JFFS2_DIRTY_BITMASK initially. this helps out ECC'd NOR 441 /* Pad with JFFS2_DIRTY_BITMASK initially. this helps out ECC'd NOR
@@ -486,7 +486,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
486 spin_lock(&c->erase_completion_lock); 486 spin_lock(&c->erase_completion_lock);
487 487
488 /* Adjust free size of the block if we padded. */ 488 /* Adjust free size of the block if we padded. */
489 if (pad) { 489 if (pad && !jffs2_dataflash(c)) {
490 struct jffs2_eraseblock *jeb; 490 struct jffs2_eraseblock *jeb;
491 491
492 jeb = &c->blocks[c->wbuf_ofs / c->sector_size]; 492 jeb = &c->blocks[c->wbuf_ofs / c->sector_size];
@@ -604,8 +604,14 @@ int jffs2_flush_wbuf_pad(struct jffs2_sb_info *c)
604 return ret; 604 return ret;
605} 605}
606 606
607#ifdef CONFIG_JFFS2_FS_DATAFLASH
608#define PAGE_DIV(x) ( ((unsigned long)(x) / (unsigned long)(c->wbuf_pagesize)) * (unsigned long)(c->wbuf_pagesize) )
609#define PAGE_MOD(x) ( (unsigned long)(x) % (unsigned long)(c->wbuf_pagesize) )
610#else
607#define PAGE_DIV(x) ( (x) & (~(c->wbuf_pagesize - 1)) ) 611#define PAGE_DIV(x) ( (x) & (~(c->wbuf_pagesize - 1)) )
608#define PAGE_MOD(x) ( (x) & (c->wbuf_pagesize - 1) ) 612#define PAGE_MOD(x) ( (x) & (c->wbuf_pagesize - 1) )
613#endif
614
609int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsigned long count, loff_t to, size_t *retlen, uint32_t ino) 615int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsigned long count, loff_t to, size_t *retlen, uint32_t ino)
610{ 616{
611 struct kvec outvecs[3]; 617 struct kvec outvecs[3];
@@ -1192,6 +1198,29 @@ void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c)
1192 kfree(c->wbuf); 1198 kfree(c->wbuf);
1193} 1199}
1194 1200
1201#ifdef CONFIG_JFFS2_FS_DATAFLASH
1202int jffs2_dataflash_setup(struct jffs2_sb_info *c) {
1203 c->cleanmarker_size = 0; /* No cleanmarkers needed */
1204
1205 /* Initialize write buffer */
1206 init_rwsem(&c->wbuf_sem);
1207 c->wbuf_pagesize = c->sector_size;
1208 c->wbuf_ofs = 0xFFFFFFFF;
1209
1210 c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
1211 if (!c->wbuf)
1212 return -ENOMEM;
1213
1214 printk(KERN_INFO "JFFS2 write-buffering enabled (%i)\n", c->wbuf_pagesize);
1215
1216 return 0;
1217}
1218
1219void jffs2_dataflash_cleanup(struct jffs2_sb_info *c) {
1220 kfree(c->wbuf);
1221}
1222#endif
1223
1195#ifdef CONFIG_JFFS2_FS_NOR_ECC 1224#ifdef CONFIG_JFFS2_FS_NOR_ECC
1196int jffs2_nor_ecc_flash_setup(struct jffs2_sb_info *c) { 1225int jffs2_nor_ecc_flash_setup(struct jffs2_sb_info *c) {
1197 /* Cleanmarker is actually larger on the flashes */ 1226 /* Cleanmarker is actually larger on the flashes */