We have several helper routines for dispatching I/O to a provider. They
are used internally by the kernel and not by the data path. None of
them handle partial I/O, but in some rare cases this is possible. Note
in particular that g_io_check() silently truncates the request to fit
within the bounds of the provider.
Truncated reads can happen in the somewhat contrived scenario where a
file-backed memory disk is larger than the file itself. I/O to a
file-backed memory disk is treated similarly to I/O to a vnode: reads
past EOF return 0 bytes, and writes past EOF extend the file. Various
classes uses g_read_data() to look for their metadata blocks when
tasting, and assume that a successful read indicates that the supplied
buffer was filled with data by the provider. If a short read occurs,
this is not the case, and they end up tasting an uninitialized buffer.
So, change g_read_data() to check for this scenario, since I believe it
is always a bug to indicate success there.
I modified g_write_data() and g_delete_data() accordingly, though I'm
not as certain about this. See also commits 8948179aba54, de66da73746f
and 9dcafe16d4e8. In particular, the change reverts commit 9dcafe16d4e8
since I believe it is redundant with this change.
Reported by: KMSAN (g_read_data() bug)
MFC after: 1 week