/*
 * Expects va args : (int elem_num, const char __user *s)
 * Element size is implicit (sizeof(char)).
 */
static char *ltt_serialize_fs_data(char *buffer, char *str,
	struct ltt_serialize_closure *closure,
	void *serialize_private,
	int align, const char *fmt, va_list *args)
{
	int elem_size;
	int elem_num;
	const char __user  *s;
	unsigned long noncopy;

	elem_num = va_arg(*args, int);
	s = va_arg(*args, const char __user *);
	elem_size = sizeof(*s);

	if (align)
		str += ltt_align((long)str, sizeof(int));
	if (buffer)
		*(int*)str = elem_num;
	str += sizeof(int);

	if (elem_num > 0) {
		/* No alignment required for char */
		if (buffer) {
			noncopy = __copy_from_user_inatomic(str, s,
					elem_num*elem_size);
			memset(str+(elem_num*elem_size)-noncopy, 0, noncopy);
		}
		str += (elem_num*elem_size);
	}
	/* Following alignment for genevent compatibility */
	if (align)
		str += ltt_align((long)str, sizeof(void*));
	return str;
}
Exemple #2
0
size_t ltt_write_event_header_slow(struct ltt_chanbuf_alloc *bufa,
				   struct ltt_chan_alloc *chana,
				   long buf_offset, u16 eID, u32 event_size,
				   u64 tsc, unsigned int rflags)
{
	struct ltt_event_header header;
	u16 small_size;

	switch (rflags) {
	case LTT_RFLAG_ID_SIZE_TSC:
		header.id_time = 29 << LTT_TSC_BITS;
		break;
	case LTT_RFLAG_ID_SIZE:
		header.id_time = 30 << LTT_TSC_BITS;
		break;
	case LTT_RFLAG_ID:
		header.id_time = 31 << LTT_TSC_BITS;
		break;
	default:
		WARN_ON_ONCE(1);
		header.id_time = 0;
	}

	header.id_time |= (u32)tsc & LTT_TSC_MASK;
	ltt_relay_write(bufa, chana, buf_offset, &header, sizeof(header));
	buf_offset += sizeof(header);

	switch (rflags) {
	case LTT_RFLAG_ID_SIZE_TSC:
		small_size = (u16)min_t(u32, event_size, LTT_MAX_SMALL_SIZE);
		ltt_relay_write(bufa, chana, buf_offset,
			&eID, sizeof(u16));
		buf_offset += sizeof(u16);
		ltt_relay_write(bufa, chana, buf_offset,
			&small_size, sizeof(u16));
		buf_offset += sizeof(u16);
		if (small_size == LTT_MAX_SMALL_SIZE) {
			ltt_relay_write(bufa, chana, buf_offset,
				&event_size, sizeof(u32));
			buf_offset += sizeof(u32);
		}
		buf_offset += ltt_align(buf_offset, sizeof(u64));
		ltt_relay_write(bufa, chana, buf_offset,
			&tsc, sizeof(u64));
		buf_offset += sizeof(u64);
		break;
	case LTT_RFLAG_ID_SIZE:
		small_size = (u16)min_t(u32, event_size, LTT_MAX_SMALL_SIZE);
		ltt_relay_write(bufa, chana, buf_offset,
			&eID, sizeof(u16));
		buf_offset += sizeof(u16);
		ltt_relay_write(bufa, chana, buf_offset,
			&small_size, sizeof(u16));
		buf_offset += sizeof(u16);
		if (small_size == LTT_MAX_SMALL_SIZE) {
			ltt_relay_write(bufa, chana, buf_offset,
				&event_size, sizeof(u32));
			buf_offset += sizeof(u32);
		}
		break;
	case LTT_RFLAG_ID:
		ltt_relay_write(bufa, chana, buf_offset,
			&eID, sizeof(u16));
		buf_offset += sizeof(u16);
		break;
	}

	return buf_offset;
}