Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fs/vfs: initialize uio only if lower implement readv/writev #15603

Merged
merged 2 commits into from
Jan 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 40 additions & 45 deletions fs/vfs/fs_read.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,19 +50,14 @@
*
****************************************************************************/

static ssize_t file_readv_compat(FAR struct file *filep, FAR struct uio *uio)
static ssize_t file_readv_compat(FAR struct file *filep,
FAR const struct iovec *iov, int iovcnt)
{
FAR const struct iovec *iov = uio->uio_iov;
int iovcnt = uio->uio_iovcnt;
FAR struct inode *inode = filep->f_inode;
ssize_t ntotal;
ssize_t nread;
size_t remaining;
FAR uint8_t *buffer;
int i;

DEBUGASSERT(inode->u.i_ops->read != NULL);
anchao marked this conversation as resolved.
Show resolved Hide resolved

anchao marked this conversation as resolved.
Show resolved Hide resolved
/* Process each entry in the struct iovec array */

for (i = 0, ntotal = 0; i < iovcnt; i++)
Expand All @@ -74,36 +69,41 @@ static ssize_t file_readv_compat(FAR struct file *filep, FAR struct uio *uio)
continue;
}

buffer = iov[i].iov_base;
remaining = iov[i].iov_len;
/* Sanity check to avoid total length overflow */

if (SSIZE_MAX - ntotal < iov[i].iov_len)
{
if (ntotal > 0)
{
break;
}

return -EINVAL;
}

nread = inode->u.i_ops->read(filep, (void *)buffer, remaining);
nread = inode->u.i_ops->read(filep, iov[i].iov_base,
iov[i].iov_len);

/* Check for a read error */

if (nread < 0)
{
return ntotal ? ntotal : nread;
if (ntotal > 0)
{
break;
}

return nread;
}

ntotal += nread;

/* Check for a parital success condition, including an end-of-file */

if (nread < remaining)
if (nread < iov[i].iov_len)
{
return ntotal;
break;
}

/* Update the pointer */

buffer += nread;
remaining -= nread;
}

if (ntotal >= 0)
{
uio_advance(uio, ntotal);
}

return ntotal;
Expand All @@ -126,15 +126,17 @@ static ssize_t file_readv_compat(FAR struct file *filep, FAR struct uio *uio)
*
* Input Parameters:
* filep - File structure instance
* uio - User buffer information
* iov - User-provided iovec to save the data
* iovcnt - The number of iovec
*
* Returned Value:
* The positive non-zero number of bytes read on success, 0 on if an
* end-of-file condition, or a negated errno value on any failure.
*
****************************************************************************/

ssize_t file_readv(FAR struct file *filep, FAR struct uio *uio)
ssize_t file_readv(FAR struct file *filep,
FAR const struct iovec *iov, int iovcnt)
{
FAR struct inode *inode;
ssize_t ret = -EBADF;
Expand Down Expand Up @@ -162,11 +164,17 @@ ssize_t file_readv(FAR struct file *filep, FAR struct uio *uio)
{
if (inode->u.i_ops->readv)
{
ret = inode->u.i_ops->readv(filep, uio);
struct uio uio;

ret = uio_init(&uio, iov, iovcnt);
if (ret == 0)
{
ret = inode->u.i_ops->readv(filep, &uio);
}
}
else if (inode->u.i_ops->read)
{
ret = file_readv_compat(filep, uio);
ret = file_readv_compat(filep, iov, iovcnt);
}
}

Expand Down Expand Up @@ -207,18 +215,11 @@ ssize_t file_readv(FAR struct file *filep, FAR struct uio *uio)
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;
ret = uio_init(&uio, &iov, 1);
if (ret != 0)
{
return ret;
}

return file_readv(filep, &uio);
return file_readv(filep, &iov, 1);
}

/****************************************************************************
Expand All @@ -244,7 +245,6 @@ ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes)

ssize_t nx_readv(int fd, FAR const struct iovec *iov, int iovcnt)
{
struct uio uio;
FAR struct file *filep;
ssize_t ret;

Expand All @@ -253,20 +253,15 @@ ssize_t nx_readv(int fd, FAR const struct iovec *iov, int iovcnt)
*/

ret = (ssize_t)fs_getfilep(fd, &filep);
if (ret < 0)
if (ret >= 0)
{
return ret;
}
/* Then let file_readv do all of the work. */

/* Then let file_readv do all of the work. */
ret = file_readv(filep, iov, iovcnt);

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

fs_putfilep(filep);
return ret;
}

Expand Down
2 changes: 1 addition & 1 deletion fs/vfs/fs_uio.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ int uio_init(FAR struct uio *uio, FAR const struct iovec *iov, int iovcnt)
resid = uio_calc_resid(uio);
if (resid < 0)
{
return -EINVAL;
return resid;
anchao marked this conversation as resolved.
Show resolved Hide resolved
}

uio->uio_resid = resid;
Expand Down
79 changes: 37 additions & 42 deletions fs/vfs/fs_write.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,19 +51,13 @@
****************************************************************************/

