@@ -554,39 +554,37 @@ int ubi_eba_read_leb_sg(struct ubi_device *ubi, struct ubi_volume *vol,
554
554
}
555
555
556
556
/**
557
- * recover_peb - recover from write failure.
558
- * @ubi: UBI device description object
557
+ * try_recover_peb - try to recover from write failure.
558
+ * @vol: volume description object
559
559
* @pnum: the physical eraseblock to recover
560
- * @vol_id: volume ID
561
560
* @lnum: logical eraseblock number
562
561
* @buf: data which was not written because of the write failure
563
562
* @offset: offset of the failed write
564
563
* @len: how many bytes should have been written
564
+ * @vid: VID header
565
+ * @retry: whether the caller should retry in case of failure
565
566
*
566
567
* This function is called in case of a write failure and moves all good data
567
568
* from the potentially bad physical eraseblock to a good physical eraseblock.
568
569
* This function also writes the data which was not written due to the failure.
569
- * Returns new physical eraseblock number in case of success, and a negative
570
- * error code in case of failure.
570
+ * Returns 0 in case of success, and a negative error code in case of failure.
571
+ * In case of failure, the %retry parameter is set to false if this is a fatal
572
+ * error (retrying won't help), and true otherwise.
571
573
*/
572
- static int recover_peb (struct ubi_device * ubi , int pnum , int vol_id , int lnum ,
573
- const void * buf , int offset , int len )
574
+ static int try_recover_peb (struct ubi_volume * vol , int pnum , int lnum ,
575
+ const void * buf , int offset , int len ,
576
+ struct ubi_vid_hdr * vid_hdr , bool * retry )
574
577
{
575
- int err , idx = vol_id2idx (ubi , vol_id ), new_pnum , data_size , tries = 0 ;
576
- struct ubi_volume * vol = ubi -> volumes [idx ];
577
- struct ubi_vid_hdr * vid_hdr ;
578
+ struct ubi_device * ubi = vol -> ubi ;
579
+ int new_pnum , err , vol_id = vol -> vol_id , data_size ;
578
580
uint32_t crc ;
579
581
580
- vid_hdr = ubi_zalloc_vid_hdr (ubi , GFP_NOFS );
581
- if (!vid_hdr )
582
- return - ENOMEM ;
582
+ * retry = false;
583
583
584
- retry :
585
584
new_pnum = ubi_wl_get_peb (ubi );
586
585
if (new_pnum < 0 ) {
587
- ubi_free_vid_hdr (ubi , vid_hdr );
588
- up_read (& ubi -> fm_eba_sem );
589
- return new_pnum ;
586
+ err = new_pnum ;
587
+ goto out_put ;
590
588
}
591
589
592
590
ubi_msg (ubi , "recover PEB %d, move data to PEB %d" ,
@@ -596,7 +594,6 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
596
594
if (err && err != UBI_IO_BITFLIPS ) {
597
595
if (err > 0 )
598
596
err = - EIO ;
599
- up_read (& ubi -> fm_eba_sem );
600
597
goto out_put ;
601
598
}
602
599
@@ -608,12 +605,12 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
608
605
/* Read everything before the area where the write failure happened */
609
606
if (offset > 0 ) {
610
607
err = ubi_io_read_data (ubi , ubi -> peb_buf , pnum , 0 , offset );
611
- if (err && err != UBI_IO_BITFLIPS ) {
612
- up_read (& ubi -> fm_eba_sem );
608
+ if (err && err != UBI_IO_BITFLIPS )
613
609
goto out_unlock ;
614
- }
615
610
}
616
611
612
+ * retry = true;
613
+
617
614
memcpy (ubi -> peb_buf + offset , buf , len );
618
615
619
616
data_size = offset + len ;
@@ -623,49 +620,76 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
623
620
vid_hdr -> data_size = cpu_to_be32 (data_size );
624
621
vid_hdr -> data_crc = cpu_to_be32 (crc );
625
622
err = ubi_io_write_vid_hdr (ubi , new_pnum , vid_hdr );
626
- if (err ) {
627
- mutex_unlock (& ubi -> buf_mutex );
628
- up_read (& ubi -> fm_eba_sem );
629
- goto write_error ;
630
- }
623
+ if (err )
624
+ goto out_unlock ;
631
625
632
626
err = ubi_io_write_data (ubi , ubi -> peb_buf , new_pnum , 0 , data_size );
633
- if (err ) {
634
- mutex_unlock (& ubi -> buf_mutex );
635
- up_read (& ubi -> fm_eba_sem );
636
- goto write_error ;
637
- }
638
627
628
+ out_unlock :
639
629
mutex_unlock (& ubi -> buf_mutex );
640
- ubi_free_vid_hdr (ubi , vid_hdr );
641
630
642
- vol -> eba_tbl [lnum ] = new_pnum ;
631
+ if (!err )
632
+ vol -> eba_tbl [lnum ] = new_pnum ;
633
+
634
+ out_put :
643
635
up_read (& ubi -> fm_eba_sem );
644
- ubi_wl_put_peb (ubi , vol_id , lnum , pnum , 1 );
645
636
646
- ubi_msg (ubi , "data was successfully recovered" );
647
- return 0 ;
637
+ if (!err ) {
638
+ ubi_wl_put_peb (ubi , vol_id , lnum , pnum , 1 );
639
+ ubi_msg (ubi , "data was successfully recovered" );
640
+ } else if (new_pnum >= 0 ) {
641
+ /*
642
+ * Bad luck? This physical eraseblock is bad too? Crud. Let's
643
+ * try to get another one.
644
+ */
645
+ ubi_wl_put_peb (ubi , vol_id , lnum , new_pnum , 1 );
646
+ ubi_warn (ubi , "failed to write to PEB %d" , new_pnum );
647
+ }
648
648
649
- out_unlock :
650
- mutex_unlock (& ubi -> buf_mutex );
651
- out_put :
652
- ubi_wl_put_peb (ubi , vol_id , lnum , new_pnum , 1 );
653
- ubi_free_vid_hdr (ubi , vid_hdr );
654
649
return err ;
650
+ }
655
651
656
- write_error :
657
- /*
658
- * Bad luck? This physical eraseblock is bad too? Crud. Let's try to
659
- * get another one.
660
- */
661
- ubi_warn (ubi , "failed to write to PEB %d" , new_pnum );
662
- ubi_wl_put_peb (ubi , vol_id , lnum , new_pnum , 1 );
663
- if (++ tries > UBI_IO_RETRIES ) {
664
- ubi_free_vid_hdr (ubi , vid_hdr );
665
- return err ;
652
+ /**
653
+ * recover_peb - recover from write failure.
654
+ * @ubi: UBI device description object
655
+ * @pnum: the physical eraseblock to recover
656
+ * @vol_id: volume ID
657
+ * @lnum: logical eraseblock number
658
+ * @buf: data which was not written because of the write failure
659
+ * @offset: offset of the failed write
660
+ * @len: how many bytes should have been written
661
+ *
662
+ * This function is called in case of a write failure and moves all good data
663
+ * from the potentially bad physical eraseblock to a good physical eraseblock.
664
+ * This function also writes the data which was not written due to the failure.
665
+ * Returns 0 in case of success, and a negative error code in case of failure.
666
+ * This function tries %UBI_IO_RETRIES before giving up.
667
+ */
668
+ static int recover_peb (struct ubi_device * ubi , int pnum , int vol_id , int lnum ,
669
+ const void * buf , int offset , int len )
670
+ {
671
+ int err , idx = vol_id2idx (ubi , vol_id ), tries ;
672
+ struct ubi_volume * vol = ubi -> volumes [idx ];
673
+ struct ubi_vid_hdr * vid_hdr ;
674
+
675
+ vid_hdr = ubi_zalloc_vid_hdr (ubi , GFP_NOFS );
676
+ if (!vid_hdr )
677
+ return - ENOMEM ;
678
+
679
+ for (tries = 0 ; tries <= UBI_IO_RETRIES ; tries ++ ) {
680
+ bool retry ;
681
+
682
+ err = try_recover_peb (vol , pnum , lnum , buf , offset , len ,
683
+ vid_hdr , & retry );
684
+ if (!err || !retry )
685
+ break ;
686
+
687
+ ubi_msg (ubi , "try again" );
666
688
}
667
- ubi_msg (ubi , "try again" );
668
- goto retry ;
689
+
690
+ ubi_free_vid_hdr (ubi , vid_hdr );
691
+
692
+ return err ;
669
693
}
670
694
671
695
/**
0 commit comments