env/dpdk: retry SO_RCVBUF if SO_RCVBUFFORCE fails
PCI event module currently requires use of SO_RCVBUFFORCE socket option which is restricted to CAP_NET_ADMIN. Retry with SO_RCVBUF for non-root (unprivileged) processes where this capability is not available. Return -ENOSPC if receive buffer is not of sufficient size. Fixes issue #2224 Signed-off-by: Tom Nabarro <tom.nabarro@intel.com> Change-Id: I0bed1b1eac0c7e8601d3d172d8027380ec8be391 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/10126 Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com> Community-CI: Mellanox Build Bot Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Changpeng Liu <changpeng.liu@intel.com> Reviewed-by: Dong Yi <dongx.yi@intel.com> Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
parent
06ab7732d1
commit
380d442f4b
@ -50,6 +50,8 @@ spdk_pci_event_listen(void)
|
|||||||
struct sockaddr_nl addr;
|
struct sockaddr_nl addr;
|
||||||
int netlink_fd;
|
int netlink_fd;
|
||||||
int size = SPDK_UEVENT_RECVBUF_SIZE;
|
int size = SPDK_UEVENT_RECVBUF_SIZE;
|
||||||
|
int buf_size;
|
||||||
|
socklen_t opt_size;
|
||||||
int flag, rc;
|
int flag, rc;
|
||||||
|
|
||||||
memset(&addr, 0, sizeof(addr));
|
memset(&addr, 0, sizeof(addr));
|
||||||
@ -64,35 +66,49 @@ spdk_pci_event_listen(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (setsockopt(netlink_fd, SOL_SOCKET, SO_RCVBUFFORCE, &size, sizeof(size)) < 0) {
|
if (setsockopt(netlink_fd, SOL_SOCKET, SO_RCVBUFFORCE, &size, sizeof(size)) < 0) {
|
||||||
rc = errno;
|
if (setsockopt(netlink_fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) < 0) {
|
||||||
SPDK_ERRLOG("Failed to set socket option\n");
|
rc = errno;
|
||||||
close(netlink_fd);
|
SPDK_ERRLOG("Failed to set socket option SO_RCVBUF\n");
|
||||||
return -rc;
|
goto error;
|
||||||
|
}
|
||||||
|
opt_size = sizeof(buf_size);
|
||||||
|
if (getsockopt(netlink_fd, SOL_SOCKET, SO_RCVBUF, &buf_size, &opt_size) < 0) {
|
||||||
|
rc = errno;
|
||||||
|
SPDK_ERRLOG("Failed to get socket option SO_RCVBUF\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (buf_size < SPDK_UEVENT_RECVBUF_SIZE) {
|
||||||
|
SPDK_ERRLOG("Socket recv buffer is too small (< %d), see SO_RCVBUF "
|
||||||
|
"section in socket(7) man page for specifics on how to "
|
||||||
|
"adjust the system setting.", SPDK_UEVENT_RECVBUF_SIZE);
|
||||||
|
rc = ENOSPC;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flag = fcntl(netlink_fd, F_GETFL);
|
flag = fcntl(netlink_fd, F_GETFL);
|
||||||
if (flag < 0) {
|
if (flag < 0) {
|
||||||
rc = errno;
|
rc = errno;
|
||||||
SPDK_ERRLOG("Failed to get socket flag, fd: %d\n", netlink_fd);
|
SPDK_ERRLOG("Failed to get socket flag, fd: %d\n", netlink_fd);
|
||||||
close(netlink_fd);
|
goto error;
|
||||||
return -rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fcntl(netlink_fd, F_SETFL, flag | O_NONBLOCK) < 0) {
|
if (fcntl(netlink_fd, F_SETFL, flag | O_NONBLOCK) < 0) {
|
||||||
rc = errno;
|
rc = errno;
|
||||||
SPDK_ERRLOG("Fcntl can't set nonblocking mode for socket, fd: %d\n", netlink_fd);
|
SPDK_ERRLOG("Fcntl can't set nonblocking mode for socket, fd: %d\n", netlink_fd);
|
||||||
close(netlink_fd);
|
goto error;
|
||||||
return -rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bind(netlink_fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
if (bind(netlink_fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
||||||
rc = errno;
|
rc = errno;
|
||||||
SPDK_ERRLOG("Failed to bind the netlink\n");
|
SPDK_ERRLOG("Failed to bind the netlink\n");
|
||||||
close(netlink_fd);
|
goto error;
|
||||||
return -rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return netlink_fd;
|
return netlink_fd;
|
||||||
|
error:
|
||||||
|
close(netlink_fd);
|
||||||
|
return -rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note: We parse the event from uio and vfio subsystem and will ignore
|
/* Note: We parse the event from uio and vfio subsystem and will ignore
|
||||||
|
Loading…
Reference in New Issue
Block a user