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;
}
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)
{
switch (request) {
/* Handle close specifically. */
case ZFD_IOCTL_CLOSE:
return offload_close((struct modem_socket *)obj);
case ZFD_IOCTL_POLL_PREPARE:
return -EXDEV;
@ -1532,6 +1533,7 @@ static const struct socket_op_vtable offload_socket_fd_op_vtable = {
.fd_vtable = {
.read = offload_read,
.write = offload_write,
.close = offload_close,
.ioctl = offload_ioctl,
},
.bind = offload_bind,

View file

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

View file

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

View file

@ -17,11 +17,12 @@ extern "C" {
/**
* 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 {
ssize_t (*read)(void *obj, 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);
};
@ -135,8 +136,7 @@ static inline int z_fdtable_call_ioctl(const struct fd_op_vtable *vtable, void *
*/
enum {
/* Codes below 0x100 are reserved for fcntl() codes. */
ZFD_IOCTL_CLOSE = 0x100,
ZFD_IOCTL_FSYNC,
ZFD_IOCTL_FSYNC = 0x100,
ZFD_IOCTL_LSEEK,
ZFD_IOCTL_POLL_PREPARE,
ZFD_IOCTL_POLL_UPDATE,

View file

@ -222,7 +222,8 @@ int close(int fd)
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);
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);
}
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)
{
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;
}
case ZFD_IOCTL_CLOSE:
efd->flags = 0;
return 0;
case ZFD_IOCTL_POLL_PREPARE: {
struct zsock_pollfd *pfd;
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 = {
.read = eventfd_read_op,
.write = eventfd_write_op,
.close = eventfd_close_op,
.ioctl = eventfd_ioctl_op,
};

View file

@ -123,17 +123,23 @@ int open(const char *name, int flags, ...)
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)
{
int rc = 0;
struct posix_fs_desc *ptr = obj;
switch (request) {
case ZFD_IOCTL_CLOSE:
rc = fs_close(&ptr->file);
posix_fs_free_obj(ptr);
break;
case ZFD_IOCTL_LSEEK: {
off_t offset;
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 = {
.read = fs_read_vmeth,
.write = fs_write_vmeth,
.close = fs_close_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;
}
case ZFD_IOCTL_CLOSE: {
/* disconnect the remote endpoint */
spair_delete(spair);
have_local_sem = false;
res = 0;
goto out;
}
case ZFD_IOCTL_POLL_PREPARE: {
pfd = va_arg(args, struct zsock_pollfd *);
pev = va_arg(args, struct k_poll_event **);
@ -1129,10 +1121,27 @@ static int spair_setsockopt(void *obj, int level, int optname,
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 = {
.fd_vtable = {
.read = spair_read,
.write = spair_write,
.close = spair_close,
.ioctl = spair_ioctl,
},
.bind = spair_bind,

View file

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

View file

@ -407,17 +407,23 @@ static int can_close_socket(struct net_context *ctx)
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);
if (ret < 0) {
NET_DBG("Cannot detach net_context %p (%d)", obj, ret);
}
ret = can_close_socket(obj);
if (ret < 0) {
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);
}
@ -670,6 +676,7 @@ static const struct socket_op_vtable can_sock_fd_op_vtable = {
.fd_vtable = {
.read = can_sock_read_vmeth,
.write = can_sock_write_vmeth,
.close = can_sock_close_vmeth,
.ioctl = can_sock_ioctl_vmeth,
},
.bind = can_sock_bind_vmeth,

View file

@ -1198,7 +1198,7 @@ int ztls_close_ctx(struct net_context *ctx)
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 succeeds, but tls_release fails, set errno
@ -1340,7 +1340,7 @@ error:
__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");
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. */
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: {
struct zsock_pollfd *pfd;
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);
}
static int tls_sock_close_vmeth(void *obj)
{
return ztls_close_ctx(obj);
}
static const struct socket_op_vtable tls_sock_fd_op_vtable = {
.fd_vtable = {
.read = tls_sock_read_vmeth,
.write = tls_sock_write_vmeth,
.close = tls_sock_close_vmeth,
.ioctl = tls_sock_ioctl_vmeth,
},
.bind = tls_sock_bind_vmeth,

View file

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