Apply basic CRC for smartfs [Description] Because of sudden power off, CRC added...
authorTaeJun Kwon <tj80.kwon@samsung.com>
Tue, 8 Aug 2017 03:52:40 +0000 (12:52 +0900)
committerKavya <kavya.nunna@partner.samsung.com>
Tue, 5 Sep 2017 09:46:06 +0000 (15:16 +0530)
os/fs/driver/mtd/smart.c

index 9ccd50d..2f246bc 100644 (file)
 #if CONFIG_SMARTFS_ERASEDSTATE == 0xFF
 #define SECTOR_IS_RELEASED(h) ((h.status & SMART_STATUS_RELEASED) == 0 ? true : false)
 #define SECTOR_IS_COMMITTED(h) ((h.status & SMART_STATUS_COMMITTED) == 0 ? true : false)
+#if SMART_STATUS_VERSION == 1
+#define HEADER_IS_CLEAN(h) ((UINT8TOUINT16(h.logicalsector) == 0xFFFF && h.seq == 0xFF && h.crc8 == 0xFF && h.status == 0xFF))
+#elif SMART_STATUS_VERSION == 2
+#define HEADER_IS_CLEAN(h) ((UINT8TOUINT16(h.logicalsector) == 0xFFFF && h.seq == 0xFF && h.crc16 == 0xFFFF && h.status == 0xFF))
+#elif SMART_STATUS_VERSION == 3
+#define HEADER_IS_CLEAN(h) ((UINT8TOUINT16(h.logicalsector) == 0xFFFFFFFF && h.seq == 0xFF && h.crc32 == 0xFFFFFFFF && h.status == 0xFF))
+#endif
 #else
 #define SECTOR_IS_RELEASED(h) ((h.status & SMART_STATUS_RELEASED) == SMART_STATUS_RELEASED ? true : false)
 #define SECTOR_IS_COMMITTED(h) ((h.status & SMART_STATUS_COMMITTED) == SMART_STATUS_COMMITTED ? true : false)
+#if SMART_STATUS_VERSION == 1
+#define HEADER_IS_CLEAN(h) ((UINT8TOUINT16(h.logicalsector) == 0x0000 && h.seq == 0x00 && h.crc8 == 0x00 && h.status == 0x00))
+#elif SMART_STATUS_VERSION == 2
+#define HEADER_IS_CLEAN(h) ((UINT8TOUINT16(h.logicalsector) == 0x0000 && h.seq == 0x00 && h.crc16 == 0x0000 && h.status == 0x00))
+#elif SMART_STATUS_VERSION == 3
+#define HEADER_IS_CLEAN(h) ((UINT8TOUINT16(h.logicalsector) == 0x00000000 && h.seq == 0x00 && h.crc32 == 0x00000000 && h.status == 0x00))
+#endif
+
 #endif
 
 #define SET_TO_TRUE(v, n) v[n/8] |= (1<<(7-(n%8)))
@@ -410,8 +425,10 @@ static int smart_readsector(FAR struct smart_struct_s *dev, unsigned long arg);
 static int smart_read_wearstatus(FAR struct smart_struct_s *dev);
 static int smart_relocate_static_data(FAR struct smart_struct_s *dev, uint16_t block);
 #endif
-
+static void smart_erase_block_if_empty(FAR struct smart_struct_s *dev, uint16_t block, uint8_t forceerase);
 static int smart_relocate_sector(FAR struct smart_struct_s *dev, uint16_t oldsector, uint16_t newsector);
+static int smart_validate_crc(FAR struct smart_struct_s *dev);
+static crc_t smart_calc_sector_crc(FAR struct smart_struct_s *dev);
 
 /****************************************************************************
  * Private Data
@@ -1679,11 +1696,9 @@ static int smart_set_wear_level(FAR struct smart_struct_s *dev, uint16_t block,
                        }
                }
        }
-
        return 0;
 }
 #endif
-
 /****************************************************************************
  * Name: smart_scan
  *
@@ -1709,6 +1724,7 @@ static int smart_scan(FAR struct smart_struct_s *dev)
        struct smart_sect_header_s header;
        uint8_t *sector_seq_log = NULL;
        bool status_released, status_committed;
+       bool corrupted;
 #ifdef CONFIG_MTD_SMART_MINIMIZE_RAM
        int dupsector;
        uint16_t duplogsector;
@@ -1718,6 +1734,7 @@ static int smart_scan(FAR struct smart_struct_s *dev)
        char devname[22];
        FAR struct smart_multiroot_device_s *rootdirdev;
 #endif
+       int i;
 
        fvdbg("Entry\n");
 
@@ -1819,6 +1836,7 @@ static int smart_scan(FAR struct smart_struct_s *dev)
 
        for (sector = 0; sector < totalsectors; sector++) {
                winner = sector;
+               corrupted = false;
                fvdbg("Scan sector %d\n", sector);
 
                /* Calculate the read address for this sector */
