AIO now also supports socket transfers
This commit is contained in:
parent
0218f01f12
commit
ae3cc327c7
20
TODO
20
TODO
@ -1,4 +1,4 @@
|
||||
NuttX TODO List (Last updated October 10, 2014)
|
||||
NuttX TODO List (Last updated October 11, 2014)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This file summarizes known NuttX bugs, limitations, inconsistencies with
|
||||
@ -18,7 +18,7 @@ nuttx/
|
||||
(13) Network (net/, drivers/net)
|
||||
(4) USB (drivers/usbdev, drivers/usbhost)
|
||||
(10) Libraries (libc/, )
|
||||
(12) File system/Generic drivers (fs/, drivers/)
|
||||
(11) File system/Generic drivers (fs/, drivers/)
|
||||
(6) Graphics subystem (graphics/)
|
||||
(1) Pascal add-on (pcode/)
|
||||
(1) Documentation (Documentation/)
|
||||
@ -1163,22 +1163,6 @@ o File system / Generic drivers (fs/, drivers/)
|
||||
Status: Open
|
||||
Priority: Medium
|
||||
|
||||
Title: ASYNCHRONOUS I/O DOES NOT WORK WITH SOCKETS
|
||||
Description: The current asynchronous I/O logic will only work with
|
||||
file descriptions. If given a socket descriptor, the
|
||||
AIO interfaces will fail with EBADF. The existing logic
|
||||
should be extended to handle socket descriptors.
|
||||
|
||||
This should be an easy fix: There could have to be a
|
||||
tagged union of a struct file and struct socket in the
|
||||
AIO container and the worker logic would have to select
|
||||
the correct low-level, internal interface. There would
|
||||
be no lseek'ing on sockets.
|
||||
|
||||
Status: Open
|
||||
Priority: Pretty high because this limits the usefulness of the
|
||||
AIO implementation.
|
||||
|
||||
o Graphics subsystem (graphics/)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
37
fs/aio/aio.h
37
fs/aio/aio.h
@ -48,6 +48,7 @@
|
||||
#include <queue.h>
|
||||
|
||||
#include <nuttx/wqueue.h>
|
||||
#include <nuttx/net/net.h>
|
||||
|
||||
#ifdef CONFIG_FS_AIO
|
||||
|
||||
@ -62,6 +63,21 @@
|
||||
# define CONFIG_FS_NAIOC 8
|
||||
#endif
|
||||
|
||||
#undef AIO_HAVE_FILEP
|
||||
#undef AIO_HAVE_PSOCK
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
# define AIO_HAVE_FILEP
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_TCP) && CONFIG_NSOCKET_DESCRIPTORS > 0
|
||||
# define AIO_HAVE_PSOCK
|
||||
#endif
|
||||
|
||||
#if !defined(AIO_HAVE_FILEP) && !defined(AIO_HAVE_PSOCK)
|
||||
# error AIO needs file and/or socket descriptors
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
@ -73,13 +89,22 @@
|
||||
struct file;
|
||||
struct aio_container_s
|
||||
{
|
||||
dq_entry_t aioc_link; /* Supports a doubly linked list */
|
||||
FAR struct aiocb *aioc_aiocbp; /* The contained AIO control block */
|
||||
FAR struct file *aioc_filep; /* File structure to use with the I/O */
|
||||
struct work_s aioc_work; /* Used to defer I/O to the work thread */
|
||||
pid_t aioc_pid; /* ID of the waiting task */
|
||||
dq_entry_t aioc_link; /* Supports a doubly linked list */
|
||||
FAR struct aiocb *aioc_aiocbp; /* The contained AIO control block */
|
||||
union
|
||||
{
|
||||
#ifdef AIO_HAVE_FILEP
|
||||
FAR struct file *aioc_filep; /* File structure to use with the I/O */
|
||||
#endif
|
||||
#ifdef AIO_HAVE_PSOCK
|
||||
FAR struct socket *aioc_psock; /* Socket structure to use with the I/O */
|
||||
#endif
|
||||
FAR void *ptr; /* Generic pointer to FAR data */
|
||||
} u;
|
||||
struct work_s aioc_work; /* Used to defer I/O to the work thread */
|
||||
pid_t aioc_pid; /* ID of the waiting task */
|
||||
#ifdef CONFIG_PRIORITY_INHERITANCE
|
||||
uint8_t aioc_prio; /* Priority of the waiting task */
|
||||
uint8_t aioc_prio; /* Priority of the waiting task */
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -110,9 +110,9 @@ static void aio_fsync_worker(FAR void *arg)
|
||||
#endif
|
||||
aiocbp = aioc_decant(aioc);
|
||||
|
||||
/* Perform the fsync using aioc_filep */
|
||||
/* Perform the fsync using u.aioc_filep */
|
||||
|
||||
ret = file_fsync(aioc->aioc_filep);
|
||||
ret = file_fsync(aioc->u.aioc_filep);
|
||||
if (ret < 0)
|
||||
{
|
||||
int errcode = get_errno();
|
||||
|
@ -46,6 +46,8 @@
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/net/net.h>
|
||||
|
||||
#include "aio/aio.h"
|
||||
|
||||
#ifdef CONFIG_FS_AIO
|
||||
@ -108,16 +110,39 @@ static void aio_read_worker(FAR void *arg)
|
||||
#endif
|
||||
aiocbp = aioc_decant(aioc);
|
||||
|
||||
/* Perform the read using:
|
||||
*
|
||||
* aioc_filep - File structure pointer
|
||||
* aio_buf - Location of buffer
|
||||
* aio_nbytes - Length of transfer
|
||||
* aio_offset - File offset
|
||||
*/
|
||||
#if defined(AIO_HAVE_FILEP) && defined(AIO_HAVE_PSOCK)
|
||||
if (aioc->fildes >= CONFIG_NFILE_DESCRIPTORS)
|
||||
#endif
|
||||
#ifdef AIO_HAVE_FILEP
|
||||
{
|
||||
/* Perform the file read using:
|
||||
*
|
||||
* u.aioc_filep - File structure pointer
|
||||
* aio_buf - Location of buffer
|
||||
* aio_nbytes - Length of transfer
|
||||
* aio_offset - File offset
|
||||
*/
|
||||
|
||||
nread = file_pread(aioc->aioc_filep, (FAR void *)aiocbp->aio_buf,
|
||||
aiocbp->aio_nbytes, aiocbp->aio_offset);
|
||||
nread = file_pread(aioc->u.aioc_filep, (FAR void *)aiocbp->aio_buf,
|
||||
aiocbp->aio_nbytes, aiocbp->aio_offset);
|
||||
}
|
||||
#endif
|
||||
#if defined(AIO_HAVE_FILEP) && defined(AIO_HAVE_PSOCK)
|
||||
else
|
||||
#endif
|
||||
#ifdef AIO_HAVE_PSOCK
|
||||
{
|
||||
/* Perform the socket receive using:
|
||||
*
|
||||
* u.aioc_psock - Socket structure pointer
|
||||
* aio_buf - Location of buffer
|
||||
* aio_nbytes - Length of transfer
|
||||
*/
|
||||
|
||||
nread = psock_recv(aioc->u.aioc_psock, (FAR void *)aiocbp->aio_buf,
|
||||
aiocbp->aio_nbytes, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Set the result of the read */
|
||||
|
||||
|
@ -76,6 +76,7 @@
|
||||
* Name: file_fcntl
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef AIO_HAVE_FILEP
|
||||
static inline int file_fcntl(FAR struct file *filep, int cmd, ...)
|
||||
{
|
||||
va_list ap;
|
||||
@ -86,6 +87,7 @@ static inline int file_fcntl(FAR struct file *filep, int cmd, ...)
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: aio_write_worker
|
||||
@ -126,23 +128,28 @@ static void aio_write_worker(FAR void *arg)
|
||||
#endif
|
||||
aiocbp = aioc_decant(aioc);
|
||||
|
||||
/* Call fcntl(F_GETFL) to get the file open mode. */
|
||||
#if defined(AIO_HAVE_FILEP) && defined(AIO_HAVE_PSOCK)
|
||||
if (aioc->fildes >= CONFIG_NFILE_DESCRIPTORS)
|
||||
#endif
|
||||
#ifdef AIO_HAVE_FILEP
|
||||
{
|
||||
/* Call fcntl(F_GETFL) to get the file open mode. */
|
||||
|
||||
oflags = file_fcntl(aioc->u.aioc_filep, F_GETFL);
|
||||
if (oflags < 0)
|
||||
{
|
||||
int errcode = get_errno();
|
||||
fdbg("ERROR: fcntl failed: %d\n", errcode);
|
||||
aiocbp->aio_result = -errcode;
|
||||
goto errout:
|
||||
}
|
||||
|
||||
oflags = file_fcntl(aioc->aioc_filep, F_GETFL);
|
||||
if (oflags < 0)
|
||||
{
|
||||
int errcode = get_errno();
|
||||
fdbg("ERROR: fcntl failed: %d\n", errcode);
|
||||
aiocbp->aio_result = -errcode;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Perform the write using:
|
||||
*
|
||||
* aioc_filep - File descriptor
|
||||
* aio_buf - Location of buffer
|
||||
* aio_nbytes - Length of transfer
|
||||
* aio_offset - File offset
|
||||
* u.aioc_filep - File structure pointer
|
||||
* aio_buf - Location of buffer
|
||||
* aio_nbytes - Length of transfer
|
||||
* aio_offset - File offset
|
||||
*/
|
||||
|
||||
/* Check if O_APPEND is set in the file open flags */
|
||||
@ -151,32 +158,54 @@ static void aio_write_worker(FAR void *arg)
|
||||
{
|
||||
/* Append to the current file position */
|
||||
|
||||
nwritten = file_write(aioc->aioc_filep,
|
||||
nwritten = file_write(aioc->u.aioc_filep,
|
||||
(FAR const void *)aiocbp->aio_buf,
|
||||
aiocbp->aio_nbytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
nwritten = file_pwrite(aioc->aioc_filep,
|
||||
nwritten = file_pwrite(aioc->u.aioc_filep,
|
||||
(FAR const void *)aiocbp->aio_buf,
|
||||
aiocbp->aio_nbytes,
|
||||
aiocbp->aio_offset);
|
||||
}
|
||||
|
||||
/* Set the result of the write */
|
||||
|
||||
if (nwritten < 0)
|
||||
{
|
||||
int errcode = get_errno();
|
||||
fdbg("ERROR: write/pwrite failed: %d\n", errcode);
|
||||
DEBUGASSERT(errcode > 0);
|
||||
aiocbp->aio_result = -errcode;
|
||||
}
|
||||
else
|
||||
{
|
||||
aiocbp->aio_result = nwritten;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(AIO_HAVE_FILEP) && defined(AIO_HAVE_PSOCK)
|
||||
else
|
||||
#endif
|
||||
#ifdef AIO_HAVE_PSOCK
|
||||
{
|
||||
/* Perform the send using:
|
||||
*
|
||||
* u.aioc_psock - Socket structure pointer
|
||||
* aio_buf - Location of buffer
|
||||
* aio_nbytes - Length of transfer
|
||||
*/
|
||||
|
||||
nwritten = psock_send(aioc->u.aioc_psock,
|
||||
(FAR const void *)aiocbp->aio_buf,
|
||||
aiocbp->aio_nbytes, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check the result of the write */
|
||||
|
||||
if (nwritten < 0)
|
||||
{
|
||||
int errcode = get_errno();
|
||||
fdbg("ERROR: write/pwrite failed: %d\n", errcode);
|
||||
DEBUGASSERT(errcode > 0);
|
||||
aiocbp->aio_result = -errcode;
|
||||
}
|
||||
else
|
||||
{
|
||||
aiocbp->aio_result = nwritten;
|
||||
}
|
||||
|
||||
#ifdef AIO_HAVE_FILEP
|
||||
errout:
|
||||
#endif
|
||||
|
||||
/* Signal the client */
|
||||
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include <sched.h>
|
||||
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/net/net.h>
|
||||
|
||||
#include "aio/aio.h"
|
||||
|
||||
@ -90,20 +91,53 @@
|
||||
FAR struct aio_container_s *aio_contain(FAR struct aiocb *aiocbp)
|
||||
{
|
||||
FAR struct aio_container_s *aioc;
|
||||
FAR struct file *filep;
|
||||
union
|
||||
{
|
||||
#ifdef AIO_HAVE_FILEP
|
||||
FAR struct file *filep;
|
||||
#endif
|
||||
#ifdef AIO_HAVE_FILEP
|
||||
FAR struct socket *psock;
|
||||
#endif
|
||||
FAR void *ptr;
|
||||
} u;
|
||||
#ifdef CONFIG_PRIORITY_INHERITANCE
|
||||
struct sched_param param;
|
||||
#endif
|
||||
|
||||
/* Get the file structure corresponding to the file descriptor. */
|
||||
|
||||
filep = fs_getfilep(aiocbp->aio_fildes);
|
||||
if (!filep)
|
||||
#if defined(AIO_HAVE_FILEP) && defined(AIO_HAVE_PSOCK)
|
||||
if (aioc->fildes >= CONFIG_NFILE_DESCRIPTORS)
|
||||
#endif
|
||||
#ifdef AIO_HAVE_FILEP
|
||||
{
|
||||
/* The errno value has already been set */
|
||||
/* Get the file structure corresponding to the file descriptor. */
|
||||
|
||||
return NULL;
|
||||
u.filep = fs_getfilep(aiocbp->aio_fildes);
|
||||
if (!u.filep)
|
||||
{
|
||||
/* The errno value has already been set */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(AIO_HAVE_FILEP) && defined(AIO_HAVE_PSOCK)
|
||||
else
|
||||
#endif
|
||||
#ifdef AIO_HAVE_PSOCK
|
||||
{
|
||||
/* Get the socket structure corresponding to the socket descriptor */
|
||||
|
||||
u.psock = sockfd_socket(aiocbp->aio_fildes);
|
||||
if (!u.psock)
|
||||
{
|
||||
/* Does not set the errno. EBADF is the most likely explanation. */
|
||||
|
||||
set_errno(EBADF);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Allocate the AIO control block container, waiting for one to become
|
||||
* available if necessary. This should never fail.
|
||||
@ -116,7 +150,7 @@ FAR struct aio_container_s *aio_contain(FAR struct aiocb *aiocbp)
|
||||
|
||||
memset(aioc, 0, sizeof(struct aio_container_s));
|
||||
aioc->aioc_aiocbp = aiocbp;
|
||||
aioc->aioc_filep = filep;
|
||||
aioc->u.aioc_filep = u.ptr;
|
||||
aioc->aioc_pid = getpid();
|
||||
|
||||
#ifdef CONFIG_PRIORITY_INHERITANCE
|
||||
|
@ -125,7 +125,7 @@ struct aiocb
|
||||
FAR volatile void *aio_buf; /* Location of buffer */
|
||||
off_t aio_offset; /* File offset */
|
||||
size_t aio_nbytes; /* Length of transfer */
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 127
|
||||
#if (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS) > 127
|
||||
int16_t aio_fildes; /* File descriptor (should be int) */
|
||||
#else
|
||||
int8_t aio_fildes; /* File descriptor (should be int) */
|
||||
|
@ -302,16 +302,17 @@ void net_initlist(FAR struct socketlist *list);
|
||||
void net_releaselist(FAR struct socketlist *list);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sockfd_release
|
||||
* Name: sockfd_socket
|
||||
*
|
||||
* Description:
|
||||
* Free the socket by its socket descriptor.
|
||||
* Given a socket descriptor, return the underlying socket structure.
|
||||
*
|
||||
* Input Parameters:
|
||||
* sockfd - Socket descriptor identifies the socket to be released.
|
||||
* sockfd - The socket descriptor index o use.
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
* On success, a reference to the socket structure associated with the
|
||||
* the socket descriptor is returned. NULL is returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
@ -94,7 +94,7 @@ static void _net_semtake(FAR struct socketlist *list)
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name:
|
||||
* Name: net_initlist
|
||||
*
|
||||
* Description:
|
||||
* Initialize a list of sockets for a new task
|
||||
|
Loading…
x
Reference in New Issue
Block a user