Skip to content

Commit 1b921f1

Browse files
committed
refactor(driver,iocp): remove wheels of fs op
1 parent 12f09a7 commit 1b921f1

File tree

16 files changed

+148
-784
lines changed

16 files changed

+148
-784
lines changed

compio-driver/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ socket2 = { workspace = true }
4343
compio-buf = { workspace = true, features = ["arrayvec"] }
4444
aligned-array = "1.0.1"
4545
once_cell = { workspace = true }
46-
widestring = { workspace = true }
4746
windows-sys = { workspace = true, features = [
4847
"Win32_Foundation",
4948
"Win32_Networking_WinSock",

compio-driver/src/iocp/op.rs

Lines changed: 3 additions & 293 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use std::{
44
io,
55
marker::PhantomPinned,
66
net::Shutdown,
7-
os::windows::io::{AsRawHandle, FromRawHandle, OwnedHandle},
87
pin::Pin,
98
ptr::{null, null_mut},
109
task::Poll,
@@ -15,14 +14,12 @@ use compio_buf::{BufResult, IntoInner, IoBuf, IoBufMut, IoVectoredBuf, IoVectore
1514
#[cfg(not(feature = "once_cell_try"))]
1615
use once_cell::sync::OnceCell as OnceLock;
1716
use socket2::SockAddr;
18-
use widestring::U16CString;
1917
use windows_sys::{
2018
core::GUID,
2119
Win32::{
2220
Foundation::{
23-
CloseHandle, GetLastError, ERROR_ACCESS_DENIED, ERROR_HANDLE_EOF, ERROR_IO_INCOMPLETE,
24-
ERROR_IO_PENDING, ERROR_NOT_FOUND, ERROR_NO_DATA, ERROR_PIPE_CONNECTED,
25-
ERROR_SHARING_VIOLATION, FILETIME, INVALID_HANDLE_VALUE,
21+
CloseHandle, GetLastError, ERROR_HANDLE_EOF, ERROR_IO_INCOMPLETE, ERROR_IO_PENDING,
22+
ERROR_NOT_FOUND, ERROR_NO_DATA, ERROR_PIPE_CONNECTED,
2623
},
2724
Networking::WinSock::{
2825
closesocket, setsockopt, shutdown, socklen_t, WSAIoctl, WSARecv, WSARecvFrom, WSASend,
@@ -31,15 +28,7 @@ use windows_sys::{
3128
SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, SO_UPDATE_CONNECT_CONTEXT, WSAID_ACCEPTEX,
3229
WSAID_CONNECTEX, WSAID_GETACCEPTEXSOCKADDRS,
3330
},
34-
Security::SECURITY_ATTRIBUTES,
35-
Storage::FileSystem::{
36-
CreateFileW, FileAttributeTagInfo, FindClose, FindFirstFileW, FlushFileBuffers,
37-
GetFileInformationByHandle, GetFileInformationByHandleEx, ReadFile, WriteFile,
38-
BY_HANDLE_FILE_INFORMATION, FILE_ATTRIBUTE_REPARSE_POINT, FILE_ATTRIBUTE_TAG_INFO,
39-
FILE_CREATION_DISPOSITION, FILE_FLAGS_AND_ATTRIBUTES, FILE_FLAG_BACKUP_SEMANTICS,
40-
FILE_FLAG_OPEN_REPARSE_POINT, FILE_SHARE_DELETE, FILE_SHARE_MODE, FILE_SHARE_READ,
41-
FILE_SHARE_WRITE, OPEN_EXISTING, WIN32_FIND_DATAW,
42-
},
31+
Storage::FileSystem::{FlushFileBuffers, ReadFile, WriteFile},
4332
System::{
4433
Pipes::ConnectNamedPipe,
4534
IO::{CancelIoEx, OVERLAPPED},
@@ -136,69 +125,6 @@ impl<
136125
}
137126
}
138127

139-
/// Open or create a file with flags and mode.
140-
pub struct OpenFile {
141-
pub(crate) path: U16CString,
142-
pub(crate) access_mode: u32,
143-
pub(crate) share_mode: FILE_SHARE_MODE,
144-
pub(crate) security_attributes: *const SECURITY_ATTRIBUTES,
145-
pub(crate) creation_mode: FILE_CREATION_DISPOSITION,
146-
pub(crate) flags_and_attributes: FILE_FLAGS_AND_ATTRIBUTES,
147-
pub(crate) error_code: u32,
148-
}
149-
150-
impl OpenFile {
151-
/// Create [`OpenFile`].
152-
pub fn new(
153-
path: U16CString,
154-
access_mode: u32,
155-
share_mode: FILE_SHARE_MODE,
156-
security_attributes: *const SECURITY_ATTRIBUTES,
157-
creation_mode: FILE_CREATION_DISPOSITION,
158-
flags_and_attributes: FILE_FLAGS_AND_ATTRIBUTES,
159-
) -> Self {
160-
Self {
161-
path,
162-
access_mode,
163-
share_mode,
164-
security_attributes,
165-
creation_mode,
166-
flags_and_attributes,
167-
error_code: 0,
168-
}
169-
}
170-
171-
/// The result of [`GetLastError`]. It may not be 0 even if the operation is
172-
/// successful.
173-
pub fn last_os_error(&self) -> u32 {
174-
self.error_code
175-
}
176-
}
177-
178-
impl OpCode for OpenFile {
179-
fn op_type(&self) -> OpType {
180-
OpType::Blocking
181-
}
182-
183-
unsafe fn operate(mut self: Pin<&mut Self>, _optr: *mut OVERLAPPED) -> Poll<io::Result<usize>> {
184-
let handle = CreateFileW(
185-
self.path.as_ptr(),
186-
self.access_mode,
187-
self.share_mode,
188-
self.security_attributes,
189-
self.creation_mode,
190-
self.flags_and_attributes,
191-
0,
192-
);
193-
self.error_code = GetLastError();
194-
if handle == INVALID_HANDLE_VALUE {
195-
Poll::Ready(Err(io::Error::from_raw_os_error(self.error_code as _)))
196-
} else {
197-
Poll::Ready(Ok(handle as _))
198-
}
199-
}
200-
}
201-
202128
impl OpCode for CloseFile {
203129
fn op_type(&self) -> OpType {
204130
OpType::Blocking
@@ -209,222 +135,6 @@ impl OpCode for CloseFile {
209135
}
210136
}
211137

212-
/// A mixture of [`BY_HANDLE_FILE_INFORMATION`], [`FILE_ATTRIBUTE_TAG_INFO`] and
213-
/// [`WIN32_FIND_DATAW`]. The field names follows Hungarian case, to make it
214-
/// look like Windows API.
215-
#[derive(Default, Clone)]
216-
#[allow(non_snake_case, missing_docs)]
217-
pub struct FileMetadata {
218-
pub dwFileAttributes: u32,
219-
pub ftCreationTime: u64,
220-
pub ftLastAccessTime: u64,
221-
pub ftLastWriteTime: u64,
222-
pub nFileSize: u64,
223-
pub dwReparseTag: u32,
224-
pub dwVolumeSerialNumber: Option<u32>,
225-
pub nNumberOfLinks: Option<u32>,
226-
pub nFileIndex: Option<u64>,
227-
}
228-
229-
impl FileMetadata {
230-
fn is_reparse_point(&self) -> bool {
231-
self.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT != 0
232-
}
233-
}
234-
235-
const fn create_u64(high: u32, low: u32) -> u64 {
236-
((high as u64) << 32) | (low as u64)
237-
}
238-
239-
const fn filetime_u64(t: FILETIME) -> u64 {
240-
create_u64(t.dwHighDateTime, t.dwLowDateTime)
241-
}
242-
243-
impl From<BY_HANDLE_FILE_INFORMATION> for FileMetadata {
244-
fn from(value: BY_HANDLE_FILE_INFORMATION) -> Self {
245-
Self {
246-
dwFileAttributes: value.dwFileAttributes,
247-
ftCreationTime: filetime_u64(value.ftCreationTime),
248-
ftLastAccessTime: filetime_u64(value.ftLastAccessTime),
249-
ftLastWriteTime: filetime_u64(value.ftLastWriteTime),
250-
nFileSize: create_u64(value.nFileSizeHigh, value.nFileSizeLow),
251-
dwReparseTag: 0,
252-
dwVolumeSerialNumber: Some(value.dwVolumeSerialNumber),
253-
nNumberOfLinks: Some(value.nNumberOfLinks),
254-
nFileIndex: Some(create_u64(value.nFileIndexHigh, value.nFileIndexLow)),
255-
}
256-
}
257-
}
258-
259-
impl From<WIN32_FIND_DATAW> for FileMetadata {
260-
fn from(value: WIN32_FIND_DATAW) -> Self {
261-
let mut this = Self {
262-
dwFileAttributes: value.dwFileAttributes,
263-
ftCreationTime: filetime_u64(value.ftCreationTime),
264-
ftLastAccessTime: filetime_u64(value.ftLastAccessTime),
265-
ftLastWriteTime: filetime_u64(value.ftLastWriteTime),
266-
nFileSize: create_u64(value.nFileSizeHigh, value.nFileSizeLow),
267-
dwReparseTag: 0,
268-
dwVolumeSerialNumber: None,
269-
nNumberOfLinks: None,
270-
nFileIndex: None,
271-
};
272-
if this.is_reparse_point() {
273-
this.dwReparseTag = value.dwReserved0;
274-
}
275-
this
276-
}
277-
}
278-
279-
/// Get metadata of an opened file.
280-
pub struct FileStat {
281-
pub(crate) fd: RawFd,
282-
pub(crate) stat: FileMetadata,
283-
}
284-
285-
impl FileStat {
286-
/// Create [`FileStat`].
287-
pub fn new(fd: RawFd) -> Self {
288-
Self {
289-
fd,
290-
stat: Default::default(),
291-
}
292-
}
293-
}
294-
295-
impl OpCode for FileStat {
296-
fn op_type(&self) -> OpType {
297-
OpType::Blocking
298-
}
299-
300-
unsafe fn operate(mut self: Pin<&mut Self>, _optr: *mut OVERLAPPED) -> Poll<io::Result<usize>> {
301-
let mut stat = unsafe { std::mem::zeroed() };
302-
syscall!(BOOL, GetFileInformationByHandle(self.fd as _, &mut stat))?;
303-
self.stat = stat.into();
304-
if self.stat.is_reparse_point() {
305-
let mut tag: FILE_ATTRIBUTE_TAG_INFO = std::mem::zeroed();
306-
syscall!(
307-
BOOL,
308-
GetFileInformationByHandleEx(
309-
self.fd as _,
310-
FileAttributeTagInfo,
311-
&mut tag as *mut _ as _,
312-
std::mem::size_of::<FILE_ATTRIBUTE_TAG_INFO>() as _
313-
)
314-
)?;
315-
debug_assert_eq!(self.stat.dwFileAttributes, tag.FileAttributes);
316-
self.stat.dwReparseTag = tag.ReparseTag;
317-
}
318-
Poll::Ready(Ok(0))
319-
}
320-
321-
unsafe fn cancel(self: Pin<&mut Self>, _optr: *mut OVERLAPPED) -> io::Result<()> {
322-
Ok(())
323-
}
324-
}
325-
326-
impl IntoInner for FileStat {
327-
type Inner = FileMetadata;
328-
329-
fn into_inner(self) -> Self::Inner {
330-
self.stat
331-
}
332-
}
333-
334-
/// Get metadata from path.
335-
pub struct PathStat {
336-
pub(crate) path: U16CString,
337-
pub(crate) follow_symlink: bool,
338-
pub(crate) stat: FileMetadata,
339-
}
340-
341-
impl PathStat {
342-
/// Create [`PathStat`].
343-
pub fn new(path: U16CString, follow_symlink: bool) -> Self {
344-
Self {
345-
path,
346-
follow_symlink,
347-
stat: Default::default(),
348-
}
349-
}
350-
351-
unsafe fn open_and_stat(&self, optr: *mut OVERLAPPED) -> io::Result<FileMetadata> {
352-
let mut flags = FILE_FLAG_BACKUP_SEMANTICS;
353-
if !self.follow_symlink {
354-
flags |= FILE_FLAG_OPEN_REPARSE_POINT;
355-
}
356-
let handle = syscall!(
357-
HANDLE,
358-
CreateFileW(
359-
self.path.as_ptr(),
360-
0,
361-
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
362-
null(),
363-
OPEN_EXISTING,
364-
flags,
365-
0
366-
)
367-
)?;
368-
let handle = OwnedHandle::from_raw_handle(handle as _);
369-
let mut op = FileStat::new(handle.as_raw_handle());
370-
let op_pin = std::pin::Pin::new(&mut op);
371-
let res = op_pin.operate(optr);
372-
if let Poll::Ready(res) = res {
373-
res.map(|_| op.into_inner())
374-
} else {
375-
unreachable!("FileStat could not return Poll::Pending")
376-
}
377-
}
378-
}
379-
380-
impl OpCode for PathStat {
381-
fn op_type(&self) -> OpType {
382-
OpType::Blocking
383-
}
384-
385-
unsafe fn operate(mut self: Pin<&mut Self>, optr: *mut OVERLAPPED) -> Poll<io::Result<usize>> {
386-
let res = match self.open_and_stat(optr) {
387-
Ok(stat) => {
388-
self.stat = stat;
389-
Ok(0)
390-
}
391-
Err(e)
392-
if [
393-
Some(ERROR_SHARING_VIOLATION as _),
394-
Some(ERROR_ACCESS_DENIED as _),
395-
]
396-
.contains(&e.raw_os_error()) =>
397-
{
398-
let mut wfd: WIN32_FIND_DATAW = std::mem::zeroed();
399-
let handle = syscall!(HANDLE, FindFirstFileW(self.path.as_ptr(), &mut wfd))?;
400-
FindClose(handle);
401-
self.stat = wfd.into();
402-
let is_reparse = self.stat.is_reparse_point();
403-
let surrogate = self.stat.dwReparseTag & 0x20000000 != 0;
404-
if self.follow_symlink && is_reparse && surrogate {
405-
Err(e)
406-
} else {
407-
Ok(0)
408-
}
409-
}
410-
Err(e) => Err(e),
411-
};
412-
Poll::Ready(res)
413-
}
414-
415-
unsafe fn cancel(self: Pin<&mut Self>, _optr: *mut OVERLAPPED) -> io::Result<()> {
416-
Ok(())
417-
}
418-
}
419-
420-
impl IntoInner for PathStat {
421-
type Inner = FileMetadata;
422-
423-
fn into_inner(self) -> Self::Inner {
424-
self.stat
425-
}
426-
}
427-
428138
impl<T: IoBufMut> OpCode for ReadAt<T> {
429139
unsafe fn operate(self: Pin<&mut Self>, optr: *mut OVERLAPPED) -> Poll<io::Result<usize>> {
430140
if let Some(overlapped) = optr.as_mut() {

compio-driver/src/op.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ use std::{marker::PhantomPinned, net::Shutdown};
88
use compio_buf::{BufResult, IntoInner, IoBuf, IoBufMut, SetBufInit};
99
use socket2::SockAddr;
1010

11+
#[cfg(windows)]
12+
pub use crate::sys::op::ConnectNamedPipe;
1113
pub use crate::sys::op::{
12-
Accept, FileStat, OpenFile, PathStat, Recv, RecvFrom, RecvFromVectored, RecvVectored, Send,
13-
SendTo, SendToVectored, SendVectored,
14+
Accept, Recv, RecvFrom, RecvFromVectored, RecvVectored, Send, SendTo, SendToVectored,
15+
SendVectored,
1416
};
15-
#[cfg(windows)]
16-
pub use crate::sys::op::{ConnectNamedPipe, FileMetadata};
1717
#[cfg(unix)]
18-
pub use crate::sys::op::{ReadVectoredAt, WriteVectoredAt};
18+
pub use crate::sys::op::{FileStat, OpenFile, PathStat, ReadVectoredAt, WriteVectoredAt};
1919
use crate::sys::{sockaddr_storage, socklen_t, RawFd};
2020

2121
/// Trait to update the buffer length inside the [`BufResult`].

0 commit comments

Comments
 (0)