rust: uaccess: add UserSliceWriter::write_truncated()

Add a helper that writes as much of an AsBytes value as fits in the
remaining userspace buffer and returns the number of bytes copied. This
avoids requiring callers of versioned UAPIs to convert values to byte
slices and truncate them manually.

Suggested-by: Danilo Krummrich <dakr@kernel.org>
Link: https://lore.kernel.org/nova-gpu/DKC6T1DQX2L3.HTHPB2L167TC@kernel.org/
Signed-off-by: Alistair Popple <apopple@nvidia.com>
Acked-by: Miguel Ojeda <ojeda@kernel.org>
Link: https://patch.msgid.link/20260909064506.910162-7-apopple@nvidia.com
[ Inline write_slice_partial() and use it to simplify write_truncated().
  - Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
This commit is contained in:
Alistair Popple 2026-09-09 16:44:59 +10:00 committed by Danilo Krummrich
parent a1678ed1f8
commit b40f5ed85c

View File

@ -558,6 +558,7 @@ pub fn write_dma<T: KnownSize + AsBytes + ?Sized>(
/// truncates the write to the boundaries of `self` and `data`.
///
/// On success, returns the number of bytes written.
#[inline]
pub fn write_slice_partial(&mut self, data: &[u8], offset: usize) -> Result<usize> {
let end = offset.saturating_add(self.len()).min(data.len());
@ -624,6 +625,19 @@ pub fn write<T: AsBytes>(&mut self, value: &T) -> Result {
self.length -= len;
Ok(())
}
/// Writes as much of the provided value as fits in the remaining buffer.
///
/// Copies `min(size_of::<T>(), self.len())` bytes to userspace. Returns the number of bytes
/// actually written. This is useful for versioned structs where an older userspace may provide
/// a smaller buffer than the current kernel struct.
///
/// Fails with [`EFAULT`] if the write happens on a bad address. This call may modify the
/// associated userspace slice even if it returns an error.
#[inline]
pub fn write_truncated<T: AsBytes>(&mut self, value: &T) -> Result<usize> {
self.write_slice_partial(value.as_bytes(), 0)
}
}
/// Reads a nul-terminated string into `dst` and returns the length.