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
+2 -2
View File
@@ -293,7 +293,7 @@ struct lib_lzfoutstream_s
#ifndef CONFIG_DISABLE_MOUNTPOINT #ifndef CONFIG_DISABLE_MOUNTPOINT
struct lib_blkoutstream_s struct lib_blkoutstream_s
{ {
struct lib_outstream_s common; struct lib_sostream_s common;
FAR struct inode *inode; FAR struct inode *inode;
struct geometry geo; struct geometry geo;
FAR unsigned char *cache; FAR unsigned char *cache;
@@ -303,7 +303,7 @@ struct lib_blkoutstream_s
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_MTD) #if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_MTD)
struct lib_mtdoutstream_s struct lib_mtdoutstream_s
{ {
struct lib_outstream_s common; struct lib_sostream_s common;
FAR struct inode *inode; FAR struct inode *inode;
struct mtd_geometry_s geo; struct mtd_geometry_s geo;
FAR unsigned char *cache; FAR unsigned char *cache;
+74 -3
View File
@@ -45,7 +45,7 @@
* Name: blkoutstream_flush * 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 *stream =
(FAR struct lib_blkoutstream_s *)self; (FAR struct lib_blkoutstream_s *)self;
@@ -61,11 +61,81 @@ static int blkoutstream_flush(FAR struct lib_outstream_s *self)
return ret; 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 * 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 const void *buf, size_t len)
{ {
FAR struct lib_blkoutstream_s *stream = FAR struct lib_blkoutstream_s *stream =
@@ -140,7 +210,7 @@ static ssize_t blkoutstream_puts(FAR struct lib_outstream_s *self,
* Name: blkoutstream_putc * 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; char tmp = ch;
blkoutstream_puts(self, &tmp, 1); 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.putc = blkoutstream_putc;
stream->common.puts = blkoutstream_puts; stream->common.puts = blkoutstream_puts;
stream->common.flush = blkoutstream_flush; stream->common.flush = blkoutstream_flush;
stream->common.seek = blkoutstream_seek;
return OK; return OK;
} }
+96 -16
View File
@@ -47,11 +47,11 @@
* Name: mtdoutstream_flush * 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 *stream =
(FAR struct lib_mtdoutstream_s *)self; (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 erasesize = stream->geo.erasesize;
size_t nblkpererase = erasesize / stream->geo.blocksize; size_t nblkpererase = erasesize / stream->geo.blocksize;
int ret = OK; int ret = OK;
@@ -60,13 +60,13 @@ static int mtdoutstream_flush(FAR struct lib_outstream_s *self)
{ {
size_t sblock = self->nput / erasesize; 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) if (ret < 0)
{ {
return ret; return ret;
} }
ret = MTD_BWRITE(inode->u.i_mtd, sblock * nblkpererase, ret = MTD_BWRITE(i_mtd, sblock * nblkpererase,
nblkpererase, stream->cache); nblkpererase, stream->cache);
} }
@@ -77,15 +77,15 @@ static int mtdoutstream_flush(FAR struct lib_outstream_s *self)
* Name: mtdoutstream_puts * 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 const void *buf, size_t len)
{ {
FAR struct lib_mtdoutstream_s *stream = FAR struct lib_mtdoutstream_s *stream =
(FAR struct lib_mtdoutstream_s *)self; (FAR struct lib_mtdoutstream_s *)self;
FAR struct inode *inode = stream->inode; FAR struct mtd_dev_s *i_mtd = stream->inode->u.i_mtd;
FAR const unsigned char *ptr = buf;
size_t erasesize = stream->geo.erasesize; size_t erasesize = stream->geo.erasesize;
size_t nblkpererase = erasesize / stream->geo.blocksize; size_t nblkpererase = erasesize / stream->geo.blocksize;
FAR const unsigned char *ptr = buf;
size_t remain = len; size_t remain = len;
ssize_t ret; ssize_t ret;
@@ -113,14 +113,14 @@ static ssize_t mtdoutstream_puts(FAR struct lib_outstream_s *self,
if (offset == erasesize) if (offset == erasesize)
{ {
ret = MTD_ERASE(inode->u.i_mtd, sblock, 1); ret = MTD_ERASE(i_mtd, sblock, 1);
if (ret < 0) if (ret < 0)
{ {
return ret; return ret;
} }
ret = MTD_BWRITE(inode->u.i_mtd, sblock * nblkpererase, ret = MTD_BWRITE(i_mtd, sblock * nblkpererase,
nblkpererase, stream->cache); nblkpererase, stream->cache);
if (ret < 0) if (ret < 0)
{ {
return ret; return ret;
@@ -129,8 +129,8 @@ static ssize_t mtdoutstream_puts(FAR struct lib_outstream_s *self,
} }
else if (remain < erasesize) else if (remain < erasesize)
{ {
ret = MTD_READ(stream->inode->u.i_mtd, sblock * erasesize, ret = MTD_BREAD(i_mtd, sblock * nblkpererase,
erasesize, stream->cache); nblkpererase, stream->cache);
if (ret < 0) if (ret < 0)
{ {
return ret; return ret;
@@ -145,14 +145,14 @@ static ssize_t mtdoutstream_puts(FAR struct lib_outstream_s *self,
size_t nblock = remain / erasesize; size_t nblock = remain / erasesize;
size_t copyin = nblock * 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) if (ret < 0)
{ {
return ret; return ret;
} }
ret = MTD_BWRITE(inode->u.i_mtd, sblock * nblkpererase, ret = MTD_BWRITE(i_mtd, sblock * nblkpererase,
nblock * nblkpererase, ptr); nblock * nblkpererase, ptr);
if (ret < 0) if (ret < 0)
{ {
return ret; return ret;
@@ -171,12 +171,91 @@ static ssize_t mtdoutstream_puts(FAR struct lib_outstream_s *self,
* Name: mtdoutstream_putc * 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; char tmp = ch;
mtdoutstream_puts(self, &tmp, 1); 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 * Public Functions
****************************************************************************/ ****************************************************************************/
@@ -274,6 +353,7 @@ int lib_mtdoutstream_open(FAR struct lib_mtdoutstream_s *stream,
stream->common.putc = mtdoutstream_putc; stream->common.putc = mtdoutstream_putc;
stream->common.puts = mtdoutstream_puts; stream->common.puts = mtdoutstream_puts;
stream->common.flush = mtdoutstream_flush; stream->common.flush = mtdoutstream_flush;
stream->common.seek = mtdoutstream_seek;
return OK; return OK;
} }