cube(2): CUBE_OP_FLAG_SCAN takes a scope — one space, or every space
"Every error anywhere" and "every error here" are different questions, and a space is a hard partition, so the scope is a field rather than a widening. It is not a reserved space id because there is no such id to reserve: every 32-byte value is a legitimate space, root 0x00 and edge 0xFF…FF among them, so a sentinel would be a space somebody could name. The field occupies what was padding, which keeps sizeof unchanged — and that matters, because size is what says which argument block arrived and cube_args is exactly eight bytes wider. An every-space answer carries each frame's space, and that is not decoration: a walk's frame omits the space on the grounds that the caller named it, and this caller named none. A coordinate is meaningless without its space, so an answer that left it out would be unusable rather than merely terse. The space leads because the (space, key) pair it forms is the order records are stored in and returned in — so an every-space scan answers in exactly the order a checkpoint writes. The walk visits the space table's order and puts a space only the log writes into in its place in that same order, which is the one thing a plain walk of the table would miss entirely. A scope or mode this build does not know is refused rather than defaulted: silently answering a narrower question than the one asked is as quiet a way to be wrong as answering a wider one.
This commit is contained in:
@@ -138,13 +138,21 @@ struct cube_range_args {
|
||||
* — the walk's frame with the class mask in it. The mask travels because a scan's answer has to say
|
||||
* what class each record answered with: a record can carry bits beyond the one asked for, and no
|
||||
* other operation returns a mask.
|
||||
*
|
||||
* Under CUBE_SPACE_EVERY the frame gains a leading `space(32)`, because it has to: a walk's frame
|
||||
* leaves the space out on the grounds that the caller named it, and a caller who named no space
|
||||
* cannot be told which one a record came from any other way. A coordinate is meaningless without
|
||||
* its space, so an every-space answer that omitted it would be unusable rather than merely terse.
|
||||
* The space leads because the (space, key) pair it forms is the order records are stored in and
|
||||
* returned in.
|
||||
*/
|
||||
struct cube_flag_scan_args {
|
||||
__u32 size; /* sizeof(struct cube_flag_scan_args) as the caller built it */
|
||||
__u32 op; /* CUBE_OP_FLAG_SCAN */
|
||||
__u8 space[32]; /* in: the space to scan */
|
||||
__u8 space[32]; /* in: the space to scan, or ignored with CUBE_SPACE_EVERY */
|
||||
__u16 mask; /* in: the class mask to match; 0 matches nothing */
|
||||
__u16 mode; /* in: CUBE_FLAG_ANY or CUBE_FLAG_ALL */
|
||||
__u32 every_space; /* in: CUBE_SPACE_ONE or CUBE_SPACE_EVERY — see below */
|
||||
__u64 cursor; /* in: 0 to start, or what the last call returned;
|
||||
* out: what to pass next — see the end-of-scan rule above
|
||||
*/
|
||||
@@ -157,4 +165,21 @@ struct cube_flag_scan_args {
|
||||
#define CUBE_FLAG_ANY 0 /* the record shares at least one bit with the mask */
|
||||
#define CUBE_FLAG_ALL 1 /* the record carries every bit of the mask */
|
||||
|
||||
/*
|
||||
* The scan's scope. A space is a hard partition, so this is a choice between two different
|
||||
* questions and never a filter that can be widened by accident:
|
||||
*
|
||||
* CUBE_SPACE_ONE the records of `space` — "this class here"
|
||||
* CUBE_SPACE_EVERY the records of every space — "this class anywhere"
|
||||
*
|
||||
* It is a field and not a reserved space id because there is no such id to reserve: every 32-byte
|
||||
* value is a legitimate space (root `0x00` and edge `0xFF…FF` are both in use), so a sentinel would
|
||||
* be a space somebody could name. The field occupies what was padding, so `sizeof` is unchanged —
|
||||
* which matters, because `size` is what says which argument block arrived and `cube_args` is
|
||||
* exactly eight bytes wider. A caller that zeroes its block (and every caller does) gets
|
||||
* CUBE_SPACE_ONE, which is the narrower question.
|
||||
*/
|
||||
#define CUBE_SPACE_ONE 0 /* scan only `space` */
|
||||
#define CUBE_SPACE_EVERY 1 /* scan every space */
|
||||
|
||||
#endif /* _UAPI_LINUX_CUBE_H */
|
||||
|
||||
Reference in New Issue
Block a user