CUBELinux.0.6: cube(2) — the coordinate interface
The write path was proven but unreachable: its operations lived behind a device node. This is the interface the decision chose (DESIGN-cube-interface.md) — one syscall number, an opcode, and a versioned argument block, with operations that are the verbs the command language already defines: put, get, del, sync. long cube(unsigned int op, struct cube_args __user *args) `size` comes first and is checked, because syscall numbers are permanent and an interface that cannot grow would have to be replaced. A coordinate is the space and its three axes; nothing here resolves a name and nothing enumerates. Split deliberately: the entry point, the user copies and the argument validation are in C (cube_syscall.c) because `SYSCALL_DEFINE*` is a C macro this kernel has no Rust equivalent for; everything that touches the store's bytes is in Rust, which passes the coordinate to the format code as its parts so that Morton encoding stays in the one module that must get it exactly right. A read that does not fit returns the size it needs rather than truncating — a short read would be worse than an error. Number 548: the x86_64 table says numbers 548 and above are available for non-x32 use. Gate (kernel/verify-syscall.sh): a static client in the initramfs does four writes (including an empty value and a second space), reads one back *through the same interface*, and folds with `sync`. Three different failures are separated — the calls failing (a broken ABI), a read not returning what a write stored (a wrong key encoding or index), and the folded image differing (a wrong format, order or merge). put 7,0,0 ok (21 bytes) put 8,0,0 ok (0 bytes) put 9,0,0 ok (28 bytes) put 1,2,3 ok (13 bytes) get 7,0,0 21 bytes: the kernel wrote this sync ok and the image left on the device is byte-identical to the one userspace writes from the same mutations, with the log empty. The interface's store is the same store. All nine gates pass on 0.6.
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/*
|
||||
* CUBELinux: the coordinate interface.
|
||||
*
|
||||
* The kernel's native interface to the store. Operations are the verbs the command language
|
||||
* already defines — one language, and this is its kernel form (DESIGN-cube-interface.md).
|
||||
*
|
||||
* A coordinate is not a name and not a path: it is *where* a record is, and knowing it is the
|
||||
* authorisation to use it. Nothing here resolves a name, and nothing enumerates.
|
||||
*/
|
||||
#ifndef _UAPI_LINUX_CUBE_H
|
||||
#define _UAPI_LINUX_CUBE_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/* Which cube, and where in it. 32-byte space: unguessable, deliberately. */
|
||||
struct cube_coord {
|
||||
__u8 space[32];
|
||||
__u64 x;
|
||||
__u64 y;
|
||||
__u64 z;
|
||||
};
|
||||
|
||||
/*
|
||||
* The argument block. `size` first, and checked: an interface that cannot grow is an
|
||||
* interface that has to be replaced, and syscall numbers are permanent.
|
||||
*/
|
||||
struct cube_args {
|
||||
__u32 size; /* sizeof(struct cube_args) as the caller built it */
|
||||
__u32 op; /* CUBE_OP_* */
|
||||
struct cube_coord coord; /* unused by CUBE_OP_SYNC */
|
||||
__u64 value; /* user pointer: bytes to write, or where to put them */
|
||||
__u64 len; /* in: bytes offered, or the buffer's capacity.
|
||||
* out: on -ERANGE, the bytes that would be needed;
|
||||
* on success for CUBE_OP_GET, the bytes read.
|
||||
*/
|
||||
};
|
||||
|
||||
#define CUBE_OP_PUT 1 /* store bytes at a coordinate */
|
||||
#define CUBE_OP_GET 2 /* read them back */
|
||||
#define CUBE_OP_DEL 3 /* remove the record */
|
||||
#define CUBE_OP_SYNC 4 /* fold the log into the image */
|
||||
|
||||
#endif /* _UAPI_LINUX_CUBE_H */
|
||||
Reference in New Issue
Block a user