mirror of
https://github.com/apache/nuttx.git
synced 2026-05-21 13:13:08 +08:00
drivers/mtd/smart.c Fixed SmartFS wear level error that occurs when the logical sector size is too small to save all wear level status bytes in a single sector. Logical sectors 1 and 2 were simply not being allocated and then the read_sector and write_sector routines were failing. From Ken Petit
This commit is contained in:
@@ -11119,4 +11119,9 @@
|
||||
* configs/same70-xplained: Add basic NSH configuration for the SAME70
|
||||
Xplained board. Initial commit is just the SAMV71-XULT files with
|
||||
names changed appropriately (2015-11-18).
|
||||
* drivers/mtd/smart.c: Fixed SmartFS wear level error that occurs when
|
||||
the logical sector size is too small to save all wear level status
|
||||
bytes in a single sector. Logical sectors 1 and 2 were simply not
|
||||
being allocated and then the read_sector and write_sector routinesi
|
||||
were failing. From Ken Petit (2015-11-18).
|
||||
|
||||
|
||||
+1
-1
Submodule configs updated: 8615cb1106...165837ff2a
+46
-13
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Sector Mapped Allocation for Really Tiny (SMART) Flash block driver.
|
||||
*
|
||||
* Copyright (C) 2013-2014 Ken Pettit. All rights reserved.
|
||||
* Copyright (C) 2013-2015 Ken Pettit. All rights reserved.
|
||||
* Author: Ken Pettit <pettitkd@gmail.com>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -372,6 +372,8 @@ static int smart_findfreephyssector(FAR struct smart_struct_s *dev, uint8_t canr
|
||||
|
||||
#ifdef CONFIG_FS_WRITABLE
|
||||
static int smart_writesector(FAR struct smart_struct_s *dev, unsigned long arg);
|
||||
static inline int smart_allocsector(FAR struct smart_struct_s *dev,
|
||||
unsigned long requested);
|
||||
#endif
|
||||
static int smart_readsector(FAR struct smart_struct_s *dev, unsigned long arg);
|
||||
|
||||
@@ -381,7 +383,7 @@ static int smart_relocate_static_data(FAR struct smart_struct_s *dev, uint16_t b
|
||||
#endif
|
||||
|
||||
static int smart_relocate_sector(FAR struct smart_struct_s *dev,
|
||||
uint16_t oldsector, uint16_t newsector);
|
||||
uint16_t oldsector, uint16_t newsector);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
@@ -3782,9 +3784,9 @@ static int smart_write_wearstatus(struct smart_struct_s *dev)
|
||||
/* Calculate the number of bytes to write to this sector */
|
||||
|
||||
towrite = remaining;
|
||||
if (towrite > dev->sectorsize - SMARTFS_FMT_WEAR_POS)
|
||||
if (towrite > dev->sectorsize - (SMARTFS_FMT_WEAR_POS + sizeof(struct smart_sect_header_s)))
|
||||
{
|
||||
towrite = dev->sectorsize - SMARTFS_FMT_WEAR_POS;
|
||||
towrite = dev->sectorsize - (SMARTFS_FMT_WEAR_POS + sizeof(struct smart_sect_header_s));
|
||||
}
|
||||
|
||||
/* Setup the sector write request (we are our own client) */
|
||||
@@ -3843,19 +3845,20 @@ errout:
|
||||
#ifdef CONFIG_MTD_SMART_WEAR_LEVEL
|
||||
static inline int smart_read_wearstatus(FAR struct smart_struct_s *dev)
|
||||
{
|
||||
uint16_t sector;
|
||||
uint16_t remaining, toread;
|
||||
struct smart_read_write_s req;
|
||||
int ret;
|
||||
uint8_t buffer[8];
|
||||
uint16_t sector, physsector;
|
||||
uint16_t remaining, toread;
|
||||
uint8_t buffer[8];
|
||||
int ret;
|
||||
|
||||
/* Prepare to read the total block erases and uneven wearcount values */
|
||||
|
||||
sector = 0;
|
||||
sector = 0;
|
||||
req.logsector = sector;
|
||||
req.offset = SMARTFS_FMT_WEAR_POS - 8;
|
||||
req.count = sizeof(buffer);
|
||||
req.buffer = buffer;
|
||||
req.offset = SMARTFS_FMT_WEAR_POS - 8;
|
||||
req.count = sizeof(buffer);
|
||||
req.buffer = buffer;
|
||||
|
||||
ret = smart_readsector(dev, (unsigned long) &req);
|
||||
if (ret != sizeof(buffer))
|
||||
{
|
||||
@@ -3908,6 +3911,29 @@ static inline int smart_read_wearstatus(FAR struct smart_struct_s *dev)
|
||||
req.buffer = &dev->wearstatus[(dev->geo.neraseblocks >> SMART_WEAR_BIT_DIVIDE) -
|
||||
remaining];
|
||||
|
||||
/* Validate wear status sector has been allocated */
|
||||
|
||||
#ifndef CONFIG_MTD_SMART_MINIMIZE_RAM
|
||||
physsector = dev->sMap[req.logsector];
|
||||
#else
|
||||
physsector = smart_cache_lookup(dev, req->logsector);
|
||||
#endif
|
||||
if ((sector != 0) && (physsector == 0xFFFF))
|
||||
{
|
||||
#ifdef CONFIG_FS_WRITABLE
|
||||
|
||||
/* This logical sector does not exist yet. We must allocate it */
|
||||
|
||||
ret = smart_allocsector(dev, sector);
|
||||
if (ret != sector)
|
||||
{
|
||||
fdbg("Unable to allocate wear level status sector %d\n", sector);
|
||||
ret = -EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Read the sector */
|
||||
|
||||
ret = smart_readsector(dev, (unsigned long) &req);
|
||||
@@ -4690,7 +4716,7 @@ static inline int smart_allocsector(FAR struct smart_struct_s *dev,
|
||||
* sector if it isn't already in use.
|
||||
*/
|
||||
|
||||
if ((requested > 2) && (requested < dev->totalsectors))
|
||||
if ((requested > 0) && (requested < dev->totalsectors))
|
||||
{
|
||||
/* Validate the sector is not already allocated */
|
||||
|
||||
@@ -5059,6 +5085,13 @@ static int smart_ioctl(FAR struct inode *inode, int cmd, unsigned long arg)
|
||||
|
||||
case BIOC_ALLOCSECT:
|
||||
|
||||
/* Ensure the FS is not trying to allocate a reserved sector */
|
||||
|
||||
if (arg < 3)
|
||||
{
|
||||
arg = (unsigned long) -1;
|
||||
}
|
||||
|
||||
/* Allocate a logical sector for the upper layer file system */
|
||||
|
||||
ret = smart_allocsector(dev, arg);
|
||||
|
||||
Reference in New Issue
Block a user