Skip to content

Commit 9938d8a

Browse files
committed
add msg_ring_*, setxattr and getxattr IoUring operations
TODO: add SetXattr flags Signed-off-by: Bernard Assan <mega.alpha100@gmail.com>
1 parent d3cee98 commit 9938d8a

2 files changed

Lines changed: 244 additions & 0 deletions

File tree

lib/std/os/linux.zig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6860,6 +6860,9 @@ pub const Rename = packed struct(u32) {
68606860
_: u29 = 0,
68616861
};
68626862

6863+
pub const SetXattr = packed struct(u32) {
6864+
_: u32 = 0, // TODO: add flags
6865+
};
68636866
pub const statx_timestamp = extern struct {
68646867
sec: i64,
68656868
nsec: u32,

lib/std/os/linux/IoUring.zig

Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1516,6 +1516,137 @@ pub fn link(
15161516
return try self.linkat(user_data, linux.At.fdcwd, old_path, linux.At.fdcwd, new_path, flags);
15171517
}
15181518

1519+
/// Queues (but does not submit) an SQE to send a CQE to an io_uring file
1520+
/// descriptor. The use case for this can be anything from simply waking up
1521+
/// someone waiting on the targeted ring, or it can be used to pass messages
1522+
/// between the two rings
1523+
/// Returns a pointer to the SQE.
1524+
pub fn msg_ring(
1525+
self: *IoUring,
1526+
user_data: u64,
1527+
fd: linux.fd_t,
1528+
len: u32,
1529+
data: u64,
1530+
flags: uflags.MsgRing,
1531+
) !*Sqe {
1532+
const sqe = try self.get_sqe();
1533+
sqe.prep_msg_ring(fd, len, data, flags);
1534+
sqe.user_data = user_data;
1535+
return sqe;
1536+
}
1537+
1538+
/// Queues (but does not submit) an SQE to send a CQE to an io_uring file
1539+
/// descriptor. See `msg_ring`
1540+
/// This has and additonal `cqe_flags` parameter that allows you to set the CQE
1541+
/// flags field cqe.flags when sending a message
1542+
/// Returns a pointer to the SQE.
1543+
pub fn msg_ring_cqe_flags(
1544+
self: *IoUring,
1545+
user_data: u64,
1546+
fd: linux.fd_t,
1547+
len: u32,
1548+
data: u64,
1549+
msg_flags: uflags.MsgRing,
1550+
cqe_flags: Cqe.Flags,
1551+
) !*Sqe {
1552+
const sqe = try self.get_sqe();
1553+
sqe.prep_msg_ring_cqe_flags(
1554+
fd,
1555+
len,
1556+
data,
1557+
msg_flags,
1558+
cqe_flags,
1559+
);
1560+
sqe.user_data = user_data;
1561+
return sqe;
1562+
}
1563+
1564+
/// Queues (but does not submit) an SQE to to send a direct file descriptor to
1565+
/// another ring.
1566+
/// This has and additonal `cqe_flags` parameter that allows you to set the CQE
1567+
/// flags field cqe.flags when sending a message
1568+
/// Returns a pointer to the SQE.
1569+
pub fn msg_ring_fd(
1570+
self: *IoUring,
1571+
user_data: u64,
1572+
fd: linux.fd_t,
1573+
source_fd: linux.fd_t,
1574+
target_fd: linux.fd_t,
1575+
data: u64,
1576+
flags: uflags.MsgRing,
1577+
) !*Sqe {
1578+
const sqe = try self.get_sqe();
1579+
sqe.prep_msg_ring_fd(
1580+
fd,
1581+
source_fd,
1582+
target_fd,
1583+
data,
1584+
flags,
1585+
);
1586+
sqe.user_data = user_data;
1587+
return sqe;
1588+
}
1589+
1590+
/// Queues (but does not submit) an SQE to send a direct file descriptor to
1591+
/// another ring. See `msg_ring_fd()`
1592+
/// `msg_ring_fd_alloc()` is similar to `msg_ring_fd()`, but doesn't specify a
1593+
/// target_fd for the descriptor. Instead, this target_fd is allocated in the
1594+
/// target ring and returned in the CQE res field.
1595+
/// Returns a pointer to the SQE.
1596+
pub fn msg_ring_fd_alloc(
1597+
self: *IoUring,
1598+
user_data: u64,
1599+
fd: linux.fd_t,
1600+
source_fd: linux.fd_t,
1601+
data: u64,
1602+
flags: uflags.MsgRing,
1603+
) !*Sqe {
1604+
const sqe = try self.get_sqe();
1605+
sqe.prep_msg_ring_fd_alloc(
1606+
fd,
1607+
source_fd,
1608+
data,
1609+
flags,
1610+
);
1611+
sqe.user_data = user_data;
1612+
return sqe;
1613+
}
1614+
1615+
/// Queues (but does not submit) an SQE to prepares a request to get an
1616+
/// extended attribute value
1617+
/// Returns a pointer to the SQE.
1618+
pub fn getxattr(
1619+
self: *IoUring,
1620+
user_data: u64,
1621+
name: []const u8,
1622+
value: []const u8,
1623+
path: []const u8,
1624+
len: u32,
1625+
) !*Sqe {
1626+
const sqe = try self.get_sqe();
1627+
sqe.prep_getxattr(name, value, path, len);
1628+
sqe.user_data = user_data;
1629+
return sqe;
1630+
}
1631+
1632+
/// Queues (but does not submit) an SQE to prepares a request to set an
1633+
/// extended attribute value
1634+
/// Returns a pointer to the SQE.
1635+
pub fn setxattr(
1636+
self: *IoUring,
1637+
user_data: u64,
1638+
name: []const u8,
1639+
value: []const u8,
1640+
path: []const u8,
1641+
flags: linux.SetXattr,
1642+
len: u32,
1643+
) !*Sqe {
1644+
const sqe = try self.get_sqe();
1645+
sqe.prep_setxattr(name, value, path, flags, len);
1646+
sqe.user_data = user_data;
1647+
return sqe;
1648+
}
1649+
15191650
/// Queues (but does not submit) an SQE to perform a `waitid(2)`.
15201651
/// Returns a pointer to the SQE.
15211652
pub fn waitid(
@@ -2820,6 +2951,116 @@ pub const Sqe = extern struct {
28202951
sqe.rw_flags = @bitCast(flags);
28212952
}
28222953

2954+
pub fn prep_msg_ring(
2955+
sqe: *Sqe,
2956+
fd: linux.fd_t,
2957+
len: u32,
2958+
data: u64,
2959+
flags: uflags.MsgRing,
2960+
) void {
2961+
sqe.prep_rw(
2962+
.msg_ring,
2963+
fd,
2964+
undefined,
2965+
len,
2966+
data,
2967+
);
2968+
sqe.rw_flags = @bitCast(flags);
2969+
}
2970+
2971+
pub fn prep_msg_ring_cqe_flags(
2972+
sqe: *Sqe,
2973+
fd: linux.fd_t,
2974+
len: u32,
2975+
data: u64,
2976+
msg_flags: uflags.MsgRing,
2977+
cqe_flags: Cqe.Flags,
2978+
) void {
2979+
const enable_flags_pass = blk: {
2980+
var flags = msg_flags;
2981+
flags.flags_pass = true;
2982+
break :blk flags;
2983+
};
2984+
sqe.prep_msg_ring(fd, len, data, enable_flags_pass);
2985+
// sqe.file_index in liburing maps to splice_fd_in in Zig sqe
2986+
sqe.splice_fd_in = @intCast(@as(u32, @bitCast(cqe_flags)));
2987+
}
2988+
2989+
pub fn prep_msg_ring_fd(
2990+
sqe: *Sqe,
2991+
fd: linux.fd_t,
2992+
source_fd: linux.fd_t,
2993+
target_fd: linux.fd_t,
2994+
data: u64,
2995+
flags: uflags.MsgRing,
2996+
) void {
2997+
sqe.prep_rw(
2998+
.msg_ring,
2999+
fd,
3000+
@ptrFromInt(@intFromEnum(MsgRingCmd.send_fd)),
3001+
0,
3002+
data,
3003+
);
3004+
sqe.addr3 = @intCast(source_fd);
3005+
sqe.rw_flags = @bitCast(flags);
3006+
sqe.set_target_fixed_file(@intCast(target_fd));
3007+
}
3008+
3009+
pub fn prep_msg_ring_fd_alloc(
3010+
sqe: *Sqe,
3011+
fd: linux.fd_t,
3012+
source_fd: linux.fd_t,
3013+
data: u64,
3014+
flags: uflags.MsgRing,
3015+
) void {
3016+
sqe.prep_rw(
3017+
.msg_ring,
3018+
fd,
3019+
@ptrFromInt(@intFromEnum(MsgRingCmd.send_fd)),
3020+
0,
3021+
data,
3022+
);
3023+
sqe.addr3 = @intCast(source_fd);
3024+
sqe.rw_flags = @bitCast(flags);
3025+
sqe.set_target_fixed_file(constants.FILE_INDEX_ALLOC);
3026+
}
3027+
3028+
pub fn prep_getxattr(
3029+
sqe: *Sqe,
3030+
name: []const u8,
3031+
value: []const u8,
3032+
path: []const u8,
3033+
len: u32,
3034+
) void {
3035+
sqe.prep_rw(
3036+
.getxattr,
3037+
0,
3038+
@intFromPtr(name.ptr),
3039+
len,
3040+
@intFromPtr(value.ptr),
3041+
);
3042+
sqe.addr3 = @intFromPtr(path.ptr);
3043+
}
3044+
3045+
pub fn prep_setxattr(
3046+
sqe: *Sqe,
3047+
name: []const u8,
3048+
value: []const u8,
3049+
path: []const u8,
3050+
flags: linux.SetXattr,
3051+
len: u32,
3052+
) void {
3053+
sqe.prep_rw(
3054+
.setxattr,
3055+
0,
3056+
@intFromPtr(name.ptr),
3057+
len,
3058+
@intFromPtr(value.ptr),
3059+
);
3060+
sqe.addr3 = @intFromPtr(path.ptr);
3061+
sqe.rw_flags = @bitCast(flags);
3062+
}
3063+
28233064
pub fn prep_files_update(
28243065
sqe: *Sqe,
28253066
fds: []const linux.fd_t,

0 commit comments

Comments
 (0)