From 06f7ce70f5b0b75240599e65db715908446be8a5 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Tue, 31 Oct 2023 15:14:05 +1100 Subject: [PATCH] extmod/vfs_reader: Add file ioctl to set read buffer size. Can be used to speed up importing a file from a vfs based filesystem. Signed-off-by: Andrew Leech --- extmod/vfs_reader.c | 25 ++++++++++++++++++------- py/mpconfig.h | 4 ++++ py/stream.h | 1 + tests/extmod/vfs_userfs.py.exp | 4 ++++ 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/extmod/vfs_reader.c b/extmod/vfs_reader.c index 3c6ff52a991b0..3c459d927874d 100644 --- a/extmod/vfs_reader.c +++ b/extmod/vfs_reader.c @@ -38,17 +38,18 @@ typedef struct _mp_reader_vfs_t { mp_obj_t file; uint16_t len; uint16_t pos; - byte buf[24]; + uint8_t bufsize; + byte buf[]; } mp_reader_vfs_t; STATIC mp_uint_t mp_reader_vfs_readbyte(void *data) { mp_reader_vfs_t *reader = (mp_reader_vfs_t *)data; if (reader->pos >= reader->len) { - if (reader->len < sizeof(reader->buf)) { + if (reader->len < reader->bufsize) { return MP_READER_EOF; } else { int errcode; - reader->len = mp_stream_rw(reader->file, reader->buf, sizeof(reader->buf), + reader->len = mp_stream_rw(reader->file, reader->buf, reader->bufsize, &errcode, MP_STREAM_RW_READ | MP_STREAM_RW_ONCE); if (errcode != 0) { // TODO handle errors properly @@ -70,14 +71,24 @@ STATIC void mp_reader_vfs_close(void *data) { } void mp_reader_new_file(mp_reader_t *reader, qstr filename) { - mp_reader_vfs_t *rf = m_new_obj(mp_reader_vfs_t); mp_obj_t args[2] = { MP_OBJ_NEW_QSTR(filename), MP_OBJ_NEW_QSTR(MP_QSTR_rb), }; - rf->file = mp_vfs_open(MP_ARRAY_SIZE(args), &args[0], (mp_map_t *)&mp_const_empty_map); - int errcode; - rf->len = mp_stream_rw(rf->file, rf->buf, sizeof(rf->buf), &errcode, MP_STREAM_RW_READ | MP_STREAM_RW_ONCE); + mp_obj_t file = mp_vfs_open(MP_ARRAY_SIZE(args), &args[0], (mp_map_t *)&mp_const_empty_map); + + const mp_stream_p_t *stream_p = mp_get_stream(file); + int errcode = 0; + mp_uint_t bufsize = stream_p->ioctl(file, MP_STREAM_BUFFER_SIZE, 0, &errcode); + if (bufsize < 7 || bufsize > 255) { + errcode = 0; + bufsize = MICROPY_READER_VFS_DEFAULT_BUFFER_SIZE; + } + + mp_reader_vfs_t *rf = m_new_obj_var(mp_reader_vfs_t, uint8_t, bufsize); + rf->file = file; + rf->bufsize = bufsize; + rf->len = mp_stream_rw(rf->file, rf->buf, rf->bufsize, &errcode, MP_STREAM_RW_READ | MP_STREAM_RW_ONCE); if (errcode != 0) { mp_raise_OSError(errcode); } diff --git a/py/mpconfig.h b/py/mpconfig.h index 6995600abeb7e..278591f3cfac7 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -597,6 +597,10 @@ #define MICROPY_READER_VFS (0) #endif +#ifndef MICROPY_READER_VFS_DEFAULT_BUFFER_SIZE +#define MICROPY_READER_VFS_DEFAULT_BUFFER_SIZE (23) +#endif + // Whether any readers have been defined #ifndef MICROPY_HAS_FILE_READER #define MICROPY_HAS_FILE_READER (MICROPY_READER_POSIX || MICROPY_READER_VFS) diff --git a/py/stream.h b/py/stream.h index 6b5c85ab15c2b..44a12faa1a9fb 100644 --- a/py/stream.h +++ b/py/stream.h @@ -43,6 +43,7 @@ #define MP_STREAM_GET_DATA_OPTS (8) // Get data/message options #define MP_STREAM_SET_DATA_OPTS (9) // Set data/message options #define MP_STREAM_GET_FILENO (10) // Get fileno of underlying file +#define MP_STREAM_BUFFER_SIZE (11) // Get preferred buffer size for file // These poll ioctl values are compatible with Linux #define MP_STREAM_POLL_RD (0x0001) diff --git a/tests/extmod/vfs_userfs.py.exp b/tests/extmod/vfs_userfs.py.exp index 05cff0452c68f..f86e0fa3d66e9 100644 --- a/tests/extmod/vfs_userfs.py.exp +++ b/tests/extmod/vfs_userfs.py.exp @@ -3,21 +3,25 @@ some data in a text file stat /usermod1 stat /usermod1.py open /usermod1.py rb +ioctl 11 0 ioctl 4 0 in usermod1 stat /usermod2 stat /usermod2.py open /usermod2.py rb +ioctl 11 0 ioctl 4 0 in usermod2 stat /usermod3 stat /usermod3.py open /usermod3.py rb +ioctl 11 0 ioctl 4 0 SyntaxError in usermod3 stat /usermod4 stat /usermod4.py stat /usermod4.mpy open /usermod4.mpy rb +ioctl 11 0 ioctl 4 0 ValueError in usermod4