mirror of
https://github.com/apache/nuttx.git
synced 2026-05-31 05:55:46 +08:00
MTD read-ahear/write buffering layer seems functional
This commit is contained in:
@@ -124,8 +124,8 @@ static int bch_open(FAR struct file *filep)
|
|||||||
{
|
{
|
||||||
bch->refs++;
|
bch->refs++;
|
||||||
}
|
}
|
||||||
bchlib_semgive(bch);
|
|
||||||
|
|
||||||
|
bchlib_semgive(bch);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,8 +162,8 @@ static int bch_close(FAR struct file *filep)
|
|||||||
{
|
{
|
||||||
bch->refs--;
|
bch->refs--;
|
||||||
}
|
}
|
||||||
bchlib_semgive(bch);
|
|
||||||
|
|
||||||
|
bchlib_semgive(bch);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,6 +212,7 @@ static ssize_t bch_write(FAR struct file *filep, FAR const char *buffer, size_t
|
|||||||
{
|
{
|
||||||
filep->f_pos += len;
|
filep->f_pos += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
bchlib_semgive(bch);
|
bchlib_semgive(bch);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,6 +249,7 @@ static int bch_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||||||
bch->refs++;
|
bch->refs++;
|
||||||
*bchr = bch;
|
*bchr = bch;
|
||||||
}
|
}
|
||||||
|
|
||||||
bchlib_semgive(bch);
|
bchlib_semgive(bch);
|
||||||
}
|
}
|
||||||
#if defined(CONFIG_BCH_ENCRYPTION)
|
#if defined(CONFIG_BCH_ENCRYPTION)
|
||||||
|
|||||||
@@ -168,6 +168,7 @@ static ssize_t ftl_reload(FAR void *priv, FAR uint8_t *buffer,
|
|||||||
fdbg("Read %d blocks starting at block %d failed: %d\n",
|
fdbg("Read %d blocks starting at block %d failed: %d\n",
|
||||||
nblocks, startblock, nread);
|
nblocks, startblock, nread);
|
||||||
}
|
}
|
||||||
|
|
||||||
return nread;
|
return nread;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -431,6 +432,7 @@ static int ftl_geometry(FAR struct inode *inode, struct geometry *geometry)
|
|||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -599,5 +601,6 @@ int ftl_initialize(int minor, FAR struct mtd_dev_s *mtd)
|
|||||||
kmm_free(dev);
|
kmm_free(dev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -272,8 +272,8 @@ static int mtd_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
geo->blocksize = priv->rwb.blocksize;
|
geo->blocksize = priv->rwb.blocksize;
|
||||||
geo->erasesize = priv->rwb.blocksize* priv->spb;
|
geo->erasesize = priv->rwb.blocksize * priv->spb;
|
||||||
geo->neraseblocks = priv->rwb.nblocks * priv->spb;
|
geo->neraseblocks = priv->rwb.nblocks / priv->spb;
|
||||||
ret = OK;
|
ret = OK;
|
||||||
|
|
||||||
fvdbg("blocksize: %d erasesize: %d neraseblocks: %d\n",
|
fvdbg("blocksize: %d erasesize: %d neraseblocks: %d\n",
|
||||||
|
|||||||
+65
-35
@@ -150,6 +150,10 @@ static inline void rwb_resetwrbuffer(struct rwbuffer_s *rwb)
|
|||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: rwb_wrflush
|
* Name: rwb_wrflush
|
||||||
|
*
|
||||||
|
* Assumptions:
|
||||||
|
* The caller holds the wrsem semaphore.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifdef CONFIG_DRVR_WRITEBUFFER
|
#ifdef CONFIG_DRVR_WRITEBUFFER
|
||||||
@@ -159,7 +163,6 @@ static void rwb_wrflush(struct rwbuffer_s *rwb)
|
|||||||
|
|
||||||
fvdbg("Timeout!\n");
|
fvdbg("Timeout!\n");
|
||||||
|
|
||||||
rwb_semtake(&rwb->wrsem);
|
|
||||||
if (rwb->wrnblocks > 0)
|
if (rwb->wrnblocks > 0)
|
||||||
{
|
{
|
||||||
fvdbg("Flushing: blockstart=0x%08lx nblocks=%d from buffer=%p\n",
|
fvdbg("Flushing: blockstart=0x%08lx nblocks=%d from buffer=%p\n",
|
||||||
@@ -179,7 +182,6 @@ static void rwb_wrflush(struct rwbuffer_s *rwb)
|
|||||||
rwb_resetwrbuffer(rwb);
|
rwb_resetwrbuffer(rwb);
|
||||||
}
|
}
|
||||||
|
|
||||||
rwb_semgive(&rwb->wrsem);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -199,7 +201,9 @@ static void rwb_wrtimeout(FAR void *arg)
|
|||||||
* worker thread.
|
* worker thread.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
rwb_semtake(&rwb->wrsem);
|
||||||
rwb_wrflush(rwb);
|
rwb_wrflush(rwb);
|
||||||
|
rwb_semgive(&rwb->wrsem);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -341,17 +345,22 @@ rwb_bufferread(struct rwbuffer_s *rwb, off_t startblock,
|
|||||||
#ifdef CONFIG_DRVR_READAHEAD
|
#ifdef CONFIG_DRVR_READAHEAD
|
||||||
static int rwb_rhreload(struct rwbuffer_s *rwb, off_t startblock)
|
static int rwb_rhreload(struct rwbuffer_s *rwb, off_t startblock)
|
||||||
{
|
{
|
||||||
|
off_t endblock;
|
||||||
|
size_t nblocks;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Check for attempts to read beyond the end of the media */
|
||||||
|
|
||||||
|
if (startblock >= rwb->nblocks)
|
||||||
|
{
|
||||||
|
return -ESPIPE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the block number +1 of the last block that will fit in the
|
/* Get the block number +1 of the last block that will fit in the
|
||||||
* read-ahead buffer
|
* read-ahead buffer
|
||||||
*/
|
*/
|
||||||
|
|
||||||
off_t endblock = startblock + rwb->rhmaxblocks;
|
endblock = startblock + rwb->rhmaxblocks;
|
||||||
size_t nblocks;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* Reset the read buffer */
|
|
||||||
|
|
||||||
rwb_resetrhbuffer(rwb);
|
|
||||||
|
|
||||||
/* Make sure that we don't read past the end of the device */
|
/* Make sure that we don't read past the end of the device */
|
||||||
|
|
||||||
@@ -362,6 +371,10 @@ static int rwb_rhreload(struct rwbuffer_s *rwb, off_t startblock)
|
|||||||
|
|
||||||
nblocks = endblock - startblock;
|
nblocks = endblock - startblock;
|
||||||
|
|
||||||
|
/* Reset the read buffer */
|
||||||
|
|
||||||
|
rwb_resetrhbuffer(rwb);
|
||||||
|
|
||||||
/* Now perform the read */
|
/* Now perform the read */
|
||||||
|
|
||||||
ret = rwb->rhreload(rwb->dev, rwb->rhbuffer, startblock, nblocks);
|
ret = rwb->rhreload(rwb->dev, rwb->rhbuffer, startblock, nblocks);
|
||||||
@@ -471,13 +484,13 @@ int rwb_invalidate_writebuffer(FAR struct rwbuffer_s *rwb,
|
|||||||
|
|
||||||
/* 4. We invalidate a portion at the beginning of the write buffer */
|
/* 4. We invalidate a portion at the beginning of the write buffer */
|
||||||
|
|
||||||
else /* if (rwb->wrblockstart >= startblock && wrbend < invend) */
|
else /* if (rwb->wrblockstart >= startblock && wrbend > invend) */
|
||||||
{
|
{
|
||||||
uint8_t *src;
|
uint8_t *src;
|
||||||
size_t ninval;
|
size_t ninval;
|
||||||
size_t nkeep;
|
size_t nkeep;
|
||||||
|
|
||||||
DEBUGASSERT(rwb->wrblockstart >= startblock && wrbend < invend);
|
DEBUGASSERT(rwb->wrblockstart >= startblock && wrbend > invend);
|
||||||
|
|
||||||
/* Copy the data from the uninvalidated region to the beginning
|
/* Copy the data from the uninvalidated region to the beginning
|
||||||
* of the write buffer.
|
* of the write buffer.
|
||||||
@@ -548,7 +561,7 @@ int rwb_invalidate_readahead(FAR struct rwbuffer_s *rwb,
|
|||||||
rhbend = rwb->rhblockstart + rwb->rhnblocks;
|
rhbend = rwb->rhblockstart + rwb->rhnblocks;
|
||||||
invend = startblock + blockcount;
|
invend = startblock + blockcount;
|
||||||
|
|
||||||
if (rwb->rhblockstart > invend || rhbend < startblock)
|
if (rhbend <= startblock || rwb->rhblockstart >= invend )
|
||||||
{
|
{
|
||||||
ret = OK;
|
ret = OK;
|
||||||
}
|
}
|
||||||
@@ -564,7 +577,7 @@ int rwb_invalidate_readahead(FAR struct rwbuffer_s *rwb,
|
|||||||
/* We are going to invalidate a subset of the read-ahead buffer.
|
/* We are going to invalidate a subset of the read-ahead buffer.
|
||||||
* Three more cases to consider:
|
* Three more cases to consider:
|
||||||
*
|
*
|
||||||
* 2. We invalidate a portion in the middle of the write buffer
|
* 2. We invalidate a portion in the middle of the read-ahead buffer
|
||||||
*/
|
*/
|
||||||
|
|
||||||
else if (rwb->rhblockstart < startblock && rhbend > invend)
|
else if (rwb->rhblockstart < startblock && rhbend > invend)
|
||||||
@@ -587,14 +600,14 @@ int rwb_invalidate_readahead(FAR struct rwbuffer_s *rwb,
|
|||||||
|
|
||||||
/* 4. We invalidate a portion at the beginning of the write buffer */
|
/* 4. We invalidate a portion at the beginning of the write buffer */
|
||||||
|
|
||||||
else /* if (rwb->rhblockstart >= startblock && rhbend < invend) */
|
else /* if (rwb->rhblockstart >= startblock && rhbend > invend) */
|
||||||
{
|
{
|
||||||
/* Let's just force the whole read-ahead buffer to be reloaded.
|
/* Let's just force the whole read-ahead buffer to be reloaded.
|
||||||
* That might cost s small amount of performance, but well worth
|
* That might cost s small amount of performance, but well worth
|
||||||
* the lower complexity.
|
* the lower complexity.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DEBUGASSERT(rwb->rhblockstart >= startblock && rhbend < invend);
|
DEBUGASSERT(rwb->rhblockstart >= startblock && rhbend > invend);
|
||||||
rwb->rhnblocks = 0;
|
rwb->rhnblocks = 0;
|
||||||
ret = OK;
|
ret = OK;
|
||||||
}
|
}
|
||||||
@@ -778,34 +791,25 @@ int rwb_read(FAR struct rwbuffer_s *rwb, off_t startblock, uint32_t nblocks,
|
|||||||
|
|
||||||
if (rwb->rhnblocks > 0)
|
if (rwb->rhnblocks > 0)
|
||||||
{
|
{
|
||||||
off_t block = startblock;
|
|
||||||
size_t nbufblocks = 0;
|
|
||||||
off_t bufferend;
|
off_t bufferend;
|
||||||
|
|
||||||
/* Loop for each block we find in the read-head buffer. Count
|
/* How many blocks are available in this buffer? */
|
||||||
* the number of buffers that we can read from read-ahead
|
|
||||||
* buffer.
|
|
||||||
*/
|
|
||||||
|
|
||||||
bufferend = rwb->rhblockstart + rwb->rhnblocks;
|
bufferend = rwb->rhblockstart + rwb->rhnblocks;
|
||||||
|
if (startblock >= rwb->rhblockstart && startblock < bufferend)
|
||||||
while (block >= rwb->rhblockstart && block < bufferend && remaining > 0)
|
|
||||||
{
|
{
|
||||||
/* This is one more that we will read from the read ahead
|
size_t rdblocks = bufferend - startblock;
|
||||||
* buffer.
|
if (rdblocks > remaining)
|
||||||
*/
|
{
|
||||||
|
rdblocks = remaining;
|
||||||
|
}
|
||||||
|
|
||||||
nbufblocks++;
|
/* Then read the data from the read-ahead buffer */
|
||||||
|
|
||||||
/* And one less that we will read from the media */
|
rwb_bufferread(rwb, startblock, rdblocks, &rdbuffer);
|
||||||
|
startblock += rdblocks;
|
||||||
startblock++;
|
remaining -= rdblocks;
|
||||||
remaining--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Then read the data from the read-ahead buffer */
|
|
||||||
|
|
||||||
rwb_bufferread(rwb, startblock, nbufblocks, &rdbuffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we did not get all of the data from the buffer, then we have
|
/* If we did not get all of the data from the buffer, then we have
|
||||||
@@ -919,6 +923,32 @@ int rwb_write(FAR struct rwbuffer_s *rwb, off_t startblock,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: rwb_readbytes
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Character-oriented read
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_DRVR_READBYTES
|
||||||
|
ssize_t rwb_readbytes(FAR struct rwbuffer_s *dev, off_t offset,
|
||||||
|
size_t nbytes, FAR uint8_t *buffer)
|
||||||
|
{
|
||||||
|
/* Loop while there are bytes still be be read */
|
||||||
|
/* Make sure that the sector containing the next bytes to transfer is in
|
||||||
|
* memory.
|
||||||
|
*/
|
||||||
|
/* How many bytes can be transfer from the in-memory data? */
|
||||||
|
/* Transfer the bytes */
|
||||||
|
/* Adjust counts and offsets for the next time through the loop */
|
||||||
|
|
||||||
|
#warning Not Implemented
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: rwb_mediaremoved
|
* Name: rwb_mediaremoved
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user