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 "xtc_export.h"
35
36#include <stddef.h>
37#include <stdint.h>
38
39/* The pread/pwrite return values use the standard POSIX `ssize_t`. We
40 * provide it portably WITHOUT a namespace-polluting #define of the name
41 * and WITHOUT redefining it where the platform already has it:
42 * - POSIX: <sys/types.h> defines the real ssize_t; we just use it.
43 * - MinGW/Cygwin on Windows: same -- their <sys/types.h> defines
44 * ssize_t and sets _SSIZE_T_DEFINED.
45 * - MSVC: the CRT has no ssize_t, so we typedef it from SSIZE_T,
46 * guarded by _SSIZE_T_DEFINED (the de-facto sentinel) so a consumer
47 * header that already defined it wins, and a later include of ours
48 * cannot double-define. */
49#if defined(_WIN32) && defined(_MSC_VER)
50# ifndef _SSIZE_T_DEFINED
51# define _SSIZE_T_DEFINED
52# include <BaseTsd.h> /* SSIZE_T */
53typedef SSIZE_T ssize_t;
54# endif
55#else
56# include <sys/types.h> /* real ssize_t (POSIX, MinGW, Cygwin) */
57#endif
58
59/* Open flags for xtc_bdev_open (subset of xtc_fs flags that make sense
60 * for a block device; mapped to O_* per platform). */
61#define XTC_BDEV_READ 0x01u /* open for reading */
62#define XTC_BDEV_WRITE 0x02u /* open for writing (implies read too) */
63
64/* Opaque device handle. */
65typedef struct xtc_bdev xtc_bdev_t;
66
67/*
68 * PUBLIC: int xtc_bdev_open __P((const char *, int, xtc_bdev_t **));
69 *
70 * Open path as a block device, probing its geometry. flags is a mask of
71 * XTC_BDEV_READ / XTC_BDEV_WRITE. On success stores the handle in *out
72 * and returns XTC_OK; otherwise a negative XTC_E_* code.
73 */
74XTC_API int xtc_bdev_open(const char *path, int flags, xtc_bdev_t **out);
75
76/*
77 * PUBLIC: void xtc_bdev_close __P((xtc_bdev_t *));
78 *
79 * Close the device and free the handle. NULL is a no-op.
80 */
81XTC_API void xtc_bdev_close(xtc_bdev_t *b);
82
83/*
84 * PUBLIC: uint32_t xtc_bdev_logical_sector __P((const xtc_bdev_t *));
85 * PUBLIC: uint32_t xtc_bdev_physical_sector __P((const xtc_bdev_t *));
86 * PUBLIC: uint64_t xtc_bdev_capacity __P((const xtc_bdev_t *));
87 *
88 * Report the probed logical sector size, physical sector size, and total
89 * capacity in bytes. Offsets and lengths passed to pread/pwrite must be
90 * multiples of the logical sector size.
91 */
92XTC_API uint32_t xtc_bdev_logical_sector(const xtc_bdev_t *b);
93XTC_API uint32_t xtc_bdev_physical_sector(const xtc_bdev_t *b);
94XTC_API uint64_t xtc_bdev_capacity(const xtc_bdev_t *b);
95
96/*
97 * PUBLIC: ssize_t xtc_bdev_pread __P((xtc_bdev_t *, void *, size_t, uint64_t));
98 * PUBLIC: ssize_t xtc_bdev_pwrite __P((xtc_bdev_t *, const void *, size_t, uint64_t));
99 *
100 * Read n bytes into buf / write n bytes from buf at absolute byte offset
101 * off, routed through xtc_aio so the fiber parks and the loop stays live.
102 * off and n must each be a multiple of the logical sector size, else the
103 * call returns XTC_E_INVAL. On success returns the byte count
104 * transferred (>= 0); a short read at end of device returns the partial
105 * count. On failure returns a negative XTC_E_* code.
106 */
107XTC_API ssize_t xtc_bdev_pread(xtc_bdev_t *b, void *buf, size_t n, uint64_t off);
108XTC_API ssize_t xtc_bdev_pwrite(xtc_bdev_t *b, const void *buf, size_t n, uint64_t off);
109
110/*
111 * PUBLIC: int xtc_bdev_flush __P((xtc_bdev_t *));
112 *
113 * Flush the device's data and metadata durably via xtc_aio_fsync.
114 * Returns XTC_OK or a negative XTC_E_* code.
115 */
116XTC_API int xtc_bdev_flush(xtc_bdev_t *b);
117
118#endif /* XTC_BDEV_H */