blk/mtdoutstream: use lib_sostream_s to support seek
Signed-off-by: buxiasen <buxiasen@xiaomi.com>
This commit is contained in:
parent
321419491e
commit
eca83c4a73
3 changed files with 172 additions and 21 deletions
|
|
@ -293,7 +293,7 @@ struct lib_lzfoutstream_s
|
|||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
struct lib_blkoutstream_s
|
||||
{
|
||||
struct lib_outstream_s common;
|
||||
struct lib_sostream_s common;
|
||||
FAR struct inode *inode;
|
||||
struct geometry geo;
|
||||
FAR unsigned char *cache;
|
||||
|
|
@ -303,7 +303,7 @@ struct lib_blkoutstream_s
|
|||
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_MTD)
|
||||
struct lib_mtdoutstream_s
|
||||
{
|
||||
struct lib_outstream_s common;
|
||||
struct lib_sostream_s common;
|
||||
FAR struct inode *inode;
|
||||
struct mtd_geometry_s geo;
|
||||
FAR unsigned char *cache;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@
|
|||
* Name: blkoutstream_flush
|
||||
****************************************************************************/
|
||||
|
||||
static int blkoutstream_flush(FAR struct lib_outstream_s *self)
|
||||
static int blkoutstream_flush(FAR struct lib_sostream_s *self)
|
||||
{
|
||||
FAR struct lib_blkoutstream_s *stream =
|
||||
(FAR struct lib_blkoutstream_s *)self;
|
||||
|
|
@ -61,11 +61,81 @@ static int blkoutstream_flush(FAR struct lib_outstream_s *self)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: blkoutstream_seek
|
||||
****************************************************************************/
|
||||
|
||||
static off_t blkoutstream_seek(FAR struct lib_sostream_s *self,
|
||||
off_t offset, int whence)
|
||||
{
|
||||
FAR struct lib_blkoutstream_s *stream =
|
||||
(FAR struct lib_blkoutstream_s *)self;
|
||||
size_t sectorsize = stream->geo.geo_sectorsize;
|
||||
off_t streamsize = sectorsize * stream->geo.geo_nsectors;
|
||||
FAR struct inode *inode = stream->inode;
|
||||
off_t sector;
|
||||
off_t ret;
|
||||
|
||||
switch (whence)
|
||||
{
|
||||
case SEEK_SET:
|
||||
break;
|
||||
case SEEK_END:
|
||||
offset += streamsize;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
offset += self->nput;
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* Seek to negative value or value larger than maximum size shall fail. */
|
||||
|
||||
if (offset < 0 || offset > streamsize)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (self->nput % sectorsize)
|
||||
{
|
||||
sector = self->nput / sectorsize;
|
||||
if (offset >= sector * sectorsize &&
|
||||
offset < (sector + 1) * sectorsize)
|
||||
{
|
||||
/* Inside same sector */
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = inode->u.i_bops->write(stream->inode, stream->cache,
|
||||
sector, 1);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (offset % sectorsize)
|
||||
{
|
||||
ret = inode->u.i_bops->read(inode, stream->cache,
|
||||
offset / sectorsize, 1);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
self->nput = offset;
|
||||
return offset;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: blkoutstream_puts
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t blkoutstream_puts(FAR struct lib_outstream_s *self,
|
||||
static ssize_t blkoutstream_puts(FAR struct lib_sostream_s *self,
|
||||
FAR const void *buf, size_t len)
|
||||
{
|
||||
FAR struct lib_blkoutstream_s *stream =
|
||||
|
|
@ -140,7 +210,7 @@ static ssize_t blkoutstream_puts(FAR struct lib_outstream_s *self,
|
|||
* Name: blkoutstream_putc
|
||||
****************************************************************************/
|
||||
|
||||
static void blkoutstream_putc(FAR struct lib_outstream_s *self, int ch)
|
||||
static void blkoutstream_putc(FAR struct lib_sostream_s *self, int ch)
|
||||
{
|
||||
char tmp = ch;
|
||||
blkoutstream_puts(self, &tmp, 1);
|
||||
|
|
@ -240,6 +310,7 @@ int lib_blkoutstream_open(FAR struct lib_blkoutstream_s *stream,
|
|||
stream->common.putc = blkoutstream_putc;
|
||||
stream->common.puts = blkoutstream_puts;
|
||||
stream->common.flush = blkoutstream_flush;
|
||||
stream->common.seek = blkoutstream_seek;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,11 +47,11 @@
|
|||
* Name: mtdoutstream_flush
|
||||
****************************************************************************/
|
||||
|
||||
static int mtdoutstream_flush(FAR struct lib_outstream_s *self)
|
||||
static int mtdoutstream_flush(FAR struct lib_sostream_s *self)
|
||||
{
|
||||
FAR struct lib_mtdoutstream_s *stream =
|
||||
(FAR struct lib_mtdoutstream_s *)self;
|
||||
FAR struct inode *inode = stream->inode;
|
||||
FAR struct mtd_dev_s *i_mtd = stream->inode->u.i_mtd;
|
||||
size_t erasesize = stream->geo.erasesize;
|
||||
size_t nblkpererase = erasesize / stream->geo.blocksize;
|
||||
int ret = OK;
|
||||
|
|
@ -60,13 +60,13 @@ static int mtdoutstream_flush(FAR struct lib_outstream_s *self)
|
|||
{
|
||||
size_t sblock = self->nput / erasesize;
|
||||
|
||||
ret = MTD_ERASE(inode->u.i_mtd, sblock, 1);
|
||||
ret = MTD_ERASE(i_mtd, sblock, 1);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = MTD_BWRITE(inode->u.i_mtd, sblock * nblkpererase,
|
||||
ret = MTD_BWRITE(i_mtd, sblock * nblkpererase,
|
||||
nblkpererase, stream->cache);
|
||||
}
|
||||
|
||||
|
|
@ -77,15 +77,15 @@ static int mtdoutstream_flush(FAR struct lib_outstream_s *self)
|
|||
* Name: mtdoutstream_puts
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t mtdoutstream_puts(FAR struct lib_outstream_s *self,
|
||||
static ssize_t mtdoutstream_puts(FAR struct lib_sostream_s *self,
|
||||
FAR const void *buf, size_t len)
|
||||
{
|
||||
FAR struct lib_mtdoutstream_s *stream =
|
||||
(FAR struct lib_mtdoutstream_s *)self;
|
||||
FAR struct inode *inode = stream->inode;
|
||||
FAR const unsigned char *ptr = buf;
|
||||
FAR struct mtd_dev_s *i_mtd = stream->inode->u.i_mtd;
|
||||
size_t erasesize = stream->geo.erasesize;
|
||||
size_t nblkpererase = erasesize / stream->geo.blocksize;
|
||||
FAR const unsigned char *ptr = buf;
|
||||
size_t remain = len;
|
||||
ssize_t ret;
|
||||
|
||||
|
|
@ -113,14 +113,14 @@ static ssize_t mtdoutstream_puts(FAR struct lib_outstream_s *self,
|
|||
|
||||
if (offset == erasesize)
|
||||
{
|
||||
ret = MTD_ERASE(inode->u.i_mtd, sblock, 1);
|
||||
ret = MTD_ERASE(i_mtd, sblock, 1);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = MTD_BWRITE(inode->u.i_mtd, sblock * nblkpererase,
|
||||
nblkpererase, stream->cache);
|
||||
ret = MTD_BWRITE(i_mtd, sblock * nblkpererase,
|
||||
nblkpererase, stream->cache);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
|
|
@ -129,8 +129,8 @@ static ssize_t mtdoutstream_puts(FAR struct lib_outstream_s *self,
|
|||
}
|
||||
else if (remain < erasesize)
|
||||
{
|
||||
ret = MTD_READ(stream->inode->u.i_mtd, sblock * erasesize,
|
||||
erasesize, stream->cache);
|
||||
ret = MTD_BREAD(i_mtd, sblock * nblkpererase,
|
||||
nblkpererase, stream->cache);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
|
|
@ -145,14 +145,14 @@ static ssize_t mtdoutstream_puts(FAR struct lib_outstream_s *self,
|
|||
size_t nblock = remain / erasesize;
|
||||
size_t copyin = nblock * erasesize;
|
||||
|
||||
ret = MTD_ERASE(inode->u.i_mtd, sblock, nblock);
|
||||
ret = MTD_ERASE(i_mtd, sblock, nblock);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = MTD_BWRITE(inode->u.i_mtd, sblock * nblkpererase,
|
||||
nblock * nblkpererase, ptr);
|
||||
ret = MTD_BWRITE(i_mtd, sblock * nblkpererase,
|
||||
nblock * nblkpererase, ptr);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
|
|
@ -171,12 +171,91 @@ static ssize_t mtdoutstream_puts(FAR struct lib_outstream_s *self,
|
|||
* Name: mtdoutstream_putc
|
||||
****************************************************************************/
|
||||
|
||||
static void mtdoutstream_putc(FAR struct lib_outstream_s *self, int ch)
|
||||
static void mtdoutstream_putc(FAR struct lib_sostream_s *self, int ch)
|
||||
{
|
||||
char tmp = ch;
|
||||
mtdoutstream_puts(self, &tmp, 1);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mtdoutstream_seek
|
||||
****************************************************************************/
|
||||
|
||||
static off_t mtdoutstream_seek(FAR struct lib_sostream_s *self,
|
||||
off_t offset, int whence)
|
||||
{
|
||||
FAR struct lib_mtdoutstream_s *stream =
|
||||
(FAR struct lib_mtdoutstream_s *)self;
|
||||
FAR struct mtd_dev_s *i_mtd = stream->inode->u.i_mtd;
|
||||
size_t erasesize = stream->geo.erasesize;
|
||||
off_t streamsize = erasesize * stream->geo.neraseblocks;
|
||||
size_t nblkpererase = erasesize / stream->geo.blocksize;
|
||||
size_t block;
|
||||
off_t ret;
|
||||
|
||||
switch (whence)
|
||||
{
|
||||
case SEEK_SET:
|
||||
break;
|
||||
case SEEK_END:
|
||||
offset += streamsize;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
offset += self->nput;
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* Seek to negative value or value larger than maximum size shall fail */
|
||||
|
||||
if (offset < 0 || offset > streamsize)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (self->nput % erasesize)
|
||||
{
|
||||
block = self->nput / erasesize;
|
||||
if (offset >= block * erasesize &&
|
||||
offset < (block + 1) * erasesize)
|
||||
{
|
||||
/* Inside same erase block */
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = MTD_ERASE(i_mtd, block, 1);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = MTD_BWRITE(i_mtd, block * nblkpererase,
|
||||
nblkpererase, stream->cache);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (offset % erasesize)
|
||||
{
|
||||
block = offset / erasesize;
|
||||
|
||||
ret = MTD_BREAD(i_mtd, block * nblkpererase,
|
||||
nblkpererase, stream->cache);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
self->nput = offset;
|
||||
return offset;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
|
@ -274,6 +353,7 @@ int lib_mtdoutstream_open(FAR struct lib_mtdoutstream_s *stream,
|
|||
stream->common.putc = mtdoutstream_putc;
|
||||
stream->common.puts = mtdoutstream_puts;
|
||||
stream->common.flush = mtdoutstream_flush;
|
||||
stream->common.seek = mtdoutstream_seek;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue