Skip to content

Commit 12564c2

Browse files
authored
Merge pull request #51 from alexcu2718/subtle_refactor
Subtle refactor
2 parents ab359c7 + 4ba96c9 commit 12564c2

6 files changed

Lines changed: 65 additions & 48 deletions

File tree

src/fs/buffer.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#[cfg(any(target_os = "linux", target_os = "android", target_os = "macos"))]
2-
use crate::fs::FileDes;
31
use core::marker::Copy;
42
use core::mem::MaybeUninit;
53
use core::ops::{Index, IndexMut};
@@ -127,6 +125,8 @@ where
127125
}
128126
}
129127

128+
pub const BUFFER_SIZE: usize = SIZE;
129+
130130
/// Returns a mutable pointer to the buffer's data
131131
#[inline]
132132
#[must_use]
@@ -169,14 +169,18 @@ where
169169
/// Executes the getdents64 system call using <unistd.h>/direct `libc` syscalls
170170
#[inline]
171171
#[cfg(any(target_os = "linux", target_os = "android"))]
172-
pub fn getdents(&mut self, fd: &FileDes) -> isize {
172+
pub fn getdents(&mut self, fd: &crate::fs::FileDes) -> isize {
173173
// SAFETY: we're passing a valid buffer
174174
unsafe { crate::util::getdents64(fd.0, self.as_mut_ptr(), SIZE) }
175175
}
176176

177177
#[inline]
178178
#[cfg(target_os = "macos")]
179-
pub(crate) unsafe fn getdirentries64(&mut self, fd: &FileDes, basep: *mut i64) -> isize {
179+
pub(crate) unsafe fn getdirentries64(
180+
&mut self,
181+
fd: &crate::fs::FileDes,
182+
basep: *mut i64,
183+
) -> isize {
180184
// SAFETY: we're passing a valid buffer
181185
unsafe { crate::util::getdirentries64(fd.0, self.as_mut_ptr(), SIZE, basep) }
182186
}

src/fs/iter.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,7 @@ impl GetDents {
321321
return None;
322322
}
323323
}
324+
324325
// We have data in buffer, get next entry
325326
// SAFETY: the buffer is not empty and therefore has remaining bytes to be read
326327
let drnt = unsafe {
@@ -589,8 +590,6 @@ impl GetDirEntries {
589590
let is_more_remaining = remaining_bytes.is_positive();
590591
#[cfg(has_eof_trick)] // Check at build time for the optimisation
591592
{
592-
use crate::fs::BUFFER_SIZE;
593-
594593
// SAFETY: Buffer is already initialised by the kernel
595594
// The kernel writes the WHOLE of the buffer passed to `getdirentries`
596595
//(also it's to u8, which has no restrictions on alignment)
@@ -604,8 +603,7 @@ impl GetDirEntries {
604603

605604
self.end_of_stream =
606605
// SAFETY: AS ABOVE
607-
unsafe { self.syscall_buffer.as_ptr().add(BUFFER_SIZE - 4).read() == 1 };
608-
const { assert!(BUFFER_SIZE >= 1024, "Invalid size EOF optimisation") }
606+
unsafe { self.syscall_buffer.as_ptr().add(SyscallBuffer::BUFFER_SIZE - 4).read() == 1 };
609607
}
610608
#[cfg(not(has_eof_trick))]
611609
{

src/fs/mod.rs

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -13,36 +13,3 @@ pub use iter::GetDents;
1313
pub use iter::GetDirEntries;
1414
pub use iter::ReadDir;
1515
pub use types::{FileDes, Result};
16-
17-
#[cfg(all(any(target_os = "linux", target_os = "android"), not(debug_assertions)))]
18-
pub const BUFFER_SIZE: usize = 8 * 4096;
19-
20-
#[cfg(all(any(target_os = "linux", target_os = "android"), debug_assertions))]
21-
pub const BUFFER_SIZE: usize = 4096; // Crashes during testing due to parallel processes taking up too much stack
22-
23-
#[cfg(all(target_os = "macos", not(debug_assertions)))]
24-
pub const BUFFER_SIZE: usize = 0x2000; //readdir calls this value for buffer size, look at syscall tracing below (8192)
25-
26-
#[cfg(all(target_os = "macos", debug_assertions))]
27-
pub const BUFFER_SIZE: usize = 0x1000; // Give a smaller size to avoid stack overflow when going on tests
28-
29-
/*
30-
/tmp/fdf_test getdirentries ❯ sudo dtruss fd -HI . 2>&1 | grep getdirentries | head ✘ INT alexc@alexcs-iMac 00:52:24
31-
32-
33-
getdirentries64(0x3, 0x7FD166808A00, 0x2000) = 896 0
34-
getdirentries64(0x3, 0x7FD166808A00, 0x2000) = 408 0
35-
getdirentries64(0x3, 0x7FD166808A00, 0x2000) = 288 0
36-
37-
38-
/tmp/fdf_test getdirentries ❯ sudo dtruss ls . -R 2>&1 | grep getdirentries | head alexc@alexcs-iMac 00:58:19
39-
40-
getdirentries64(0x3, 0x7FEE86013C00, 0x2000) = 896 0
41-
getdirentries64(0x3, 0x7FEE86013C00, 0x2000) = 104 0
42-
getdirentries64(0x3, 0x7FEE86013C00, 0x2000) = 1520 0
43-
getdirentries64(0x3, 0x7FEE86013C00, 0x2000) = 112 0
44-
getdirentries64(0x3, 0x7FEE86013C00, 0x2000) = 344 0
45-
46-
*/
47-
#[cfg(any(target_os = "linux", target_os = "android", target_os = "macos"))]
48-
const_assert!(BUFFER_SIZE >= 4096, "Buffer size too small!");

src/fs/types.rs

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ pub type Result<T> = core::result::Result<T, DirEntryError>;
66
/// A buffer used to hold the bytes sent from the OS for `getdents` calls
77
/// We only use a buffer for syscalls on linux/android because of stable ABI(because we don't need to use a buffer for `ReadDir`)
88
#[cfg(any(target_os = "linux", target_os = "android", target_os = "macos"))]
9-
pub type SyscallBuffer = crate::fs::AlignedBuffer<u8, { crate::fs::BUFFER_SIZE }>;
9+
pub type SyscallBuffer = crate::fs::AlignedBuffer<u8, { BUFFER_SIZE }>;
1010

1111
/// A safe abstraction around file descriptors for internal IO
1212
#[derive(Debug)]
@@ -43,3 +43,52 @@ impl FileDes {
4343
!self.is_open()
4444
}
4545
}
46+
47+
#[cfg(all(any(target_os = "linux", target_os = "android"), not(debug_assertions)))]
48+
pub const BUFFER_SIZE: usize = 8 * 4096;
49+
/*
50+
λ sudo strace -f fd NOMATCHLOL / -HI 2>&1 | grep getdents | head
51+
[pid 18321] getdents64(3, 0x7ff8e4000cb0 /* 21 entries */, 32768) = 520
52+
[pid 18321] getdents64(3, 0x7ff8e4000cb0 /* 0 entries */, 32768) = 0
53+
[pid 18321] getdents64(3, 0x7ff8e4000cb0 /* 7 entries */, 32768) = 224
54+
[pid 18321] getdents64(3, 0x7ff8e4000cb0 /* 0 entries */, 32768) = 0
55+
[pid 18321] getdents64(3 <unfinished ...>
56+
[pid 18327] getdents64(4 <unfinished ...>
57+
58+
59+
λ sudo strace -f ls / 2>&1 | grep getdents | head
60+
getdents64(3, 0x557e625c37a0 /* 21 entries */, 32768) = 520
61+
getdents64(3, 0x557e625c37a0 /* 0 entries */, 32768) = 0
62+
63+
64+
*/
65+
66+
#[cfg(all(any(target_os = "linux", target_os = "android"), debug_assertions))]
67+
pub const BUFFER_SIZE: usize = 4096; // Crashes during testing due to parallel processes taking up too much stack
68+
69+
#[cfg(all(target_os = "macos", not(debug_assertions)))]
70+
pub const BUFFER_SIZE: usize = 0x2000; //readdir calls this value for buffer size, look at syscall tracing below (8192)
71+
72+
#[cfg(all(target_os = "macos", debug_assertions))]
73+
pub const BUFFER_SIZE: usize = 0x1000; // Give a smaller size to avoid stack overflow when going on tests
74+
75+
/*
76+
/tmp/fdf_test getdirentries ❯ sudo dtruss fd -HI . 2>&1 | grep getdirentries | head ✘ INT alexc@alexcs-iMac 00:52:24
77+
78+
79+
getdirentries64(0x3, 0x7FD166808A00, 0x2000) = 896 0
80+
getdirentries64(0x3, 0x7FD166808A00, 0x2000) = 408 0
81+
getdirentries64(0x3, 0x7FD166808A00, 0x2000) = 288 0
82+
83+
84+
/tmp/fdf_test getdirentries ❯ sudo dtruss ls . -R 2>&1 | grep getdirentries | head alexc@alexcs-iMac 00:58:19
85+
86+
getdirentries64(0x3, 0x7FEE86013C00, 0x2000) = 896 0
87+
getdirentries64(0x3, 0x7FEE86013C00, 0x2000) = 104 0
88+
getdirentries64(0x3, 0x7FEE86013C00, 0x2000) = 1520 0
89+
getdirentries64(0x3, 0x7FEE86013C00, 0x2000) = 112 0
90+
getdirentries64(0x3, 0x7FEE86013C00, 0x2000) = 344 0
91+
92+
*/
93+
#[cfg(any(target_os = "linux", target_os = "android", target_os = "macos"))]
94+
const_assert!(BUFFER_SIZE >= 4096, "Buffer size too small!");

src/util/utils.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
use crate::dirent64;
2-
#[cfg(any(target_os = "linux", target_os = "android", target_os = "macos"))]
3-
use crate::fs::ValueType;
42
use crate::util::memchr_derivations::memrchr;
53
use core::ops::Deref;
64

@@ -28,7 +26,7 @@ use core::ops::Deref;
2826
#[expect(clippy::cast_possible_truncation, reason = "clong is isize on Linux")]
2927
pub unsafe fn getdents64<T>(fd: i32, buffer_ptr: *mut T, buffer_size: usize) -> isize
3028
where
31-
T: ValueType, //i8/u8
29+
T: crate::fs::ValueType, //i8/u8
3230
{
3331
//You can additionally link it like this.
3432
// unsafe extern "C" {
@@ -70,7 +68,7 @@ pub unsafe fn getdirentries64<T>(
7068
basep: *mut i64,
7169
) -> isize
7270
where
73-
T: ValueType,
71+
T: crate::fs::ValueType, //i8/u8
7472
{
7573
use libc::{c_char, c_int, off_t, size_t, ssize_t};
7674
// link to libc

src/walk/finder_builder.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,12 +268,13 @@ impl FinderBuilder {
268268

269269
let lambda: FilterType = |rconfig, rdir, rfilter| {
270270
{
271-
rfilter.is_none_or(|func| func(rdir))
272-
&& rconfig.matches_extension(&rdir.file_name())
271+
// arrange the filters by order of costliness
272+
rconfig.matches_extension(&rdir.file_name())
273273
&& rconfig.matches_path(rdir, !rconfig.file_name_only)
274274
&& rconfig.matches_type(rdir)
275275
&& rconfig.matches_size(rdir)
276276
&& rconfig.matches_time(rdir)
277+
&& rfilter.is_none_or(|func| func(rdir)) // put the custom filter last because it's almost always unlikely
277278
}
278279
};
279280

0 commit comments

Comments
 (0)