diff --git a/apps/system/utils/fscmd.c b/apps/system/utils/fscmd.c index 964acf43a7..db102a0c1b 100644 --- a/apps/system/utils/fscmd.c +++ b/apps/system/utils/fscmd.c @@ -259,38 +259,6 @@ static int tash_echo(int argc, char **args) * cat [OPTIONS] [source_file_path] [> or >>] [target_file_path] * OPTIONS: '--help' - display the usage. ****************************************************************************/ -static int check_path(char **src_fullpath, redirection_t direction, char **args) -{ - if (direction.mode != FSCMD_NONE) { - FSCMD_OUTPUT(INVALID_ARGS FSCMD_CAT_USAGE, args[0]); - return ERROR; - } - - *src_fullpath = get_fullpath(args[1]); - if (!(*src_fullpath)) { - FSCMD_OUTPUT(OUT_OF_MEMORY, args[1]); - return ERROR; - } - - return OK; -} - -static int check_path_argument(char **src_fullpath, char **args) -{ - if (strcmp(args[1], args[3]) == 0) { - FSCMD_OUTPUT(INVALID_ARGS "Same File name", args[1]); - return ERROR; - } - - *src_fullpath = get_fullpath(args[1]); - if (!(*src_fullpath)) { - FSCMD_OUTPUT(OUT_OF_MEMORY, args[1]); - return ERROR; - } - - return OK; -} - static int tash_cat(int argc, char **args) { char *src_fullpath = NULL; @@ -326,9 +294,15 @@ static int tash_cat(int argc, char **args) return OK; } /* Basic case, cat */ - ret = check_path(&src_fullpath, direction, args); - if (ret < 0) { - return ret; + if (direction.mode != FSCMD_NONE) { + FSCMD_OUTPUT(INVALID_ARGS FSCMD_CAT_USAGE, args[0]); + return ERROR; + } + + src_fullpath = get_fullpath(args[1]); + if (!src_fullpath) { + FSCMD_OUTPUT(OUT_OF_MEMORY, args[1]); + return ERROR; } fd = open(src_fullpath, O_RDONLY); @@ -350,14 +324,24 @@ static int tash_cat(int argc, char **args) } else if (argc == 4) { /* Below is redirection case */ flags = O_WRONLY | O_CREAT; - flags |= (direction.mode == FSCMD_TRUNCATE ? O_TRUNC : O_APPEND); + if (direction.mode == FSCMD_TRUNCATE) { + flags |= O_TRUNC; + } else { + flags |= O_APPEND; + } if (direction.index == 2) { /* copy contents from source file to target file * cat */ - ret = check_path_argument(&src_fullpath, args); - if (ret < 0) { - return ret; + if (strcmp(args[1], args[3]) == 0) { + FSCMD_OUTPUT(INVALID_ARGS "Same File name", args[1]); + return ERROR; + } + + src_fullpath = get_fullpath(args[1]); + if (!src_fullpath) { + FSCMD_OUTPUT(OUT_OF_MEMORY, args[1]); + return ERROR; } fd = open(src_fullpath, O_RDONLY); @@ -500,62 +484,10 @@ static int foreach_direntry(const char *cmd, const char *dirpath, direntry_handl * Description: * ls_handler displays contents of specific directory. * ls_recursive using ls_handler recursively to display whole contents - * under the specific directory + * under the specific directoy * ls_specialdir checks directory's name started '.' or '..' * ****************************************************************************/ -static void print_mode_details(struct stat buf) -{ - char details[] = "----------"; - if (S_ISDIR(buf.st_mode)) { - details[0] = 'd'; - } else if (S_ISCHR(buf.st_mode)) { - details[0] = 'c'; - } else if (S_ISBLK(buf.st_mode)) { - details[0] = 'b'; - } else if (!S_ISREG(buf.st_mode)) { - details[0] = '?'; - } - - if ((buf.st_mode & S_IRUSR) != 0) { - details[1] = 'r'; - } - - if ((buf.st_mode & S_IWUSR) != 0) { - details[2] = 'w'; - } - - if ((buf.st_mode & S_IXUSR) != 0) { - details[3] = 'x'; - } - - if ((buf.st_mode & S_IRGRP) != 0) { - details[4] = 'r'; - } - - if ((buf.st_mode & S_IWGRP) != 0) { - details[5] = 'w'; - } - - if ((buf.st_mode & S_IXGRP) != 0) { - details[6] = 'x'; - } - - if ((buf.st_mode & S_IROTH) != 0) { - details[7] = 'r'; - } - - if ((buf.st_mode & S_IWOTH) != 0) { - details[8] = 'w'; - } - - if ((buf.st_mode & S_IXOTH) != 0) { - details[9] = 'x'; - } - - FSCMD_OUTPUT(" %s", details); -} - static int ls_specialdir(const char *dir) { /* '.' and '..' directories are not listed like normal directories */ @@ -593,7 +525,54 @@ static int ls_handler(FAR const char *dirpath, FAR struct dirent *entryp, FAR vo } if ((lsflags & LSFLAGS_LONG) != 0) { - print_mode_details(buf); + char details[] = "----------"; + if (S_ISDIR(buf.st_mode)) { + details[0] = 'd'; + } else if (S_ISCHR(buf.st_mode)) { + details[0] = 'c'; + } else if (S_ISBLK(buf.st_mode)) { + details[0] = 'b'; + } else if (!S_ISREG(buf.st_mode)) { + details[0] = '?'; + } + + if ((buf.st_mode & S_IRUSR) != 0) { + details[1] = 'r'; + } + + if ((buf.st_mode & S_IWUSR) != 0) { + details[2] = 'w'; + } + + if ((buf.st_mode & S_IXUSR) != 0) { + details[3] = 'x'; + } + + if ((buf.st_mode & S_IRGRP) != 0) { + details[4] = 'r'; + } + + if ((buf.st_mode & S_IWGRP) != 0) { + details[5] = 'w'; + } + + if ((buf.st_mode & S_IXGRP) != 0) { + details[6] = 'x'; + } + + if ((buf.st_mode & S_IROTH) != 0) { + details[7] = 'r'; + } + + if ((buf.st_mode & S_IWOTH) != 0) { + details[8] = 'w'; + } + + if ((buf.st_mode & S_IXOTH) != 0) { + details[9] = 'x'; + } + + FSCMD_OUTPUT(" %s", details); } if ((lsflags & LSFLAGS_SIZE) != 0) { diff --git a/os/fs/driver/mtd/mtd_partition.c b/os/fs/driver/mtd/mtd_partition.c index 30d97ee990..80e476982d 100644 --- a/os/fs/driver/mtd/mtd_partition.c +++ b/os/fs/driver/mtd/mtd_partition.c @@ -157,7 +157,7 @@ static int part_procfs_stat(FAR const char *relpath, FAR struct stat *buf); /**************************************************************************** * Private Data ****************************************************************************/ -static struct mtd_partition_s *g_pfirstpartition = NULL; +struct mtd_partition_s *g_pfirstpartition = NULL; #if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_PROCFS_EXCLUDE_PARTITIONS) const struct procfs_operations part_procfsoperations = { diff --git a/os/fs/driver/mtd/smart.c b/os/fs/driver/mtd/smart.c index 60ced57b31..a4010e0912 100644 --- a/os/fs/driver/mtd/smart.c +++ b/os/fs/driver/mtd/smart.c @@ -173,7 +173,6 @@ #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) -#define SECTOR_IS_VALID(h, t) ((UINT8TOUINT16(h.logicalsector) < t || UINT8TOUINT16(h.logicalsector) == 0xffff) ? 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 @@ -184,7 +183,6 @@ #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) -#define SECTOR_IS_VALID(h, t) ((UINT8TOUINT16(h.logicalsector) < t || UINT8TOUINT16(h.logicalsector) == 0x0000) ? 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 @@ -413,15 +411,9 @@ static ssize_t smart_read(FAR struct inode *inode, unsigned char *buffer, size_t #ifdef CONFIG_FS_WRITABLE static ssize_t smart_write(FAR struct inode *inode, const unsigned char *buffer, size_t start_sector, unsigned int nsectors); #endif - -static void initialize_sector_information(uint16_t totalsectors, FAR struct smart_struct_s *dev, uint16_t *prerelease); -static bool smart_validate_erase_block(FAR struct smart_struct_s *dev); -static int smart_scan(FAR struct smart_struct_s *dev); - static int smart_geometry(FAR struct inode *inode, struct geometry *geometry); static int smart_ioctl(FAR struct inode *inode, int cmd, unsigned long arg); -static int find_free_physical_sector(uint16_t allocblock, FAR struct smart_struct_s *dev, uint8_t *sector_buff, uint16_t *physicalsector, bool *bitflipped); static uint16_t smart_findfreephyssector(FAR struct smart_struct_s *dev, uint8_t canrelocate); #ifdef CONFIG_FS_WRITABLE @@ -1702,288 +1694,76 @@ static int smart_set_wear_level(FAR struct smart_struct_s *dev, uint16_t block, * count, etc. * ****************************************************************************/ -static void initialize_sector_information(uint16_t totalsectors, FAR struct smart_struct_s *dev, uint16_t *prerelease) -{ - int sector; - - /* Initialize the freecount and releasecount arrays. */ - - for (sector = 0; sector < dev->neraseblocks; sector++) { - if (sector == dev->neraseblocks - 1 && dev->totalsectors == 65534) { - *prerelease = 2; - } else { - *prerelease = 0; - } - -#ifdef CONFIG_MTD_SMART_PACK_COUNTS - smart_set_count(dev, dev->freecount, sector, dev->availSectPerBlk - *prerelease); - smart_set_count(dev, dev->releasecount, sector, *prerelease); -#else - dev->freecount[sector] = dev->availSectPerBlk - *prerelease; - dev->releasecount[sector] = *prerelease; -#endif - } - - /* Initialize the sector map. */ - -#ifndef CONFIG_MTD_SMART_MINIMIZE_RAM - for (sector = 0; sector < totalsectors; sector++) { - dev->sMap[sector] = -1; - } -#else - /* Clear all logical sector used bits. */ - - memset(dev->sBitMap, 0, (dev->totalsectors + 7) >> 3); -#endif -} - -static bool smart_validate_erase_block(FAR struct smart_struct_s *dev) -{ - FAR struct smart_sect_header_s header; - bool corrupted = false; - int i; - int ret; - - memcpy(&header, dev->rwbuffer, sizeof(struct smart_sect_header_s)); - - /* Check the crc of header first. */ - ret = smart_validate_crc(dev); - if (ret != OK) { - if (HEADER_IS_CLEAN(header)) { - /* If header is erased state, then check contents */ - for (i = sizeof(struct smart_sect_header_s); i < dev->sectorsize; i++) { - if (dev->rwbuffer[i] != CONFIG_SMARTFS_ERASEDSTATE) { - fdbg("It is not Erased value offset %u, %x------------------\n", i, dev->rwbuffer[i]); - corrupted = true; - break; - } - } - } else { - /* If header is not clean & crc is not matched, then it is corrupted sector */ - fdbg("Header is not clean but crc is not matched logical : %d crc : %d sta :%d seq :%d\n", UINT8TOUINT16(header.logicalsector), header.crc8, header.status, header.seq); - corrupted = true; - } - } else { - /* Very rarely, crc can be matched with abnormal header value, so we should check boundary */ - if (!SECTOR_IS_VALID(header, dev->totalsectors)) { - fdbg("header is out of boundary, sector : %x\n", header.logicalsector); - corrupted = true; - } - } - - return corrupted; -} - -#ifdef CONFIG_SMARTFS_BAD_SECTOR -static void generate_bad_sector_information(uint16_t logicalsector, FAR struct smart_struct_s *dev) -{ - if (logicalsector == SMART_BAD_SECTOR_NUMBER) { - int bad_physical_sector_no = -1, bsm_ret; - int sect_header_size = sizeof(struct smart_sect_header_s); // sector header size - int i, j, found_bad_physical_sector; - - if (dev->bad_sector_rwbuffer != NULL) { - bad_physical_sector_no = (uint16_t)(dev->sMap[SMART_BAD_SECTOR_NUMBER]); - - if (bad_physical_sector_no == ERROR) { - fdbg("bad_physical_sector_no not found\n"); - } else { - bsm_ret = MTD_BREAD(dev->mtd, bad_physical_sector_no * dev->mtdBlksPerSector, dev->mtdBlksPerSector, (FAR uint8_t *)dev->bad_sector_rwbuffer); - - if (bsm_ret < 0) { - fdbg("error in sector read %d\n", bad_physical_sector_no); - } else { - int bad_sector_info = dev->totalsectors / dev->sectorsPerBlk; - for (i = sect_header_size; i < bad_sector_info + sect_header_size; i++) { - for (j = 7; j >= 0; j--) { - if (((dev->bad_sector_rwbuffer[i] >> j) & 1) == 0) { - /* byte = 8 bit; left shift 3 byte = 8 */ - found_bad_physical_sector = ((i << 3) + j) - (sect_header_size << 3); - fvdbg("After reboot: Found bad physical sector #%d\n", found_bad_physical_sector); - dev->badSectorList[found_bad_physical_sector] = TRUE; - } - } - } - } - } - } else { - fdbg("Error: dev->bad_sector_rwbuffer is NULL\n"); - } - } -} -#endif -static int check_logical_sector_duplication(FAR struct smart_struct_s *dev, uint16_t logicalsector, struct smart_sect_header_s header, uint32_t *readaddress, uint16_t *winner, int sector) +static int smart_scan(FAR struct smart_struct_s *dev) { + int sector; int ret; - uint16_t seq1; - uint16_t seq2; + uint16_t totalsectors; + uint16_t sectorsize, prerelease; + uint16_t logicalsector; uint16_t loser; + uint16_t winner; + uint32_t readaddress; uint32_t offset; + uint16_t seq1; + uint16_t seq2; + 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; #endif -#ifndef CONFIG_MTD_SMART_MINIMIZE_RAM - if (dev->sMap[logicalsector] != 0xFFFF) -#else - if (dev->sBitMap[logicalsector >> 3] & (1 << (logicalsector & 0x07))) -#endif - { - /* Uh-oh, we found more than 1 physical sector claiming to be - * the same logical sector. Use the sequence number information - * to resolve who wins. - */ - -#if SMART_STATUS_VERSION == 1 - if (header.status & SMART_STATUS_CRC) { - seq2 = header.seq; - } else { - //seq2 = *((FAR uint16_t *)&header.seq); - seq2 = (uint16_t)(((header.crc8 << 8) & 0xFF00) | header.seq); - } -#else - seq2 = header.seq; +#ifdef CONFIG_SMARTFS_MULTI_ROOT_DIRS + int x; + char devname[22]; + FAR struct smart_multiroot_device_s *rootdirdev; #endif + int i; - /* We must re-read the 1st physical sector to get it's seq number. */ + fvdbg("Entry\n"); -#ifndef CONFIG_MTD_SMART_MINIMIZE_RAM - *readaddress = dev->sMap[logicalsector] * dev->mtdBlksPerSector * dev->geo.blocksize; -#else - /* For minimize RAM, we have to rescan to find the 1st sector claiming to - * be this logical sector. - */ + /* Find the sector size on the volume by reading headers from + * sectors of decreasing size. On a formatted volume, the sector + * size is saved in the header status byte of seach sector, so + * by starting with the largest supported sector size and + * decreasing from there, we will be sure to find data that is + * a header and not sector data. + */ - for (dupsector = 0; dupsector < sector; dupsector++) { - /* Calculate the read address for this sector. */ + sectorsize = 0xFFFF; + offset = 16384; - *readaddress = dupsector * dev->mtdBlksPerSector * dev->geo.blocksize; + while (sectorsize == 0xFFFF) { + readaddress = 0; - /* Read the header for this sector. */ + while (readaddress < dev->erasesize * dev->geo.neraseblocks) { + /* Read the next sector from the device. */ - ret = MTD_READ(dev->mtd, *readaddress, sizeof(struct smart_sect_header_s), (FAR uint8_t *)&header); + ret = MTD_READ(dev->mtd, readaddress, sizeof(struct smart_sect_header_s), (FAR uint8_t *)&header); if (ret != sizeof(struct smart_sect_header_s)) { goto err_out; } - /* Get the logical sector number for this physical sector. */ - - duplogsector = *((FAR uint16_t *)header.logicalsector); -#if CONFIG_SMARTFS_ERASEDSTATE == 0x00 - if (duplogsector == 0) { - duplogsector = -1; - } -#endif - - /* Test if this sector has been committed. */ - - if (!SECTOR_IS_COMMITTED(header)) { - continue; - } - - /* Test if this sector has been release and skip it if it has. */ - - if (SECTOR_IS_RELEASED(header)) { - continue; - } - - if ((header.status & SMART_STATUS_VERBITS) != SMART_STATUS_VERSION) { - continue; - } - - /* Now compare if this logical sector matches the current sector. */ - - if (duplogsector == logicalsector) { + if (header.status != CONFIG_SMARTFS_ERASEDSTATE) { + sectorsize = (header.status & SMART_STATUS_SIZEBITS) << 7; break; } - } -#endif - - ret = MTD_READ(dev->mtd, *readaddress, sizeof(struct smart_sect_header_s), (FAR uint8_t *)&header); - if (ret != sizeof(struct smart_sect_header_s)) { - return ERROR; - } -#if SMART_STATUS_VERSION == 1 - if (header.status & SMART_STATUS_CRC) { - seq1 = header.seq; - } else { - seq1 = (uint16_t)(((header.crc8 << 8) & 0xFF00) | header.seq); - } -#else - seq1 = header.seq; -#endif - /* Now determine who wins. */ - - if ((seq1 > 0xFFF0 && seq2 < 10) || seq2 > seq1) { - /* Seq 2 is the winner ... bigger or it wrapped. */ - -#ifndef CONFIG_MTD_SMART_MINIMIZE_RAM - loser = dev->sMap[logicalsector]; - dev->sMap[logicalsector] = sector; -#else - loser = dupsector; -#endif - *winner = sector; - } else { - /* We keep the original mapping and seq2 is the loser. */ - - loser = sector; -#ifndef CONFIG_MTD_SMART_MINIMIZE_RAM - *winner = dev->sMap[logicalsector]; -#else - *winner = smart_cache_lookup(dev, logicalsector); -#endif + readaddress += offset; } - /* Now release the loser sector. */ - - *readaddress = loser * dev->mtdBlksPerSector * dev->geo.blocksize; - ret = MTD_READ(dev->mtd, *readaddress, sizeof(struct smart_sect_header_s), (FAR uint8_t *)&header); - if (ret != sizeof(struct smart_sect_header_s)) { - return ERROR; - } -#if CONFIG_SMARTFS_ERASEDSTATE == 0xFF - header.status &= ~SMART_STATUS_RELEASED; -#else - header.status |= SMART_STATUS_RELEASED; -#endif - offset = *readaddress + offsetof(struct smart_sect_header_s, status); - ret = smart_bytewrite(dev, offset, 1, &header.status); - if (ret < 0) { - fdbg("Error %d releasing duplicate sector\n", -ret); - return ERROR; + offset >>= 1; + if (offset < 256 && sectorsize == 0xFFFF) { + sectorsize = CONFIG_MTD_SMART_SECTOR_SIZE; } } - return OK; -} -static int smart_scan(FAR struct smart_struct_s *dev) -{ - int sector; - int ret; - uint16_t totalsectors; - uint16_t prerelease; - uint16_t logicalsector; - uint16_t winner; - uint32_t readaddress; - struct smart_sect_header_s header; - uint8_t *sector_seq_log = NULL; - bool status_released; - bool status_committed; -#ifdef CONFIG_SMARTFS_MULTI_ROOT_DIRS - int x; - char devname[22]; - FAR struct smart_multiroot_device_s *rootdirdev; -#endif - - fvdbg("Entry\n"); + /* Now set the sectorsize and other sectorsize derived variables. */ - // ToDo: Revert to the flexible logic that searches sectors and - // reads sector sizes stored in the sectors instead of - // using CONFIG_MTD_SMART_SECTOR_SIZE. - ret = smart_setsectorsize(dev, CONFIG_MTD_SMART_SECTOR_SIZE); + ret = smart_setsectorsize(dev, sectorsize); if (ret != OK) { goto err_out; } @@ -2003,7 +1783,35 @@ static int smart_scan(FAR struct smart_struct_s *dev) dev->freesectors = dev->availSectPerBlk * dev->geo.neraseblocks; dev->releasesectors = 0; - initialize_sector_information(totalsectors, dev, &prerelease); + /* Initialize the freecount and releasecount arrays. */ + + for (sector = 0; sector < dev->neraseblocks; sector++) { + if (sector == dev->neraseblocks - 1 && dev->totalsectors == 65534) { + prerelease = 2; + } else { + prerelease = 0; + } + +#ifdef CONFIG_MTD_SMART_PACK_COUNTS + smart_set_count(dev, dev->freecount, sector, dev->availSectPerBlk - prerelease); + smart_set_count(dev, dev->releasecount, sector, prerelease); +#else + dev->freecount[sector] = dev->availSectPerBlk - prerelease; + dev->releasecount[sector] = prerelease; +#endif + } + + /* Initialize the sector map. */ + +#ifndef CONFIG_MTD_SMART_MINIMIZE_RAM + for (sector = 0; sector < totalsectors; sector++) { + dev->sMap[sector] = -1; + } +#else + /* Clear all logical sector used bits. */ + + memset(dev->sBitMap, 0, (dev->totalsectors + 7) >> 3); +#endif /* Now scan the MTD device. */ sector_seq_log = (uint8_t *)kmm_zalloc(sizeof(uint8_t) * totalsectors); @@ -2015,13 +1823,14 @@ 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. */ readaddress = sector * dev->mtdBlksPerSector * dev->geo.blocksize; - /* Read the whole data of this sector. */ + /* Read the header for this sector. */ ret = MTD_BREAD(dev->mtd, sector * dev->mtdBlksPerSector, dev->mtdBlksPerSector, (uint8_t *)dev->rwbuffer); if (ret != dev->mtdBlksPerSector) { @@ -2029,27 +1838,48 @@ static int smart_scan(FAR struct smart_struct_s *dev) goto err_out; } - /* copy header data only, will be used below */ - memcpy(&header, dev->rwbuffer, sizeof(struct smart_sect_header_s)); - - /* If the current sector is corrupted due to erase failure, restore it */ - if (smart_validate_erase_block(dev)) { - fdbg("It seems that erase failed, release current sector. block : %d sector : %d\n", sector / dev->sectorsPerBlk, sector); - - /* Erase the current block forcely */ - + ret = smart_validate_crc(dev); + if (ret != OK) { + if (HEADER_IS_CLEAN(header)) { + /* Header is cleaned but all blocks are not cleaned, it means corruption occurs during erasing. */ + 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); + header.status = header.status & ~(SMART_STATUS_COMMITTED | SMART_STATUS_RELEASED); #else - header.status = header.status | SMART_STATUS_COMMITTED | SMART_STATUS_RELEASED; + 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; + ret = smart_bytewrite(dev, readaddress + offsetof(struct smart_sect_header_s, status), 1, &header.status); + if (ret < 0) { + goto err_out; + } + } } + /* Get the logical sector number for this physical sector. */ logicalsector = UINT8TOUINT16(header.logicalsector); #if CONFIG_SMARTFS_ERASEDSTATE == 0x00 @@ -2071,7 +1901,39 @@ static int smart_scan(FAR struct smart_struct_s *dev) /* Generate bad sector information from start. */ #ifdef CONFIG_SMARTFS_BAD_SECTOR - generate_bad_sector_information(dev, logicalsector); + if (logicalsector == SMART_BAD_SECTOR_NUMBER) { + int bad_physical_sector_no = -1, bsm_ret; + int sect_header_size = sizeof(struct smart_sect_header_s); // sector header size + int i, j, found_bad_physical_sector; + + if (dev->bad_sector_rwbuffer != NULL) { + bad_physical_sector_no = (uint16_t)(dev->sMap[SMART_BAD_SECTOR_NUMBER]); + + if (bad_physical_sector_no == ERROR) { + fdbg("bad_physical_sector_no not found\n"); + } else { + bsm_ret = MTD_BREAD(dev->mtd, bad_physical_sector_no * dev->mtdBlksPerSector, dev->mtdBlksPerSector, (FAR uint8_t *)dev->bad_sector_rwbuffer); + + if (bsm_ret < 0) { + fdbg("error in sector read %d\n", bad_physical_sector_no); + } else { + int bad_sector_info = dev->totalsectors / dev->sectorsPerBlk; + for (i = sect_header_size; i < bad_sector_info + sect_header_size; i++) { + for (j = 7; j >= 0; j--) { + if (((dev->bad_sector_rwbuffer[i] >> j) & 1) == 0) { + /* byte = 8 bit; left shift 3 byte = 8 */ + found_bad_physical_sector = ((i << 3) + j) - (sect_header_size << 3); + fvdbg("After reboot: Found bad physical sector #%d\n", found_bad_physical_sector); + dev->badSectorList[found_bad_physical_sector] = TRUE; + } + } + } + } + } + } else { + fdbg("Error: dev->bad_sector_rwbuffer is NULL\n"); + } + } //if(logicalsector == SMART_BAD_SECTOR_NUMBER) #endif /*CONFIG_SMARTFS_BAD_SECTOR */ } else { fvdbg("logicalsector : physicalsector -> %d : %d; status_released: %d, status_committed: %d\n", logicalsector, sector, status_released, status_committed); @@ -2199,11 +2061,138 @@ static int smart_scan(FAR struct smart_struct_s *dev) /* Test for duplicate logical sectors on the device. */ - ret = check_logical_sector_duplication(dev, logicalsector, header, &readaddress, &winner, sector); - if (ret < 0) { - goto err_out; - } +#ifndef CONFIG_MTD_SMART_MINIMIZE_RAM + if (dev->sMap[logicalsector] != 0xFFFF) +#else + if (dev->sBitMap[logicalsector >> 3] & (1 << (logicalsector & 0x07))) +#endif + { + /* Uh-oh, we found more than 1 physical sector claiming to be + * the same logical sector. Use the sequence number information + * to resolve who wins. + */ + +#if SMART_STATUS_VERSION == 1 + if (header.status & SMART_STATUS_CRC) { + seq2 = header.seq; + } else { + //seq2 = *((FAR uint16_t *)&header.seq); + seq2 = (uint16_t)(((header.crc8 << 8) & 0xFF00) | header.seq); + } +#else + seq2 = header.seq; +#endif + + /* We must re-read the 1st physical sector to get it's seq number. */ +#ifndef CONFIG_MTD_SMART_MINIMIZE_RAM + readaddress = dev->sMap[logicalsector] * dev->mtdBlksPerSector * dev->geo.blocksize; +#else + /* For minimize RAM, we have to rescan to find the 1st sector claiming to + * be this logical sector. + */ + + for (dupsector = 0; dupsector < sector; dupsector++) { + /* Calculate the read address for this sector. */ + + readaddress = dupsector * dev->mtdBlksPerSector * dev->geo.blocksize; + + /* 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)) { + goto err_out; + } + + /* Get the logical sector number for this physical sector. */ + + duplogsector = *((FAR uint16_t *)header.logicalsector); +#if CONFIG_SMARTFS_ERASEDSTATE == 0x00 + if (duplogsector == 0) { + duplogsector = -1; + } +#endif + + /* Test if this sector has been committed. */ + + if (!SECTOR_IS_COMMITTED(header)) { + continue; + } + + /* Test if this sector has been release and skip it if it has. */ + + if (SECTOR_IS_RELEASED(header)) { + continue; + } + + if ((header.status & SMART_STATUS_VERBITS) != SMART_STATUS_VERSION) { + continue; + } + + /* Now compare if this logical sector matches the current sector. */ + + if (duplogsector == logicalsector) { + break; + } + } +#endif + + ret = MTD_READ(dev->mtd, readaddress, sizeof(struct smart_sect_header_s), (FAR uint8_t *)&header); + if (ret != sizeof(struct smart_sect_header_s)) { + goto err_out; + } +#if SMART_STATUS_VERSION == 1 + if (header.status & SMART_STATUS_CRC) { + seq1 = header.seq; + } else { + seq1 = (uint16_t)(((header.crc8 << 8) & 0xFF00) | header.seq); + } +#else + seq1 = header.seq; +#endif + + /* Now determine who wins. */ + + if ((seq1 > 0xFFF0 && seq2 < 10) || seq2 > seq1) { + /* Seq 2 is the winner ... bigger or it wrapped. */ + +#ifndef CONFIG_MTD_SMART_MINIMIZE_RAM + loser = dev->sMap[logicalsector]; + dev->sMap[logicalsector] = sector; +#else + loser = dupsector; +#endif + winner = sector; + } else { + /* We keep the original mapping and seq2 is the loser. */ + + loser = sector; +#ifndef CONFIG_MTD_SMART_MINIMIZE_RAM + winner = dev->sMap[logicalsector]; +#else + winner = smart_cache_lookup(dev, logicalsector); +#endif + } + + /* Now release the loser sector. */ + + readaddress = loser * dev->mtdBlksPerSector * dev->geo.blocksize; + ret = MTD_READ(dev->mtd, readaddress, sizeof(struct smart_sect_header_s), (FAR uint8_t *)&header); + if (ret != sizeof(struct smart_sect_header_s)) { + goto err_out; + } +#if CONFIG_SMARTFS_ERASEDSTATE == 0xFF + header.status &= ~SMART_STATUS_RELEASED; +#else + header.status |= SMART_STATUS_RELEASED; +#endif + offset = readaddress + offsetof(struct smart_sect_header_s, status); + ret = smart_bytewrite(dev, offset, 1, &header.status); + if (ret < 0) { + fdbg("Error %d releasing duplicate sector\n", -ret); + goto err_out; + } + } #ifndef CONFIG_MTD_SMART_MINIMIZE_RAM /* Update the logical to physical sector map. */ @@ -3006,6 +2995,8 @@ static int smart_relocate_sector(FAR struct smart_struct_s *dev, uint16_t oldsec FAR struct smart_sect_header_s *header; uint8_t newstatus; + fvdbg("Entry\n"); + header = (FAR struct smart_sect_header_s *)dev->rwbuffer; /* Increment the sequence number and clear the "commit" flag. */ @@ -3135,6 +3126,8 @@ static int smart_relocate_block(FAR struct smart_struct_s *dev, uint16_t block) FAR struct smart_allocsector_s *allocsector; #endif + fvdbg("Entry\n"); + /* Perform collection on block with the most released sectors. * First mark the block as having no free sectors so we don't * try to move sectors into the block we are trying to erase. @@ -3359,109 +3352,6 @@ static int smart_relocate_block(FAR struct smart_struct_s *dev, uint16_t block) return ret; } -static int find_free_physical_sector(uint16_t allocblock, FAR struct smart_struct_s *dev, uint8_t *sector_buff, uint16_t *physicalsector, bool *bitflipped) -{ - int x; - int i; - int ret = -1; - uint32_t readaddr; - struct smart_sect_header_s header; - - for (x = allocblock * dev->sectorsPerBlk; x < allocblock * dev->sectorsPerBlk + dev->availSectPerBlk; x++) { - /* Check if this physical sector is available. */ - -#ifdef CONFIG_MTD_SMART_ENABLE_CRC - /* First check if there is a temporary alloc in place. */ - - FAR struct smart_allocsector_s *allocsect; - allocsect = dev->allocsector; - - while (allocsect) { - if (allocsect->physical == x) { - break; - } - allocsect = allocsect->next; - } - - /* If we found this physical sector above, then continue on - * to the next physical sector in this block ... this one has - * a temporary allocation assigned. - */ - - if (allocsect) { - continue; - } -#endif - - /* Now check on the physical media. */ - - readaddr = x * dev->mtdBlksPerSector * dev->geo.blocksize; - ret = MTD_READ(dev->mtd, readaddr, sizeof(struct smart_sect_header_s), (FAR uint8_t *)&header); - if (ret != sizeof(struct smart_sect_header_s)) { - fdbg("Error reading phys sector %d\n", physicalsector); - kmm_free(sector_buff); - return -1; - } - if ((UINT8TOUINT16(header.logicalsector) == 0xFFFF) && -#if SMART_STATUS_VERSION == 1 - ((header.seq == 0xFF) && (header.crc8 == 0xFF)) && -#else - (header.seq == CONFIG_SMARTFS_ERASEDSTATE) && -#endif - (!(SECTOR_IS_COMMITTED(header)))) { -#ifdef CONFIG_SMARTFS_BAD_SECTOR - if (dev->badSectorList[x] == FALSE) { -#endif - ret = MTD_READ(dev->mtd, readaddr, dev->mtdBlksPerSector * dev->geo.blocksize, sector_buff); - if (ret != dev->mtdBlksPerSector * dev->geo.blocksize) { - fdbg("Error reading physical sector %d\n", physicalsector); - kmm_free(sector_buff); - return -1; - } - for (i = 0; i < dev->mtdBlksPerSector * dev->geo.blocksize; i++) { - if (sector_buff[i] != 0xff) { - break; - } - } - - if (i == dev->mtdBlksPerSector * dev->geo.blocksize) { - *physicalsector = x; - dev->lastallocblock = allocblock; - break; - } else { - *bitflipped = TRUE; - fdbg("bit flip occur %d offset %d byte %x\n", x, i, sector_buff[i]); - fdbg("set Released and commited to Erase%d\n", x); -#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, readaddr + offsetof(struct smart_sect_header_s, status), 1, &header.status); - if (ret < 0) { - fdbg("Error %d releasing corrupted sector\n", -ret); - goto errout; - } -#ifdef CONFIG_MTD_SMART_PACK_COUNTS - smart_add_count(dev, dev->freecount, x / dev->sectorsPerBlk, -1); - smart_add_count(dev, dev->releasecount, allocblock, 1); -#else - dev->freecount[x / dev->sectorsPerBlk]--; - dev->releasecount[allocblock]++; -#endif - dev->freesectors--; - dev->releasesectors++; - } -#ifdef CONFIG_SMARTFS_BAD_SECTOR - } -#endif - } - } - -errout: - return ret; -} - /**************************************************************************** * Name: smart_findfreephyssector * @@ -3480,8 +3370,11 @@ static uint16_t smart_findfreephyssector(FAR struct smart_struct_s *dev, uint8_t #endif uint16_t physicalsector; uint16_t x, block; + uint32_t readaddr; + struct smart_sect_header_s header; int ret; uint8_t *sector_buff; + int i; bool bitflipped; /* Determine which erase block we should allocate the new * sector from. This is based on the number of free sectors @@ -3607,19 +3500,104 @@ static uint16_t smart_findfreephyssector(FAR struct smart_struct_s *dev, uint8_t /* Now find a free physical sector within this selected * erase block to allocate. */ - sector_buff = (uint8_t *)kmm_zalloc(dev->mtdBlksPerSector * dev->geo.blocksize); if (sector_buff == NULL) { fdbg("sector_buff allocation fail\n"); return physicalsector; } - ret = find_free_physical_sector(allocblock, dev, sector_buff, &physicalsector, &bitflipped); - if (ret < 0) { - fdbg("Failed to find a free physical sector..\n"); - return ret; + for (x = allocblock * dev->sectorsPerBlk; x < allocblock * dev->sectorsPerBlk + dev->availSectPerBlk; x++) { + /* Check if this physical sector is available. */ + +#ifdef CONFIG_MTD_SMART_ENABLE_CRC + /* First check if there is a temporary alloc in place. */ + + FAR struct smart_allocsector_s *allocsect; + allocsect = dev->allocsector; + + while (allocsect) { + if (allocsect->physical == x) { + break; + } + allocsect = allocsect->next; + } + + /* If we found this physical sector above, then continue on + * to the next physical sector in this block ... this one has + * a temporary allocation assigned. + */ + + if (allocsect) { + continue; + } +#endif + + /* Now check on the physical media. */ + + readaddr = x * dev->mtdBlksPerSector * dev->geo.blocksize; + ret = MTD_READ(dev->mtd, readaddr, sizeof(struct smart_sect_header_s), (FAR uint8_t *)&header); + if (ret != sizeof(struct smart_sect_header_s)) { + fdbg("Error reading phys sector %d\n", physicalsector); + kmm_free(sector_buff); + return -1; + } + if ((UINT8TOUINT16(header.logicalsector) == 0xFFFF) && +#if SMART_STATUS_VERSION == 1 + ((header.seq == 0xFF) && (header.crc8 == 0xFF)) && +#else + (header.seq == CONFIG_SMARTFS_ERASEDSTATE) && +#endif + (!(SECTOR_IS_COMMITTED(header)))) { +#ifdef CONFIG_SMARTFS_BAD_SECTOR + if (dev->badSectorList[x] == FALSE) { +#endif + ret = MTD_READ(dev->mtd, readaddr, dev->mtdBlksPerSector * dev->geo.blocksize, sector_buff); + if (ret != dev->mtdBlksPerSector * dev->geo.blocksize) { + fdbg("Error reading physical sector %d\n", physicalsector); + kmm_free(sector_buff); + return -1; + } + for (i = 0; i < dev->mtdBlksPerSector * dev->geo.blocksize; i++) { + if (sector_buff[i] != 0xff) { + break; + } + } + + if (i == dev->mtdBlksPerSector * dev->geo.blocksize) { + physicalsector = x; + dev->lastallocblock = allocblock; + break; + } else { + bitflipped = TRUE; + fdbg("bit flip occur %d offset %d byte %x\n", x, i, sector_buff[i]); + fdbg("set Released and commited to Erase%d\n", x); +#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, readaddr + offsetof(struct smart_sect_header_s, status), 1, &header.status); + if (ret < 0) { + fdbg("Error %d releasing corrupted sector\n", -ret); + goto error; + } +#ifdef CONFIG_MTD_SMART_PACK_COUNTS + smart_add_count(dev, dev->freecount, x / dev->sectorsPerBlk, -1); + smart_add_count(dev, dev->releasecount, allocblock, 1); +#else + dev->freecount[x / dev->sectorsPerBlk]--; + dev->releasecount[allocblock]++; +#endif + dev->freesectors--; + dev->releasesectors++; + } +#ifdef CONFIG_SMARTFS_BAD_SECTOR + } +#endif + } } +error: if (physicalsector == 0xFFFF || physicalsector >= dev->totalsectors) { if (bitflipped) { fdbg("retry allocation \n"); diff --git a/os/fs/smartfs/smartfs_smart.c b/os/fs/smartfs/smartfs_smart.c index de9fa8a866..2d8e926726 100644 --- a/os/fs/smartfs/smartfs_smart.c +++ b/os/fs/smartfs/smartfs_smart.c @@ -93,7 +93,6 @@ static int smartfs_open(FAR struct file *filep, const char *relpath, int oflags, mode_t mode); static int smartfs_close(FAR struct file *filep); static ssize_t smartfs_read(FAR struct file *filep, char *buffer, size_t buflen); -static int allocate_new_sector(size_t buflen, struct smartfs_mountpt_s *fs, struct smartfs_chain_header_s *header, struct smart_read_write_s *readwrite, struct smartfs_ofile_s *sf); static ssize_t smartfs_write(FAR struct file *filep, const char *buffer, size_t buflen); static off_t smartfs_seek(FAR struct file *filep, off_t offset, int whence); static int smartfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg); @@ -713,73 +712,6 @@ static int smartfs_sync_internal(struct smartfs_mountpt_s *fs, struct smartfs_of return ret; } -static int allocate_new_sector(size_t buflen, struct smartfs_mountpt_s *fs, struct smartfs_chain_header_s *header, struct smart_read_write_s *readwrite, struct smartfs_ofile_s *sf) -{ - int ret = OK; -#ifdef CONFIG_SMARTFS_JOURNALING - int retj; - uint16_t t_sector; - uint16_t t_offset; -#endif - - if (buflen > 0) { - /* Allocate a new sector */ - - ret = FS_IOCTL(fs, BIOC_ALLOCSECT, 0xFFFF); - if (ret < 0) { - fdbg("Error %d allocating new sector\n", ret); - goto errout_with_semaphore; - } - - /* Copy the new sector to the old one and chain it */ - - header = (struct smartfs_chain_header_s *)fs->fs_rwbuffer; - header->nextsector[0] = (uint8_t)(ret & 0x00FF); - header->nextsector[1] = (uint8_t)((ret >> 8) & 0x00FF); - - readwrite->offset = offsetof(struct smartfs_chain_header_s, nextsector); - readwrite->buffer = (uint8_t *)header->nextsector; - readwrite->count = sizeof(uint16_t); -#ifdef CONFIG_SMARTFS_JOURNALING - ret = smartfs_create_journalentry(fs, T_WRITE, readwrite->logsector, - readwrite->offset, readwrite->count, 0, 0, readwrite->buffer, &t_sector, &t_offset); - if (ret != OK) { - fdbg("Journal entry creation failed.\n"); - goto errout_with_semaphore; - } -#endif - ret = FS_IOCTL(fs, BIOC_WRITESECT, (unsigned long)readwrite); -#ifdef CONFIG_SMARTFS_JOURNALING - retj = smartfs_finish_journalentry(fs, 0, t_sector, t_offset, T_WRITE); - if (retj != OK) { - fdbg("Error finishing transaction\n"); - ret = retj; - goto errout_with_semaphore; - } -#endif - if (ret < 0) { - fdbg("Error %d writing next sector\n", ret); - goto errout_with_semaphore; - } - - /* Record the new sector in our tracking variables and - * reset the offset to "zero". - */ - - if (sf->currsector == SMARTFS_NEXTSECTOR(header)) { - /* Error allocating logical sector! */ - - fdbg("Error - duplicate logical sector %d\n", sf->currsector); - } - - sf->currsector = SMARTFS_NEXTSECTOR(header); - sf->curroffset = sizeof(struct smartfs_chain_header_s); - } - -errout_with_semaphore: - return ret; -} - /**************************************************************************** * Name: smartfs_write ****************************************************************************/ @@ -792,7 +724,7 @@ static ssize_t smartfs_write(FAR struct file *filep, const char *buffer, size_t struct smart_read_write_s readwrite; struct smartfs_chain_header_s *header; size_t byteswritten; - int ret = OK; + int ret; #ifdef CONFIG_SMARTFS_JOURNALING int retj; @@ -1030,9 +962,58 @@ static ssize_t smartfs_write(FAR struct file *filep, const char *buffer, size_t /* Allocate a new sector if needed */ - ret = allocate_new_sector(buflen, fs, header, &readwrite, sf); - if (ret < 0) { - goto errout_with_semaphore; + if (buflen > 0) { + /* Allocate a new sector */ + + ret = FS_IOCTL(fs, BIOC_ALLOCSECT, 0xFFFF); + if (ret < 0) { + fdbg("Error %d allocating new sector\n", ret); + goto errout_with_semaphore; + } + + /* Copy the new sector to the old one and chain it */ + + header = (struct smartfs_chain_header_s *)fs->fs_rwbuffer; + header->nextsector[0] = (uint8_t)(ret & 0x00FF); + header->nextsector[1] = (uint8_t)((ret >> 8) & 0x00FF); + + readwrite.offset = offsetof(struct smartfs_chain_header_s, nextsector); + readwrite.buffer = (uint8_t *)header->nextsector; + readwrite.count = sizeof(uint16_t); +#ifdef CONFIG_SMARTFS_JOURNALING + ret = smartfs_create_journalentry(fs, T_WRITE, readwrite.logsector, + readwrite.offset, readwrite.count, 0, 0, readwrite.buffer, &t_sector, &t_offset); + if (ret != OK) { + fdbg("Journal entry creation failed.\n"); + goto errout_with_semaphore; + } +#endif + ret = FS_IOCTL(fs, BIOC_WRITESECT, (unsigned long)&readwrite); +#ifdef CONFIG_SMARTFS_JOURNALING + retj = smartfs_finish_journalentry(fs, 0, t_sector, t_offset, T_WRITE); + if (retj != OK) { + fdbg("Error finishing transaction\n"); + ret = retj; + goto errout_with_semaphore; + } +#endif + if (ret < 0) { + fdbg("Error %d writing next sector\n", ret); + goto errout_with_semaphore; + } + + /* Record the new sector in our tracking variables and + * reset the offset to "zero". + */ + + if (sf->currsector == SMARTFS_NEXTSECTOR(header)) { + /* Error allocating logical sector! */ + + fdbg("Error - duplicate logical sector %d\n", sf->currsector); + } + + sf->currsector = SMARTFS_NEXTSECTOR(header); + sf->curroffset = sizeof(struct smartfs_chain_header_s); } } #endif /* CONFIG_SMARTFS_USE_SECTOR_BUFFER */ diff --git a/os/fs/smartfs/smartfs_utils.c b/os/fs/smartfs/smartfs_utils.c index 0a86c83449..aca569c440 100644 --- a/os/fs/smartfs/smartfs_utils.c +++ b/os/fs/smartfs/smartfs_utils.c @@ -766,152 +766,6 @@ int smartfs_unmount(struct smartfs_mountpt_s *fs) * ****************************************************************************/ -static int search_entry(uint16_t *offset, struct smartfs_entry_header_s *entry, struct smart_read_write_s *readwrite, uint16_t entrysize, struct smartfs_mountpt_s *fs, const char *ptr, struct smartfs_entry_s *direntry, struct smartfs_chain_header_s *header, const char **filename, uint16_t *parentdirsector, uint16_t *dirstack, uint16_t *depth, uint16_t *dirsector, const char **segment) -{ - int ret; - - while (*offset < readwrite->count) { - /* Test if this entry is valid and active */ - - if (!(ENTRY_VALID(entry))) { - /* This entry isn't valid, skip it */ - - *offset += entrysize; - entry = (struct smartfs_entry_header_s *)&fs->fs_rwbuffer[*offset]; - - continue; - } - - /* Test if the name matches */ - - if (strncmp(entry->name, fs->fs_workbuffer, fs->fs_llformat.namesize) == 0) { - /* We found it! If this is the last segment entry, - * then report the entry. If it isn't the last - * entry, then validate it is a directory entry and - * open it and continue searching. - */ - - if (*ptr == '\0') { - /* We are at the last segment. Report the entry */ - - /* Fill in the entry */ - -#ifdef CONFIG_SMARTFS_ALIGNED_ACCESS - direntry->firstsector = smartfs_rdle16(&entry->firstsector); - direntry->flags = smartfs_rdle16(&entry->flags); - direntry->utc = smartfs_rdle32(&entry->utc); -#else - direntry->firstsector = entry->firstsector; - direntry->flags = entry->flags; - direntry->utc = entry->utc; -#endif - direntry->dsector = readwrite->logsector; - direntry->doffset = *offset; - direntry->dfirst = dirstack[*depth]; - if (direntry->name == NULL) { - direntry->name = (char *)kmm_malloc(fs->fs_llformat.namesize + 1); - if (direntry->name == NULL) { - return ERROR; - } - } - - memset(direntry->name, 0, fs->fs_llformat.namesize + 1); - strncpy(direntry->name, entry->name, fs->fs_llformat.namesize); - direntry->datlen = 0; - - /* Scan the file's sectors to calculate the length and perform - * a rudimentary check. - */ - -#ifdef CONFIG_SMARTFS_ALIGNED_ACCESS - if ((smartfs_rdle16(&entry->flags) & SMARTFS_DIRENT_TYPE) == SMARTFS_DIRENT_TYPE_FILE) { - *dirsector = smartfs_rdle16(&entry->firstsector); -#else - if ((entry->flags & SMARTFS_DIRENT_TYPE) == SMARTFS_DIRENT_TYPE_FILE) { - *dirsector = entry->firstsector; -#endif - readwrite->count = sizeof(struct smartfs_chain_header_s); - readwrite->buffer = (uint8_t *)fs->fs_rwbuffer; - readwrite->offset = 0; - - while (*dirsector != SMARTFS_ERASEDSTATE_16BIT) { - /* Read the next sector of the file */ - - readwrite->logsector = *dirsector; - ret = FS_IOCTL(fs, BIOC_READSECT, (unsigned long)readwrite); - if (ret < 0) { - fdbg("Error in sector chain at %d!\n", *dirsector); - break; - } -#ifdef CONFIG_SMARTFS_DYNAMIC_HEADER - if (SMARTFS_NEXTSECTOR(header) == SMARTFS_ERASEDSTATE_16BIT) { - - readwrite->count = fs->fs_llformat.availbytes; - readwrite->buffer = (uint8_t *)fs->fs_chunk_buffer; - - ret = FS_IOCTL(fs, BIOC_READSECT, (unsigned long)readwrite); - if (ret < 0) { - fdbg("Error %d reading sector %d header\n", ret, sf->currsector); - break; - } - used_value = get_leftover_used_byte_count((uint8_t *)readwrite->buffer, get_used_byte_count((uint8_t *)header->used)); - direntry->datlen += used_value; - } else { - direntry->datlen += (fs->fs_llformat.availbytes - sizeof(struct smartfs_chain_header_s)); - } - readwrite->buffer = (uint8_t *)fs->fs_rwbuffer; -#else - /* Add used bytes to the total and point to next sector */ - if (SMARTFS_USED(header) != SMARTFS_ERASEDSTATE_16BIT) { - direntry->datlen += SMARTFS_USED(header); - } -#endif - *dirsector = SMARTFS_NEXTSECTOR(header); - } - } - *parentdirsector = dirstack[*depth]; - *filename = *segment; - return OK; - } else { - /* Validate it's a directory */ - -#ifdef CONFIG_SMARTFS_ALIGNED_ACCESS - if ((smartfs_rdle16(&entry->flags) & SMARTFS_DIRENT_TYPE) != SMARTFS_DIRENT_TYPE_DIR) -#else - if ((entry->flags & SMARTFS_DIRENT_TYPE) != SMARTFS_DIRENT_TYPE_DIR) -#endif - { - /* Not a directory! Report the error */ - - return -ENOTDIR; - } - - /* "Push" the directory and continue searching */ - - if (*depth >= CONFIG_SMARTFS_DIRDEPTH - 1) { - /* Directory depth too big */ - - return -ENAMETOOLONG; - } -#ifdef CONFIG_SMARTFS_ALIGNED_ACCESS - dirstack[++(*depth)] = smartfs_rdle16(&entry->firstsector); -#else - dirstack[++(*depth)] = entry->firstsector; -#endif - *segment = ptr + 1; - break; - } - } - - /* Not this entry. Skip to the next one */ - - *offset += entrysize; - entry = (struct smartfs_entry_header_s *)&fs->fs_rwbuffer[*offset]; - } - - return 1; -} - int smartfs_finddirentry(struct smartfs_mountpt_s *fs, struct smartfs_entry_s *direntry, const char *relpath, uint16_t *parentdirsector, const char **filename) { int ret = -ENOENT; @@ -1031,9 +885,150 @@ int smartfs_finddirentry(struct smartfs_mountpt_s *fs, struct smartfs_entry_s *d offset = sizeof(struct smartfs_chain_header_s); entry = (struct smartfs_entry_header_s *)&fs->fs_rwbuffer[offset]; - ret = search_entry(&offset, entry, &readwrite, entrysize, fs, ptr, direntry, header, filename, parentdirsector, dirstack, &depth, &dirsector, &segment); - if (ret <= 0) { - goto errout; + while (offset < readwrite.count) { + /* Test if this entry is valid and active */ + + if (!(ENTRY_VALID(entry))) { + /* This entry isn't valid, skip it */ + + offset += entrysize; + entry = (struct smartfs_entry_header_s *) + &fs->fs_rwbuffer[offset]; + + continue; + } + + /* Test if the name matches */ + + if (strncmp(entry->name, fs->fs_workbuffer, fs->fs_llformat.namesize) == 0) { + /* We found it! If this is the last segment entry, + * then report the entry. If it isn't the last + * entry, then validate it is a directory entry and + * open it and continue searching. + */ + + if (*ptr == '\0') { + /* We are at the last segment. Report the entry */ + + /* Fill in the entry */ + +#ifdef CONFIG_SMARTFS_ALIGNED_ACCESS + direntry->firstsector = smartfs_rdle16(&entry->firstsector); + direntry->flags = smartfs_rdle16(&entry->flags); + direntry->utc = smartfs_rdle32(&entry->utc); +#else + direntry->firstsector = entry->firstsector; + direntry->flags = entry->flags; + direntry->utc = entry->utc; +#endif + direntry->dsector = readwrite.logsector; + direntry->doffset = offset; + direntry->dfirst = dirstack[depth]; + if (direntry->name == NULL) { + direntry->name = (char *)kmm_malloc(fs->fs_llformat.namesize + 1); + if (direntry->name == NULL) { + ret = ERROR; + goto errout; + } + } + + memset(direntry->name, 0, fs->fs_llformat.namesize + 1); + strncpy(direntry->name, entry->name, fs->fs_llformat.namesize); + direntry->datlen = 0; + + /* Scan the file's sectors to calculate the length and perform + * a rudimentary check. + */ + +#ifdef CONFIG_SMARTFS_ALIGNED_ACCESS + if ((smartfs_rdle16(&entry->flags) & SMARTFS_DIRENT_TYPE) == SMARTFS_DIRENT_TYPE_FILE) { + dirsector = smartfs_rdle16(&entry->firstsector); +#else + if ((entry->flags & SMARTFS_DIRENT_TYPE) == SMARTFS_DIRENT_TYPE_FILE) { + dirsector = entry->firstsector; +#endif + readwrite.count = sizeof(struct smartfs_chain_header_s); + readwrite.buffer = (uint8_t *)fs->fs_rwbuffer; + readwrite.offset = 0; + + while (dirsector != SMARTFS_ERASEDSTATE_16BIT) { + /* Read the next sector of the file */ + + readwrite.logsector = dirsector; + ret = FS_IOCTL(fs, BIOC_READSECT, (unsigned long)&readwrite); + if (ret < 0) { + fdbg("Error in sector chain at %d!\n", dirsector); + break; + } +#ifdef CONFIG_SMARTFS_DYNAMIC_HEADER + if (SMARTFS_NEXTSECTOR(header) == SMARTFS_ERASEDSTATE_16BIT) { + + readwrite.count = fs->fs_llformat.availbytes; + readwrite.buffer = (uint8_t *)fs->fs_chunk_buffer; + + ret = FS_IOCTL(fs, BIOC_READSECT, (unsigned long)&readwrite); + if (ret < 0) { + fdbg("Error %d reading sector %d header\n", ret, sf->currsector); + break; + } + used_value = get_leftover_used_byte_count((uint8_t *)readwrite.buffer, get_used_byte_count((uint8_t *)header->used)); + direntry->datlen += used_value; + } else { + direntry->datlen += (fs->fs_llformat.availbytes - sizeof(struct smartfs_chain_header_s)); + } + readwrite.buffer = (uint8_t *)fs->fs_rwbuffer; +#else + /* Add used bytes to the total and point to next sector */ + if (SMARTFS_USED(header) != SMARTFS_ERASEDSTATE_16BIT) { + direntry->datlen += SMARTFS_USED(header); + } +#endif + dirsector = SMARTFS_NEXTSECTOR(header); + } + } + + *parentdirsector = dirstack[depth]; + *filename = segment; + ret = OK; + goto errout; + } else { + /* Validate it's a directory */ + +#ifdef CONFIG_SMARTFS_ALIGNED_ACCESS + if ((smartfs_rdle16(&entry->flags) & SMARTFS_DIRENT_TYPE) != SMARTFS_DIRENT_TYPE_DIR) +#else + if ((entry->flags & SMARTFS_DIRENT_TYPE) != SMARTFS_DIRENT_TYPE_DIR) +#endif + { + /* Not a directory! Report the error */ + + ret = -ENOTDIR; + goto errout; + } + + /* "Push" the directory and continue searching */ + + if (depth >= CONFIG_SMARTFS_DIRDEPTH - 1) { + /* Directory depth too big */ + + ret = -ENAMETOOLONG; + goto errout; + } +#ifdef CONFIG_SMARTFS_ALIGNED_ACCESS + dirstack[++depth] = smartfs_rdle16(&entry->firstsector); +#else + dirstack[++depth] = entry->firstsector; +#endif + segment = ptr + 1; + break; + } + } + + /* Not this entry. Skip to the next one */ + + offset += entrysize; + entry = (struct smartfs_entry_header_s *) + &fs->fs_rwbuffer[offset]; } /* Test if a directory entry was found and break if it was */ @@ -1900,77 +1895,10 @@ int smartfs_recover(struct smartfs_mountpt_s *fs) #endif #ifdef CONFIG_SMARTFS_JOURNALING -int execute_unfinished_journal_data(struct smartfs_mountpt_s *fs, struct journal_transaction_manager_s *journal) -{ - int ret; - uint16_t startsector; - uint16_t readoffset; - uint16_t readsect; - struct smartfs_logging_entry_s *entry; - -#ifdef CONFIG_DEBUG_FS - print_journal_sectors(fs); -#endif - startsector = SMARTFS_LOGGING_SECTOR + journal->jarea * CONFIG_SMARTFS_NLOGGING_SECTORS; - journal->sector = startsector; - readsect = startsector; - readoffset = 1; - - while (readsect < startsector + CONFIG_SMARTFS_NLOGGING_SECTORS) { - /* Read transactions in journal sector */ - fvdbg("readsector : %d offset : %d\n", readsect, readoffset); - ret = read_logging_entry(fs, journal, &readsect, &readoffset); - if (ret != OK) { - break; - } - entry = (struct smartfs_logging_entry_s *)journal->buffer; - if (entry->crc16[0] != smartfs_calc_crc_entry(journal)) { - fdbg("Journal entry header crc mismatch! sector : %d type : %d entry crc : %d calc-crc : %d\n", journal->sector, GET_TRANS_TYPE(entry->trans_info), entry->crc16[0], smartfs_calc_crc_entry(journal)); - break; - } - /* Check whether this transaction exists, and logging of transaction has been completed */ - if (T_EXIST_CHECK(entry->trans_info) && T_START_CHECK(entry->trans_info)) { - journal->sector = readsect; - journal->offset = readoffset - sizeof(struct smartfs_logging_entry_s); - - /* If this entry has additional data, read additional data - Skip reading additional data if transaction os of type DELETE, where we have reused datalen field - */ - if (entry->datalen > 0 && GET_TRANS_TYPE(entry->trans_info) != T_DELETE) { - /* We skip reading additional data if transaction needs sync, - * because these type of transactions are restored from list later. - * So, we only increment the offset here */ - /* If not a T_WRITE transaction which needs sync, read the additional data */ - ret = read_logging_data(fs, journal, &readsect, &readoffset); - if (ret != OK) { - fdbg("Cannot read entry data.\n"); - break; - } - if (entry->crc16[1] != smartfs_calc_crc_data(journal)) { - fdbg("Journal entry data crc mismatch! sector : %d type : %d entry crc : %d calc-crc : %d\n", journal->sector, GET_TRANS_TYPE(entry->trans_info), entry->crc16[1], smartfs_calc_crc_data(journal)); - break; - } - } - /* Restore the transaction. (T_WRITE with sync type transaction will not be - * restored yet */ - ret = process_transaction(fs); - if (ret != OK) { - fdbg("process_transaction failed, and cleaning journal areas\n"); - break; - } - } else { - /* If a valid transaction does not exist here, stop checking further */ - break; - } - } - - return ret; -} - /**************************************************************************** * Name: smartfs_journal_init * - * Description: Initialize a journal manager + * Description: Initialize jornal manager * Read logs to restore any previously failed transaction * ****************************************************************************/ @@ -1978,7 +1906,11 @@ int smartfs_journal_init(struct smartfs_mountpt_s *fs) { int ret; uint16_t mapsize; + uint16_t readoffset; + uint16_t readsect; + uint16_t startsector; struct smart_format_s fmt; + struct smartfs_logging_entry_s *entry; struct journal_transaction_manager_s *journal; journal = (struct journal_transaction_manager_s *)kmm_malloc(sizeof(struct journal_transaction_manager_s)); @@ -2019,7 +1951,61 @@ int smartfs_journal_init(struct smartfs_mountpt_s *fs) memset(journal->active_sectors, 0, mapsize); if (journal->jarea != -1) { - ret = execute_unfinished_journal_data(fs, journal); +#ifdef CONFIG_DEBUG_FS + print_journal_sectors(fs); +#endif + startsector = SMARTFS_LOGGING_SECTOR + journal->jarea * CONFIG_SMARTFS_NLOGGING_SECTORS; + journal->sector = startsector; + readsect = startsector; + readoffset = 1; + + while (readsect < startsector + CONFIG_SMARTFS_NLOGGING_SECTORS) { + /* Read transactions in journal sector */ + fvdbg("readsector : %d offset : %d\n", readsect, readoffset); + ret = read_logging_entry(fs, journal, &readsect, &readoffset); + if (ret != OK) { + break; + } + entry = (struct smartfs_logging_entry_s *)journal->buffer; + if (entry->crc16[0] != smartfs_calc_crc_entry(journal)) { + fdbg("Journal entry header crc mismatch! sector : %d type : %d entry crc : %d calc-crc : %d\n", journal->sector, GET_TRANS_TYPE(entry->trans_info), entry->crc16[0], smartfs_calc_crc_entry(journal)); + break; + } + /* Check whether this transaction exists, and logging of transaction has been completed */ + if (T_EXIST_CHECK(entry->trans_info) && T_START_CHECK(entry->trans_info)) { + journal->sector = readsect; + journal->offset = readoffset - sizeof(struct smartfs_logging_entry_s); + + /* If this entry has additional data, read additional data + Skip reading additional data if transaction os of type DELETE, where we have reused datalen field + */ + if (entry->datalen > 0 && GET_TRANS_TYPE(entry->trans_info) != T_DELETE) { + /* We skip reading additional data if transaction needs sync, + * because these type of transactions are restored from list later. + * So, we only increment the offset here */ + /* If not a T_WRITE transaction which needs sync, read the additional data */ + ret = read_logging_data(fs, journal, &readsect, &readoffset); + if (ret != OK) { + fdbg("Cannot read entry data.\n"); + break; + } + if (entry->crc16[1] != smartfs_calc_crc_data(journal)) { + fdbg("Journal entry data crc mismatch! sector : %d type : %d entry crc : %d calc-crc : %d\n", journal->sector, GET_TRANS_TYPE(entry->trans_info), entry->crc16[1], smartfs_calc_crc_data(journal)); + break; + } + } + /* Restore the transaction. (T_WRITE with sync type transaction will not be + * restored yet */ + ret = process_transaction(fs); + if (ret != OK) { + fdbg("process_transaction failed, but clean journal area\n"); + break; + } + } else { + /* If a valid transaction does not exist here, stop checking further */ + break; + } + } if (journal->list) { /* Now restore write transactions from the list */ diff --git a/os/fs/tmpfs/fs_tmpfs.c b/os/fs/tmpfs/fs_tmpfs.c index 825e133318..f77696af0a 100644 --- a/os/fs/tmpfs/fs_tmpfs.c +++ b/os/fs/tmpfs/fs_tmpfs.c @@ -629,9 +629,15 @@ static FAR struct tmpfs_file_s *tmpfs_alloc_file(void) * Name: tmpfs_create_file ****************************************************************************/ -static int verify_path(FAR char *copy, FAR const char *relpath, FAR char *name, FAR struct tmpfs_directory_s **parent, FAR struct tmpfs_s *fs) +static int tmpfs_create_file(FAR struct tmpfs_s *fs, + FAR const char *relpath, + FAR struct tmpfs_file_s **tfo) { - int ret = OK; + FAR struct tmpfs_directory_s *parent; + FAR struct tmpfs_file_s *newtfo; + FAR char *copy; + FAR char *name; + int ret; /* Duplicate the path variable so that we can modify it */ @@ -649,12 +655,12 @@ static int verify_path(FAR char *copy, FAR const char *relpath, FAR char *name, /* No subdirectories... use the root directory */ name = copy; - *parent = (FAR struct tmpfs_directory_s *)fs->tfs_root.tde_object; + parent = (FAR struct tmpfs_directory_s *)fs->tfs_root.tde_object; /* Lock the root directory to emulate the behavior of tmpfs_find_directory() */ - tmpfs_lock_directory(*parent); - (*parent)->tdo_refs++; + tmpfs_lock_directory(parent); + parent->tdo_refs++; } else { /* Terminate the parent directory path */ @@ -665,7 +671,7 @@ static int verify_path(FAR char *copy, FAR const char *relpath, FAR char *name, * directory and increment the reference count. */ - ret = tmpfs_find_directory(fs, copy, parent, NULL); + ret = tmpfs_find_directory(fs, copy, &parent, NULL); if (ret < 0) { goto errout_with_copy; } @@ -673,7 +679,7 @@ static int verify_path(FAR char *copy, FAR const char *relpath, FAR char *name, /* Verify that no object of this name already exists in the directory */ - ret = tmpfs_find_dirent(*parent, name); + ret = tmpfs_find_dirent(parent, name); if (ret != -ENOENT) { /* Something with this name already exists in the directory. * OR perhaps some fatal error occurred. @@ -685,30 +691,6 @@ static int verify_path(FAR char *copy, FAR const char *relpath, FAR char *name, goto errout_with_parent; } -errout_with_parent: - (*parent)->tdo_refs--; - tmpfs_unlock_directory(*parent); - -errout_with_copy: - kmm_free(copy); - return ret; -} - -static int tmpfs_create_file(FAR struct tmpfs_s *fs, - FAR const char *relpath, - FAR struct tmpfs_file_s **tfo) -{ - FAR struct tmpfs_directory_s *parent; - FAR struct tmpfs_file_s *newtfo; - FAR char *copy = NULL; - FAR char *name = NULL; - int ret = OK; - - ret = verify_path(copy, relpath, name, &parent, fs); - if (ret < 0) { - return ret; - } - /* Allocate an empty file. The initial state of the file is locked with one * reference count. */ @@ -746,6 +728,7 @@ static int tmpfs_create_file(FAR struct tmpfs_s *fs, parent->tdo_refs--; tmpfs_unlock_directory(parent); +errout_with_copy: kmm_free(copy); return ret; } @@ -797,13 +780,57 @@ static int tmpfs_create_directory(FAR struct tmpfs_s *fs, { FAR struct tmpfs_directory_s *parent; FAR struct tmpfs_directory_s *newtdo; - FAR char *copy = NULL; - FAR char *name = NULL; + FAR char *copy; + FAR char *name; int ret; - ret = verify_path(copy, relpath, name, &parent, fs); - if (ret < 0) { - return ret; + /* Duplicate the path variable so that we can modify it */ + + copy = strdup(relpath); + if (copy == NULL) { + return -ENOMEM; + } + /* Separate the path into the file name and the path to the parent + * directory. + */ + + name = strrchr(copy, '/'); + if (name == NULL) { + /* No subdirectories... use the root directory */ + + name = copy; + parent = (FAR struct tmpfs_directory_s *)fs->tfs_root.tde_object; + + tmpfs_lock_directory(parent); + parent->tdo_refs++; + } else { + /* Terminate the parent directory path */ + + *name++ = '\0'; + + /* Locate the parent directory that should contain this name. + * On success, tmpfs_find_directory() will lockthe parent + * directory and increment the reference count. + */ + + ret = tmpfs_find_directory(fs, copy, &parent, NULL); + if (ret < 0) { + goto errout_with_copy; + } + } + + /* Verify that no object of this name already exists in the directory */ + + ret = tmpfs_find_dirent(parent, name); + if (ret != -ENOENT) { + /* Something with this name already exists in the directory. + * OR perhaps some fatal error occurred. + */ + + if (ret >= 0) { + ret = -EEXIST; + } + goto errout_with_parent; } /* Allocate an empty directory object. NOTE that there is no reference on @@ -847,6 +874,7 @@ static int tmpfs_create_directory(FAR struct tmpfs_s *fs, parent->tdo_refs--; tmpfs_unlock_directory(parent); +errout_with_copy: kmm_free(copy); return ret; }