aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/jffs2/wbuf.c65
1 files changed, 47 insertions, 18 deletions
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
index c8128069ecf0..4e583bfecf6e 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.82 2004/11/20 22:08:31 dwmw2 Exp $ 12 * $Id: wbuf.c,v 1.83 2005/01/24 21:24:15 hammache Exp $
13 * 13 *
14 */ 14 */
15 15
@@ -130,7 +130,10 @@ static inline void jffs2_refile_wbuf_blocks(struct jffs2_sb_info *c)
130 } 130 }
131} 131}
132 132
133static void jffs2_block_refile(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) 133#define REFILE_NOTEMPTY 0
134#define REFILE_ANYWAY 1
135
136static void jffs2_block_refile(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, int allow_empty)
134{ 137{
135 D1(printk("About to refile bad block at %08x\n", jeb->offset)); 138 D1(printk("About to refile bad block at %08x\n", jeb->offset));
136 139
@@ -144,7 +147,8 @@ static void jffs2_block_refile(struct jffs2_sb_info *c, struct jffs2_eraseblock
144 D1(printk("Refiling block at %08x to bad_used_list\n", jeb->offset)); 147 D1(printk("Refiling block at %08x to bad_used_list\n", jeb->offset));
145 list_add(&jeb->list, &c->bad_used_list); 148 list_add(&jeb->list, &c->bad_used_list);
146 } else { 149 } else {
147 BUG(); 150 if (allow_empty == REFILE_NOTEMPTY)
151 BUG();
148 /* It has to have had some nodes or we couldn't be here */ 152 /* It has to have had some nodes or we couldn't be here */
149 D1(printk("Refiling block at %08x to erase_pending_list\n", jeb->offset)); 153 D1(printk("Refiling block at %08x to erase_pending_list\n", jeb->offset));
150 list_add(&jeb->list, &c->erase_pending_list); 154 list_add(&jeb->list, &c->erase_pending_list);
@@ -179,7 +183,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
179 183
180 jeb = &c->blocks[c->wbuf_ofs / c->sector_size]; 184 jeb = &c->blocks[c->wbuf_ofs / c->sector_size];
181 185
182 jffs2_block_refile(c, jeb); 186 jffs2_block_refile(c, jeb, REFILE_NOTEMPTY);
183 187
184 /* Find the first node to be recovered, by skipping over every 188 /* Find the first node to be recovered, by skipping over every
185 node which ends before the wbuf starts, or which is obsolete. */ 189 node which ends before the wbuf starts, or which is obsolete. */
@@ -269,12 +273,12 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
269 return; 273 return;
270 } 274 }
271 if (end-start >= c->wbuf_pagesize) { 275 if (end-start >= c->wbuf_pagesize) {
272 /* Need to do another write immediately. This, btw, 276 /* Need to do another write immediately, but it's possible
273 means that we'll be writing from 'buf' and not from 277 that this is just because the wbuf itself is completely
274 the wbuf. Since if we're writing from the wbuf there 278 full, and there's nothing earlier read back from the
275 won't be more than a wbuf full of data, now will 279 flash. Hence 'buf' isn't necessarily what we're writing
276 there? :) */ 280 from. */
277 281 unsigned char *rewrite_buf = buf?:c->wbuf;
278 uint32_t towrite = (end-start) - ((end-start)%c->wbuf_pagesize); 282 uint32_t towrite = (end-start) - ((end-start)%c->wbuf_pagesize);
279 283
280 D1(printk(KERN_DEBUG "Write 0x%x bytes at 0x%08x in wbuf recover\n", 284 D1(printk(KERN_DEBUG "Write 0x%x bytes at 0x%08x in wbuf recover\n",
@@ -292,14 +296,15 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
292#endif 296#endif
293 if (jffs2_cleanmarker_oob(c)) 297 if (jffs2_cleanmarker_oob(c))
294 ret = c->mtd->write_ecc(c->mtd, ofs, towrite, &retlen, 298 ret = c->mtd->write_ecc(c->mtd, ofs, towrite, &retlen,
295 buf, NULL, c->oobinfo); 299 rewrite_buf, NULL, c->oobinfo);
296 else 300 else
297 ret = c->mtd->write(c->mtd, ofs, towrite, &retlen, buf); 301 ret = c->mtd->write(c->mtd, ofs, towrite, &retlen, rewrite_buf);
298 302
299 if (ret || retlen != towrite) { 303 if (ret || retlen != towrite) {
300 /* Argh. We tried. Really we did. */ 304 /* Argh. We tried. Really we did. */
301 printk(KERN_CRIT "Recovery of wbuf failed due to a second write error\n"); 305 printk(KERN_CRIT "Recovery of wbuf failed due to a second write error\n");
302 kfree(buf); 306 if (buf)
307 kfree(buf);
303 308
304 if (retlen) { 309 if (retlen) {
305 struct jffs2_raw_node_ref *raw2; 310 struct jffs2_raw_node_ref *raw2;
@@ -321,10 +326,10 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
321 326
322 c->wbuf_len = (end - start) - towrite; 327 c->wbuf_len = (end - start) - towrite;
323 c->wbuf_ofs = ofs + towrite; 328 c->wbuf_ofs = ofs + towrite;
324 memcpy(c->wbuf, buf + towrite, c->wbuf_len); 329 memmove(c->wbuf, rewrite_buf + towrite, c->wbuf_len);
325 /* Don't muck about with c->wbuf_inodes. False positives are harmless. */ 330 /* Don't muck about with c->wbuf_inodes. False positives are harmless. */
326 331 if (buf)
327 kfree(buf); 332 kfree(buf);
328 } else { 333 } else {
329 /* OK, now we're left with the dregs in whichever buffer we're using */ 334 /* OK, now we're left with the dregs in whichever buffer we're using */
330 if (buf) { 335 if (buf) {
@@ -547,6 +552,12 @@ int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino)
547 D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() padding. Not finished checking\n")); 552 D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() padding. Not finished checking\n"));
548 down_write(&c->wbuf_sem); 553 down_write(&c->wbuf_sem);
549 ret = __jffs2_flush_wbuf(c, PAD_ACCOUNTING); 554 ret = __jffs2_flush_wbuf(c, PAD_ACCOUNTING);
555 /* retry flushing wbuf in case jffs2_wbuf_recover
556 left some data in the wbuf */
557 if (ret)
558 {
559 ret = __jffs2_flush_wbuf(c, PAD_ACCOUNTING);
560 }
550 up_write(&c->wbuf_sem); 561 up_write(&c->wbuf_sem);
551 } else while (old_wbuf_len && 562 } else while (old_wbuf_len &&
552 old_wbuf_ofs == c->wbuf_ofs) { 563 old_wbuf_ofs == c->wbuf_ofs) {
@@ -561,6 +572,12 @@ int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino)
561 down(&c->alloc_sem); 572 down(&c->alloc_sem);
562 down_write(&c->wbuf_sem); 573 down_write(&c->wbuf_sem);
563 ret = __jffs2_flush_wbuf(c, PAD_ACCOUNTING); 574 ret = __jffs2_flush_wbuf(c, PAD_ACCOUNTING);
575 /* retry flushing wbuf in case jffs2_wbuf_recover
576 left some data in the wbuf */
577 if (ret)
578 {
579 ret = __jffs2_flush_wbuf(c, PAD_ACCOUNTING);
580 }
564 up_write(&c->wbuf_sem); 581 up_write(&c->wbuf_sem);
565 break; 582 break;
566 } 583 }
@@ -580,6 +597,9 @@ int jffs2_flush_wbuf_pad(struct jffs2_sb_info *c)
580 597
581 down_write(&c->wbuf_sem); 598 down_write(&c->wbuf_sem);
582 ret = __jffs2_flush_wbuf(c, PAD_NOACCOUNT); 599 ret = __jffs2_flush_wbuf(c, PAD_NOACCOUNT);
600 /* retry - maybe wbuf recover left some data in wbuf. */
601 if (ret)
602 ret = __jffs2_flush_wbuf(c, PAD_NOACCOUNT);
583 up_write(&c->wbuf_sem); 603 up_write(&c->wbuf_sem);
584 604
585 return ret; 605 return ret;
@@ -762,9 +782,18 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig
762 782
763 if (ret < 0 || wbuf_retlen != PAGE_DIV(totlen)) { 783 if (ret < 0 || wbuf_retlen != PAGE_DIV(totlen)) {
764 /* At this point we have no problem, 784 /* At this point we have no problem,
765 c->wbuf is empty. 785 c->wbuf is empty. However refile nextblock to avoid
786 writing again to same address.
766 */ 787 */
767 *retlen = donelen; 788 struct jffs2_eraseblock *jeb;
789
790 spin_lock(&c->erase_completion_lock);
791
792 jeb = &c->blocks[outvec_to / c->sector_size];
793 jffs2_block_refile(c, jeb, REFILE_ANYWAY);
794
795 *retlen = 0;
796 spin_unlock(&c->erase_completion_lock);
768 goto exit; 797 goto exit;
769 } 798 }
770 799