Skip to content

Commit 2678fe3

Browse files
committed
Add Eio_linux.Low_level.statx
1 parent b741881 commit 2678fe3

File tree

5 files changed

+69
-2
lines changed

5 files changed

+69
-2
lines changed

dune-project

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
(logs (>= 0.7.0))
4343
(fmt (>= 0.8.9))
4444
(cmdliner (and (>= 1.1.0) :with-test))
45-
(uring (>= 0.5))))
45+
(uring (>= 0.7))))
4646
(package
4747
(name eio_posix)
4848
(allow_empty) ; Work-around for dune bug #6938

eio_linux.opam

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ depends: [
1616
"logs" {>= "0.7.0"}
1717
"fmt" {>= "0.8.9"}
1818
"cmdliner" {>= "1.1.0" & with-test}
19-
"uring" {>= "0.5"}
19+
"uring" {>= "0.7"}
2020
"odoc" {with-doc}
2121
]
2222
build: [

lib_eio_linux/eio_linux.mli

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,12 @@ module Low_level : sig
156156
val fstat : fd -> Eio.File.Stat.t
157157
(** Like {!Unix.LargeFile.fstat}. *)
158158

159+
val statx : ?fd:fd -> mask:Uring.Statx.Mask.t -> string -> Uring.Statx.t -> Uring.Statx.Flags.t -> unit
160+
(** [statx t ?fd ~mask path buf flags] stats [path], which is resolved relative to [fd]
161+
(or the current directory if [fd] is not given).
162+
163+
The results are written to [buf]. *)
164+
159165
val read_dir : fd -> string list
160166
(** [read_dir dir] reads all directory entries from [dir].
161167
The entries are not returned in any particular order

lib_eio_linux/low_level.ml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,15 @@ let rec enqueue_openat2 ((access, flags, perm, resolve, fd, path) as args) st ac
5656
if retry then (* wait until an sqe is available *)
5757
Queue.push (fun st -> enqueue_openat2 args st action) st.io_q
5858

59+
let rec enqueue_statx ((fd, path, buf, flags, mask) as args) st action =
60+
Ctf.label "statx";
61+
let retry = Sched.with_cancel_hook ~action st (fun () ->
62+
Uring.statx st.uring ?fd ~mask path buf flags (Job action)
63+
)
64+
in
65+
if retry then (* wait until an sqe is available *)
66+
Queue.push (fun st -> enqueue_statx args st action) st.io_q
67+
5968
let rec enqueue_unlink ((dir, fd, path) as args) st action =
6069
Ctf.label "unlinkat";
6170
let retry = Sched.with_cancel_hook ~action st (fun () ->
@@ -360,6 +369,16 @@ let with_parent_dir op dir path fn =
360369
fn parent leaf
361370
)
362371

372+
let statx ?fd ~mask path buf flags =
373+
let res =
374+
match fd with
375+
| None -> Sched.enter (enqueue_statx (None, path, buf, flags, mask))
376+
| Some fd ->
377+
Fd.use_exn "statx" fd @@ fun fd ->
378+
Sched.enter (enqueue_statx (Some fd, path, buf, flags, mask))
379+
in
380+
if res <> 0 then raise @@ Err.wrap_fs (Uring.error_of_errno res) "statx" path
381+
363382
let mkdir_beneath ~perm dir path =
364383
(* [mkdir] is really an operation on [path]'s parent. Get a reference to that first: *)
365384
with_parent_dir "mkdir" dir path @@ fun parent leaf ->

lib_eio_linux/tests/test.ml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,47 @@ let test_expose_backend () =
155155
let backend = Eio.Stdenv.backend_id env in
156156
assert (backend = "linux")
157157

158+
let kind_t = Alcotest.of_pp Uring.Statx.pp_kind
159+
160+
let test_statx () =
161+
let module X = Uring.Statx in
162+
Eio_linux.run ~queue_depth:4 @@ fun env ->
163+
let ( / ) = Eio.Path.( / ) in
164+
let path = env#cwd / "test2.data" in
165+
let msg = "hello" in
166+
Eio.Path.save path ("!" ^ msg) ~create:(`Exclusive 0o600);
167+
let buf = Uring.Statx.create () in
168+
let test ~flags ?fd path =
169+
Eio_linux.Low_level.statx ~mask:X.Mask.(type' + size) ?fd path buf flags;
170+
Alcotest.check kind_t "kind" `Regular_file (Uring.Statx.kind buf);
171+
Alcotest.(check int64) "size" 6L (Uring.Statx.size buf)
172+
in
173+
(* Lookup via cwd *)
174+
test ~flags:X.Flags.empty ?fd:None "test.data";
175+
(* Lookup via file FD *)
176+
Switch.run (fun sw ->
177+
let fd = Eio_linux.Low_level.openat2 ~sw
178+
~access:`R
179+
~flags:Uring.Open_flags.empty
180+
~perm:0
181+
~resolve:Uring.Resolve.empty
182+
"test.data"
183+
in
184+
test ~flags:X.Flags.empty_path ~fd ""
185+
);
186+
(* Lookup via directory FD *)
187+
Switch.run (fun sw ->
188+
let fd = Eio_linux.Low_level.openat2 ~sw
189+
~access:`R
190+
~flags:Uring.Open_flags.path
191+
~perm:0
192+
~resolve:Uring.Resolve.empty
193+
"."
194+
in
195+
test ~flags:X.Flags.empty_path ~fd "test.data"
196+
);
197+
()
198+
158199
let () =
159200
let open Alcotest in
160201
run "eio_linux" [
@@ -167,5 +208,6 @@ let () =
167208
test_case "no_sqe" `Quick test_no_sqe;
168209
test_case "read_exact" `Quick test_read_exact;
169210
test_case "expose_backend" `Quick test_expose_backend;
211+
test_case "statx" `Quick test_statx;
170212
];
171213
]

0 commit comments

Comments
 (0)