f3
f3 copied to clipboard
f3probe unit test
The "real limbo drive" unit test cases suggest an intention to detect wrapping by modulus other than a power of 2. However, the code offset &= fdev->address_mask; in fdev_write_block() that is used for the simulation of the fake drive and fdev->address_mask = (((uint64_t)1) << wrap) - 1; in create_file_device() suggests that only powers of 2 are supported. Furthermore, the code seems to use only the wrap variable, not real_size_bytes, to do the wrapping, effectively operating the test with a power of 2 wrapping, rendering it unable to detect whether or not wrapping with a different modulus that is not a power of 2 would be detected.
Either there needs to be clear comment with each real limbo drive unit test record what it is meant to test or the simulated fake drive needs support wrapping at the real device size. (If a fake device uses a 2^n-1 mask as in the code and the real device has slightly more capacity this extra capacity will never be seen and the fake device will behave as if it has a 2^n capacity real drive.)
Your observations are correct.
Notice that while the code uses masks, low-level hardware just ignores the high bits of the address bus. The code is simulating real fake drives and not hypothetical fake drives. More information on this subject can be found on issue #144.
A pull request to improve the documentation with your acquired knowledge would be welcome.
Trying to add a note like "Note that sectors are NOT wrapped at real_size_bytes but at 2^wrap bytes" poses the questions what is real_size_bytes used for. It seems to influence the behaviour of fdev_{read|write}_block. Using grep on the code, real_size_bytes seems also to be a variable for the detected real size.
real_size_bytes is the size from the beginning of the drive (i.e. from block 0) that is expected to be usable. This information has to be detected. f3probe even accounts for the fact that the region may have some failing blocks (see find_a_bad_block()), so this value is actually a lower bound of all the available memory on the drive.
Yes, I see the real_size_bytes variables in a good few functions for this purpose. However, here I am wondering what the real_size_bytes attribute of the unit_test_item is for. The value 1777645568ULL for the first real limbo drive in ftype_to_params is not a power of 2, hence can only be reached with simulated bad blocks in the unit test. I don't see any parameters for bad blocks in ftype_to_params, so I guess bad block detection is not part of the unit test or maybe it is and a bad block is simulated exactly after real_size_bytes provided in ftype_to_params and the resulting real_size_bytes is compared to the provided value for correctness of the detection algorithm.
Bad blocks are inferred from the description of the simulated drives. For example, the parameters of the first limbo drive in the unit test are as follows:
/* Geometry of a real limbo drive. */
{1777645568ULL, 32505331712ULL, 35, 9, -1, false},
So this drive announces its size as 32505331712ULL bytes, but it has only 1777645568ULL bytes. So any byte after 1777645568ULL and before 32505331712ULL is bad since it's a limbo drive. Notice that bytes, more precisely blocks, are numbered from zero.
Yes, the found real_size_bytes is compared to the provided value to check for correctness.
What needs to be a power of two is the wrapping edge, that is why the wrap parameter is the exponent of a power of 2. The real size of the drive doesn't need to be a power of 2 in general. However, if 2^(wrap) < (real_size_byte), the real size can only be detected as a power of 2. This kind of detail is tricky.
With the definitions above in mind, a limbo drive is a drive that has the following properties: 2^(wrap) >= (announced_size_byte) > (real_size_byte). The definitions of the other types of drives are found in dev_param_to_type().