static ssize_t file_writev_compat(FAR struct file *filep,
FAR struct uio *uio)
FAR const struct iovec *iov, int iovcnt)
{
FAR const struct iovec *iov = uio->uio_iov;
int iovcnt = uio->uio_iovcnt;
FAR struct inode *inode = filep->f_inode;
ssize_t ntotal;
ssize_t nwritten;
size_t remaining;
FAR uint8_t *buffer;
ssize_t ntotal;
anchao marked this conversation as resolved.
Show resolved Hide resolved
int i;

DEBUGASSERT(inode->u.i_ops->write != NULL);

/* Process each entry in the struct iovec array */

for (i = 0, ntotal = 0; i < iovcnt; i++)
Expand All @@ -75,36 +69,41 @@ static ssize_t file_writev_compat(FAR struct file *filep,
continue;
}

buffer = iov[i].iov_base;
remaining = iov[i].iov_len;
/* Sanity check to avoid total length overflow */

nwritten = inode->u.i_ops->write(filep, (void *)buffer, remaining);
if (SSIZE_MAX - ntotal < iov[i].iov_len)
{
if (ntotal > 0)
{
break;
}

return -EINVAL;
}

nwritten = inode->u.i_ops->write(filep, iov[i].iov_base,
iov[i].iov_len);

/* Check for a write error */

if (nwritten < 0)
{
return ntotal ? ntotal : nwritten;
if (ntotal > 0)
{
break;
}

return nwritten;
}

ntotal += nwritten;

/* Check for a parital success condition */

if (nwritten < remaining)
if (nwritten < iov[i].iov_len)
{
return ntotal;
break;
}

anchao marked this conversation as resolved.
Show resolved Hide resolved
/* Update the pointer */

buffer += nwritten;
remaining -= nwritten;
}

if (ntotal >= 0)
{
uio_advance(uio, ntotal);
}

return ntotal;
Expand All @@ -128,7 +127,8 @@ static ssize_t file_writev_compat(FAR struct file *filep,
*
* Input Parameters:
* filep - Instance of struct file to use with the write
* uio - User buffer information
* iov - Data to write
* iovcnt - The number of vectors
*
* Returned Value:
* On success, the number of bytes written are returned (zero indicates
Expand All @@ -138,7 +138,8 @@ static ssize_t file_writev_compat(FAR struct file *filep,
*
****************************************************************************/

ssize_t file_writev(FAR struct file *filep, FAR struct uio *uio)
ssize_t file_writev(FAR struct file *filep,
FAR const struct iovec *iov, int iovcnt)
{
FAR struct inode *inode;
ssize_t ret = -EBADF;
Expand All @@ -159,11 +160,17 @@ ssize_t file_writev(FAR struct file *filep, FAR struct uio *uio)
{
if (inode->u.i_ops->writev)
{
ret = inode->u.i_ops->writev(filep, uio);
struct uio uio;

ret = uio_init(&uio, iov, iovcnt);
if (ret == 0)
{
ret = inode->u.i_ops->writev(filep, &uio);
}
}
else if (inode->u.i_ops->write)
{
ret = file_writev_compat(filep, uio);
ret = file_writev_compat(filep, iov, iovcnt);
}
}

Expand Down Expand Up @@ -206,18 +213,11 @@ ssize_t file_write(FAR struct file *filep, FAR const void *buf,
size_t nbytes)
{
struct iovec iov;
struct uio uio;
ssize_t ret;

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

return file_writev(filep, &uio);
return file_writev(filep, &iov, 1);
}

/****************************************************************************
Expand Down Expand Up @@ -247,7 +247,6 @@ ssize_t file_write(FAR struct file *filep, FAR const void *buf,

ssize_t nx_writev(int fd, FAR const struct iovec *iov, int iovcnt)
{
struct uio uio;
FAR struct file *filep;
ssize_t ret;

Expand All @@ -262,11 +261,7 @@ ssize_t nx_writev(int fd, FAR const struct iovec *iov, int iovcnt)
* index. Note that file_writev() will return the errno on failure.
*/

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

fs_putfilep(filep);
}
Expand Down
6 changes: 4 additions & 2 deletions include/nuttx/fs/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1419,7 +1419,8 @@ int close_mtddriver(FAR struct inode *pinode);
****************************************************************************/

ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes);
ssize_t file_readv(FAR struct file *filep, FAR struct uio *uio);
ssize_t file_readv(FAR struct file *filep,
FAR const struct iovec *iov, int iovcnt);

/****************************************************************************
* Name: nx_read
Expand Down Expand Up @@ -1473,7 +1474,8 @@ ssize_t nx_readv(int fd, FAR const struct iovec *iov, int iovcnt);

ssize_t file_write(FAR struct file *filep, FAR const void *buf,
size_t nbytes);
ssize_t file_writev(FAR struct file *filep, FAR struct uio *uio);
ssize_t file_writev(FAR struct file *filep,
FAR const struct iovec *iov, int iovcnt);

/****************************************************************************
* Name: nx_write
Expand Down
Loading