]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commit
msg/async/rdma: don't abort on an invalid per-connection eventfd 69614/head
authorDax Kelson <daxkelson@gmail.com>
Sat, 20 Jun 2026 19:18:19 +0000 (13:18 -0600)
committerDax Kelson <daxkelson@gmail.com>
Sun, 21 Jun 2026 03:03:25 +0000 (21:03 -0600)
commitb11c0eaedc3c9108bab9c85b72d4fcc074c8e1d5
tree9695997ea97843367cfb5eb5ff4c90804074220a
parentca0bc48a2a27f64176942b54341b640905c89a3e
msg/async/rdma: don't abort on an invalid per-connection eventfd

The async RDMA messenger reports each connection's per-connection eventfd
(notify_fd) as its socket fd().  notify_fd can legitimately be -1 -- under
fd-table pressure eventfd() returns -1, and the base RDMAConnectedSocketImpl
constructor skips queue pair *and* eventfd creation entirely when
ms_async_rdma_cm=true (the cm path is only implemented by the iwarp socket
classes).  Either way an fd() == -1 socket reaches the success path of
Processor::accept and trips ceph_assert(socket.fd() >= 0) in
AsyncConnection::accept, or is fed to EventCenter::create_file_event() and
indexes file_events[-1] out of bounds.  Both abort the OSD under connection
load.

Make the messenger surface the failure instead of handing back a broken
socket:

- Initialize RDMAConnectedSocketImpl::qp to nullptr.  It was uninitialized and
  read via get_qp() when ms_async_rdma_cm=true skips its assignment.

- Create the notify eventfd before the queue pair in the base constructor, and
  adopt the cm id/channel before the eventfd in the iwarp constructor, so a
  failure leaks nothing and the two failure causes stay distinguishable.  Check
  the rdma_create_event_channel()/rdma_create_id() return values on the touched
  paths, and destroy the per-request cm id on the accept error paths (acking the
  event does not free it).

- At each accept/connect construction site, reject a socket with fd() < 0
  (-EMFILE) or a null queue pair (-EIO) instead of returning it.  Free the
  half-built socket on its owning worker thread via center.submit_to() so
  ~RDMAConnectedSocketImpl's center.in_thread() assertion holds and no RDMA/fd
  state leaks (this also fixes the pre-existing leak on the rdma_accept()
  failure path).

- Require ms_async_rdma_cm and ms_async_rdma_type=iwarp to be enabled together
  in RDMAWorker::listen()/connect() (-EOPNOTSUPP with a clear message).  The
  two are coupled -- only the iwarp classes implement rdma_cm and they always
  use it -- so any mismatch leaves a socket half-built and would otherwise
  crash-loop the daemon.

- Guard EventCenter::create_file_event() against a negative fd as defense in
  depth.

Fixes: https://tracker.ceph.com/issues/77547
Signed-off-by: Dax Kelson <daxkelson@gmail.com>
src/msg/async/Event.cc
src/msg/async/rdma/RDMAConnectedSocketImpl.cc
src/msg/async/rdma/RDMAIWARPConnectedSocketImpl.cc
src/msg/async/rdma/RDMAIWARPServerSocketImpl.cc
src/msg/async/rdma/RDMAServerSocketImpl.cc
src/msg/async/rdma/RDMAStack.cc
src/msg/async/rdma/RDMAStack.h