[JFFS2] Core changes required to support JFFS2-on-Dataflash devices.
authorAndrew Victor <andrew@sanpeople.com>
Wed, 9 Feb 2005 09:09:05 +0000 (09:09 +0000)
committerThomas Gleixner <tglx@mtd.linutronix.de>
Mon, 23 May 2005 10:27:09 +0000 (12:27 +0200)
DataFlash page-sizes are not a power of two (they're multiples of 528
bytes).  There are a few places in JFFS2 code where sector_size is used
as a bitmask.  A new macro (SECTOR_ADDR) was defined to calculate these
sector addresses. For non-DataFlash devices, the original (faster)
bitmask operation is still used.

In scan.c, the EMPTY_SCAN_SIZE was a constant of 1024.
Since this could be larger than the sector size of the DataFlash, this
is now basically set to MIN(sector_size, 1024).

Addition of a jffs2_is_writebuffered() macro.

Signed-off-by: Andrew Victor <andrew@sanpeople.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
fs/jffs2/erase.c
fs/jffs2/gc.c
fs/jffs2/os-linux.h
fs/jffs2/scan.c
fs/jffs2/wbuf.c

index 41451e8bf36125d9bb25be772f0f4e4a79caefd4..ae858f8788751fe9dea1e5af0b2a24fbd384fdbb 100644 (file)
@@ -7,7 +7,7 @@
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
- * $Id: erase.c,v 1.66 2004/11/16 20:36:11 dwmw2 Exp $
+ * $Id: erase.c,v 1.70 2005/02/09 09:09:01 pavlov Exp $
  *
  */
 
@@ -233,7 +233,7 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c,
                        continue;
                } 
 
-               if (((*prev)->flash_offset & ~(c->sector_size -1)) == jeb->offset) {
+               if (SECTOR_ADDR((*prev)->flash_offset) == jeb->offset) {
                        /* It's in the block we're erasing */
                        struct jffs2_raw_node_ref *this;
 
index 87ec74ff5930eb0b9d591a93dbb9d8d1aab9c800..61ae001eced5ed2796f59b72a13c7bf856030508 100644 (file)
@@ -7,7 +7,7 @@
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
- * $Id: gc.c,v 1.144 2004/12/21 11:18:50 dwmw2 Exp $
+ * $Id: gc.c,v 1.145 2005/02/09 09:09:01 pavlov Exp $
  *
  */
 
@@ -816,8 +816,7 @@ static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct
 
                        /* Doesn't matter if there's one in the same erase block. We're going to 
                           delete it too at the same time. */
-                       if ((raw->flash_offset & ~(c->sector_size-1)) ==
-                           (fd->raw->flash_offset & ~(c->sector_size-1)))
+                       if (SECTOR_ADDR(raw->flash_offset) == SECTOR_ADDR(fd->raw->flash_offset))
                                continue;
 
                        D1(printk(KERN_DEBUG "Check potential deletion dirent at %08x\n", ref_offset(raw)));
index 03b0acc37b736c93f3dfbbecad7c954dafc84790..0412416d1f2d026b5183a9de43caaf4ef96b18e5 100644 (file)
@@ -7,7 +7,7 @@
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
- * $Id: os-linux.h,v 1.51 2004/11/16 20:36:11 dwmw2 Exp $
+ * $Id: os-linux.h,v 1.52 2005/02/09 09:09:01 pavlov Exp $
  *
  */
 
@@ -97,7 +97,10 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f)
 #endif
 }
 
+#define SECTOR_ADDR(x) ( ((unsigned long)(x) & ~(c->sector_size-1)) )
+
 #define jffs2_is_readonly(c) (OFNI_BS_2SFFJ(c)->s_flags & MS_RDONLY)
+#define jffs2_is_writebuffered(c) (c->wbuf != NULL)
 
 #if (!defined CONFIG_JFFS2_FS_NAND && !defined CONFIG_JFFS2_FS_NOR_ECC)
 #define jffs2_can_mark_obsolete(c) (1)
