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:
@@ -62,7 +62,7 @@ int cubelinux_kernel_range(const __u8 *space,
|
||||
* what lets a new vocabulary attach without a format change.
|
||||
*/
|
||||
int cubelinux_kernel_flag_scan(const __u8 *space, __u16 mask, __u16 mode,
|
||||
__u64 cursor, void *buf, size_t cap,
|
||||
__u32 every_space, __u64 cursor, void *buf, size_t cap,
|
||||
__u64 *out_len, __u64 *out_cursor);
|
||||
|
||||
/* The store device path, resolved from the `cube_store=` boot parameter at boot. */
|
||||
@@ -393,6 +393,8 @@ static long cube_flag_scan_op(void __user *uargs)
|
||||
return -EINVAL;
|
||||
if (f.mode != CUBE_FLAG_ANY && f.mode != CUBE_FLAG_ALL)
|
||||
return -EINVAL;
|
||||
if (f.every_space != CUBE_SPACE_ONE && f.every_space != CUBE_SPACE_EVERY)
|
||||
return -EINVAL;
|
||||
|
||||
if (f.len > CUBE_MAX_WALK)
|
||||
return -E2BIG;
|
||||
@@ -402,8 +404,8 @@ static long cube_flag_scan_op(void __user *uargs)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = cubelinux_kernel_flag_scan(f.space, f.mask, f.mode, f.cursor,
|
||||
buf, f.len, &out_len, &out_cursor);
|
||||
ret = cubelinux_kernel_flag_scan(f.space, f.mask, f.mode, f.every_space,
|
||||
f.cursor, buf, f.len, &out_len, &out_cursor);
|
||||
if (ret == 0) {
|
||||
if (out_len > 0 && copy_to_user((void __user *)f.value, buf, out_len))
|
||||
ret = -EFAULT;
|
||||
|
||||
Reference in New Issue
Block a user