Skip to content

Commit a961f76

Browse files
authored
Drop OPTE port lock earlier (#10281)
Fixes a possible deadlock in the OPTE port manager. When failing to add external IPs for a new port, we both the `PortTicket` and a lock guard around the mananger's mapping of all ports. Unforunately, we do that in the wrong order: `PortTicket` first, which attempts to take that same lock in its drop implementation. This drops the port lock earlier, to avoid a deadlock. Fixes #10280
1 parent 00f5b0a commit a961f76

1 file changed

Lines changed: 12 additions & 2 deletions

File tree

illumos-utils/src/opte/port_manager.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,6 @@ impl PortManager {
414414
hdl
415415
};
416416
let (port, ticket) = {
417-
let mut ports = self.inner.ports.lock().unwrap();
418417
let ticket = PortTicket::new(nic.id, nic.kind, self.inner.clone());
419418
let port = Port::new(PortData {
420419
name: port_name.clone(),
@@ -424,7 +423,18 @@ impl PortManager {
424423
vni,
425424
gateway,
426425
});
427-
let old = ports.insert((nic.id, nic.kind), port.clone());
426+
427+
// NOTE: We may add external IPs below, which can fail. If that
428+
// does, we drop the `ticket` on the way out of this block. That
429+
// attempts to acquire this lock, in order to remove itself on drop.
430+
// We need to drop the lock before that, to avoid a deadlock, so
431+
// let's do it right away, after inserting.
432+
let old = self
433+
.inner
434+
.ports
435+
.lock()
436+
.unwrap()
437+
.insert((nic.id, nic.kind), port.clone());
428438
assert!(
429439
old.is_none(),
430440
"Duplicate OPTE port detected: interface_id = {}, kind = {:?}",

0 commit comments

Comments
 (0)