vfs: Fix epoll cannot work under 64-bit operating system
by switching to the real file handle Signed-off-by: buyuer <dingddding@163.com>
This commit is contained in:
parent
d66d881b87
commit
c0f9c7b48c
2 changed files with 102 additions and 59 deletions
|
@ -52,6 +52,8 @@
|
|||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
|
||||
#include "inode/inode.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
@ -70,8 +72,9 @@ struct epoll_head
|
|||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static int epoll_poll(FAR struct file *filep,
|
||||
FAR struct pollfd *fds, bool setup);
|
||||
static int epoll_do_close(FAR struct file *filep);
|
||||
static int epoll_do_poll(FAR struct file *filep,
|
||||
FAR struct pollfd *fds, bool setup);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
|
@ -79,19 +82,94 @@ static int epoll_poll(FAR struct file *filep,
|
|||
|
||||
static const struct file_operations g_epoll_ops =
|
||||
{
|
||||
.poll = epoll_poll
|
||||
.close = epoll_do_close,
|
||||
.poll = epoll_do_poll
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static int epoll_poll(FAR struct file *filep,
|
||||
FAR struct pollfd *fds, bool setup)
|
||||
static FAR struct epoll_head *epoll_head_from_fd(int fd)
|
||||
{
|
||||
FAR struct file *filep;
|
||||
int ret;
|
||||
|
||||
/* Get file pointer by file descriptor */
|
||||
|
||||
ret = fs_getfilep(fd, &filep);
|
||||
if (ret < 0)
|
||||
{
|
||||
set_errno(-ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check fd come from us */
|
||||
|
||||
if (filep->f_inode->u.i_ops != &g_epoll_ops)
|
||||
{
|
||||
set_errno(EBADF);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (FAR struct epoll_head *)filep->f_inode->i_private;
|
||||
}
|
||||
|
||||
static int epoll_do_close(FAR struct file *filep)
|
||||
{
|
||||
FAR struct epoll_head *eph = filep->f_inode->i_private;
|
||||
|
||||
kmm_free(eph);
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int epoll_do_poll(FAR struct file *filep,
|
||||
FAR struct pollfd *fds, bool setup)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int epoll_do_create(int size, int flags)
|
||||
{
|
||||
FAR struct epoll_head *eph;
|
||||
int reserve = size + 1;
|
||||
int fd;
|
||||
|
||||
eph = (FAR struct epoll_head *)
|
||||
kmm_zalloc(sizeof(struct epoll_head) +
|
||||
sizeof(epoll_data_t) * reserve +
|
||||
sizeof(struct pollfd) * reserve);
|
||||
if (eph == NULL)
|
||||
{
|
||||
set_errno(ENOMEM);
|
||||
return -1;
|
||||
}
|
||||
|
||||
eph->size = size;
|
||||
eph->data = (FAR epoll_data_t *)(eph + 1);
|
||||
eph->poll = (FAR struct pollfd *)(eph->data + reserve);
|
||||
|
||||
INODE_SET_DRIVER(&eph->in);
|
||||
eph->in.u.i_ops = &g_epoll_ops;
|
||||
eph->fp.f_inode = &eph->in;
|
||||
eph->in.i_private = eph;
|
||||
|
||||
eph->poll[0].ptr = &eph->fp;
|
||||
eph->poll[0].events = POLLIN | POLLFILE;
|
||||
|
||||
/* Alloc the file descriptor */
|
||||
|
||||
fd = files_allocate(&eph->in, flags, 0, eph, 0);
|
||||
if (fd < 0)
|
||||
{
|
||||
kmm_free(eph);
|
||||
set_errno(-fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
@ -109,31 +187,7 @@ static int epoll_poll(FAR struct file *filep,
|
|||
|
||||
int epoll_create(int size)
|
||||
{
|
||||
FAR struct epoll_head *eph;
|
||||
int reserve = size + 1;
|
||||
|
||||
eph = (FAR struct epoll_head *)
|
||||
kmm_zalloc(sizeof(struct epoll_head) +
|
||||
sizeof(epoll_data_t) * reserve +
|
||||
sizeof(struct pollfd) * reserve);
|
||||
|
||||
eph->size = size;
|
||||
eph->data = (FAR epoll_data_t *)(eph + 1);
|
||||
eph->poll = (FAR struct pollfd *)(eph->data + reserve);
|
||||
|
||||
INODE_SET_DRIVER(&eph->in);
|
||||
eph->in.u.i_ops = &g_epoll_ops;
|
||||
eph->fp.f_inode = &eph->in;
|
||||
eph->in.i_private = eph;
|
||||
|
||||
eph->poll[0].ptr = &eph->fp;
|
||||
eph->poll[0].events = POLLIN | POLLFILE;
|
||||
|
||||
/* REVISIT: This will not work on machines where:
|
||||
* sizeof(struct epoll_head *) > sizeof(int)
|
||||
*/
|
||||
|
||||
return (int)((intptr_t)eph);
|
||||
return epoll_do_create(size, 0);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -149,17 +203,7 @@ int epoll_create(int size)
|
|||
|
||||
int epoll_create1(int flags)
|
||||
{
|
||||
/* For current implementation, Close-on-exec is a default behavior,
|
||||
* the handle of epoll(2) is not a real file handle.
|
||||
*/
|
||||
|
||||
if (flags != EPOLL_CLOEXEC)
|
||||
{
|
||||
set_errno(EINVAL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return epoll_create(CONFIG_FS_NEPOLL_DESCRIPTORS);
|
||||
return epoll_do_create(CONFIG_FS_NEPOLL_DESCRIPTORS, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -175,13 +219,7 @@ int epoll_create1(int flags)
|
|||
|
||||
void epoll_close(int epfd)
|
||||
{
|
||||
/* REVISIT: This will not work on machines where:
|
||||
* sizeof(struct epoll_head *) > sizeof(int)
|
||||
*/
|
||||
|
||||
FAR struct epoll_head *eph = (FAR struct epoll_head *)((intptr_t)epfd);
|
||||
|
||||
kmm_free(eph);
|
||||
close(epfd);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -197,13 +235,15 @@ void epoll_close(int epfd)
|
|||
|
||||
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *ev)
|
||||
{
|
||||
/* REVISIT: This will not work on machines where:
|
||||
* sizeof(struct epoll_head *) > sizeof(int)
|
||||
*/
|
||||
|
||||
FAR struct epoll_head *eph = (FAR struct epoll_head *)((intptr_t)epfd);
|
||||
FAR struct epoll_head *eph;
|
||||
int i;
|
||||
|
||||
eph = epoll_head_from_fd(epfd);
|
||||
if (eph == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case EPOLL_CTL_ADD:
|
||||
|
@ -288,11 +328,7 @@ int epoll_ctl(int epfd, int op, int fd, struct epoll_event *ev)
|
|||
int epoll_pwait(int epfd, FAR struct epoll_event *evs,
|
||||
int maxevents, int timeout, FAR const sigset_t *sigmask)
|
||||
{
|
||||
/* REVISIT: This will not work on machines where:
|
||||
* sizeof(struct epoll_head *) > sizeof(int)
|
||||
*/
|
||||
|
||||
FAR struct epoll_head *eph = (FAR struct epoll_head *)((intptr_t)epfd);
|
||||
FAR struct epoll_head *eph;
|
||||
struct timespec expire;
|
||||
struct timespec curr;
|
||||
struct timespec diff;
|
||||
|
@ -300,6 +336,12 @@ int epoll_pwait(int epfd, FAR struct epoll_event *evs,
|
|||
int rc;
|
||||
int i;
|
||||
|
||||
eph = epoll_head_from_fd(epfd);
|
||||
if (eph == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (timeout >= 0)
|
||||
{
|
||||
expire.tv_sec = timeout / 1000;
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
****************************************************************************/
|
||||
|
||||
#include <poll.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
@ -86,7 +87,7 @@ enum EPOLL_EVENTS
|
|||
|
||||
enum
|
||||
{
|
||||
EPOLL_CLOEXEC = 02000000
|
||||
EPOLL_CLOEXEC = O_CLOEXEC
|
||||
#define EPOLL_CLOEXEC EPOLL_CLOEXEC
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue