MTD read-ahear/write buffering layer seems functional

This commit is contained in:
Gregory Nutt
2014-09-25 13:35:10 -06:00
parent a5bc26db4a
commit b33f8b3013
4 changed files with 74 additions and 39 deletions
+4 -2
View File
@@ -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)
+3
View File
@@ -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;
} }
+2 -2
View File
@@ -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
View File
@@ -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
* *