cube(2): CUBE_OP_GET answers with the record's class
The last hole in the substrate: a caller could write a class through the syscall but not read one back. `CUBE_OP_GET` now fills `args.flags` from the same index entry the address came from, so learning what a record *is* costs nothing beyond a read that was going to happen. One field for both directions, because it is one thing — the class of this record. A write states it, a read learns it, and neither is a special case of the other. `find` hands the mask back with the address for the same reason: it is in the same stride the binary search already read, so wanting both does not mean searching twice. A read that finds nothing leaves 0 rather than a stale class for the caller to believe. The size of `cube_args` does not change, which matters because `size` is what says which argument block arrived.
This commit is contained in:
+14
-11
@@ -34,18 +34,21 @@ struct cube_args {
|
||||
* out: on -ERANGE, the bytes that would be needed;
|
||||
* 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.
|
||||
__u16 flags; /* in: CUBE_OP_PUT — the class mask to stamp on the record;
|
||||
* out: CUBE_OP_GET — the mask the record carries.
|
||||
*
|
||||
* 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.
|
||||
* One field for both directions because it is one thing: the
|
||||
* class of this record. A write states it, a read learns it,
|
||||
* and neither is a special case of the other. 0 is "no class",
|
||||
* which is what every record written before the field existed
|
||||
* reads as — so not classifying is not writing a special value,
|
||||
* and a read that found nothing leaves 0 rather than a stale
|
||||
* class for the caller to believe.
|
||||
*
|
||||
* 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. A read from such a store answers 0 for the same reason.
|
||||
*/
|
||||
__u16 reserved; /* must be 0 */
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user