Skip to content

Commit

Permalink
uio_resid api tweak
Browse files Browse the repository at this point in the history
* add uio_resid member to struct uio

* retire uio_resid() function

* move the overflow check into uio_init

* change the error number on the overflow from EOVERFLOW to EINVAL
  to match NetBSD
  • Loading branch information
yamt committed Dec 25, 2024
1 parent 8283811 commit 69ecff8
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 64 deletions.
7 changes: 2 additions & 5 deletions drivers/loop/loop.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,9 @@ static ssize_t loop_writev(FAR struct file *filep, FAR struct uio *uio)
{
/* Say that everything was written */

ssize_t ret = uio_resid(uio);
if (ret >= 0)
{
uio_advance(uio, ret);
}
size_t ret = uio->uio_resid;

uio_advance(uio, ret);
return ret;
}

Expand Down
9 changes: 4 additions & 5 deletions drivers/misc/dev_null.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,11 @@ static ssize_t devnull_writev(FAR struct file *filep, FAR struct uio *uio)
{
UNUSED(filep);

ssize_t ret = uio_resid(uio); /* Say that everything was written */
if (ret >= 0)
{
uio_advance(uio, ret);
}
/* Say that everything was written */

size_t ret = uio->uio_resid;

uio_advance(uio, ret);
return ret;
}

Expand Down
16 changes: 4 additions & 12 deletions drivers/misc/dev_zero.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,18 +74,13 @@ static const struct file_operations g_devzero_fops =

static ssize_t devzero_readv(FAR struct file *filep, FAR struct uio *uio)
{
ssize_t total = uio_resid(uio);
size_t total = uio->uio_resid;
FAR const struct iovec *iov = uio->uio_iov;
int iovcnt = uio->uio_iovcnt;
int i;

UNUSED(filep);

if (total < 0)
{
return total;
}

for (i = 0; i < iovcnt; i++)
{
memset(iov[i].iov_base, 0, iov[i].iov_len);
Expand All @@ -102,15 +97,12 @@ static ssize_t devzero_readv(FAR struct file *filep, FAR struct uio *uio)

static ssize_t devzero_writev(FAR struct file *filep, FAR struct uio *uio)
{
ssize_t total;
size_t total;
UNUSED(filep);

total = uio_resid(uio);
if (total >= 0)
{
uio_advance(uio, total);
}
total = uio->uio_resid;

uio_advance(uio, total);
return total;
}

Expand Down
13 changes: 2 additions & 11 deletions drivers/serial/serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -910,12 +910,6 @@ static ssize_t uart_readv(FAR struct file *filep, FAR struct uio *uio)
char ch;
int ret;

buflen = uio_resid(uio);
if (buflen < 0)
{
return buflen;
}

/* Only one user can access rxbuf->tail at a time */

ret = nxmutex_lock(&dev->recv.lock);
Expand All @@ -934,6 +928,7 @@ static ssize_t uart_readv(FAR struct file *filep, FAR struct uio *uio)
* data from the end of the buffer.
*/

buflen = uio->uio_resid;
while (recvd < buflen)
{
#ifdef CONFIG_SERIAL_REMOVABLE
Expand Down Expand Up @@ -1424,11 +1419,7 @@ static ssize_t uart_writev(FAR struct file *filep, FAR struct uio *uio)
return ret;
}

buflen = nwritten = uio_resid(uio);
if (nwritten < 0)
{
return nwritten;
}
buflen = nwritten = uio->uio_resid;

/* Only one user can access dev->xmit.head at a time */

Expand Down
16 changes: 13 additions & 3 deletions fs/vfs/fs_read.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,10 +208,16 @@ ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes)
{
struct iovec iov;
struct uio uio;
ssize_t ret;

iov.iov_base = buf;
iov.iov_len = nbytes;
uio_init(&uio, &iov, 1);
ret = uio_init(&uio, &iov, 1);
if (ret != 0)
{
return ret;
}

return file_readv(filep, &uio);
}

Expand Down Expand Up @@ -254,8 +260,12 @@ ssize_t nx_readv(int fd, FAR const struct iovec *iov, int iovcnt)

/* Then let file_readv do all of the work. */

uio_init(&uio, iov, iovcnt);
ret = file_readv(filep, &uio);
ret = uio_init(&uio, iov, iovcnt);
if (ret == 0)
{
ret = file_readv(filep, &uio);
}

fs_putfilep(filep);
return ret;
}
Expand Down
41 changes: 28 additions & 13 deletions fs/vfs/fs_uio.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,19 @@
#include <errno.h>

/****************************************************************************
* Public Functions
* Private Functions
****************************************************************************/

/****************************************************************************
* Name: uio_resid
* Name: uio_calc_resid
*
* Description:
* Return the remaining length of data in bytes.
* Or -EOVERFLOW.
* Or -EINVAL.
*
****************************************************************************/

ssize_t uio_resid(FAR const struct uio *uio)
ssize_t uio_calc_resid(FAR const struct uio *uio)
{
const struct iovec *iov = uio->uio_iov;
int iovcnt = uio->uio_iovcnt;
Expand All @@ -60,7 +60,7 @@ ssize_t uio_resid(FAR const struct uio *uio)
DEBUGASSERT(offset_in_iov <= iov[i].iov_len);
if (SSIZE_MAX - len < iov[i].iov_len - offset_in_iov)
{
return -EOVERFLOW;
return -EINVAL;
}

len += iov[i].iov_len - offset_in_iov;
Expand All @@ -70,6 +70,10 @@ ssize_t uio_resid(FAR const struct uio *uio)
return len;
}