@@ -1827,14 +1845,55 @@ static int smart_scan(FAR struct smart_struct_s *dev)
 
                /* Read the header for this sector */
 
-               ret = MTD_READ(dev->mtd, readaddress, sizeof(struct smart_sect_header_s), (FAR uint8_t *)&header);
-               if (ret != sizeof(struct smart_sect_header_s)) {
+               ret = MTD_BREAD(dev->mtd, sector * dev->mtdBlksPerSector, dev->mtdBlksPerSector, (uint8_t *)dev->rwbuffer);
+               if (ret != dev->mtdBlksPerSector) {
+                       fdbg("Error reading physical sector %d.\n", sector);
                        goto err_out;
                }
 
-               /* Get the logical sector number for this physical sector */
+               memcpy(&header, dev->rwbuffer, sizeof(struct smart_sect_header_s));
+               ret = smart_validate_crc(dev);
+               if (ret != OK) {
+                       if (HEADER_IS_CLEAN(header)) {
+                               /* Header is cleaned but all block is not cleaned, it means por druing erase */
+                               for (i = sizeof(struct smart_sect_header_s); i < dev->sectorsize; i++) {
+                                       if (dev->rwbuffer[i] != 0xFF) {
+                                               fdbg("It is not Erased value sector %u, offset %u, %x------------------\n", sector, i, dev->rwbuffer[i]);
+                                               corrupted = true;
+                                               break;
+                                       }
+                               }
+                               if (corrupted) {
+                                       fdbg("It seems erase-fail, physical sector : %d eraseblock : %d\n", sector, sector / dev->sectorsPerBlk);
+                                       smart_erase_block_if_empty(dev, sector / dev->sectorsPerBlk, TRUE);
+                                       sector = ((sector / dev->sectorsPerBlk) * dev->sectorsPerBlk) + dev->sectorsPerBlk - 1;
+                                       continue;
+                               }
+                       } else {
+                               fdbg("It seems corrupted, physical sector : %d eraseblock : %d\n", sector, sector / dev->sectorsPerBlk);
+#ifdef CONFIG_DEBUG_FS
+//#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_DEBUG_VERBOSE)
+                               for (i = 0; i < sizeof(struct smart_sect_header_s); i++) {
+                                       fsdbg("%02x ", dev->rwbuffer[i]);
+                               }
+                               fsdbg("\n");
+#endif
+                               fdbg("set Released and commited sector : %d\n", sector);
+#if CONFIG_SMARTFS_ERASEDSTATE == 0xFF
+                               header.status = header.status & ~(SMART_STATUS_COMMITTED | SMART_STATUS_RELEASED);
+#else
+                               header.status = header.status | SMART_STATUS_COMMITTED | SMART_STATUS_RELEASED;
+#endif
+                               ret = smart_bytewrite(dev, readaddress + offsetof(struct smart_sect_header_s, status), 1, &header.status);
+                               if (ret < 0) {
+                                       goto err_out;
+                               }
 
-               //logicalsector = *((FAR uint16_t *)header.logicalsector);
+                       }
+               }
+
+
+               /* Get the logical sector number for this physical sector */
                logicalsector = UINT8TOUINT16(header.logicalsector);
 #if CONFIG_SMARTFS_ERASEDSTATE == 0x00
                if (logicalsector == 0) {
@@ -1844,7 +1903,7 @@ static int smart_scan(FAR struct smart_struct_s *dev)
 
                status_released = SECTOR_IS_RELEASED(header);
                status_committed = SECTOR_IS_COMMITTED(header);
-
+               fvdbg("released : %d committed : %d logical : %d physical : %d sta :%d seq :%d\n", status_released, status_committed, logicalsector, sector, header.status, header.seq);
                if (logicalsector > 0 && header.status != CONFIG_SMARTFS_ERASEDSTATE && !status_released && status_committed) {
 
                        /* Map the sector and update the free sector counts */
@@ -2620,7 +2679,6 @@ errout:
  *
  ****************************************************************************/
 
-#ifdef CONFIG_MTD_SMART_ENABLE_CRC
 static crc_t smart_calc_sector_crc(FAR struct smart_struct_s *dev)
 {
        crc_t crc = 0;
@@ -2661,12 +2719,15 @@ static crc_t smart_calc_sector_crc(FAR struct smart_struct_s *dev)
 
        crc = crc32part((uint8_t *)dev->rwbuffer, 6, crc);
 #else
-#error "Unknown CRC size!"
+       /* Add logical sector number and seq to the CRC calculation for basic crc */
+
+       crc = crc8((uint8_t *)dev->rwbuffer, 3);
+
 #endif
 
        return crc;
 }
-#endif                                                 /* CONFIG_MTD_SMART_ENABLE_CRC  */
+
 
 /*Name: smart_write_bad_sector_info
  *
@@ -2802,11 +2863,9 @@ static inline int smart_llformat(FAR struct smart_struct_s *dev, unsigned long a
 
        sectorheader->seq = 0;
 #else
-       /* CRC not enabled.  Using a 16-bit sequence number */
+       /* Use Basic CRC, using an 8-bit sequence number */
 
-       sectorheader->crc8 = 0;
        sectorheader->seq = 0;
-       //*((FAR uint16_t *)&sectorheader->seq) = 0;
 #endif
 #else                                                  /* SMART_STATUS_VERSION == 1 */
        sectorheader->seq = 0;
@@ -2855,6 +2914,8 @@ static inline int smart_llformat(FAR struct smart_struct_s *dev, unsigned long a
        *((uint16_t *)sectorheader->crc16) = smart_calc_sector_crc(dev);
 #elif defined(CONFIG_SMART_CRC_32)
        *((uint32_t *)sectorheader->crc32) = smart_calc_sector_crc(dev);
+#else
+       sectorheader->crc8 = smart_calc_sector_crc(dev);
 #endif
 
        /* Write the sector to the flash */
@@ -3017,6 +3078,7 @@ static int smart_relocate_sector(FAR struct smart_struct_s *dev, uint16_t oldsec
 #else
        header->status &= ~SMART_STATUS_COMMITTED;
 #endif
+       header->crc8 = smart_calc_sector_crc(dev);
 
        /* Write the data to the new physical sector location */
 
@@ -3869,19 +3931,9 @@ static int smart_write_alloc_sector(FAR struct smart_struct_s *dev, uint16_t log
        header->logicalsector[0] = (uint8_t)(logical & 0x00FF);
        header->logicalsector[1] = (uint8_t)(logical >> 8);
        //*((FAR uint16_t *)header->logicalsector) = logical;
-#if SMART_STATUS_VERSION == 1
-#ifdef CONFIG_MTD_SMART_ENABLE_CRC
-       header->seq = 0;
-#else
-       //*((FAR uint16_t *)&header->crc8) = 0;
-       uint8_t *tmp = &header->crc8;
-       *tmp = 0;
-       tmp++;
-       *tmp = 0;
-#endif                                                 /* CONFIG_MTD_SMART_ENABLE_CRC */
-#else
+
        header->seq = 0;
-#endif
+
        sectsize = dev->sectorsize >> 7;
 
 #if CONFIG_SMARTFS_ERASEDSTATE == 0xFF
@@ -3899,6 +3951,7 @@ static int smart_write_alloc_sector(FAR struct smart_struct_s *dev, uint16_t log
        /* Write the header to the physical sector location */
 
 #ifndef CONFIG_MTD_SMART_ENABLE_CRC
+       header->crc8 = smart_calc_sector_crc(dev);
        fvdbg("Write MTD block %d\n", physical * dev->mtdBlksPerSector);
        ret = MTD_BWRITE(dev->mtd, physical * dev->mtdBlksPerSector, 1, (FAR uint8_t *)dev->rwbuffer);
        if (ret != 1) {
@@ -3925,7 +3978,6 @@ static int smart_write_alloc_sector(FAR struct smart_struct_s *dev, uint16_t log
  *
  ****************************************************************************/
 
-#ifdef CONFIG_MTD_SMART_ENABLE_CRC
 static int smart_validate_crc(FAR struct smart_struct_s *dev)
 {
        crc_t crc;
@@ -3936,14 +3988,7 @@ static int smart_validate_crc(FAR struct smart_struct_s *dev)
        crc = smart_calc_sector_crc(dev);
        header = (FAR struct smart_sect_header_s *)dev->rwbuffer;
 
-#ifdef CONFIG_SMART_CRC_8
-
-       /* Test 8-bit CRC */
-
-       if (crc != header->crc8) {
-               return -EIO;
-       }
-#elif defined(CONFIG_SMART_CRC_16)
+#ifdef CONFIG_SMART_CRC_16
 
        /* Test 16-bit CRC */
 
@@ -3955,13 +4000,19 @@ static int smart_validate_crc(FAR struct smart_struct_s *dev)
        if (crc != *((uint32_t *)header->crc32)) {
                return -EIO;
        }
+#else
+       /* Test 8-bit CRC for CRC8 & basic case for smart_scan */
+       if (crc != header->crc8) {
+               return -EIO;
+       }
+
 #endif
 
        /* CRC checkout out okay */
 
        return OK;
 }
-#endif
+
 
 /****************************************************************************
  * Name: smart_writesector
@@ -4220,8 +4271,9 @@ relocate_good_sector:
 #else                                                  /* CONFIG_MTD_SMART_ENABLE_CRC */
 
        /* Now copy the data to the sector buffer. */
-       memcpy(&dev->rwbuffer[sizeof(struct smart_sect_header_s) + req->offset], req->buffer, req->count);
-
+       memcpy(&dev->rwbuffer[sizeof(struct smart_sect_header_s) + req->offset],
+                  req->buffer, req->count);
+       header->crc8 = smart_calc_sector_crc(dev);
 #endif                                                 /* CONFIG_MTD_SMART_ENABLE_CRC */
 
        /* Now write the sector buffer to the device. */