Skip to content

Commit 36375c6

Browse files
committed
add support of the system call poll for the vsock interface
1 parent 7190b40 commit 36375c6

File tree

1 file changed

+76
-1
lines changed

1 file changed

+76
-1
lines changed

src/fd/socket/vsock.rs

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use crate::arch::kernel::mmio as hardware;
1313
#[cfg(feature = "pci")]
1414
use crate::drivers::pci as hardware;
1515
use crate::executor::vsock::{VsockState, VSOCK_MAP};
16-
use crate::fd::{block_on, Endpoint, IoCtl, ListenEndpoint, ObjectInterface};
16+
use crate::fd::{block_on, Endpoint, IoCtl, ListenEndpoint, ObjectInterface, PollEvent};
1717
use crate::io::{self, Error};
1818

1919
#[derive(Debug)]
@@ -59,6 +59,77 @@ impl Socket {
5959

6060
#[async_trait]
6161
impl ObjectInterface for Socket {
62+
async fn poll(&self, event: PollEvent) -> io::Result<PollEvent> {
63+
let port = self.port.load(Ordering::Acquire);
64+
65+
future::poll_fn(|cx| {
66+
let mut guard = VSOCK_MAP.lock();
67+
let raw = guard.get_mut_socket(port).ok_or(Error::EINVAL)?;
68+
69+
match raw.state {
70+
VsockState::Shutdown | VsockState::ReceiveRequest => {
71+
let available = PollEvent::POLLOUT
72+
| PollEvent::POLLWRNORM
73+
| PollEvent::POLLWRBAND
74+
| PollEvent::POLLIN
75+
| PollEvent::POLLRDNORM
76+
| PollEvent::POLLRDBAND;
77+
78+
let ret = event & available;
79+
80+
if ret.is_empty() {
81+
Poll::Ready(Ok(PollEvent::POLLHUP))
82+
} else {
83+
Poll::Ready(Ok(ret))
84+
}
85+
}
86+
VsockState::Listen | VsockState::Connecting => {
87+
raw.rx_waker.register(cx.waker());
88+
raw.tx_waker.register(cx.waker());
89+
Poll::Pending
90+
}
91+
VsockState::Connected => {
92+
let mut available = PollEvent::empty();
93+
94+
if !raw.buffer.is_empty() {
95+
// In case, we just establish a fresh connection in non-blocking mode, we try to read data.
96+
available.insert(
97+
PollEvent::POLLIN | PollEvent::POLLRDNORM | PollEvent::POLLRDBAND,
98+
);
99+
}
100+
101+
let diff = raw.tx_cnt.abs_diff(raw.peer_fwd_cnt);
102+
if diff < raw.peer_buf_alloc {
103+
available.insert(
104+
PollEvent::POLLOUT | PollEvent::POLLWRNORM | PollEvent::POLLWRBAND,
105+
);
106+
}
107+
108+
let ret = event & available;
109+
110+
if ret.is_empty() {
111+
if event.intersects(
112+
PollEvent::POLLIN | PollEvent::POLLRDNORM | PollEvent::POLLRDBAND,
113+
) {
114+
raw.rx_waker.register(cx.waker());
115+
}
116+
117+
if event.intersects(
118+
PollEvent::POLLOUT | PollEvent::POLLWRNORM | PollEvent::POLLWRBAND,
119+
) {
120+
raw.tx_waker.register(cx.waker());
121+
}
122+
123+
Poll::Pending
124+
} else {
125+
Poll::Ready(Ok(ret))
126+
}
127+
}
128+
}
129+
})
130+
.await
131+
}
132+
62133
fn bind(&self, endpoint: ListenEndpoint) -> io::Result<()> {
63134
match endpoint {
64135
ListenEndpoint::Vsock(ep) => {
@@ -144,6 +215,10 @@ impl ObjectInterface for Socket {
144215
Ok(Endpoint::Vsock(endpoint))
145216
}
146217

218+
fn shutdown(&self, _how: i32) -> io::Result<()> {
219+
Ok(())
220+
}
221+
147222
fn ioctl(&self, cmd: IoCtl, value: bool) -> io::Result<()> {
148223
if cmd == IoCtl::NonBlocking {
149224
if value {

0 commit comments

Comments
 (0)