From 2f68778f08471fb7f13a8634ebb48c6db13c0f69 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Mon, 16 Dec 2013 13:44:13 +0100 Subject: Filesystem: Add readv/writev handlers The readv() and writev() support was implemented in terms of multiple calls to the read and write handlers. This imposes a problem on device files which use an IO vector as single request entity. For example a low-level network device (e.g. BPF(4)) may use an IO vector to create one frame from multiple protocol layers each with its own IO vector entry. --- cpukit/libcsupport/include/rtems/libio.h | 73 ++++++++++++++++++++++++++++++++ cpukit/libcsupport/src/__usrenv.c | 4 +- cpukit/libcsupport/src/readv.c | 21 +-------- cpukit/libcsupport/src/writev.c | 21 +-------- 4 files changed, 78 insertions(+), 41 deletions(-) (limited to 'cpukit/libcsupport') diff --git a/cpukit/libcsupport/include/rtems/libio.h b/cpukit/libcsupport/include/rtems/libio.h index 21d57ebddf..4bfa02a3a5 100644 --- a/cpukit/libcsupport/include/rtems/libio.h +++ b/cpukit/libcsupport/include/rtems/libio.h @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -807,6 +808,29 @@ typedef ssize_t (*rtems_filesystem_read_t)( size_t count ); +/** + * @brief Reads an IO vector from a node. + * + * This handler is responsible to update the offset field of the IO descriptor. + * + * @param[in, out] iop The IO pointer. + * @param[in] iov The IO vector with buffer for read data. The caller must + * ensure that the IO vector values are valid. + * @param[in] iovcnt The count of buffers in the IO vector. + * @param[in] total The total count of bytes in the buffers in the IO vector. + * + * @retval non-negative Count of read characters. + * @retval -1 An error occurred. The errno is set to indicate the error. + * + * @see rtems_filesystem_default_readv(). + */ +typedef ssize_t (*rtems_filesystem_readv_t)( + rtems_libio_t *iop, + const struct iovec *iov, + int iovcnt, + ssize_t total +); + /** * @brief Writes to a node. * @@ -827,6 +851,29 @@ typedef ssize_t (*rtems_filesystem_write_t)( size_t count ); +/** + * @brief Writes an IO vector to a node. + * + * This handler is responsible to update the offset field of the IO descriptor. + * + * @param[in, out] iop The IO pointer. + * @param[in] iov The IO vector with buffer for write data. The caller must + * ensure that the IO vector values are valid. + * @param[in] iovcnt The count of buffers in the IO vector. + * @param[in] total The total count of bytes in the buffers in the IO vector. + * + * @retval non-negative Count of written characters. + * @retval -1 An error occurred. The errno is set to indicate the error. + * + * @see rtems_filesystem_default_writev(). + */ +typedef ssize_t (*rtems_filesystem_writev_t)( + rtems_libio_t *iop, + const struct iovec *iov, + int iovcnt, + ssize_t total +); + /** * @brief IO control of a node. * @@ -992,6 +1039,8 @@ struct _rtems_filesystem_file_handlers_r { rtems_filesystem_fcntl_t fcntl_h; rtems_filesystem_poll_t poll_h; rtems_filesystem_kqfilter_t kqfilter_h; + rtems_filesystem_readv_t readv_h; + rtems_filesystem_writev_t writev_h; }; /** @@ -1032,6 +1081,18 @@ ssize_t rtems_filesystem_default_read( size_t count ); +/** + * @brief Calls the read handler for each IO vector entry. + * + * @see rtems_filesystem_readv_t. + */ +ssize_t rtems_filesystem_default_readv( + rtems_libio_t *iop, + const struct iovec *iov, + int iovcnt, + ssize_t total +); + /** * @retval -1 Always. The errno is set to ENOTSUP. * @@ -1043,6 +1104,18 @@ ssize_t rtems_filesystem_default_write( size_t count ); +/** + * @brief Calls the write handler for each IO vector entry. + * + * @see rtems_filesystem_write_t. + */ +ssize_t rtems_filesystem_default_writev( + rtems_libio_t *iop, + const struct iovec *iov, + int iovcnt, + ssize_t total +); + /** * @retval -1 Always. The errno is set to ENOTTY. * diff --git a/cpukit/libcsupport/src/__usrenv.c b/cpukit/libcsupport/src/__usrenv.c index 88058c4714..f8604479a5 100644 --- a/cpukit/libcsupport/src/__usrenv.c +++ b/cpukit/libcsupport/src/__usrenv.c @@ -54,7 +54,9 @@ const rtems_filesystem_file_handlers_r rtems_filesystem_null_handlers = { .ftruncate_h = rtems_filesystem_default_ftruncate, .fsync_h = rtems_filesystem_default_fsync_or_fdatasync, .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync, - .fcntl_h = rtems_filesystem_default_fcntl + .fcntl_h = rtems_filesystem_default_fcntl, + .readv_h = rtems_filesystem_default_readv, + .writev_h = rtems_filesystem_default_writev }; static void null_op_lock_or_unlock( diff --git a/cpukit/libcsupport/src/readv.c b/cpukit/libcsupport/src/readv.c index e47f22850a..6a4e0579f3 100644 --- a/cpukit/libcsupport/src/readv.c +++ b/cpukit/libcsupport/src/readv.c @@ -36,31 +36,12 @@ ssize_t readv( ) { ssize_t total; - int v; rtems_libio_t *iop; total = rtems_libio_iovec_eval( fd, iov, iovcnt, LIBIO_FLAGS_READ, &iop ); if ( total > 0 ) { - /* - * Now process the readv(). - */ - total = 0; - for ( v = 0 ; v < iovcnt ; v++ ) { - ssize_t bytes = ( *iop->pathinfo.handlers->read_h )( - iop, - iov[ v ].iov_base, - iov[ v ].iov_len - ); - - if ( bytes < 0 ) - return -1; - - total += bytes; - - if ( bytes != iov[ v ].iov_len ) - break; - } + total = ( *iop->pathinfo.handlers->readv_h )( iop, iov, iovcnt, total ); } return total; diff --git a/cpukit/libcsupport/src/writev.c b/cpukit/libcsupport/src/writev.c index 4a8dc735b8..7fa55bdbe5 100644 --- a/cpukit/libcsupport/src/writev.c +++ b/cpukit/libcsupport/src/writev.c @@ -28,31 +28,12 @@ ssize_t writev( ) { ssize_t total; - int v; rtems_libio_t *iop; total = rtems_libio_iovec_eval( fd, iov, iovcnt, LIBIO_FLAGS_WRITE, &iop ); if ( total > 0 ) { - /* - * Now process the writev(). - */ - total = 0; - for ( v = 0 ; v < iovcnt ; v++ ) { - ssize_t bytes = ( *iop->pathinfo.handlers->write_h )( - iop, - iov[ v ].iov_base, - iov[ v ].iov_len - ); - - if ( bytes < 0 ) - return -1; - - total += bytes; - - if ( bytes != iov[ v ].iov_len ) - break; - } + total = ( *iop->pathinfo.handlers->writev_h )( iop, iov, iovcnt, total ); } return total; -- cgit v1.2.3