diff options
Diffstat (limited to 'fs/jffs2/wbuf.c')
-rw-r--r-- | fs/jffs2/wbuf.c | 215 |
1 files changed, 127 insertions, 88 deletions
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 316133c626b7..4cebf0e57c46 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.92 2005/04/05 12:51:54 dedekind Exp $ | 12 | * $Id: wbuf.c,v 1.100 2005/09/30 13:59:13 dedekind Exp $ |
13 | * | 13 | * |
14 | */ | 14 | */ |
15 | 15 | ||
@@ -30,12 +30,12 @@ | |||
30 | static unsigned char *brokenbuf; | 30 | static unsigned char *brokenbuf; |
31 | #endif | 31 | #endif |
32 | 32 | ||
33 | #define PAGE_DIV(x) ( ((unsigned long)(x) / (unsigned long)(c->wbuf_pagesize)) * (unsigned long)(c->wbuf_pagesize) ) | ||
34 | #define PAGE_MOD(x) ( (unsigned long)(x) % (unsigned long)(c->wbuf_pagesize) ) | ||
35 | |||
33 | /* max. erase failures before we mark a block bad */ | 36 | /* max. erase failures before we mark a block bad */ |
34 | #define MAX_ERASE_FAILURES 2 | 37 | #define MAX_ERASE_FAILURES 2 |
35 | 38 | ||
36 | /* two seconds timeout for timed wbuf-flushing */ | ||
37 | #define WBUF_FLUSH_TIMEOUT 2 * HZ | ||
38 | |||
39 | struct jffs2_inodirty { | 39 | struct jffs2_inodirty { |
40 | uint32_t ino; | 40 | uint32_t ino; |
41 | struct jffs2_inodirty *next; | 41 | struct jffs2_inodirty *next; |
@@ -139,7 +139,6 @@ static void jffs2_block_refile(struct jffs2_sb_info *c, struct jffs2_eraseblock | |||
139 | { | 139 | { |
140 | D1(printk("About to refile bad block at %08x\n", jeb->offset)); | 140 | D1(printk("About to refile bad block at %08x\n", jeb->offset)); |
141 | 141 | ||
142 | D2(jffs2_dump_block_lists(c)); | ||
143 | /* File the existing block on the bad_used_list.... */ | 142 | /* File the existing block on the bad_used_list.... */ |
144 | if (c->nextblock == jeb) | 143 | if (c->nextblock == jeb) |
145 | c->nextblock = NULL; | 144 | c->nextblock = NULL; |
@@ -156,7 +155,6 @@ static void jffs2_block_refile(struct jffs2_sb_info *c, struct jffs2_eraseblock | |||
156 | c->nr_erasing_blocks++; | 155 | c->nr_erasing_blocks++; |
157 | jffs2_erase_pending_trigger(c); | 156 | jffs2_erase_pending_trigger(c); |
158 | } | 157 | } |
159 | D2(jffs2_dump_block_lists(c)); | ||
160 | 158 | ||
161 | /* Adjust its size counts accordingly */ | 159 | /* Adjust its size counts accordingly */ |
162 | c->wasted_size += jeb->free_size; | 160 | c->wasted_size += jeb->free_size; |
@@ -164,8 +162,9 @@ static void jffs2_block_refile(struct jffs2_sb_info *c, struct jffs2_eraseblock | |||
164 | jeb->wasted_size += jeb->free_size; | 162 | jeb->wasted_size += jeb->free_size; |
165 | jeb->free_size = 0; | 163 | jeb->free_size = 0; |
166 | 164 | ||
167 | ACCT_SANITY_CHECK(c,jeb); | 165 | jffs2_dbg_dump_block_lists_nolock(c); |
168 | D1(ACCT_PARANOIA_CHECK(jeb)); | 166 | jffs2_dbg_acct_sanity_check_nolock(c,jeb); |
167 | jffs2_dbg_acct_paranoia_check_nolock(c, jeb); | ||
169 | } | 168 | } |
170 | 169 | ||
171 | /* Recover from failure to write wbuf. Recover the nodes up to the | 170 | /* Recover from failure to write wbuf. Recover the nodes up to the |
@@ -189,7 +188,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) | |||
189 | /* Find the first node to be recovered, by skipping over every | 188 | /* Find the first node to be recovered, by skipping over every |
190 | node which ends before the wbuf starts, or which is obsolete. */ | 189 | node which ends before the wbuf starts, or which is obsolete. */ |
191 | first_raw = &jeb->first_node; | 190 | first_raw = &jeb->first_node; |
192 | while (*first_raw && | 191 | while (*first_raw && |
193 | (ref_obsolete(*first_raw) || | 192 | (ref_obsolete(*first_raw) || |
194 | (ref_offset(*first_raw)+ref_totlen(c, jeb, *first_raw)) < c->wbuf_ofs)) { | 193 | (ref_offset(*first_raw)+ref_totlen(c, jeb, *first_raw)) < c->wbuf_ofs)) { |
195 | D1(printk(KERN_DEBUG "Skipping node at 0x%08x(%d)-0x%08x which is either before 0x%08x or obsolete\n", | 194 | D1(printk(KERN_DEBUG "Skipping node at 0x%08x(%d)-0x%08x which is either before 0x%08x or obsolete\n", |
@@ -238,7 +237,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) | |||
238 | ret = c->mtd->read_ecc(c->mtd, start, c->wbuf_ofs - start, &retlen, buf, NULL, c->oobinfo); | 237 | ret = c->mtd->read_ecc(c->mtd, start, c->wbuf_ofs - start, &retlen, buf, NULL, c->oobinfo); |
239 | else | 238 | else |
240 | ret = c->mtd->read(c->mtd, start, c->wbuf_ofs - start, &retlen, buf); | 239 | ret = c->mtd->read(c->mtd, start, c->wbuf_ofs - start, &retlen, buf); |
241 | 240 | ||
242 | if (ret == -EBADMSG && retlen == c->wbuf_ofs - start) { | 241 | if (ret == -EBADMSG && retlen == c->wbuf_ofs - start) { |
243 | /* ECC recovered */ | 242 | /* ECC recovered */ |
244 | ret = 0; | 243 | ret = 0; |
@@ -266,7 +265,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) | |||
266 | 265 | ||
267 | 266 | ||
268 | /* ... and get an allocation of space from a shiny new block instead */ | 267 | /* ... and get an allocation of space from a shiny new block instead */ |
269 | ret = jffs2_reserve_space_gc(c, end-start, &ofs, &len); | 268 | ret = jffs2_reserve_space_gc(c, end-start, &ofs, &len, JFFS2_SUMMARY_NOSUM_SIZE); |
270 | if (ret) { | 269 | if (ret) { |
271 | printk(KERN_WARNING "Failed to allocate space for wbuf recovery. Data loss ensues.\n"); | 270 | printk(KERN_WARNING "Failed to allocate space for wbuf recovery. Data loss ensues.\n"); |
272 | kfree(buf); | 271 | kfree(buf); |
@@ -275,15 +274,15 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) | |||
275 | if (end-start >= c->wbuf_pagesize) { | 274 | if (end-start >= c->wbuf_pagesize) { |
276 | /* Need to do another write immediately, but it's possible | 275 | /* Need to do another write immediately, but it's possible |
277 | that this is just because the wbuf itself is completely | 276 | that this is just because the wbuf itself is completely |
278 | full, and there's nothing earlier read back from the | 277 | full, and there's nothing earlier read back from the |
279 | flash. Hence 'buf' isn't necessarily what we're writing | 278 | flash. Hence 'buf' isn't necessarily what we're writing |
280 | from. */ | 279 | from. */ |
281 | unsigned char *rewrite_buf = buf?:c->wbuf; | 280 | unsigned char *rewrite_buf = buf?:c->wbuf; |
282 | uint32_t towrite = (end-start) - ((end-start)%c->wbuf_pagesize); | 281 | uint32_t towrite = (end-start) - ((end-start)%c->wbuf_pagesize); |
283 | 282 | ||
284 | D1(printk(KERN_DEBUG "Write 0x%x bytes at 0x%08x in wbuf recover\n", | 283 | D1(printk(KERN_DEBUG "Write 0x%x bytes at 0x%08x in wbuf recover\n", |
285 | towrite, ofs)); | 284 | towrite, ofs)); |
286 | 285 | ||
287 | #ifdef BREAKMEHEADER | 286 | #ifdef BREAKMEHEADER |
288 | static int breakme; | 287 | static int breakme; |
289 | if (breakme++ == 20) { | 288 | if (breakme++ == 20) { |
@@ -327,8 +326,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) | |||
327 | c->wbuf_ofs = ofs + towrite; | 326 | c->wbuf_ofs = ofs + towrite; |
328 | memmove(c->wbuf, rewrite_buf + towrite, c->wbuf_len); | 327 | memmove(c->wbuf, rewrite_buf + towrite, c->wbuf_len); |
329 | /* Don't muck about with c->wbuf_inodes. False positives are harmless. */ | 328 | /* Don't muck about with c->wbuf_inodes. False positives are harmless. */ |
330 | if (buf) | 329 | kfree(buf); |
331 | kfree(buf); | ||
332 | } else { | 330 | } else { |
333 | /* OK, now we're left with the dregs in whichever buffer we're using */ | 331 | /* OK, now we're left with the dregs in whichever buffer we're using */ |
334 | if (buf) { | 332 | if (buf) { |
@@ -392,11 +390,11 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) | |||
392 | else | 390 | else |
393 | jeb->last_node = container_of(first_raw, struct jffs2_raw_node_ref, next_phys); | 391 | jeb->last_node = container_of(first_raw, struct jffs2_raw_node_ref, next_phys); |
394 | 392 | ||
395 | ACCT_SANITY_CHECK(c,jeb); | 393 | jffs2_dbg_acct_sanity_check_nolock(c, jeb); |
396 | D1(ACCT_PARANOIA_CHECK(jeb)); | 394 | jffs2_dbg_acct_paranoia_check_nolock(c, jeb); |
397 | 395 | ||
398 | ACCT_SANITY_CHECK(c,new_jeb); | 396 | jffs2_dbg_acct_sanity_check_nolock(c, new_jeb); |
399 | D1(ACCT_PARANOIA_CHECK(new_jeb)); | 397 | jffs2_dbg_acct_paranoia_check_nolock(c, new_jeb); |
400 | 398 | ||
401 | spin_unlock(&c->erase_completion_lock); | 399 | spin_unlock(&c->erase_completion_lock); |
402 | 400 | ||
@@ -435,15 +433,15 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) | |||
435 | this happens, if we have a change to a new block, | 433 | this happens, if we have a change to a new block, |
436 | or if fsync forces us to flush the writebuffer. | 434 | or if fsync forces us to flush the writebuffer. |
437 | 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 |
438 | enough remaining space for this. | 436 | enough remaining space for this. |
439 | */ | 437 | */ |
440 | if (pad && !jffs2_dataflash(c)) { | 438 | if (pad ) { |
441 | c->wbuf_len = PAD(c->wbuf_len); | 439 | c->wbuf_len = PAD(c->wbuf_len); |
442 | 440 | ||
443 | /* 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 |
444 | with 8 byte page size */ | 442 | with 8 byte page size */ |
445 | memset(c->wbuf + c->wbuf_len, 0, c->wbuf_pagesize - c->wbuf_len); | 443 | memset(c->wbuf + c->wbuf_len, 0, c->wbuf_pagesize - c->wbuf_len); |
446 | 444 | ||
447 | if ( c->wbuf_len + sizeof(struct jffs2_unknown_node) < c->wbuf_pagesize) { | 445 | if ( c->wbuf_len + sizeof(struct jffs2_unknown_node) < c->wbuf_pagesize) { |
448 | struct jffs2_unknown_node *padnode = (void *)(c->wbuf + c->wbuf_len); | 446 | struct jffs2_unknown_node *padnode = (void *)(c->wbuf + c->wbuf_len); |
449 | padnode->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); | 447 | padnode->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); |
@@ -454,7 +452,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) | |||
454 | } | 452 | } |
455 | /* else jffs2_flash_writev has actually filled in the rest of the | 453 | /* else jffs2_flash_writev has actually filled in the rest of the |
456 | buffer for us, and will deal with the node refs etc. later. */ | 454 | buffer for us, and will deal with the node refs etc. later. */ |
457 | 455 | ||
458 | #ifdef BREAKME | 456 | #ifdef BREAKME |
459 | static int breakme; | 457 | static int breakme; |
460 | if (breakme++ == 20) { | 458 | if (breakme++ == 20) { |
@@ -463,9 +461,9 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) | |||
463 | c->mtd->write_ecc(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, | 461 | c->mtd->write_ecc(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, |
464 | &retlen, brokenbuf, NULL, c->oobinfo); | 462 | &retlen, brokenbuf, NULL, c->oobinfo); |
465 | ret = -EIO; | 463 | ret = -EIO; |
466 | } else | 464 | } else |
467 | #endif | 465 | #endif |
468 | 466 | ||
469 | if (jffs2_cleanmarker_oob(c)) | 467 | if (jffs2_cleanmarker_oob(c)) |
470 | ret = c->mtd->write_ecc(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf, NULL, c->oobinfo); | 468 | ret = c->mtd->write_ecc(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf, NULL, c->oobinfo); |
471 | else | 469 | else |
@@ -488,7 +486,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) | |||
488 | spin_lock(&c->erase_completion_lock); | 486 | spin_lock(&c->erase_completion_lock); |
489 | 487 | ||
490 | /* Adjust free size of the block if we padded. */ | 488 | /* Adjust free size of the block if we padded. */ |
491 | if (pad && !jffs2_dataflash(c)) { | 489 | if (pad) { |
492 | struct jffs2_eraseblock *jeb; | 490 | struct jffs2_eraseblock *jeb; |
493 | 491 | ||
494 | jeb = &c->blocks[c->wbuf_ofs / c->sector_size]; | 492 | jeb = &c->blocks[c->wbuf_ofs / c->sector_size]; |
@@ -496,7 +494,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) | |||
496 | D1(printk(KERN_DEBUG "jffs2_flush_wbuf() adjusting free_size of %sblock at %08x\n", | 494 | D1(printk(KERN_DEBUG "jffs2_flush_wbuf() adjusting free_size of %sblock at %08x\n", |
497 | (jeb==c->nextblock)?"next":"", jeb->offset)); | 495 | (jeb==c->nextblock)?"next":"", jeb->offset)); |
498 | 496 | ||
499 | /* wbuf_pagesize - wbuf_len is the amount of space that's to be | 497 | /* wbuf_pagesize - wbuf_len is the amount of space that's to be |
500 | padded. If there is less free space in the block than that, | 498 | padded. If there is less free space in the block than that, |
501 | something screwed up */ | 499 | something screwed up */ |
502 | if (jeb->free_size < (c->wbuf_pagesize - c->wbuf_len)) { | 500 | if (jeb->free_size < (c->wbuf_pagesize - c->wbuf_len)) { |
@@ -524,9 +522,9 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) | |||
524 | return 0; | 522 | return 0; |
525 | } | 523 | } |
526 | 524 | ||
527 | /* Trigger garbage collection to flush the write-buffer. | 525 | /* Trigger garbage collection to flush the write-buffer. |
528 | If ino arg is zero, do it if _any_ real (i.e. not GC) writes are | 526 | If ino arg is zero, do it if _any_ real (i.e. not GC) writes are |
529 | outstanding. If ino arg non-zero, do it only if a write for the | 527 | outstanding. If ino arg non-zero, do it only if a write for the |
530 | given inode is outstanding. */ | 528 | given inode is outstanding. */ |
531 | int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino) | 529 | int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino) |
532 | { | 530 | { |
@@ -605,15 +603,6 @@ int jffs2_flush_wbuf_pad(struct jffs2_sb_info *c) | |||
605 | 603 | ||
606 | return ret; | 604 | return ret; |
607 | } | 605 | } |
608 | |||
609 | #ifdef CONFIG_JFFS2_FS_WRITEBUFFER | ||
610 | #define PAGE_DIV(x) ( ((unsigned long)(x) / (unsigned long)(c->wbuf_pagesize)) * (unsigned long)(c->wbuf_pagesize) ) | ||
611 | #define PAGE_MOD(x) ( (unsigned long)(x) % (unsigned long)(c->wbuf_pagesize) ) | ||
612 | #else | ||
613 | #define PAGE_DIV(x) ( (x) & (~(c->wbuf_pagesize - 1)) ) | ||
614 | #define PAGE_MOD(x) ( (x) & (c->wbuf_pagesize - 1) ) | ||
615 | #endif | ||
616 | |||
617 | int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsigned long count, loff_t to, size_t *retlen, uint32_t ino) | 606 | int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsigned long count, loff_t to, size_t *retlen, uint32_t ino) |
618 | { | 607 | { |
619 | struct kvec outvecs[3]; | 608 | struct kvec outvecs[3]; |
@@ -630,13 +619,13 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig | |||
630 | /* If not NAND flash, don't bother */ | 619 | /* If not NAND flash, don't bother */ |
631 | if (!jffs2_is_writebuffered(c)) | 620 | if (!jffs2_is_writebuffered(c)) |
632 | return jffs2_flash_direct_writev(c, invecs, count, to, retlen); | 621 | return jffs2_flash_direct_writev(c, invecs, count, to, retlen); |
633 | 622 | ||
634 | down_write(&c->wbuf_sem); | 623 | down_write(&c->wbuf_sem); |
635 | 624 | ||
636 | /* If wbuf_ofs is not initialized, set it to target address */ | 625 | /* If wbuf_ofs is not initialized, set it to target address */ |
637 | if (c->wbuf_ofs == 0xFFFFFFFF) { | 626 | if (c->wbuf_ofs == 0xFFFFFFFF) { |
638 | c->wbuf_ofs = PAGE_DIV(to); | 627 | c->wbuf_ofs = PAGE_DIV(to); |
639 | c->wbuf_len = PAGE_MOD(to); | 628 | c->wbuf_len = PAGE_MOD(to); |
640 | memset(c->wbuf,0xff,c->wbuf_pagesize); | 629 | memset(c->wbuf,0xff,c->wbuf_pagesize); |
641 | } | 630 | } |
642 | 631 | ||
@@ -650,10 +639,10 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig | |||
650 | memset(c->wbuf,0xff,c->wbuf_pagesize); | 639 | memset(c->wbuf,0xff,c->wbuf_pagesize); |
651 | } | 640 | } |
652 | } | 641 | } |
653 | 642 | ||
654 | /* Sanity checks on target address. | 643 | /* Sanity checks on target address. |
655 | It's permitted to write at PAD(c->wbuf_len+c->wbuf_ofs), | 644 | It's permitted to write at PAD(c->wbuf_len+c->wbuf_ofs), |
656 | and it's permitted to write at the beginning of a new | 645 | and it's permitted to write at the beginning of a new |
657 | erase block. Anything else, and you die. | 646 | erase block. Anything else, and you die. |
658 | New block starts at xxx000c (0-b = block header) | 647 | New block starts at xxx000c (0-b = block header) |
659 | */ | 648 | */ |
@@ -671,8 +660,8 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig | |||
671 | } | 660 | } |
672 | /* set pointer to new block */ | 661 | /* set pointer to new block */ |
673 | c->wbuf_ofs = PAGE_DIV(to); | 662 | c->wbuf_ofs = PAGE_DIV(to); |
674 | c->wbuf_len = PAGE_MOD(to); | 663 | c->wbuf_len = PAGE_MOD(to); |
675 | } | 664 | } |
676 | 665 | ||
677 | if (to != PAD(c->wbuf_ofs + c->wbuf_len)) { | 666 | if (to != PAD(c->wbuf_ofs + c->wbuf_len)) { |
678 | /* We're not writing immediately after the writebuffer. Bad. */ | 667 | /* We're not writing immediately after the writebuffer. Bad. */ |
@@ -692,21 +681,21 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig | |||
692 | invec = 0; | 681 | invec = 0; |
693 | outvec = 0; | 682 | outvec = 0; |
694 | 683 | ||
695 | /* Fill writebuffer first, if already in use */ | 684 | /* Fill writebuffer first, if already in use */ |
696 | if (c->wbuf_len) { | 685 | if (c->wbuf_len) { |
697 | uint32_t invec_ofs = 0; | 686 | uint32_t invec_ofs = 0; |
698 | 687 | ||
699 | /* adjust alignment offset */ | 688 | /* adjust alignment offset */ |
700 | if (c->wbuf_len != PAGE_MOD(to)) { | 689 | if (c->wbuf_len != PAGE_MOD(to)) { |
701 | c->wbuf_len = PAGE_MOD(to); | 690 | c->wbuf_len = PAGE_MOD(to); |
702 | /* take care of alignment to next page */ | 691 | /* take care of alignment to next page */ |
703 | if (!c->wbuf_len) | 692 | if (!c->wbuf_len) |
704 | c->wbuf_len = c->wbuf_pagesize; | 693 | c->wbuf_len = c->wbuf_pagesize; |
705 | } | 694 | } |
706 | 695 | ||
707 | while(c->wbuf_len < c->wbuf_pagesize) { | 696 | while(c->wbuf_len < c->wbuf_pagesize) { |
708 | uint32_t thislen; | 697 | uint32_t thislen; |
709 | 698 | ||
710 | if (invec == count) | 699 | if (invec == count) |
711 | goto alldone; | 700 | goto alldone; |
712 | 701 | ||
@@ -714,17 +703,17 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig | |||
714 | 703 | ||
715 | if (thislen >= invecs[invec].iov_len) | 704 | if (thislen >= invecs[invec].iov_len) |
716 | thislen = invecs[invec].iov_len; | 705 | thislen = invecs[invec].iov_len; |
717 | 706 | ||
718 | invec_ofs = thislen; | 707 | invec_ofs = thislen; |
719 | 708 | ||
720 | memcpy(c->wbuf + c->wbuf_len, invecs[invec].iov_base, thislen); | 709 | memcpy(c->wbuf + c->wbuf_len, invecs[invec].iov_base, thislen); |
721 | c->wbuf_len += thislen; | 710 | c->wbuf_len += thislen; |
722 | donelen += thislen; | 711 | donelen += thislen; |
723 | /* Get next invec, if actual did not fill the buffer */ | 712 | /* Get next invec, if actual did not fill the buffer */ |
724 | if (c->wbuf_len < c->wbuf_pagesize) | 713 | if (c->wbuf_len < c->wbuf_pagesize) |
725 | invec++; | 714 | invec++; |
726 | } | 715 | } |
727 | 716 | ||
728 | /* write buffer is full, flush buffer */ | 717 | /* write buffer is full, flush buffer */ |
729 | ret = __jffs2_flush_wbuf(c, NOPAD); | 718 | ret = __jffs2_flush_wbuf(c, NOPAD); |
730 | if (ret) { | 719 | if (ret) { |
@@ -783,10 +772,10 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig | |||
783 | 772 | ||
784 | /* We did cross a page boundary, so we write some now */ | 773 | /* We did cross a page boundary, so we write some now */ |
785 | if (jffs2_cleanmarker_oob(c)) | 774 | if (jffs2_cleanmarker_oob(c)) |
786 | ret = c->mtd->writev_ecc(c->mtd, outvecs, splitvec+1, outvec_to, &wbuf_retlen, NULL, c->oobinfo); | 775 | ret = c->mtd->writev_ecc(c->mtd, outvecs, splitvec+1, outvec_to, &wbuf_retlen, NULL, c->oobinfo); |
787 | else | 776 | else |
788 | ret = jffs2_flash_direct_writev(c, outvecs, splitvec+1, outvec_to, &wbuf_retlen); | 777 | ret = jffs2_flash_direct_writev(c, outvecs, splitvec+1, outvec_to, &wbuf_retlen); |
789 | 778 | ||
790 | if (ret < 0 || wbuf_retlen != PAGE_DIV(totlen)) { | 779 | if (ret < 0 || wbuf_retlen != PAGE_DIV(totlen)) { |
791 | /* At this point we have no problem, | 780 | /* At this point we have no problem, |
792 | c->wbuf is empty. However refile nextblock to avoid | 781 | c->wbuf is empty. However refile nextblock to avoid |
@@ -803,7 +792,7 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig | |||
803 | spin_unlock(&c->erase_completion_lock); | 792 | spin_unlock(&c->erase_completion_lock); |
804 | goto exit; | 793 | goto exit; |
805 | } | 794 | } |
806 | 795 | ||
807 | donelen += wbuf_retlen; | 796 | donelen += wbuf_retlen; |
808 | c->wbuf_ofs = PAGE_DIV(outvec_to) + PAGE_DIV(totlen); | 797 | c->wbuf_ofs = PAGE_DIV(outvec_to) + PAGE_DIV(totlen); |
809 | 798 | ||
@@ -837,11 +826,17 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig | |||
837 | alldone: | 826 | alldone: |
838 | *retlen = donelen; | 827 | *retlen = donelen; |
839 | 828 | ||
829 | if (jffs2_sum_active()) { | ||
830 | int res = jffs2_sum_add_kvec(c, invecs, count, (uint32_t) to); | ||
831 | if (res) | ||
832 | return res; | ||
833 | } | ||
834 | |||
840 | if (c->wbuf_len && ino) | 835 | if (c->wbuf_len && ino) |
841 | jffs2_wbuf_dirties_inode(c, ino); | 836 | jffs2_wbuf_dirties_inode(c, ino); |
842 | 837 | ||
843 | ret = 0; | 838 | ret = 0; |
844 | 839 | ||
845 | exit: | 840 | exit: |
846 | up_write(&c->wbuf_sem); | 841 | up_write(&c->wbuf_sem); |
847 | return ret; | 842 | return ret; |
@@ -856,7 +851,7 @@ int jffs2_flash_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *r | |||
856 | struct kvec vecs[1]; | 851 | struct kvec vecs[1]; |
857 | 852 | ||
858 | if (!jffs2_is_writebuffered(c)) | 853 | if (!jffs2_is_writebuffered(c)) |
859 | return c->mtd->write(c->mtd, ofs, len, retlen, buf); | 854 | return jffs2_flash_direct_write(c, ofs, len, retlen, buf); |
860 | 855 | ||
861 | vecs[0].iov_base = (unsigned char *) buf; | 856 | vecs[0].iov_base = (unsigned char *) buf; |
862 | vecs[0].iov_len = len; | 857 | vecs[0].iov_len = len; |
@@ -884,18 +879,18 @@ int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *re | |||
884 | if ( (ret == -EBADMSG) && (*retlen == len) ) { | 879 | if ( (ret == -EBADMSG) && (*retlen == len) ) { |
885 | printk(KERN_WARNING "mtd->read(0x%zx bytes from 0x%llx) returned ECC error\n", | 880 | printk(KERN_WARNING "mtd->read(0x%zx bytes from 0x%llx) returned ECC error\n", |
886 | len, ofs); | 881 | len, ofs); |
887 | /* | 882 | /* |
888 | * We have the raw data without ECC correction in the buffer, maybe | 883 | * We have the raw data without ECC correction in the buffer, maybe |
889 | * we are lucky and all data or parts are correct. We check the node. | 884 | * we are lucky and all data or parts are correct. We check the node. |
890 | * If data are corrupted node check will sort it out. | 885 | * If data are corrupted node check will sort it out. |
891 | * We keep this block, it will fail on write or erase and the we | 886 | * We keep this block, it will fail on write or erase and the we |
892 | * mark it bad. Or should we do that now? But we should give him a chance. | 887 | * mark it bad. Or should we do that now? But we should give him a chance. |
893 | * Maybe we had a system crash or power loss before the ecc write or | 888 | * Maybe we had a system crash or power loss before the ecc write or |
894 | * a erase was completed. | 889 | * a erase was completed. |
895 | * So we return success. :) | 890 | * So we return success. :) |
896 | */ | 891 | */ |
897 | ret = 0; | 892 | ret = 0; |
898 | } | 893 | } |
899 | 894 | ||
900 | /* if no writebuffer available or write buffer empty, return */ | 895 | /* if no writebuffer available or write buffer empty, return */ |
901 | if (!c->wbuf_pagesize || !c->wbuf_len) | 896 | if (!c->wbuf_pagesize || !c->wbuf_len) |
@@ -910,16 +905,16 @@ int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *re | |||
910 | if (owbf > c->wbuf_len) /* is read beyond write buffer ? */ | 905 | if (owbf > c->wbuf_len) /* is read beyond write buffer ? */ |
911 | goto exit; | 906 | goto exit; |
912 | lwbf = c->wbuf_len - owbf; /* number of bytes to copy */ | 907 | lwbf = c->wbuf_len - owbf; /* number of bytes to copy */ |
913 | if (lwbf > len) | 908 | if (lwbf > len) |
914 | lwbf = len; | 909 | lwbf = len; |
915 | } else { | 910 | } else { |
916 | orbf = (c->wbuf_ofs - ofs); /* offset in read buffer */ | 911 | orbf = (c->wbuf_ofs - ofs); /* offset in read buffer */ |
917 | if (orbf > len) /* is write beyond write buffer ? */ | 912 | if (orbf > len) /* is write beyond write buffer ? */ |
918 | goto exit; | 913 | goto exit; |
919 | lwbf = len - orbf; /* number of bytes to copy */ | 914 | lwbf = len - orbf; /* number of bytes to copy */ |
920 | if (lwbf > c->wbuf_len) | 915 | if (lwbf > c->wbuf_len) |
921 | lwbf = c->wbuf_len; | 916 | lwbf = c->wbuf_len; |
922 | } | 917 | } |
923 | if (lwbf > 0) | 918 | if (lwbf > 0) |
924 | memcpy(buf+orbf,c->wbuf+owbf,lwbf); | 919 | memcpy(buf+orbf,c->wbuf+owbf,lwbf); |
925 | 920 | ||
@@ -947,7 +942,7 @@ int jffs2_check_oob_empty( struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb | |||
947 | printk(KERN_NOTICE "jffs2_check_oob_empty(): allocation of temporary data buffer for oob check failed\n"); | 942 | printk(KERN_NOTICE "jffs2_check_oob_empty(): allocation of temporary data buffer for oob check failed\n"); |
948 | return -ENOMEM; | 943 | return -ENOMEM; |
949 | } | 944 | } |
950 | /* | 945 | /* |
951 | * if mode = 0, we scan for a total empty oob area, else we have | 946 | * if mode = 0, we scan for a total empty oob area, else we have |
952 | * to take care of the cleanmarker in the first page of the block | 947 | * to take care of the cleanmarker in the first page of the block |
953 | */ | 948 | */ |
@@ -956,41 +951,41 @@ int jffs2_check_oob_empty( struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb | |||
956 | D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB failed %d for block at %08x\n", ret, jeb->offset)); | 951 | D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB failed %d for block at %08x\n", ret, jeb->offset)); |
957 | goto out; | 952 | goto out; |
958 | } | 953 | } |
959 | 954 | ||
960 | if (retlen < len) { | 955 | if (retlen < len) { |
961 | D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB return short read " | 956 | D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB return short read " |
962 | "(%zd bytes not %d) for block at %08x\n", retlen, len, jeb->offset)); | 957 | "(%zd bytes not %d) for block at %08x\n", retlen, len, jeb->offset)); |
963 | ret = -EIO; | 958 | ret = -EIO; |
964 | goto out; | 959 | goto out; |
965 | } | 960 | } |
966 | 961 | ||
967 | /* Special check for first page */ | 962 | /* Special check for first page */ |
968 | for(i = 0; i < oob_size ; i++) { | 963 | for(i = 0; i < oob_size ; i++) { |
969 | /* Yeah, we know about the cleanmarker. */ | 964 | /* Yeah, we know about the cleanmarker. */ |
970 | if (mode && i >= c->fsdata_pos && | 965 | if (mode && i >= c->fsdata_pos && |
971 | i < c->fsdata_pos + c->fsdata_len) | 966 | i < c->fsdata_pos + c->fsdata_len) |
972 | continue; | 967 | continue; |
973 | 968 | ||
974 | if (buf[i] != 0xFF) { | 969 | if (buf[i] != 0xFF) { |
975 | D2(printk(KERN_DEBUG "Found %02x at %x in OOB for %08x\n", | 970 | D2(printk(KERN_DEBUG "Found %02x at %x in OOB for %08x\n", |
976 | buf[page+i], page+i, jeb->offset)); | 971 | buf[i], i, jeb->offset)); |
977 | ret = 1; | 972 | ret = 1; |
978 | goto out; | 973 | goto out; |
979 | } | 974 | } |
980 | } | 975 | } |
981 | 976 | ||
982 | /* we know, we are aligned :) */ | 977 | /* we know, we are aligned :) */ |
983 | for (page = oob_size; page < len; page += sizeof(long)) { | 978 | for (page = oob_size; page < len; page += sizeof(long)) { |
984 | unsigned long dat = *(unsigned long *)(&buf[page]); | 979 | unsigned long dat = *(unsigned long *)(&buf[page]); |
985 | if(dat != -1) { | 980 | if(dat != -1) { |
986 | ret = 1; | 981 | ret = 1; |
987 | goto out; | 982 | goto out; |
988 | } | 983 | } |
989 | } | 984 | } |
990 | 985 | ||
991 | out: | 986 | out: |
992 | kfree(buf); | 987 | kfree(buf); |
993 | 988 | ||
994 | return ret; | 989 | return ret; |
995 | } | 990 | } |
996 | 991 | ||
@@ -1072,7 +1067,7 @@ int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_erasebloc | |||
1072 | n.totlen = cpu_to_je32(8); | 1067 | n.totlen = cpu_to_je32(8); |
1073 | 1068 | ||
1074 | ret = jffs2_flash_write_oob(c, jeb->offset + c->fsdata_pos, c->fsdata_len, &retlen, (unsigned char *)&n); | 1069 | ret = jffs2_flash_write_oob(c, jeb->offset + c->fsdata_pos, c->fsdata_len, &retlen, (unsigned char *)&n); |
1075 | 1070 | ||
1076 | if (ret) { | 1071 | if (ret) { |
1077 | D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): Write failed for block at %08x: error %d\n", jeb->offset, ret)); | 1072 | D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): Write failed for block at %08x: error %d\n", jeb->offset, ret)); |
1078 | return ret; | 1073 | return ret; |
@@ -1084,7 +1079,7 @@ int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_erasebloc | |||
1084 | return 0; | 1079 | return 0; |
1085 | } | 1080 | } |
1086 | 1081 | ||
1087 | /* | 1082 | /* |
1088 | * On NAND we try to mark this block bad. If the block was erased more | 1083 | * On NAND we try to mark this block bad. If the block was erased more |
1089 | * than MAX_ERASE_FAILURES we mark it finaly bad. | 1084 | * than MAX_ERASE_FAILURES we mark it finaly bad. |
1090 | * Don't care about failures. This block remains on the erase-pending | 1085 | * Don't care about failures. This block remains on the erase-pending |
@@ -1105,7 +1100,7 @@ int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock * | |||
1105 | 1100 | ||
1106 | D1(printk(KERN_WARNING "jffs2_write_nand_badblock(): Marking bad block at %08x\n", bad_offset)); | 1101 | D1(printk(KERN_WARNING "jffs2_write_nand_badblock(): Marking bad block at %08x\n", bad_offset)); |
1107 | ret = c->mtd->block_markbad(c->mtd, bad_offset); | 1102 | ret = c->mtd->block_markbad(c->mtd, bad_offset); |
1108 | 1103 | ||
1109 | if (ret) { | 1104 | if (ret) { |
1110 | D1(printk(KERN_WARNING "jffs2_write_nand_badblock(): Write failed for block at %08x: error %d\n", jeb->offset, ret)); | 1105 | D1(printk(KERN_WARNING "jffs2_write_nand_badblock(): Write failed for block at %08x: error %d\n", jeb->offset, ret)); |
1111 | return ret; | 1106 | return ret; |
@@ -1129,7 +1124,7 @@ static int jffs2_nand_set_oobinfo(struct jffs2_sb_info *c) | |||
1129 | /* Do this only, if we have an oob buffer */ | 1124 | /* Do this only, if we have an oob buffer */ |
1130 | if (!c->mtd->oobsize) | 1125 | if (!c->mtd->oobsize) |
1131 | return 0; | 1126 | return 0; |
1132 | 1127 | ||
1133 | /* Cleanmarker is out-of-band, so inline size zero */ | 1128 | /* Cleanmarker is out-of-band, so inline size zero */ |
1134 | c->cleanmarker_size = 0; | 1129 | c->cleanmarker_size = 0; |
1135 | 1130 | ||
@@ -1155,7 +1150,7 @@ static int jffs2_nand_set_oobinfo(struct jffs2_sb_info *c) | |||
1155 | c->fsdata_len = NAND_JFFS2_OOB16_FSDALEN; | 1150 | c->fsdata_len = NAND_JFFS2_OOB16_FSDALEN; |
1156 | c->badblock_pos = 15; | 1151 | c->badblock_pos = 15; |
1157 | break; | 1152 | break; |
1158 | 1153 | ||
1159 | default: | 1154 | default: |
1160 | D1(printk(KERN_DEBUG "JFFS2 on NAND. No autoplacment info found\n")); | 1155 | D1(printk(KERN_DEBUG "JFFS2 on NAND. No autoplacment info found\n")); |
1161 | return -EINVAL; | 1156 | return -EINVAL; |
@@ -1172,7 +1167,7 @@ int jffs2_nand_flash_setup(struct jffs2_sb_info *c) | |||
1172 | init_rwsem(&c->wbuf_sem); | 1167 | init_rwsem(&c->wbuf_sem); |
1173 | c->wbuf_pagesize = c->mtd->oobblock; | 1168 | c->wbuf_pagesize = c->mtd->oobblock; |
1174 | c->wbuf_ofs = 0xFFFFFFFF; | 1169 | c->wbuf_ofs = 0xFFFFFFFF; |
1175 | 1170 | ||
1176 | c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL); | 1171 | c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL); |
1177 | if (!c->wbuf) | 1172 | if (!c->wbuf) |
1178 | return -ENOMEM; | 1173 | return -ENOMEM; |
@@ -1198,17 +1193,41 @@ void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c) | |||
1198 | 1193 | ||
1199 | int jffs2_dataflash_setup(struct jffs2_sb_info *c) { | 1194 | int jffs2_dataflash_setup(struct jffs2_sb_info *c) { |
1200 | c->cleanmarker_size = 0; /* No cleanmarkers needed */ | 1195 | c->cleanmarker_size = 0; /* No cleanmarkers needed */ |
1201 | 1196 | ||
1202 | /* Initialize write buffer */ | 1197 | /* Initialize write buffer */ |
1203 | init_rwsem(&c->wbuf_sem); | 1198 | init_rwsem(&c->wbuf_sem); |
1204 | c->wbuf_pagesize = c->sector_size; | ||
1205 | c->wbuf_ofs = 0xFFFFFFFF; | ||
1206 | 1199 | ||
1200 | |||
1201 | c->wbuf_pagesize = c->mtd->erasesize; | ||
1202 | |||
1203 | /* Find a suitable c->sector_size | ||
1204 | * - Not too much sectors | ||
1205 | * - Sectors have to be at least 4 K + some bytes | ||
1206 | * - All known dataflashes have erase sizes of 528 or 1056 | ||
1207 | * - we take at least 8 eraseblocks and want to have at least 8K size | ||
1208 | * - The concatenation should be a power of 2 | ||
1209 | */ | ||
1210 | |||
1211 | c->sector_size = 8 * c->mtd->erasesize; | ||
1212 | |||
1213 | while (c->sector_size < 8192) { | ||
1214 | c->sector_size *= 2; | ||
1215 | } | ||
1216 | |||
1217 | /* It may be necessary to adjust the flash size */ | ||
1218 | c->flash_size = c->mtd->size; | ||
1219 | |||
1220 | if ((c->flash_size % c->sector_size) != 0) { | ||
1221 | c->flash_size = (c->flash_size / c->sector_size) * c->sector_size; | ||
1222 | printk(KERN_WARNING "JFFS2 flash size adjusted to %dKiB\n", c->flash_size); | ||
1223 | }; | ||
1224 | |||
1225 | c->wbuf_ofs = 0xFFFFFFFF; | ||
1207 | c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL); | 1226 | c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL); |
1208 | if (!c->wbuf) | 1227 | if (!c->wbuf) |
1209 | return -ENOMEM; | 1228 | return -ENOMEM; |
1210 | 1229 | ||
1211 | printk(KERN_INFO "JFFS2 write-buffering enabled (%i)\n", c->wbuf_pagesize); | 1230 | printk(KERN_INFO "JFFS2 write-buffering enabled buffer (%d) erasesize (%d)\n", c->wbuf_pagesize, c->sector_size); |
1212 | 1231 | ||
1213 | return 0; | 1232 | return 0; |
1214 | } | 1233 | } |
@@ -1236,3 +1255,23 @@ int jffs2_nor_ecc_flash_setup(struct jffs2_sb_info *c) { | |||
1236 | void jffs2_nor_ecc_flash_cleanup(struct jffs2_sb_info *c) { | 1255 | void jffs2_nor_ecc_flash_cleanup(struct jffs2_sb_info *c) { |
1237 | kfree(c->wbuf); | 1256 | kfree(c->wbuf); |
1238 | } | 1257 | } |
1258 | |||
1259 | int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c) { | ||
1260 | /* Cleanmarker currently occupies a whole programming region */ | ||
1261 | c->cleanmarker_size = MTD_PROGREGION_SIZE(c->mtd); | ||
1262 | |||
1263 | /* Initialize write buffer */ | ||
1264 | init_rwsem(&c->wbuf_sem); | ||
1265 | c->wbuf_pagesize = MTD_PROGREGION_SIZE(c->mtd); | ||
1266 | c->wbuf_ofs = 0xFFFFFFFF; | ||
1267 | |||
1268 | c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL); | ||
1269 | if (!c->wbuf) | ||
1270 | return -ENOMEM; | ||
1271 | |||
1272 | return 0; | ||
1273 | } | ||
1274 | |||
1275 | void jffs2_nor_wbuf_flash_cleanup(struct jffs2_sb_info *c) { | ||
1276 | kfree(c->wbuf); | ||
1277 | } | ||