This sounds overly complex to me. It seems better to pass in addresses
in which to store source/destination errors, and let that be NULL if
you aren't expecting them. Thus you get the crash on the second pass. ;-)
> The problem with clear_user and copy_user is that they return different
> thing than normal bzero/memset/memcpy, if I remember well...
Yeah, but the return values from memcpy et al are simplistic. It would
be easy to do
extern size_t copy_user(void *, const void *, size_t,
int *dst_err, int *src_err);
inline void *memcpy(void *dst, const void *src, size_t len)
{
copy_user(dst, src, len, NULL, NULL);
return dst;
}
inline size_t copy_from_user(void *dst, const void *, size_t)
{
int err;
return copy_user(dst, src, len, NULL, &err);
}
inline size_t copy_to_user(void *dst, const void *, size_t)
{
int err;
return copy_user(dst, src, len, &err, NULL);
}
Thus our additional runtime overhead is two "pushes", one of which
may be a stack address. This seems acceptable to me.
In the case of the networking code, where we want to zero the balance
of the buffer on error in csum_partial_copy_from_user, but continue
with the transfer and report later, it might be that that int* gets
passed all the way down from whoever cares.
But I'm not really clear on how networking works in general, so that's
just a wild guess.
r~