authorgravatar for eshom@noreply.codeberg.orgeshom <eshom@noreply.codeberg.org> 2026-03-18 22:38:22+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-03-20 12:12:29-07:00
log2054a257c288c44df52510ac2e7646a08df8a4bb
tree665d1f2e97eb8fb1af9b165f4d987fd8f20e3eaa
parent5119cf6ffd0cf92586bc26f3f2d6e1e623fd17a8

std.Io.Uring: handle UnsupportedOperation for O_TMPFILE case

Having `std.Io.Uring` contain OpenError error set allows handling of OperationUnsupported specifically for `.openat`, while avoiding propagating this error to the more general `File.OpenError`. This more specific subset also eliminated 2 unreachable prongs that previously inherited from `File.OpenError`. Added comments when handling OperationUnsupported, making it clear it is an unexpected error when TMPFILE bit is not set.

1 files changed, 40 insertions(+), 12 deletions(-)

lib/std/Io/Uring.zig+40-12
......@@ -593,7 +593,10 @@ const CachedFd = struct {
593593 @atomicStore(Once, &cached_fd.once, .uninitialized, .monotonic);
594594 futexWake(ev, @ptrCast(&cached_fd.once), 1);
595595 }
596 const fd = try ev.openat(cancel_region, linux.AT.FDCWD, path, flags, 0);
596 const fd = ev.openat(cancel_region, linux.AT.FDCWD, path, flags, 0) catch |err| switch (err) {
597 error.OperationUnsupported => return error.Unexpected, // Not expecting O_TMPFILE flag
598 else => |e| return e,
599 };
597600 @atomicStore(Once, &cached_fd.once, .fromFd(fd), .monotonic);
598601 futexWake(ev, @ptrCast(&cached_fd.once), std.math.maxInt(u32));
599602 return fd;
......@@ -2725,9 +2728,8 @@ fn dirOpenDir(
27252728 error.DeviceBusy => return errnoBug(.BUSY), // O_EXCL not passed
27262729 error.FileBusy => return errnoBug(.TXTBSY),
27272730 error.PathAlreadyExists => return errnoBug(.EXIST), // Not creating.
2728 error.PipeBusy => return error.Unexpected, // Not opening a pipe.
2729 error.AntivirusInterference => unreachable, // Windows-only
27302731 error.FileLocksUnsupported => return errnoBug(.OPNOTSUPP), // Not asking for locks.
2732 error.OperationUnsupported => return errnoBug(.OPNOTSUPP), // Not asking for O_TMPFILE.
27312733 else => |e| return e,
27322734 },
27332735 };
......@@ -2810,13 +2812,16 @@ fn dirCreateFile(
28102812
28112813 var maybe_sync: CancelRegion.Sync.Maybe = .{ .cancel_region = .init() };
28122814 defer maybe_sync.deinit(ev);
2813 const fd = try ev.openat(&maybe_sync.cancel_region, dir.handle, sub_path_posix, .{
2815 const fd = ev.openat(&maybe_sync.cancel_region, dir.handle, sub_path_posix, .{
28142816 .ACCMODE = if (flags.read) .RDWR else .WRONLY,
28152817 .CREAT = true,
28162818 .TRUNC = flags.truncate,
28172819 .EXCL = flags.exclusive,
28182820 .CLOEXEC = true,
2819 }, flags.permissions.toMode());
2821 }, flags.permissions.toMode()) catch |err| switch (err) {
2822 error.OperationUnsupported => return error.Unexpected, // TMPFILE bit not set.
2823 else => |e| return e,
2824 };
28202825 errdefer ev.closeAsync(fd);
28212826
28222827 switch (flags.lock) {
......@@ -2892,7 +2897,7 @@ fn dirCreateFileAtomic(
28922897 flags,
28932898 options.permissions.toMode(),
28942899 ) catch |err| switch (err) {
2895 error.IsDir, error.FileNotFound => {
2900 error.IsDir, error.FileNotFound, error.OperationUnsupported => {
28962901 // Ambiguous error code. It might mean the file system
28972902 // does not support O_TMPFILE. Therefore, we must fall
28982903 // back to not using O_TMPFILE.
......@@ -2901,8 +2906,6 @@ fn dirCreateFileAtomic(
29012906 error.FileTooBig => return errnoBug(.FBIG),
29022907 error.DeviceBusy => return errnoBug(.BUSY), // O_EXCL not passed
29032908 error.PathAlreadyExists => return errnoBug(.EXIST), // Not creating.
2904 error.PipeBusy => return error.Unexpected, // Not opening a pipe.
2905 error.AntivirusInterference => unreachable, // Windows-only
29062909 error.FileLocksUnsupported => return errnoBug(.OPNOTSUPP), // Not asking for locks.
29072910 else => |e| return e,
29082911 },
......@@ -2994,7 +2997,7 @@ fn dirOpenFile(
29942997
29952998 var maybe_sync: CancelRegion.Sync.Maybe = .{ .cancel_region = .init() };
29962999 defer maybe_sync.deinit(ev);
2997 const fd = try ev.openat(&maybe_sync.cancel_region, dir.handle, sub_path_posix, .{
3000 const fd = ev.openat(&maybe_sync.cancel_region, dir.handle, sub_path_posix, .{
29983001 .ACCMODE = switch (flags.mode) {
29993002 .read_only => .RDONLY,
30003003 .write_only => .WRONLY,
......@@ -3004,7 +3007,10 @@ fn dirOpenFile(
30043007 .NOFOLLOW = !flags.follow_symlinks,
30053008 .CLOEXEC = true,
30063009 .PATH = flags.path_only,
3007 }, 0);
3010 }, 0) catch |err| switch (err) {
3011 error.OperationUnsupported => return error.Unexpected, // TMPFILE bit not set.
3012 else => |e| return e,
3013 };
30083014 errdefer ev.closeAsync(fd);
30093015
30103016 if (!flags.allow_directory) {
......@@ -5609,6 +5615,27 @@ fn lseek(
56095615 }
56105616}
56115617
5618const OpenError = error{
5619 AccessDenied,
5620 FileTooBig,
5621 IsDir,
5622 SymLinkLoop,
5623 ProcessFdQuotaExceeded,
5624 SystemFdQuotaExceeded,
5625 NoDevice,
5626 FileNotFound,
5627 SystemResources,
5628 NoSpaceLeft,
5629 NotDir,
5630 PermissionDenied,
5631 PathAlreadyExists,
5632 DeviceBusy,
5633 OperationUnsupported,
5634 FileLocksUnsupported,
5635 WouldBlock,
5636 FileBusy,
5637} || Dir.PathNameError || Io.Cancelable || Io.UnexpectedError;
5638
56125639fn openat(
56135640 ev: *Evented,
56145641 cancel_region: *CancelRegion,
......@@ -5616,7 +5643,7 @@ fn openat(
56165643 path: [*:0]const u8,
56175644 flags: linux.O,
56185645 mode: linux.mode_t,
5619) File.OpenError!fd_t {
5646) OpenError!fd_t {
56205647 var mut_flags = flags;
56215648 if (@hasField(linux.O, "LARGEFILE")) mut_flags.LARGEFILE = true;
56225649 while (true) {
......@@ -5662,7 +5689,8 @@ fn openat(
56625689 .PERM => return error.PermissionDenied,
56635690 .EXIST => return error.PathAlreadyExists,
56645691 .BUSY => return error.DeviceBusy,
5665 .OPNOTSUPP => return error.FileLocksUnsupported,
5692 // File locking and TMPFILE are mutually exclusive
5693 .OPNOTSUPP => return if (flags.TMPFILE) error.OperationUnsupported else error.FileLocksUnsupported,
56665694 .AGAIN => return error.WouldBlock,
56675695 .TXTBSY => return error.FileBusy,
56685696 .NXIO => return error.NoDevice,