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:
buyuer 2021-03-12 15:52:19 +08:00 committed by Xiang Xiao
parent d66d881b87
commit c0f9c7b48c
2 changed files with 102 additions and 59 deletions

View File

@ -52,6 +52,8 @@
#include <nuttx/fs/fs.h> #include <nuttx/fs/fs.h>
#include <nuttx/kmalloc.h> #include <nuttx/kmalloc.h>
#include "inode/inode.h"
/**************************************************************************** /****************************************************************************
* Private Types * Private Types
****************************************************************************/ ****************************************************************************/
@ -70,7 +72,8 @@ struct epoll_head
* Private Function Prototypes * Private Function Prototypes
****************************************************************************/ ****************************************************************************/
static int epoll_poll(FAR struct file *filep, static int epoll_do_close(FAR struct file *filep);
static int epoll_do_poll(FAR struct file *filep,
FAR struct pollfd *fds, bool setup); FAR struct pollfd *fds, bool setup);
/**************************************************************************** /****************************************************************************
@ -79,19 +82,94 @@ static int epoll_poll(FAR struct file *filep,
static const struct file_operations g_epoll_ops = static const struct file_operations g_epoll_ops =
{ {
.poll = epoll_poll .close = epoll_do_close,
.poll = epoll_do_poll
}; };
/**************************************************************************** /****************************************************************************
* Private Functions * Private Functions
****************************************************************************/ ****************************************************************************/
static int epoll_poll(FAR struct file *filep, 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) FAR struct pollfd *fds, bool setup)
{ {
return OK; 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 * Public Functions
****************************************************************************/ ****************************************************************************/
@ -109,31 +187,7 @@ static int epoll_poll(FAR struct file *filep,
int epoll_create(int size) int epoll_create(int size)
{ {
FAR struct epoll_head *eph; return epoll_do_create(size, 0);
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);
} }
/**************************************************************************** /****************************************************************************
@ -149,17 +203,7 @@ int epoll_create(int size)
int epoll_create1(int flags) int epoll_create1(int flags)
{ {
/* For current implementation, Close-on-exec is a default behavior, return epoll_do_create(CONFIG_FS_NEPOLL_DESCRIPTORS, flags);
* 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);
} }
/**************************************************************************** /****************************************************************************
@ -175,13 +219,7 @@ int epoll_create1(int flags)
void epoll_close(int epfd) void epoll_close(int epfd)
{ {
/* REVISIT: This will not work on machines where: close(epfd);
* sizeof(struct epoll_head *) > sizeof(int)
*/
FAR struct epoll_head *eph = (FAR struct epoll_head *)((intptr_t)epfd);
kmm_free(eph);
} }
/**************************************************************************** /****************************************************************************
@ -197,13 +235,15 @@ void epoll_close(int epfd)
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *ev) int epoll_ctl(int epfd, int op, int fd, struct epoll_event *ev)
{ {
/* REVISIT: This will not work on machines where: FAR struct epoll_head *eph;
* sizeof(struct epoll_head *) > sizeof(int)
*/
FAR struct epoll_head *eph = (FAR struct epoll_head *)((intptr_t)epfd);
int i; int i;
eph = epoll_head_from_fd(epfd);
if (eph == NULL)
{
return -1;
}
switch (op) switch (op)
{ {
case EPOLL_CTL_ADD: 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 epoll_pwait(int epfd, FAR struct epoll_event *evs,
int maxevents, int timeout, FAR const sigset_t *sigmask) int maxevents, int timeout, FAR const sigset_t *sigmask)
{ {
/* REVISIT: This will not work on machines where: FAR struct epoll_head *eph;
* sizeof(struct epoll_head *) > sizeof(int)
*/
FAR struct epoll_head *eph = (FAR struct epoll_head *)((intptr_t)epfd);
struct timespec expire; struct timespec expire;
struct timespec curr; struct timespec curr;
struct timespec diff; struct timespec diff;
@ -300,6 +336,12 @@ int epoll_pwait(int epfd, FAR struct epoll_event *evs,
int rc; int rc;
int i; int i;
eph = epoll_head_from_fd(epfd);
if (eph == NULL)
{
return -1;
}
if (timeout >= 0) if (timeout >= 0)
{ {
expire.tv_sec = timeout / 1000; expire.tv_sec = timeout / 1000;

View File

@ -41,6 +41,7 @@
****************************************************************************/ ****************************************************************************/
#include <poll.h> #include <poll.h>
#include <fcntl.h>
/**************************************************************************** /****************************************************************************
* Pre-processor Definitions * Pre-processor Definitions
@ -86,7 +87,7 @@ enum EPOLL_EVENTS
enum enum
{ {
EPOLL_CLOEXEC = 02000000 EPOLL_CLOEXEC = O_CLOEXEC
#define EPOLL_CLOEXEC EPOLL_CLOEXEC #define EPOLL_CLOEXEC EPOLL_CLOEXEC
}; };