base: apply Red Bear patches on latest upstream/main
251 files: init, acpid, ipcd, netcfg, ihdgd, virtio-gpud, scheme-utils, inputd, block driver, ptyd, ramfs, randd, initfs bootstrap, path deps, version +rb0.3.1, author attribution
This commit is contained in:
@@ -251,17 +251,34 @@ where
|
||||
flags: usize,
|
||||
) -> SyscallResult<usize>;
|
||||
|
||||
fn get_sock_opt(
|
||||
&self,
|
||||
file: &SchemeFile<Self>,
|
||||
name: usize,
|
||||
buf: &mut [u8],
|
||||
fn call(
|
||||
&mut self,
|
||||
_file: &mut SchemeFile<Self>,
|
||||
_payload: &mut [u8],
|
||||
_metadata: &[u64],
|
||||
_ctx: &CallerCtx,
|
||||
) -> SyscallResult<usize> {
|
||||
Err(SyscallError::new(syscall::EOPNOTSUPP))
|
||||
}
|
||||
|
||||
fn get_sock_opt(
|
||||
&self,
|
||||
_file: &SchemeFile<Self>,
|
||||
_name: usize,
|
||||
_buf: &mut [u8],
|
||||
) -> SyscallResult<usize> {
|
||||
Err(SyscallError::new(syscall::ENOPROTOOPT))
|
||||
}
|
||||
|
||||
fn set_sock_opt(
|
||||
&mut self,
|
||||
_file: &SchemeFile<Self>,
|
||||
_name: usize,
|
||||
_buf: &[u8],
|
||||
) -> SyscallResult<usize> {
|
||||
// Return Err for default implementation
|
||||
Err(SyscallError::new(syscall::ENOPROTOOPT))
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Handle<SocketT>
|
||||
where
|
||||
SocketT: SchemeSocket,
|
||||
@@ -322,8 +339,8 @@ where
|
||||
}?;
|
||||
|
||||
let mut timeout = match op {
|
||||
Op::Read(_) => write_timeout,
|
||||
Op::Write(_) => read_timeout,
|
||||
Op::Read(_) => read_timeout,
|
||||
Op::Write(_) => write_timeout,
|
||||
_ => None,
|
||||
};
|
||||
|
||||
@@ -453,10 +470,20 @@ where
|
||||
// SocketCall::Bind => self.handle_bind(id, &payload),
|
||||
// SocketCall::Connect => self.handle_connect(id, &payload),
|
||||
SocketCall::SetSockOpt => {
|
||||
// currently not used
|
||||
// self.handle_setsockopt(id, metadata[1] as i32, &payload)
|
||||
// TODO: SO_REUSEADDR from null socket
|
||||
Ok(0)
|
||||
let handle = self.handles.get(fd)?;
|
||||
match handle {
|
||||
Handle::File(file) => {
|
||||
let mut socket_set = self.socket_set.borrow_mut();
|
||||
let socket = socket_set.get_mut::<SocketT>(file.socket_handle());
|
||||
SocketT::set_sock_opt(
|
||||
socket,
|
||||
file,
|
||||
metadata[1] as usize,
|
||||
payload,
|
||||
)
|
||||
}
|
||||
_ => Err(SyscallError::new(syscall::ENOPROTOOPT)),
|
||||
}
|
||||
}
|
||||
SocketCall::GetSockOpt => {
|
||||
let handle = self.handles.get_mut(fd)?;
|
||||
@@ -489,7 +516,21 @@ where
|
||||
Handle::SchemeRoot => Err(SyscallError::new(syscall::EBADF)),
|
||||
}
|
||||
}
|
||||
// SocketCall::SendMsg => self.handle_sendmsg(id, payload, ctx),
|
||||
SocketCall::SendMsg => {
|
||||
let flags = metadata[1] as usize;
|
||||
let handle = self.handles.get_mut(fd)?;
|
||||
|
||||
match *handle {
|
||||
Handle::File(ref mut file) => {
|
||||
let mut socket_set = self.socket_set.borrow_mut();
|
||||
let socket = socket_set.get_mut::<SocketT>(file.socket_handle());
|
||||
|
||||
SocketT::call(socket, file, payload, &[flags as u64], ctx)
|
||||
}
|
||||
Handle::Null(_) => Err(SyscallError::new(syscall::EINVAL)),
|
||||
Handle::SchemeRoot => Err(SyscallError::new(syscall::EBADF)),
|
||||
}
|
||||
}
|
||||
// SocketCall::Unbind => self.handle_unbind(id),
|
||||
// SocketCall::GetToken => self.handle_get_token(id, payload),
|
||||
SocketCall::GetPeerName => {
|
||||
@@ -658,32 +699,33 @@ where
|
||||
let socket_handle = scheme_file.socket_handle();
|
||||
let mut socket_set = self.socket_set.borrow_mut();
|
||||
|
||||
let socket = socket_set.get::<SocketT>(socket_handle);
|
||||
let _ = socket.close_file(&scheme_file, &mut self.scheme_data);
|
||||
|
||||
let remove = match self.ref_counts.entry(socket_handle) {
|
||||
// Compute refcount change WITHOUT calling close_file yet.
|
||||
// The port release (inside close_file) must happen exactly
|
||||
// once when the LAST file referencing this socket is
|
||||
// closed — otherwise a dup'd socket's port would be
|
||||
// double-freed.
|
||||
let new_count = match self.ref_counts.entry(socket_handle) {
|
||||
Entry::Vacant(_) => {
|
||||
warn!("Closing a socket_handle with no ref");
|
||||
true
|
||||
0
|
||||
}
|
||||
Entry::Occupied(mut e) => {
|
||||
if *e.get() == 0 {
|
||||
warn!("Closing a socket_handle with no ref");
|
||||
let count = *e.get();
|
||||
if count <= 1 {
|
||||
e.remove();
|
||||
true
|
||||
0
|
||||
} else {
|
||||
*e.get_mut() -= 1;
|
||||
if *e.get() == 0 {
|
||||
e.remove();
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
count - 1
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if remove {
|
||||
// Only close the socket (which releases the port) when
|
||||
// the last reference is gone.
|
||||
if new_count == 0 {
|
||||
let socket = socket_set.get::<SocketT>(socket_handle);
|
||||
let _ = socket.close_file(&scheme_file, &mut self.scheme_data);
|
||||
socket_set.remove(socket_handle);
|
||||
}
|
||||
}
|
||||
@@ -817,22 +859,27 @@ where
|
||||
|
||||
if let Some((socket_handle, data)) = update_with {
|
||||
if let SchemeFile::Socket(ref mut file) = *file {
|
||||
// We replace the socket_handle pointed by file so update the ref_counts
|
||||
// accordingly
|
||||
// We replace the socket_handle pointed by file so update
|
||||
// the ref_counts accordingly.
|
||||
self.ref_counts
|
||||
.entry(file.socket_handle)
|
||||
.and_modify(|e| *e = e.saturating_sub(1))
|
||||
.or_insert(0);
|
||||
|
||||
// Increment refcount of the NEW socket (socket_handle)
|
||||
// that the file is being updated to point at.
|
||||
*self
|
||||
.ref_counts
|
||||
.entry(new_handle.socket_handle())
|
||||
.entry(socket_handle)
|
||||
.or_insert(0) += 1;
|
||||
|
||||
file.socket_handle = socket_handle;
|
||||
file.data = data;
|
||||
}
|
||||
}
|
||||
// Increment refcount for the new_handle fd being inserted.
|
||||
// This is always done (regardless of update_with) because
|
||||
// new_handle represents a new fd in the handle table.
|
||||
*self
|
||||
.ref_counts
|
||||
.entry(new_handle.socket_handle())
|
||||
@@ -875,12 +922,14 @@ where
|
||||
}
|
||||
|
||||
fn fsync(&mut self, fd: usize, _ctx: &CallerCtx) -> SyscallResult<()> {
|
||||
{
|
||||
let _file = self.handles.get_mut(fd)?;
|
||||
}
|
||||
// Verify the socket exists. The netstack is event-driven (polled by
|
||||
// userspace via fevent), so there is no kernel-side buffer to flush.
|
||||
// POSIX fsync(2) on a socket is required to return success when the
|
||||
// socket is valid; the underlying protocol (TCP) handles acknowledgements
|
||||
// asynchronously through the normal poll loop.
|
||||
// Cross-referenced with Linux net/socket.c: sockfs_fsync -> sock_no_fsync.
|
||||
let _file = self.handles.get(fd)?;
|
||||
Ok(())
|
||||
// TODO Implement fsyncing
|
||||
// self.0.network_fsync()
|
||||
}
|
||||
|
||||
fn fpath(&mut self, fd: usize, buf: &mut [u8], _ctx: &CallerCtx) -> SyscallResult<usize> {
|
||||
|
||||
Reference in New Issue
Block a user