This is a best-effort solution to the latency induced by the RCU synchronization that happens in the kernel whenever the file descriptor table fills up. The table has initially 64 entries on amd64 and every time it fills up, a new table is created, double the size of the current one, and the entries are copied to the new table. The filesystem code that does this uses synchronize_rcu() to ensure al
()
| 804 | // The code tries to resize the table to an adequate size for most use cases, |
| 805 | // 4096, this way we avoid any expansion that might take place later. |
| 806 | fn expand_fdtable() -> Result<(), FdTableError> { |
| 807 | let mut limits = libc::rlimit { |
| 808 | rlim_cur: 0, |
| 809 | rlim_max: 0, |
| 810 | }; |
| 811 | |
| 812 | // SAFETY: FFI call with valid arguments |
| 813 | if unsafe { libc::getrlimit(libc::RLIMIT_NOFILE, &mut limits) } < 0 { |
| 814 | return Err(FdTableError::GetRLimit(io::Error::last_os_error())); |
| 815 | } |
| 816 | |
| 817 | let table_size = if limits.rlim_cur == libc::RLIM_INFINITY { |
| 818 | 4096 |
| 819 | } else { |
| 820 | std::cmp::min(limits.rlim_cur, 4096) as libc::c_int |
| 821 | }; |
| 822 | |
| 823 | // The first 3 handles are stdin, stdout, stderr. We don't want to touch |
| 824 | // any of them. |
| 825 | if table_size <= 3 { |
| 826 | return Ok(()); |
| 827 | } |
| 828 | |
| 829 | let dummy_evt = EventFd::new(0).map_err(FdTableError::CreateEventFd)?; |
| 830 | |
| 831 | // Test if the file descriptor is empty |
| 832 | // SAFETY: FFI call with valid arguments |
| 833 | let flags: i32 = unsafe { libc::fcntl(table_size - 1, libc::F_GETFD) }; |
| 834 | if flags >= 0 { |
| 835 | // Nothing to do, the table is already big enough |
| 836 | return Ok(()); |
| 837 | } |
| 838 | |
| 839 | let err = io::Error::last_os_error(); |
| 840 | if err.raw_os_error() != Some(libc::EBADF) { |
| 841 | return Err(FdTableError::GetFd(err)); |
| 842 | } |
| 843 | // SAFETY: FFI call with valid arguments |
| 844 | if unsafe { libc::dup2(dummy_evt.as_raw_fd(), table_size - 1) } < 0 { |
| 845 | return Err(FdTableError::Dup2(io::Error::last_os_error())); |
| 846 | } |
| 847 | // SAFETY: FFI call, trivially |
| 848 | unsafe { libc::close(table_size - 1) }; |
| 849 | |
| 850 | Ok(()) |
| 851 | } |
| 852 | |
| 853 | fn main() { |
| 854 | #[cfg(all(feature = "tdx", feature = "sev_snp"))] |