Compare commits

...

6 Commits

Author SHA1 Message Date
Jarred Sumner
acf0cbef80 Fixup 2024-03-14 18:54:29 +01:00
Jarred Sumner
2670405fed Less flaky 2024-03-14 18:48:16 +01:00
Jarred Sumner
11ee235762 Fallback to fstat 2024-03-14 18:44:10 +01:00
Jarred Sumner
587f8646f5 Fallback to fstat 2024-03-14 18:41:17 +01:00
Jarred Sumner
082f5a7cfa Fallback to fstat 2024-03-14 18:40:29 +01:00
Jarred Sumner
a1eb9ce186 Use statx 2024-03-14 18:33:19 +01:00
6 changed files with 113 additions and 23 deletions

View File

@@ -16,7 +16,7 @@ ARG BUILD_MACHINE_ARCH=x86_64
ARG BUILDARCH=amd64
ARG TRIPLET=${ARCH}-linux-gnu
ARG GIT_SHA=""
ARG BUN_VERSION="bun-v1.0.7"
ARG BUN_VERSION="bun-v1.0.30"
ARG BUN_DOWNLOAD_URL_BASE="https://pub-5e11e972747a44bf9aaf9394f185a982.r2.dev/releases/${BUN_VERSION}"
ARG CANARY=0
ARG ASSERTIONS=OFF

View File

