This is an automated email from the ASF dual-hosted git repository. jiuzhudong pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 379f2466251a1eb52c2fb44fdc12c7fce054eabf Author: buxiasen <buxia...@xiaomi.com> AuthorDate: Sat Dec 21 20:17:38 2024 +0800 mtdstream: use mtdsostream to support seek Decrease memory cost, flush should not be called too frequency, for not bytewrite mtd, will cause not able to write again in same block. Signed-off-by: buxiasen <buxia...@xiaomi.com> --- include/nuttx/streams.h | 48 ++++ libs/libc/stream/lib_mtdoutstream.c | 294 ++++++++++----------- .../{lib_mtdoutstream.c => lib_mtdsostream.c} | 94 ++++--- 3 files changed, 239 insertions(+), 197 deletions(-) diff --git a/include/nuttx/streams.h b/include/nuttx/streams.h index dedf16a5f6..cc82d68de3 100644 --- a/include/nuttx/streams.h +++ b/include/nuttx/streams.h @@ -302,6 +302,14 @@ struct lib_blkoutstream_s #if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_MTD) struct lib_mtdoutstream_s +{ + struct lib_outstream_s common; + FAR struct inode *inode; + struct mtd_geometry_s geo; + FAR unsigned char *cache; +}; + +struct lib_mtdsostream_s { struct lib_sostream_s common; FAR struct inode *inode; @@ -686,6 +694,46 @@ int lib_mtdoutstream_open(FAR struct lib_mtdoutstream_s *stream, void lib_mtdoutstream_close(FAR struct lib_mtdoutstream_s *stream); #endif +/**************************************************************************** + * Name: lib_mtdsostream_open + * + * Description: + * mtd driver seekable outstream backend + * + * Input Parameters: + * stream - User allocated, uninitialized instance of struct + * lib_mtdsostream_s to be initialized. + * name - The full path of mtd device. + * + * Returned Value: + * Returns zero on success or a negated errno on failure + * + ****************************************************************************/ + +#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_MTD) +int lib_mtdsostream_open(FAR struct lib_mtdsostream_s *stream, + FAR const char *name); +#endif + +/**************************************************************************** + * Name: lib_mtdsostream_close + * + * Description: + * close mtd driver seekable outstream backend + * + * Input Parameters: + * stream - User allocated, uninitialized instance of struct + * lib_mtdsostream_s to be initialized. + * + * Returned Value: + * None (User allocated instance initialized). + * + ****************************************************************************/ + +#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_MTD) +void lib_mtdsostream_close(FAR struct lib_mtdsostream_s *stream); +#endif + /**************************************************************************** * Name: lib_noflush * diff --git a/libs/libc/stream/lib_mtdoutstream.c b/libs/libc/stream/lib_mtdoutstream.c index 37ed5d3891..138e9f985e 100644 --- a/libs/libc/stream/lib_mtdoutstream.c +++ b/libs/libc/stream/lib_mtdoutstream.c @@ -43,31 +43,86 @@ * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: mtdoutstream_bwrite_cache + ****************************************************************************/ + +static ssize_t +mtdoutstream_bwrite_cache(FAR struct lib_mtdoutstream_s *stream, + FAR struct mtd_dev_s *mtd, size_t block) +{ + size_t nblkpererase = stream->geo.erasesize / stream->geo.blocksize; + ssize_t ret; + + if (block % nblkpererase == 0) + { + ret = MTD_ERASE(mtd, block / nblkpererase, 1); + if (ret < 0) + { + return ret; + } + } + + ret = MTD_BWRITE(mtd, block, 1, stream->cache); + if (ret < 0) + { + return ret; + } + + return ret; +} + +static ssize_t mtdoutstream_bwrite(FAR struct lib_mtdoutstream_s *stream, + FAR struct mtd_dev_s *mtd, + size_t sblock, size_t nblock, + FAR const unsigned char *buf) +{ + size_t nblkpererase = stream->geo.erasesize / stream->geo.blocksize; + size_t serase = (sblock + nblkpererase - 1) / nblkpererase; + size_t eerase = (sblock + nblock + nblkpererase - 1) / nblkpererase; + ssize_t ret; + + if (serase != eerase) + { + ret = MTD_ERASE(mtd, serase, eerase - serase); + if (ret < 0) + { + return ret; + } + } + + ret = MTD_BWRITE(mtd, sblock, nblock, buf); + if (ret < 0) + { + return ret; + } + + return ret; +} + /**************************************************************************** * Name: mtdoutstream_flush ****************************************************************************/ -static int mtdoutstream_flush(FAR struct lib_sostream_s *self) +static int mtdoutstream_flush(FAR struct lib_outstream_s *self) { 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; - size_t nblkpererase = erasesize / stream->geo.blocksize; + FAR struct mtd_dev_s *mtd = stream->inode->u.i_mtd; + size_t blocksize = stream->geo.blocksize; int ret = OK; - if (self->nput % erasesize > 0) + if (self->nput % blocksize > 0) { - size_t sblock = self->nput / erasesize; +#ifdef CONFIG_MTD_BYTE_WRITE + /* If byte write, flush won't be needed */ - ret = MTD_ERASE(i_mtd, sblock, 1); - if (ret < 0) + if (mtd->write == NULL) +#endif { - return ret; + ret = mtdoutstream_bwrite_cache(stream, mtd, + self->nput / blocksize); } - - ret = MTD_BWRITE(i_mtd, sblock * nblkpererase, - nblkpererase, stream->cache); } return ret; @@ -77,14 +132,14 @@ static int mtdoutstream_flush(FAR struct lib_sostream_s *self) * Name: mtdoutstream_puts ****************************************************************************/ -static ssize_t mtdoutstream_puts(FAR struct lib_sostream_s *self, +static ssize_t mtdoutstream_puts(FAR struct lib_outstream_s *self, FAR const void *buf, size_t len) { FAR struct lib_mtdoutstream_s *stream = (FAR struct lib_mtdoutstream_s *)self; - FAR struct mtd_dev_s *i_mtd = stream->inode->u.i_mtd; + FAR struct mtd_dev_s *mtd = stream->inode->u.i_mtd; size_t erasesize = stream->geo.erasesize; - size_t nblkpererase = erasesize / stream->geo.blocksize; + size_t blocksize = stream->geo.blocksize; FAR const unsigned char *ptr = buf; size_t remain = len; ssize_t ret; @@ -94,73 +149,85 @@ static ssize_t mtdoutstream_puts(FAR struct lib_sostream_s *self, return -ENOSPC; } - while (remain > 0) +#ifdef CONFIG_MTD_BYTE_WRITE + if (mtd->write != NULL) { - off_t sblock = self->nput / erasesize; - off_t offset = self->nput % erasesize; + size_t serase = (self->nput + erasesize - 1) / erasesize; + size_t eerase = (self->nput + len + erasesize - 1) / erasesize; - if (offset > 0) + if (serase != eerase) { - size_t copying = offset + remain > erasesize ? - erasesize - offset : remain; + ret = MTD_ERASE(mtd, serase, eerase - serase); + if (ret < 0) + { + return ret; + } + } - memcpy(stream->cache + offset, ptr, copying); + ret = MTD_WRITE(mtd, self->nput, len, buf); + if (ret < 0) + { + return ret; + } - ptr += copying; - offset += copying; - self->nput += copying; - remain -= copying; + self->nput += len; + } + else +#endif + { + while (remain > 0) + { + off_t sblock = self->nput / blocksize; + off_t offset = self->nput % blocksize; - if (offset == erasesize) + if (offset > 0) { - ret = MTD_ERASE(i_mtd, sblock, 1); - if (ret < 0) + size_t copying = offset + remain > blocksize ? + blocksize - offset : remain; + + memcpy(stream->cache + offset, ptr, copying); + + ptr += copying; + offset += copying; + self->nput += copying; + remain -= copying; + + if (offset == blocksize) { - return ret; + ret = mtdoutstream_bwrite_cache(stream, mtd, sblock); + if (ret < 0) + { + return ret; + } } - - ret = MTD_BWRITE(i_mtd, sblock * nblkpererase, - nblkpererase, stream->cache); + } + else if (remain < blocksize) + { + ret = MTD_BREAD(mtd, sblock, 1, stream->cache); if (ret < 0) { return ret; } + + memcpy(stream->cache, ptr, remain); + self->nput += remain; + remain = 0; } - } - else if (remain < erasesize) - { - ret = MTD_BREAD(i_mtd, sblock * nblkpererase, - nblkpererase, stream->cache); - if (ret < 0) + else { - return ret; - } - - memcpy(stream->cache, ptr, remain); - self->nput += remain; - remain = 0; - } - else - { - size_t nblock = remain / erasesize; - size_t copying = nblock * erasesize; + size_t nblock = remain / blocksize; + size_t copying = nblock * blocksize; - ret = MTD_ERASE(i_mtd, sblock, nblock); - if (ret < 0) - { - return ret; - } + ret = mtdoutstream_bwrite(stream, mtd, sblock, nblock, ptr); + if (ret < 0) + { + return ret; + } - ret = MTD_BWRITE(i_mtd, sblock * nblkpererase, - nblock * nblkpererase, ptr); - if (ret < 0) - { - return ret; + ptr += copying; + self->nput += copying; + remain -= copying; } - - ptr += copying; - self->nput += copying; - remain -= copying; } } @@ -171,91 +238,12 @@ static ssize_t mtdoutstream_puts(FAR struct lib_sostream_s *self, * Name: mtdoutstream_putc ****************************************************************************/ -static void mtdoutstream_putc(FAR struct lib_sostream_s *self, int ch) +static void mtdoutstream_putc(FAR struct lib_outstream_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 ****************************************************************************/ @@ -342,18 +330,26 @@ int lib_mtdoutstream_open(FAR struct lib_mtdoutstream_s *stream, return -EINVAL; } - stream->cache = lib_malloc(stream->geo.erasesize); - if (stream->cache == NULL) + /* If mtd driver support the byte write, + * the temp buffer is not needed at all. + */ + +#ifdef CONFIG_MTD_BYTE_WRITE + if (node->u.i_mtd->write == NULL) +#endif { - close_mtddriver(node); - return -ENOMEM; + stream->cache = lib_malloc(stream->geo.blocksize); + if (stream->cache == NULL) + { + close_mtddriver(node); + return -ENOMEM; + } } stream->inode = node; stream->common.putc = mtdoutstream_putc; stream->common.puts = mtdoutstream_puts; stream->common.flush = mtdoutstream_flush; - stream->common.seek = mtdoutstream_seek; return OK; } diff --git a/libs/libc/stream/lib_mtdoutstream.c b/libs/libc/stream/lib_mtdsostream.c similarity index 77% copy from libs/libc/stream/lib_mtdoutstream.c copy to libs/libc/stream/lib_mtdsostream.c index 37ed5d3891..262fdd70e1 100644 --- a/libs/libc/stream/lib_mtdoutstream.c +++ b/libs/libc/stream/lib_mtdsostream.c @@ -1,7 +1,5 @@ /**************************************************************************** - * libs/libc/stream/lib_mtdoutstream.c - * - * SPDX-License-Identifier: Apache-2.0 + * libs/libc/stream/lib_mtdsostream.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -44,14 +42,14 @@ ****************************************************************************/ /**************************************************************************** - * Name: mtdoutstream_flush + * Name: mtdsostream_flush ****************************************************************************/ -static int mtdoutstream_flush(FAR struct lib_sostream_s *self) +static int mtdsostream_flush(FAR struct lib_sostream_s *self) { - FAR struct lib_mtdoutstream_s *stream = - (FAR struct lib_mtdoutstream_s *)self; - FAR struct mtd_dev_s *i_mtd = stream->inode->u.i_mtd; + FAR struct lib_mtdsostream_s *stream = + (FAR struct lib_mtdsostream_s *)self; + FAR struct mtd_dev_s *mtd = stream->inode->u.i_mtd; size_t erasesize = stream->geo.erasesize; size_t nblkpererase = erasesize / stream->geo.blocksize; int ret = OK; @@ -60,29 +58,29 @@ static int mtdoutstream_flush(FAR struct lib_sostream_s *self) { size_t sblock = self->nput / erasesize; - ret = MTD_ERASE(i_mtd, sblock, 1); + ret = MTD_ERASE(mtd, sblock, 1); if (ret < 0) { return ret; } - ret = MTD_BWRITE(i_mtd, sblock * nblkpererase, - nblkpererase, stream->cache); + ret = MTD_BWRITE(mtd, sblock * nblkpererase, + nblkpererase, stream->cache); } return ret; } /**************************************************************************** - * Name: mtdoutstream_puts + * Name: mtdsostream_puts ****************************************************************************/ -static ssize_t mtdoutstream_puts(FAR struct lib_sostream_s *self, - FAR const void *buf, size_t len) +static ssize_t mtdsostream_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 mtd_dev_s *i_mtd = stream->inode->u.i_mtd; + FAR struct lib_mtdsostream_s *stream = + (FAR struct lib_mtdsostream_s *)self; + FAR struct mtd_dev_s *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; @@ -113,13 +111,13 @@ static ssize_t mtdoutstream_puts(FAR struct lib_sostream_s *self, if (offset == erasesize) { - ret = MTD_ERASE(i_mtd, sblock, 1); + ret = MTD_ERASE(mtd, sblock, 1); if (ret < 0) { return ret; } - ret = MTD_BWRITE(i_mtd, sblock * nblkpererase, + ret = MTD_BWRITE(mtd, sblock * nblkpererase, nblkpererase, stream->cache); if (ret < 0) { @@ -129,7 +127,7 @@ static ssize_t mtdoutstream_puts(FAR struct lib_sostream_s *self, } else if (remain < erasesize) { - ret = MTD_BREAD(i_mtd, sblock * nblkpererase, + ret = MTD_BREAD(mtd, sblock * nblkpererase, nblkpererase, stream->cache); if (ret < 0) { @@ -145,13 +143,13 @@ static ssize_t mtdoutstream_puts(FAR struct lib_sostream_s *self, size_t nblock = remain / erasesize; size_t copying = nblock * erasesize; - ret = MTD_ERASE(i_mtd, sblock, nblock); + ret = MTD_ERASE(mtd, sblock, nblock); if (ret < 0) { return ret; } - ret = MTD_BWRITE(i_mtd, sblock * nblkpererase, + ret = MTD_BWRITE(mtd, sblock * nblkpererase, nblock * nblkpererase, ptr); if (ret < 0) { @@ -168,25 +166,25 @@ static ssize_t mtdoutstream_puts(FAR struct lib_sostream_s *self, } /**************************************************************************** - * Name: mtdoutstream_putc + * Name: mtdsostream_putc ****************************************************************************/ -static void mtdoutstream_putc(FAR struct lib_sostream_s *self, int ch) +static void mtdsostream_putc(FAR struct lib_sostream_s *self, int ch) { char tmp = ch; - mtdoutstream_puts(self, &tmp, 1); + mtdsostream_puts(self, &tmp, 1); } /**************************************************************************** - * Name: mtdoutstream_seek + * Name: mtdsostream_seek ****************************************************************************/ -static off_t mtdoutstream_seek(FAR struct lib_sostream_s *self, - off_t offset, int whence) +static off_t mtdsostream_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; + FAR struct lib_mtdsostream_s *stream = + (FAR struct lib_mtdsostream_s *)self; + FAR struct mtd_dev_s *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; @@ -214,7 +212,7 @@ static off_t mtdoutstream_seek(FAR struct lib_sostream_s *self, return -EINVAL; } - if (self->nput % erasesize) + if (self->nput % erasesize > 0) { block = self->nput / erasesize; if (offset >= block * erasesize && @@ -225,13 +223,13 @@ static off_t mtdoutstream_seek(FAR struct lib_sostream_s *self, goto out; } - ret = MTD_ERASE(i_mtd, block, 1); + ret = MTD_ERASE(mtd, block, 1); if (ret < 0) { return ret; } - ret = MTD_BWRITE(i_mtd, block * nblkpererase, + ret = MTD_BWRITE(mtd, block * nblkpererase, nblkpererase, stream->cache); if (ret < 0) { @@ -239,11 +237,11 @@ static off_t mtdoutstream_seek(FAR struct lib_sostream_s *self, } } - if (offset % erasesize) + if (offset % erasesize > 0) { block = offset / erasesize; - ret = MTD_BREAD(i_mtd, block * nblkpererase, + ret = MTD_BREAD(mtd, block * nblkpererase, nblkpererase, stream->cache); if (ret < 0) { @@ -261,21 +259,21 @@ out: ****************************************************************************/ /**************************************************************************** - * Name: lib_mtdoutstream_close + * Name: lib_mtdsostream_close * * Description: * close mtd driver stream backend * * Input Parameters: * stream - User allocated, uninitialized instance of struct - * lib_mtdoutstream_s to be initialized. + * lib_mtdsostream_s to be initialized. * * Returned Value: * None (User allocated instance initialized). * ****************************************************************************/ -void lib_mtdoutstream_close(FAR struct lib_mtdoutstream_s *stream) +void lib_mtdsostream_close(FAR struct lib_mtdsostream_s *stream) { if (stream != NULL) { @@ -287,7 +285,7 @@ void lib_mtdoutstream_close(FAR struct lib_mtdoutstream_s *stream) if (stream->cache != NULL) { - mtdoutstream_flush(&stream->common); + mtdsostream_flush(&stream->common); lib_free(stream->cache); stream->cache = NULL; } @@ -295,14 +293,14 @@ void lib_mtdoutstream_close(FAR struct lib_mtdoutstream_s *stream) } /**************************************************************************** - * Name: lib_mtdoutstream_open + * Name: lib_mtdsostream_open * * Description: * mtd driver stream backend * * Input Parameters: * stream - User allocated, uninitialized instance of struct - * lib_mtdoutstream_s to be initialized. + * lib_mtdsostream_s to be initialized. * name - The full path of mtd device. * * Returned Value: @@ -310,8 +308,8 @@ void lib_mtdoutstream_close(FAR struct lib_mtdoutstream_s *stream) * ****************************************************************************/ -int lib_mtdoutstream_open(FAR struct lib_mtdoutstream_s *stream, - FAR const char *name) +int lib_mtdsostream_open(FAR struct lib_mtdsostream_s *stream, + FAR const char *name) { FAR struct inode *node = NULL; int ret; @@ -350,10 +348,10 @@ int lib_mtdoutstream_open(FAR struct lib_mtdoutstream_s *stream, } stream->inode = node; - stream->common.putc = mtdoutstream_putc; - stream->common.puts = mtdoutstream_puts; - stream->common.flush = mtdoutstream_flush; - stream->common.seek = mtdoutstream_seek; + stream->common.putc = mtdsostream_putc; + stream->common.puts = mtdsostream_puts; + stream->common.flush = mtdsostream_flush; + stream->common.seek = mtdsostream_seek; return OK; }