/* This is a little worse than the above because it's "chunked copy_to_user". The return value is an error code, not an offset.  */
static int copy_from_buf(const struct mon_reader_bin *this, unsigned int off, char __user *to, int length)
/* This is a little worse than the above because it's "chunked copy_to_user". The return value is an error code, not an offset.  */
static int copy_from_buf(const struct mon_reader_bin *this, unsigned int off, char __user *to, int length)
{
	unsigned int step_len;
	unsigned char *buf;
	unsigned int in_page;
	while (length) {
		step_len = length;
		in_page = CHUNK_SIZE - (off & (CHUNK_SIZE-1));
		if (in_page < step_len)
			step_len = in_page;
		buf = this->b_vec[off / CHUNK_SIZE].ptr + off % CHUNK_SIZE;
		if (copy_to_user(to, buf, step_len))
			return -EINVAL;
		if ((off += step_len) >= this->b_size) off = 0;
		to += step_len;
		length -= step_len;
	}
	return 0;
}