@@ -119,7 +119,7 @@ __asm__(".symver pow,pow@GLIBC_2.2.5");
__asm__(".symver log,log@GLIBC_2.2.5");
#endif
// ban statx, for now
// ban libc statx, for now
extern "C" int __wrap_statx(int fd, const char* path, int flags,
unsigned int mask, struct statx* buf)
{

View File

@@ -5158,7 +5158,7 @@ pub const NodeFS = struct {
break :brk switch (Syscall.open(
path,
os.O.RDONLY | os.O.NOCTTY,
os.O.RDONLY | os.O.NOCTTY | os.O.CLOEXEC,
0,
)) {
.err => |err| return .{
@@ -5175,7 +5175,9 @@ pub const NodeFS = struct {
_ = Syscall.close(fd);
}
const stat_ = switch (Syscall.fstat(fd)) {
const stat_ = switch (Syscall.fstatx(fd, &.{
.size,
})) {
.err => |err| return .{
.err = err,
},
@@ -5352,7 +5354,7 @@ pub const NodeFS = struct {
const open_result = Syscall.openat(
dirfd,
path,
@intFromEnum(args.flag) | os.O.NOCTTY,
@intFromEnum(args.flag) | os.O.NOCTTY | os.O.CLOEXEC,
args.mode,
);

View File

@@ -1968,22 +1968,22 @@ pub const uv_timeval64_t = extern struct {
tv_usec: i32,
};
pub const uv_stat_t = extern struct {
dev: u64,
mode: u64,
nlink: u64,
uid: u64,
gid: u64,
rdev: u64,
ino: u64,
size: u64,
blksize: u64,
blocks: u64,
flags: u64,
gen: u64,
atim: uv_timespec_t,
mtim: uv_timespec_t,
ctim: uv_timespec_t,
birthtim: uv_timespec_t,
dev: u64 = 0,
mode: u64 = 0,
nlink: u64 = 0,
uid: u64 = 0,
gid: u64 = 0,
rdev: u64 = 0,
ino: u64 = 0,
size: u64 = 0,
blksize: u64 = 0,
blocks: u64 = 0,
flags: u64 = 0,
gen: u64 = 0,
atim: uv_timespec_t = std.mem.zeroes(uv_timespec_t),
mtim: uv_timespec_t = std.mem.zeroes(uv_timespec_t),
ctim: uv_timespec_t = std.mem.zeroes(uv_timespec_t),
birthtim: uv_timespec_t = std.mem.zeroes(uv_timespec_t),
pub fn atime(self: @This()) uv_timespec_t {
return self.atim;

View File

@@ -1145,10 +1145,10 @@ pub const FileSystem = struct {
FileSystem.setMaxFd(file.handle);
// Skip the extra file.stat() call when possible
var size = _size orelse (file.getEndPos() catch |err| {
var size = _size orelse @as(usize, @intCast((bun.sys.fstatx(bun.toFD(file.handle), &.{.size}).unwrap() catch |err| {
fs.readFileError(path, err);
return err;
});
}).size));
debug("stat({d}) = {d}", .{ file.handle, size });
// Skip the pread call for empty files

View File

@@ -1319,6 +1319,94 @@ pub fn pwrite(fd: bun.FileDescriptor, bytes: []const u8, offset: i64) Maybe(usiz
}
}
pub const StatxField = enum(comptime_int) {
type = linux.STATX_TYPE,
mode = linux.STATX_MODE,
nlink = linux.STATX_NLINK,
uid = linux.STATX_UID,
gid = linux.STATX_GID,
atime = linux.STATX_ATIME,
mtime = linux.STATX_MTIME,
ctime = linux.STATX_CTIME,
ino = linux.STATX_INO,
size = linux.STATX_SIZE,
blocks = linux.STATX_BLOCKS,
};
// Linux Kernel v4.11
var supports_statx_on_linux = std.atomic.Value(bool).init(true);
pub fn fstatx(fd: bun.FileDescriptor, comptime fields: []const StatxField) Maybe(bun.Stat) {
if (comptime Environment.isWindows) {
if (comptime fields.len == 1 and fields[0] == .size) {
// if we only care about file size we can use a faster path
const hFile: windows.HANDLE = fd.cast();
var fileSize: windows.LARGE_INTEGER = 0;
if (bun.windows.GetFileSizeEx(hFile, &fileSize) == 0) {
return .{
.err = Syscall.Error{
.errno = @intFromEnum(bun.windows.getLastErrno()),
.syscall = .fstat,
.fd = fd,
},
};
}
return .{ .result = bun.Stat{ .size = @intCast(fileSize) } };
}
}
if (comptime !Environment.isLinux) {
return fstat(fd);
}
if (!supports_statx_on_linux.load(.Monotonic)) {
return fstat(fd);
}
var buf: std.os.linux.Statx = comptime std.mem.zeroes(linux.Statx);
const mask: u32 = comptime brk: {
var i: u32 = 0;
for (fields) |field| {
i |= @intFromEnum(field);
}
break :brk i;
};
const rc = linux.statx(@intCast(fd.cast()), "", linux.AT.EMPTY_PATH | 0, mask, &buf);
if (Maybe(bun.Stat).errnoSysFd(rc, .fstat, fd)) |err| {
if (err.getErrno() == .NOSYS) {
supports_statx_on_linux.store(false, .Monotonic);
return fstat(fd);
}
return .{ .err = err.err };
}
var stat_ = std.mem.zeroes(bun.Stat);
stat_.dev = buf.dev_major | (buf.dev_minor << 8);
// These intcasts are to deal with:
// - architecture-specific differences
// - differences between stat and statx return types
stat_.ino = @intCast(buf.ino);
stat_.mode = @intCast(buf.mode);
stat_.nlink = @intCast(buf.nlink);
stat_.uid = @intCast(buf.uid);
stat_.gid = @intCast(buf.gid);
stat_.size = @intCast(buf.size);
stat_.blksize = @intCast(buf.blksize);
stat_.blocks = @intCast(buf.blocks);
stat_.atim = .{ .tv_sec = @intCast(buf.atime.tv_sec), .tv_nsec = @intCast(buf.atime.tv_nsec) };
stat_.mtim = .{ .tv_sec = @intCast(buf.mtime.tv_sec), .tv_nsec = @intCast(buf.atime.tv_nsec) };
stat_.ctim = .{ .tv_sec = @intCast(buf.ctime.tv_sec), .tv_nsec = @intCast(buf.atime.tv_nsec) };
return .{ .result = stat_ };
}
pub fn read(fd: bun.FileDescriptor, buf: []u8) Maybe(usize) {
if (comptime Environment.allow_assert) {
if (buf.len == 0) {