index ded53584a897dff6d0e93f3d005222288b442d6c..76859ff5343717049cb407d7f8de0ac3f9d1c466 100644 (file)
@@ -7,7 +7,7 @@
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
- * $Id: scan.c,v 1.115 2004/11/17 12:59:08 dedekind Exp $
+ * $Id: scan.c,v 1.116 2005/02/09 09:09:02 pavlov Exp $
  *
  */
 #include <linux/kernel.h>
@@ -19,7 +19,7 @@
 #include <linux/compiler.h>
 #include "nodelist.h"
 
-#define EMPTY_SCAN_SIZE 1024
+#define DEFAULT_EMPTY_SCAN_SIZE 1024
 
 #define DIRTY_SPACE(x) do { typeof(x) _x = (x); \
                c->free_size -= _x; c->dirty_size += _x; \
@@ -75,6 +75,14 @@ static inline int min_free(struct jffs2_sb_info *c)
        return min;
 
 }
+
+static inline uint32_t EMPTY_SCAN_SIZE(uint32_t sector_size) {
+       if (sector_size < DEFAULT_EMPTY_SCAN_SIZE)
+               return sector_size;
+       else
+               return DEFAULT_EMPTY_SCAN_SIZE;
+}
+
 int jffs2_scan_medium(struct jffs2_sb_info *c)
 {
        int i, ret;
@@ -316,7 +324,7 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo
        if (!buf_size) {
                buf_len = c->sector_size;
        } else {
-               buf_len = EMPTY_SCAN_SIZE;
+               buf_len = EMPTY_SCAN_SIZE(c->sector_size);
                err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len);
                if (err)
                        return err;
@@ -326,10 +334,10 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo
        ofs = 0;
 
        /* Scan only 4KiB of 0xFF before declaring it's empty */
-       while(ofs < EMPTY_SCAN_SIZE && *(uint32_t *)(&buf[ofs]) == 0xFFFFFFFF)
+       while(ofs < EMPTY_SCAN_SIZE(c->sector_size) && *(uint32_t *)(&buf[ofs]) == 0xFFFFFFFF)
                ofs += 4;
 
-       if (ofs == EMPTY_SCAN_SIZE) {
+       if (ofs == EMPTY_SCAN_SIZE(c->sector_size)) {
 #ifdef CONFIG_JFFS2_FS_NAND
                if (jffs2_cleanmarker_oob(c)) {
                        /* scan oob, take care of cleanmarker */
@@ -423,7 +431,7 @@ scan_more:
                           bail now */
                        if (buf_ofs == jeb->offset && jeb->used_size == PAD(c->cleanmarker_size) && 
                            c->cleanmarker_size && !jeb->dirty_size && !jeb->first_node->next_in_ino) {
-                               D1(printk(KERN_DEBUG "%d bytes at start of block seems clean... assuming all clean\n", EMPTY_SCAN_SIZE));
+                               D1(printk(KERN_DEBUG "%d bytes at start of block seems clean... assuming all clean\n", EMPTY_SCAN_SIZE(c->sector_size)));
                                return BLK_STATE_CLEANMARKER;
                        }
 
index 79414abadd5e8b505536e86dc2faf169eb5cd8ea..894dea88678dd8a9406c29a8c5a5950c2b079d81 100644 (file)
@@ -9,7 +9,7 @@
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
- * $Id: wbuf.c,v 1.86 2005/02/05 18:23:37 hammache Exp $
+ * $Id: wbuf.c,v 1.87 2005/02/09 09:09:02 pavlov Exp $
  *
  */
 
@@ -415,9 +415,9 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
        int ret;
        size_t retlen;
 
-       /* Nothing to do if not NAND flash. In particular, we shouldn't
+       /* Nothing to do if not write-buffering the flash. In particular, we shouldn't
           del_timer() the timer we never initialised. */
-       if (jffs2_can_mark_obsolete(c))
+       if (!jffs2_is_writebuffered(c))
                return 0;
 
        if (!down_trylock(&c->alloc_sem)) {
@@ -426,7 +426,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
                BUG();
        }
 
-       if(!c->wbuf || !c->wbuf_len)
+       if (!c->wbuf_len)       /* already checked c->wbuf above */
                return 0;
 
        /* claim remaining space on the page
@@ -620,7 +620,7 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig
        uint32_t outvec_to = to;
 
        /* If not NAND flash, don't bother */
-       if (!c->wbuf)
+       if (!jffs2_is_writebuffered(c))
                return jffs2_flash_direct_writev(c, invecs, count, to, retlen);
        
        down_write(&c->wbuf_sem);
@@ -649,7 +649,7 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig
           erase block. Anything else, and you die.
           New block starts at xxx000c (0-b = block header)
        */
-       if ( (to & ~(c->sector_size-1)) != (c->wbuf_ofs & ~(c->sector_size-1)) ) {
+       if (SECTOR_ADDR(to) != SECTOR_ADDR(c->wbuf_ofs)) {
                /* It's a write to a new block */
                if (c->wbuf_len) {
                        D1(printk(KERN_DEBUG "jffs2_flash_writev() to 0x%lx causes flush of wbuf at 0x%08x\n", (unsigned long)to, c->wbuf_ofs));
@@ -847,7 +847,7 @@ int jffs2_flash_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *r
 {
        struct kvec vecs[1];
 
-       if (jffs2_can_mark_obsolete(c))
+       if (!jffs2_is_writebuffered(c))
                return c->mtd->write(c->mtd, ofs, len, retlen, buf);
 
        vecs[0].iov_base = (unsigned char *) buf;
@@ -863,38 +863,37 @@ int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *re
        loff_t  orbf = 0, owbf = 0, lwbf = 0;
        int     ret;
 
-       /* Read flash */
-       if (!jffs2_can_mark_obsolete(c)) {
-
-               if (jffs2_cleanmarker_oob(c))
-                       ret = c->mtd->read_ecc(c->mtd, ofs, len, retlen, buf, NULL, c->oobinfo);
-               else
-                       ret = c->mtd->read(c->mtd, ofs, len, retlen, buf);
-
-               if ( (ret == -EBADMSG) && (*retlen == len) ) {
-                       printk(KERN_WARNING "mtd->read(0x%zx bytes from 0x%llx) returned ECC error\n",
-                              len, ofs);
-                       /* 
-                        * We have the raw data without ECC correction in the buffer, maybe 
-                        * we are lucky and all data or parts are correct. We check the node.
-                        * If data are corrupted node check will sort it out.
-                        * We keep this block, it will fail on write or erase and the we
-                        * mark it bad. Or should we do that now? But we should give him a chance.
-                        * Maybe we had a system crash or power loss before the ecc write or  
-                        * a erase was completed.
-                        * So we return success. :)
-                        */
-                       ret = 0;
-                }      
-       } else
+       if (!jffs2_is_writebuffered(c))
                return c->mtd->read(c->mtd, ofs, len, retlen, buf);
 
+       /* Read flash */
+       if (jffs2_cleanmarker_oob(c))
+               ret = c->mtd->read_ecc(c->mtd, ofs, len, retlen, buf, NULL, c->oobinfo);
+       else
+               ret = c->mtd->read(c->mtd, ofs, len, retlen, buf);
+
+       if ( (ret == -EBADMSG) && (*retlen == len) ) {
+               printk(KERN_WARNING "mtd->read(0x%zx bytes from 0x%llx) returned ECC error\n",
+                      len, ofs);
+               /* 
+                * We have the raw data without ECC correction in the buffer, maybe 
+                * we are lucky and all data or parts are correct. We check the node.
+                * If data are corrupted node check will sort it out.
+                * We keep this block, it will fail on write or erase and the we
+                * mark it bad. Or should we do that now? But we should give him a chance.
+                * Maybe we had a system crash or power loss before the ecc write or  
+                * a erase was completed.
+                * So we return success. :)
+                */
+               ret = 0;
+       }       
+
        /* if no writebuffer available or write buffer empty, return */
        if (!c->wbuf_pagesize || !c->wbuf_len)
                return ret;;
 
        /* if we read in a different block, return */
-       if ( (ofs & ~(c->sector_size-1)) != (c->wbuf_ofs & ~(c->sector_size-1)) ) 
+       if (SECTOR_ADDR(ofs) != SECTOR_ADDR(c->wbuf_ofs))
                return ret;
 
        /* Lock only if we have reason to believe wbuf contains relevant data,