libxtc 0.4.0
Async concurrency for C: Tokio + Seastar + BEAM, in one library
Loading...
Searching...
No Matches
xtc_bdev.h
1/*-
2 * Copyright (c) 2026, The XTC Project
3 * Use of this source code is governed by the ISC License.
4 *
5 * src/inc/xtc_bdev.h
6 * Portable block-device I/O over the async xtc_aio path. A thin,
7 * uniform surface for reading and writing a raw block device (or a
8 * regular file treated as one) with sector-aligned positioned I/O
9 * that suspends the calling fiber and resumes it on completion --
10 * the same "write once, runs as AIO everywhere" model as
11 * xtc_aio(3), on top of which this layer is built.
12 *
13 * xtc_bdev_open probes the device for its logical and physical
14 * sector sizes and total capacity using the host's native query
15 * (BLKSSZGET / BLKGETSIZE64 on Linux, DIOCGSECTORSIZE on the BSDs
16 * and macOS, DKIOCGMEDIAINFO on illumos, the drive geometry IOCTL on
17 * Windows) and opens the descriptor with direct I/O (O_DIRECT) for a
18 * real device so transfers bypass the page cache. A regular file or
19 * an unqueryable target falls back to logical=512, physical=4096, and
20 * the capacity reported by fstat, with buffered I/O.
21 *
22 * xtc_bdev_pread / xtc_bdev_pwrite route through
23 * xtc_aio_pread / xtc_aio_pwrite: on a fiber loop the call parks the
24 * fiber and the loop keeps running other work. The offset and the
25 * length must both be multiples of the logical sector size, else the
26 * call returns XTC_E_INVAL. xtc_bdev_flush issues xtc_aio_fsync.
27 *
28 * See xtc_bdev(3).
29 */
30
31#ifndef XTC_BDEV_H
32#define XTC_BDEV_H
33
34#include <stddef.h>
35#include <stdint.h>
36
37/* The pread/pwrite return values use the standard POSIX `ssize_t`. We
38 * provide it portably WITHOUT a namespace-polluting #define of the name
39 * and WITHOUT redefining it where the platform already has it:
40 * - POSIX: <sys/types.h> defines the real ssize_t; we just use it.
41 * - MinGW/Cygwin on Windows: same -- their <sys/types.h> defines
42 * ssize_t and sets _SSIZE_T_DEFINED.
43 * - MSVC: the CRT has no ssize_t, so we typedef it from SSIZE_T,
44 * guarded by _SSIZE_T_DEFINED (the de-facto sentinel) so a consumer
45 * header that already defined it wins, and a later include of ours
46 * cannot double-define. */
47#if defined(_WIN32) && defined(_MSC_VER)
48# ifndef _SSIZE_T_DEFINED
49# define _SSIZE_T_DEFINED
50# include <BaseTsd.h> /* SSIZE_T */
51typedef SSIZE_T ssize_t;
52# endif
53#else
54# include <sys/types.h> /* real ssize_t (POSIX, MinGW, Cygwin) */
55#endif
56
57/* Open flags for xtc_bdev_open (subset of xtc_fs flags that make sense
58 * for a block device; mapped to O_* per platform). */
59#define XTC_BDEV_READ 0x01u /* open for reading */
60#define XTC_BDEV_WRITE 0x02u /* open for writing (implies read too) */
61
62/* Opaque device handle. */
63typedef struct xtc_bdev xtc_bdev_t;
64
65/*
66 * PUBLIC: int xtc_bdev_open __P((const char *, int, xtc_bdev_t **));
67 *
68 * Open path as a block device, probing its geometry. flags is a mask of
69 * XTC_BDEV_READ / XTC_BDEV_WRITE. On success stores the handle in *out
70 * and returns XTC_OK; otherwise a negative XTC_E_* code.
71 */
72int xtc_bdev_open(const char *path, int flags, xtc_bdev_t **out);
73
74/*
75 * PUBLIC: void xtc_bdev_close __P((xtc_bdev_t *));
76 *
77 * Close the device and free the handle. NULL is a no-op.
78 */
79void xtc_bdev_close(xtc_bdev_t *b);
80
81/*
82 * PUBLIC: uint32_t xtc_bdev_logical_sector __P((const xtc_bdev_t *));
83 * PUBLIC: uint32_t xtc_bdev_physical_sector __P((const xtc_bdev_t *));
84 * PUBLIC: uint64_t xtc_bdev_capacity __P((const xtc_bdev_t *));
85 *
86 * Report the probed logical sector size, physical sector size, and total
87 * capacity in bytes. Offsets and lengths passed to pread/pwrite must be
88 * multiples of the logical sector size.
89 */
90uint32_t xtc_bdev_logical_sector(const xtc_bdev_t *b);
91uint32_t xtc_bdev_physical_sector(const xtc_bdev_t *b);
92uint64_t xtc_bdev_capacity(const xtc_bdev_t *b);
93
94/*
95 * PUBLIC: ssize_t xtc_bdev_pread __P((xtc_bdev_t *, void *, size_t, uint64_t));
96 * PUBLIC: ssize_t xtc_bdev_pwrite __P((xtc_bdev_t *, const void *, size_t, uint64_t));
97 *
98 * Read n bytes into buf / write n bytes from buf at absolute byte offset
99 * off, routed through xtc_aio so the fiber parks and the loop stays live.
100 * off and n must each be a multiple of the logical sector size, else the
101 * call returns XTC_E_INVAL. On success returns the byte count
102 * transferred (>= 0); a short read at end of device returns the partial
103 * count. On failure returns a negative XTC_E_* code.
104 */
105ssize_t xtc_bdev_pread(xtc_bdev_t *b, void *buf, size_t n, uint64_t off);
106ssize_t xtc_bdev_pwrite(xtc_bdev_t *b, const void *buf, size_t n, uint64_t off);
107
108/*
109 * PUBLIC: int xtc_bdev_flush __P((xtc_bdev_t *));
110 *
111 * Flush the device's data and metadata durably via xtc_aio_fsync.
112 * Returns XTC_OK or a negative XTC_E_* code.
113 */
114int xtc_bdev_flush(xtc_bdev_t *b);
115
116#endif /* XTC_BDEV_H */