blk/mtdoutstream: use lib_sostream_s to support seek

Signed-off-by: buxiasen <buxiasen@xiaomi.com>
This commit is contained in:
buxiasen 2024-11-08 20:59:08 +08:00 committed by Xiang Xiao
parent 321419491e
commit eca83c4a73
3 changed files with 172 additions and 21 deletions

View file

@ -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;

View file

@ -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;
}

View file

@ -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;
}