/****************************************************************************
* Public Functions
****************************************************************************/

/****************************************************************************
* Name: uio_advance
*
Expand All @@ -84,7 +88,9 @@ void uio_advance(FAR struct uio *uio, size_t sz)
int iovcnt = uio->uio_iovcnt;
size_t offset_in_iov = uio->uio_offset_in_iov;

DEBUGASSERT(sz <= uio_resid(uio));
DEBUGASSERT(sz <= SSIZE_MAX);
DEBUGASSERT(uio->uio_resid <= SSIZE_MAX);
DEBUGASSERT(sz <= uio->uio_resid);
while (iovcnt > 0)
{
DEBUGASSERT(offset_in_iov <= iov->iov_len);
Expand Down Expand Up @@ -113,11 +119,18 @@ void uio_advance(FAR struct uio *uio, size_t sz)
*
****************************************************************************/

void uio_init(FAR struct uio *uio, FAR const struct iovec *iov, int iovcnt)
int uio_init(FAR struct uio *uio, FAR const struct iovec *iov, int iovcnt)
{
memset(uio, 0, sizeof(*uio));
uio->uio_iov = iov;
uio->uio_iovcnt = iovcnt;
uio->uio_resid = uio_calc_resid(uio);
if (uio->uio_resid < 0)
{
return -EINVAL;
}

return 0;
}

/****************************************************************************
Expand All @@ -133,9 +146,10 @@ void uio_copyfrom(FAR struct uio *uio, size_t offset, FAR const void *buf,
{
FAR const struct iovec *iov = uio->uio_iov;

DEBUGASSERT(uio_resid(uio) >= 0);
DEBUGASSERT(len <= uio_resid(uio));
DEBUGASSERT(offset <= uio_resid(uio) - len);
DEBUGASSERT(uio->uio_resid >= 0);
DEBUGASSERT(uio->uio_resid <= SSIZE_MAX);
DEBUGASSERT(len <= uio->uio_resid);
DEBUGASSERT(offset <= uio->uio_resid - len);
DEBUGASSERT(SSIZE_MAX - offset >= uio->uio_offset_in_iov);

offset += uio->uio_offset_in_iov;
Expand Down Expand Up @@ -180,9 +194,10 @@ void uio_copyto(FAR struct uio *uio, size_t offset, FAR void *buf,
{
FAR const struct iovec *iov = uio->uio_iov;

DEBUGASSERT(uio_resid(uio) >= 0);
DEBUGASSERT(len <= uio_resid(uio));
DEBUGASSERT(offset <= uio_resid(uio) - len);
DEBUGASSERT(uio->uio_resid >= 0);
DEBUGASSERT(uio->uio_resid <= SSIZE_MAX);
DEBUGASSERT(len <= uio->uio_resid);
DEBUGASSERT(offset <= uio->uio_resid - len);
DEBUGASSERT(SSIZE_MAX - offset >= uio->uio_offset_in_iov);

offset += uio->uio_offset_in_iov;
Expand Down
16 changes: 13 additions & 3 deletions fs/vfs/fs_write.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,10 +207,16 @@ ssize_t file_write(FAR struct file *filep, FAR const void *buf,
{
struct iovec iov;
struct uio uio;
ssize_t ret;

iov.iov_base = (FAR void *)buf;
iov.iov_len = nbytes;
uio_init(&uio, &iov, 1);
ret = uio_init(&uio, &iov, 1);
if (ret != 0)
{
return ret;
}

return file_writev(filep, &uio);
}

Expand Down Expand Up @@ -256,8 +262,12 @@ ssize_t nx_writev(int fd, FAR const struct iovec *iov, int iovcnt)
* index. Note that file_writev() will return the errno on failure.
*/

uio_init(&uio, iov, iovcnt);
ret = file_writev(filep, &uio);
ret = uio_init(&uio, iov, iovcnt);
if (ret == 0)
{
ret = file_writev(filep, &uio);
}

fs_putfilep(filep);
}

Expand Down
21 changes: 9 additions & 12 deletions include/nuttx/fs/uio.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,24 +45,14 @@ struct uio
{
FAR const struct iovec *uio_iov;
int uio_iovcnt;
size_t uio_resid; /* the remaining bytes in the request */
size_t uio_offset_in_iov; /* offset in uio_iov[0].iov_base */
};

/****************************************************************************
* Public Function Prototypes
****************************************************************************/

/****************************************************************************
* Name: uio_resid
*
* Description:
* Return the remaining length of data in bytes.
* Or -EOVERFLOW.
*
****************************************************************************/

ssize_t uio_resid(FAR const struct uio *uio);

/****************************************************************************
* Name: uio_advance
*
Expand All @@ -79,9 +69,16 @@ void uio_advance(FAR struct uio *uio, size_t sz);
* Description:
* Initialize the uio structure with reasonable default values.
*
* Return Value:
* 0 on success. A negative error number on an error.
*
* -EINVAL: The total size of the given iovec is too large.
* (Note: NetBSD's readv returns EINVAL in that case.
* I (yamamoto) couldn't find the specification in POSIX.)
*
****************************************************************************/

void uio_init(FAR struct uio *uio, FAR const struct iovec *iov, int iovcnt);
int uio_init(FAR struct uio *uio, FAR const struct iovec *iov, int iovcnt);

/****************************************************************************
* Name: uio_copyto
Expand Down

0 comments on commit 69ecff8

Please sign in to comment.