lib: fdtable: Add callback for close() calls

Do not route close() calls via ioctl() as that is error prone
and quite pointless. Instead create a callback for close() in
fdtable and use it directly.

Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
Jukka Rissanen 2020-08-11 11:43:51 +03:00 committed by Andrew Boie
commit 2ed6b6a8ed
12 changed files with 108 additions and 64 deletions

View file

@ -1453,13 +1453,14 @@ static ssize_t offload_sendto(void *obj, const void *buf, size_t len,
return ret; return ret;
} }
static int offload_close(void *obj)
{
return offload_close((struct modem_socket *)obj);
}
static int offload_ioctl(void *obj, unsigned int request, va_list args) static int offload_ioctl(void *obj, unsigned int request, va_list args)
{ {
switch (request) { switch (request) {
/* Handle close specifically. */
case ZFD_IOCTL_CLOSE:
return offload_close((struct modem_socket *)obj);
case ZFD_IOCTL_POLL_PREPARE: case ZFD_IOCTL_POLL_PREPARE:
return -EXDEV; return -EXDEV;
@ -1532,6 +1533,7 @@ static const struct socket_op_vtable offload_socket_fd_op_vtable = {
.fd_vtable = { .fd_vtable = {
.read = offload_read, .read = offload_read,
.write = offload_write, .write = offload_write,
.close = offload_close,
.ioctl = offload_ioctl, .ioctl = offload_ioctl,
}, },
.bind = offload_bind, .bind = offload_bind,

View file

@ -499,15 +499,16 @@ static int eswifi_socket_create(int family, int type, int proto)
return fd; return fd;
} }
static int eswifi_socket_close(void *obj)
{
return eswifi_socket_close(sd);
}
static int eswifi_socket_ioctl(void *obj, unsigned int request, va_list args) static int eswifi_socket_ioctl(void *obj, unsigned int request, va_list args)
{ {
int sd = OBJ_TO_SD(obj); int sd = OBJ_TO_SD(obj);
switch (request) { switch (request) {
/* Handle close specifically. */
case ZFD_IOCTL_CLOSE:
return eswifi_socket_close(sd);
case ZFD_IOCTL_POLL_PREPARE: case ZFD_IOCTL_POLL_PREPARE:
return -EXDEV; return -EXDEV;
@ -547,6 +548,7 @@ static const struct socket_op_vtable eswifi_socket_fd_op_vtable = {
.fd_vtable = { .fd_vtable = {
.read = eswifi_socket_read, .read = eswifi_socket_read,
.write = eswifi_socket_write, .write = eswifi_socket_write,
.close = eswifi_socket_close,
.ioctl = eswifi_socket_ioctl, .ioctl = eswifi_socket_ioctl,
}, },
.bind = eswifi_socket_bind, .bind = eswifi_socket_bind,

View file

@ -1124,15 +1124,16 @@ exit:
return retval; return retval;
} }
static int simplelink_close(void *obj)
{
return simplelink_close(sd);
}
static int simplelink_ioctl(void *obj, unsigned int request, va_list args) static int simplelink_ioctl(void *obj, unsigned int request, va_list args)
{ {
int sd = OBJ_TO_SD(obj); int sd = OBJ_TO_SD(obj);
switch (request) { switch (request) {
/* Handle close specifically. */
case ZFD_IOCTL_CLOSE:
return simplelink_close(sd);
case ZFD_IOCTL_POLL_PREPARE: case ZFD_IOCTL_POLL_PREPARE:
return -EXDEV; return -EXDEV;
@ -1174,6 +1175,7 @@ static const struct socket_op_vtable simplelink_socket_fd_op_vtable = {
.fd_vtable = { .fd_vtable = {
.read = simplelink_read, .read = simplelink_read,
.write = simplelink_write, .write = simplelink_write,
.close = simplelink_close,
.ioctl = simplelink_ioctl, .ioctl = simplelink_ioctl,
}, },
.bind = simplelink_bind, .bind = simplelink_bind,

View file

@ -17,11 +17,12 @@ extern "C" {
/** /**
* File descriptor virtual method table. * File descriptor virtual method table.
* All operations beyond read/write go thru ioctl method. * Currently all operations beyond read/write/close go thru ioctl method.
*/ */
struct fd_op_vtable { struct fd_op_vtable {
ssize_t (*read)(void *obj, void *buf, size_t sz); ssize_t (*read)(void *obj, void *buf, size_t sz);
ssize_t (*write)(void *obj, const void *buf, size_t sz); ssize_t (*write)(void *obj, const void *buf, size_t sz);
int (*close)(void *obj);
int (*ioctl)(void *obj, unsigned int request, va_list args); int (*ioctl)(void *obj, unsigned int request, va_list args);
}; };
@ -135,8 +136,7 @@ static inline int z_fdtable_call_ioctl(const struct fd_op_vtable *vtable, void *
*/ */
enum { enum {
/* Codes below 0x100 are reserved for fcntl() codes. */ /* Codes below 0x100 are reserved for fcntl() codes. */
ZFD_IOCTL_CLOSE = 0x100, ZFD_IOCTL_FSYNC = 0x100,
ZFD_IOCTL_FSYNC,
ZFD_IOCTL_LSEEK, ZFD_IOCTL_LSEEK,
ZFD_IOCTL_POLL_PREPARE, ZFD_IOCTL_POLL_PREPARE,
ZFD_IOCTL_POLL_UPDATE, ZFD_IOCTL_POLL_UPDATE,

View file

@ -222,7 +222,8 @@ int close(int fd)
return -1; return -1;
} }
res = z_fdtable_call_ioctl(fdtable[fd].vtable, fdtable[fd].obj, ZFD_IOCTL_CLOSE); res = fdtable[fd].vtable->close(fdtable[fd].obj);
z_free_fd(fd); z_free_fd(fd);
return res; return res;

View file

@ -130,6 +130,15 @@ static ssize_t eventfd_write_op(void *obj, const void *buf, size_t sz)
return sizeof(eventfd_t); return sizeof(eventfd_t);
} }
static int eventfd_close_op(void *obj)
{
struct eventfd *efd = (struct eventfd *)obj;
efd->flags = 0;
return 0;
}
static int eventfd_ioctl_op(void *obj, unsigned int request, va_list args) static int eventfd_ioctl_op(void *obj, unsigned int request, va_list args)
{ {
struct eventfd *efd = (struct eventfd *)obj; struct eventfd *efd = (struct eventfd *)obj;
@ -153,10 +162,6 @@ static int eventfd_ioctl_op(void *obj, unsigned int request, va_list args)
return 0; return 0;
} }
case ZFD_IOCTL_CLOSE:
efd->flags = 0;
return 0;
case ZFD_IOCTL_POLL_PREPARE: { case ZFD_IOCTL_POLL_PREPARE: {
struct zsock_pollfd *pfd; struct zsock_pollfd *pfd;
struct k_poll_event **pev; struct k_poll_event **pev;
@ -188,6 +193,7 @@ static int eventfd_ioctl_op(void *obj, unsigned int request, va_list args)
static const struct fd_op_vtable eventfd_fd_vtable = { static const struct fd_op_vtable eventfd_fd_vtable = {
.read = eventfd_read_op, .read = eventfd_read_op,
.write = eventfd_write_op, .write = eventfd_write_op,
.close = eventfd_close_op,
.ioctl = eventfd_ioctl_op, .ioctl = eventfd_ioctl_op,
}; };

View file

@ -123,17 +123,23 @@ int open(const char *name, int flags, ...)
return fd; return fd;
} }
static int fs_close_vmeth(void *obj)
{
struct posix_fs_desc *ptr = obj;
int rc;
rc = fs_close(&ptr->file);
posix_fs_free_obj(ptr);
return rc;
}
static int fs_ioctl_vmeth(void *obj, unsigned int request, va_list args) static int fs_ioctl_vmeth(void *obj, unsigned int request, va_list args)
{ {
int rc = 0; int rc = 0;
struct posix_fs_desc *ptr = obj; struct posix_fs_desc *ptr = obj;
switch (request) { switch (request) {
case ZFD_IOCTL_CLOSE:
rc = fs_close(&ptr->file);
posix_fs_free_obj(ptr);
break;
case ZFD_IOCTL_LSEEK: { case ZFD_IOCTL_LSEEK: {
off_t offset; off_t offset;
int whence; int whence;
@ -202,6 +208,7 @@ static ssize_t fs_read_vmeth(void *obj, void *buffer, size_t count)
static struct fd_op_vtable fs_fd_op_vtable = { static struct fd_op_vtable fs_fd_op_vtable = {
.read = fs_read_vmeth, .read = fs_read_vmeth,
.write = fs_write_vmeth, .write = fs_write_vmeth,
.close = fs_close_vmeth,
.ioctl = fs_ioctl_vmeth, .ioctl = fs_ioctl_vmeth,
}; };

View file

@ -927,14 +927,6 @@ static int spair_ioctl(void *obj, unsigned int request, va_list args)
goto out; goto out;
} }
case ZFD_IOCTL_CLOSE: {
/* disconnect the remote endpoint */
spair_delete(spair);
have_local_sem = false;
res = 0;
goto out;
}
case ZFD_IOCTL_POLL_PREPARE: { case ZFD_IOCTL_POLL_PREPARE: {
pfd = va_arg(args, struct zsock_pollfd *); pfd = va_arg(args, struct zsock_pollfd *);
pev = va_arg(args, struct k_poll_event **); pev = va_arg(args, struct k_poll_event **);
@ -1129,10 +1121,27 @@ static int spair_setsockopt(void *obj, int level, int optname,
return -1; return -1;
} }
static int spair_close(void *obj)
{
struct spair *const spair = (struct spair *)obj;
int res;
res = k_sem_take(&spair->sem, K_FOREVER);
__ASSERT(res == 0, "failed to take local sem: %d", res);
/* disconnect the remote endpoint */
spair_delete(spair);
/* Note that the semaphore released already so need to do it here */
return 0;
}
static const struct socket_op_vtable spair_fd_op_vtable = { static const struct socket_op_vtable spair_fd_op_vtable = {
.fd_vtable = { .fd_vtable = {
.read = spair_read, .read = spair_read,
.write = spair_write, .write = spair_write,
.close = spair_close,
.ioctl = spair_ioctl, .ioctl = spair_ioctl,
}, },
.bind = spair_bind, .bind = spair_bind,

View file

@ -247,18 +247,20 @@ int z_impl_zsock_close(int sock)
{ {
const struct socket_op_vtable *vtable; const struct socket_op_vtable *vtable;
void *ctx = get_sock_vtable(sock, &vtable); void *ctx = get_sock_vtable(sock, &vtable);
int ret;
if (ctx == NULL) { if (ctx == NULL) {
errno = EBADF; errno = EBADF;
return -1; return -1;
} }
z_free_fd(sock);
NET_DBG("close: ctx=%p, fd=%d", ctx, sock); NET_DBG("close: ctx=%p, fd=%d", ctx, sock);
return z_fdtable_call_ioctl((const struct fd_op_vtable *)vtable, ret = vtable->fd_vtable.close(ctx);
ctx, ZFD_IOCTL_CLOSE);
z_free_fd(sock);
return ret;
} }
#ifdef CONFIG_USERSPACE #ifdef CONFIG_USERSPACE
@ -1747,9 +1749,6 @@ static int sock_ioctl_vmeth(void *obj, unsigned int request, va_list args)
return 0; return 0;
} }
case ZFD_IOCTL_CLOSE:
return zsock_close_ctx(obj);
case ZFD_IOCTL_POLL_PREPARE: { case ZFD_IOCTL_POLL_PREPARE: {
struct zsock_pollfd *pfd; struct zsock_pollfd *pfd;
struct k_poll_event **pev; struct k_poll_event **pev;
@ -1844,11 +1843,16 @@ static int sock_setsockopt_vmeth(void *obj, int level, int optname,
return zsock_setsockopt_ctx(obj, level, optname, optval, optlen); return zsock_setsockopt_ctx(obj, level, optname, optval, optlen);
} }
static int sock_close_vmeth(void *obj)
{
return zsock_close_ctx(obj);
}
const struct socket_op_vtable sock_fd_op_vtable = { const struct socket_op_vtable sock_fd_op_vtable = {
.fd_vtable = { .fd_vtable = {
.read = sock_read_vmeth, .read = sock_read_vmeth,
.write = sock_write_vmeth, .write = sock_write_vmeth,
.close = sock_close_vmeth,
.ioctl = sock_ioctl_vmeth, .ioctl = sock_ioctl_vmeth,
}, },
.bind = sock_bind_vmeth, .bind = sock_bind_vmeth,

View file

@ -407,17 +407,23 @@ static int can_close_socket(struct net_context *ctx)
return 0; return 0;
} }
static int can_sock_ioctl_vmeth(void *obj, unsigned int request, va_list args) static int can_sock_close_vmeth(void *obj)
{ {
if (request == ZFD_IOCTL_CLOSE) { int ret;
int ret;
ret = can_close_socket(obj); ret = can_close_socket(obj);
if (ret < 0) { if (ret < 0) {
NET_DBG("Cannot detach net_context %p (%d)", obj, ret); NET_DBG("Cannot detach net_context %p (%d)", obj, ret);
}
errno = -ret;
ret = -1;
} }
return ret;
}
static int can_sock_ioctl_vmeth(void *obj, unsigned int request, va_list args)
{
return sock_fd_op_vtable.fd_vtable.ioctl(obj, request, args); return sock_fd_op_vtable.fd_vtable.ioctl(obj, request, args);
} }
@ -670,6 +676,7 @@ static const struct socket_op_vtable can_sock_fd_op_vtable = {
.fd_vtable = { .fd_vtable = {
.read = can_sock_read_vmeth, .read = can_sock_read_vmeth,
.write = can_sock_write_vmeth, .write = can_sock_write_vmeth,
.close = can_sock_close_vmeth,
.ioctl = can_sock_ioctl_vmeth, .ioctl = can_sock_ioctl_vmeth,
}, },
.bind = can_sock_bind_vmeth, .bind = can_sock_bind_vmeth,

View file

@ -1198,7 +1198,7 @@ int ztls_close_ctx(struct net_context *ctx)
err = -EBADF; err = -EBADF;
} }
ret = z_fdtable_call_ioctl(&sock_fd_op_vtable.fd_vtable, ctx, ZFD_IOCTL_CLOSE); ret = sock_fd_op_vtable.fd_vtable.close(ctx);
/* In case close fails, we propagate errno value set by close. /* In case close fails, we propagate errno value set by close.
* In case close succeeds, but tls_release fails, set errno * In case close succeeds, but tls_release fails, set errno
@ -1340,7 +1340,7 @@ error:
__ASSERT(err == 0, "TLS context release failed"); __ASSERT(err == 0, "TLS context release failed");
} }
err = z_fdtable_call_ioctl(&sock_fd_op_vtable.fd_vtable, child, ZFD_IOCTL_CLOSE); err = sock_fd_op_vtable.fd_vtable.close(child);
__ASSERT(err == 0, "Child socket close failed"); __ASSERT(err == 0, "Child socket close failed");
z_free_fd(fd); z_free_fd(fd);
@ -1956,9 +1956,6 @@ static int tls_sock_ioctl_vmeth(void *obj, unsigned int request, va_list args)
/* Pass the call to the core socket implementation. */ /* Pass the call to the core socket implementation. */
return sock_fd_op_vtable.fd_vtable.ioctl(obj, request, args); return sock_fd_op_vtable.fd_vtable.ioctl(obj, request, args);
case ZFD_IOCTL_CLOSE:
return ztls_close_ctx(obj);
case ZFD_IOCTL_POLL_PREPARE: { case ZFD_IOCTL_POLL_PREPARE: {
struct zsock_pollfd *pfd; struct zsock_pollfd *pfd;
struct k_poll_event **pev; struct k_poll_event **pev;
@ -2044,11 +2041,16 @@ static int tls_sock_setsockopt_vmeth(void *obj, int level, int optname,
return ztls_setsockopt_ctx(obj, level, optname, optval, optlen); return ztls_setsockopt_ctx(obj, level, optname, optval, optlen);
} }
static int tls_sock_close_vmeth(void *obj)
{
return ztls_close_ctx(obj);
}
static const struct socket_op_vtable tls_sock_fd_op_vtable = { static const struct socket_op_vtable tls_sock_fd_op_vtable = {
.fd_vtable = { .fd_vtable = {
.read = tls_sock_read_vmeth, .read = tls_sock_read_vmeth,
.write = tls_sock_write_vmeth, .write = tls_sock_write_vmeth,
.close = tls_sock_close_vmeth,
.ioctl = tls_sock_ioctl_vmeth, .ioctl = tls_sock_ioctl_vmeth,
}, },
.bind = tls_sock_bind_vmeth, .bind = tls_sock_bind_vmeth,

View file

@ -418,23 +418,24 @@ int websocket_disconnect(int ws_sock)
return ret; return ret;
} }
static int websocket_ioctl_vmeth(void *obj, unsigned int request, va_list args) static int websocket_close_vmeth(void *obj)
{ {
if (request == ZFD_IOCTL_CLOSE) { struct websocket_context *ctx = obj;
struct websocket_context *ctx = obj; int ret;
int ret;
ret = websocket_disconnect(ctx->sock); ret = websocket_disconnect(ctx->sock);
if (ret < 0) { if (ret < 0) {
NET_DBG("[%p] Cannot close (%d)", obj, ret); NET_DBG("[%p] Cannot close (%d)", obj, ret);
errno = -ret; errno = -ret;
return -1; return -1;
}
return ret;
} }
return ret;
}
static int websocket_ioctl_vmeth(void *obj, unsigned int request, va_list args)
{
return sock_fd_op_vtable.fd_vtable.ioctl(obj, request, args); return sock_fd_op_vtable.fd_vtable.ioctl(obj, request, args);
} }
@ -954,6 +955,7 @@ static const struct socket_op_vtable websocket_fd_op_vtable = {
.fd_vtable = { .fd_vtable = {
.read = websocket_read_vmeth, .read = websocket_read_vmeth,
.write = websocket_write_vmeth, .write = websocket_write_vmeth,
.close = websocket_close_vmeth,
.ioctl = websocket_ioctl_vmeth, .ioctl = websocket_ioctl_vmeth,
}, },
.sendto = websocket_sendto_ctx, .sendto = websocket_sendto_ctx,