cube(2): CUBE_OP_PUT takes a class mask
The mask is the writer's and is stamped once, at the moment the record's class is known for certain; every later reader is spared re-deriving it. It means nothing to this side — which bits are which class is a vocabulary's business, and a kernel that interpreted one would be inventing a vocabulary. 0 is "no class", which is what every record written before the field existed reads as, so a caller that does not classify is not writing a special value. A store whose image is the legacy packed layout has no field to put a mask in and drops it: that layout cannot carry a class, and saying otherwise would be a lie about the bytes on disk. The field is appended, so sizeof(cube_args) grows from 80 to 88 — still distinct from the other three argument blocks, which is what the size-first dispatch depends on.
This commit is contained in:
@@ -30,7 +30,7 @@
|
|||||||
* encoding, which must produce exactly the key a userspace reader decodes.
|
* encoding, which must produce exactly the key a userspace reader decodes.
|
||||||
*/
|
*/
|
||||||
int cubelinux_kernel_put(const __u8 *space, __u64 x, __u64 y, __u64 z,
|
int cubelinux_kernel_put(const __u8 *space, __u64 x, __u64 y, __u64 z,
|
||||||
const void *value, size_t len);
|
const void *value, size_t len, __u16 flags);
|
||||||
ssize_t cubelinux_kernel_get(const __u8 *space, __u64 x, __u64 y, __u64 z,
|
ssize_t cubelinux_kernel_get(const __u8 *space, __u64 x, __u64 y, __u64 z,
|
||||||
void *buf, size_t len);
|
void *buf, size_t len);
|
||||||
int cubelinux_kernel_del(const __u8 *space, __u64 x, __u64 y, __u64 z);
|
int cubelinux_kernel_del(const __u8 *space, __u64 x, __u64 y, __u64 z);
|
||||||
@@ -188,7 +188,8 @@ static long cube_args_op(unsigned int op, void __user *uargs)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ret = cubelinux_kernel_put(args.coord.space, args.coord.x,
|
ret = cubelinux_kernel_put(args.coord.space, args.coord.x,
|
||||||
args.coord.y, args.coord.z, buf, args.len);
|
args.coord.y, args.coord.z, buf, args.len,
|
||||||
|
args.flags);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CUBE_OP_GET: {
|
case CUBE_OP_GET: {
|
||||||
|
|||||||
@@ -1696,7 +1696,12 @@ fn ensure_boot_record() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `CUBE_OP_PUT`: store bytes at a coordinate.
|
/// `CUBE_OP_PUT`: store bytes at a coordinate, under a class mask.
|
||||||
|
///
|
||||||
|
/// The mask is the writer's and is stamped here, once — this is the moment the record's class is
|
||||||
|
/// known for certain, and every later reader is spared re-deriving it. It means nothing to this
|
||||||
|
/// side: which bits are which class is a vocabulary's business, and a kernel that interpreted one
|
||||||
|
/// would be inventing a vocabulary.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
/// `space` must point to 32 readable bytes; `value` to `len` readable bytes when `len` is
|
/// `space` must point to 32 readable bytes; `value` to `len` readable bytes when `len` is
|
||||||
@@ -1709,6 +1714,7 @@ pub unsafe extern "C" fn cubelinux_kernel_put(
|
|||||||
z: u64,
|
z: u64,
|
||||||
value: *const u8,
|
value: *const u8,
|
||||||
len: usize,
|
len: usize,
|
||||||
|
flags: u16,
|
||||||
) -> i32 {
|
) -> i32 {
|
||||||
ensure_boot_record();
|
ensure_boot_record();
|
||||||
let (sp, key) = unsafe { coord_key(space, x, y, z) };
|
let (sp, key) = unsafe { coord_key(space, x, y, z) };
|
||||||
@@ -1725,7 +1731,7 @@ pub unsafe extern "C" fn cubelinux_kernel_put(
|
|||||||
let mutation = Mutation {
|
let mutation = Mutation {
|
||||||
space: sp,
|
space: sp,
|
||||||
key,
|
key,
|
||||||
flags: 0,
|
flags,
|
||||||
value: bytes,
|
value: bytes,
|
||||||
};
|
};
|
||||||
let (device, layout) = match device_and_layout() {
|
let (device, layout) = match device_and_layout() {
|
||||||
|
|||||||
@@ -34,6 +34,20 @@ struct cube_args {
|
|||||||
* out: on -ERANGE, the bytes that would be needed;
|
* out: on -ERANGE, the bytes that would be needed;
|
||||||
* on success for CUBE_OP_GET, the bytes read.
|
* on success for CUBE_OP_GET, the bytes read.
|
||||||
*/
|
*/
|
||||||
|
__u16 flags; /* in: CUBE_OP_PUT only — the class mask to stamp on the
|
||||||
|
* record. The mask is written where the record is written,
|
||||||
|
* which is the moment its class is known for certain; a
|
||||||
|
* reader never has to re-derive it. 0 is "no class", which
|
||||||
|
* is what every record written before the field existed
|
||||||
|
* reads as, so a caller that does not classify is not
|
||||||
|
* writing a special value.
|
||||||
|
*
|
||||||
|
* A store whose image is the legacy packed layout has no
|
||||||
|
* field to put a mask in, and drops it: that layout cannot
|
||||||
|
* carry a class and saying otherwise would be a lie about
|
||||||
|
* the bytes on disk.
|
||||||
|
*/
|
||||||
|
__u16 reserved; /* must be 0 */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CUBE_OP_PUT 1 /* store bytes at a coordinate */
|
#define CUBE_OP_PUT 1 /* store bytes at a coordinate */
|
||||||
|
|||||||
Reference in New Issue
Block a user