When the captured fields end up taking more than 512 bytes of space for
the msgpack message, the notification append capture fails.
Currently, this is handled by printing a WARN_ON_ONCE() on the console,
and a printk "Error appending capture to notification" warning.
Considering that this kind of error is very much legitimate, spamming
the console with warnings is not the way we want to handle this.
Rather than print a warning on the console, reset the msgpack writer
position to skip the problematic captured field entirely when it is
erroneous.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Change-Id: I4c98dc85266dd7af5e11bbd3d73ab5118c9e03af
struct lttng_msgpack_writer *writer, size_t count);
int lttng_msgpack_end_array(struct lttng_msgpack_writer *writer);
struct lttng_msgpack_writer *writer, size_t count);
int lttng_msgpack_end_array(struct lttng_msgpack_writer *writer);
+int lttng_msgpack_save_writer_pos(struct lttng_msgpack_writer *writer, uint8_t **pos);
+int lttng_msgpack_restore_writer_pos(struct lttng_msgpack_writer *writer, uint8_t *pos);
+
#endif /* _LTTNG_KERNEL_MSGPACK_H */
#endif /* _LTTNG_KERNEL_MSGPACK_H */
+int lttng_msgpack_save_writer_pos(struct lttng_msgpack_writer *writer, uint8_t **pos)
+{
+ *pos = writer->write_pos;
+ return 0;
+}
+
+int lttng_msgpack_restore_writer_pos(struct lttng_msgpack_writer *writer, uint8_t *pos)
+{
+ writer->write_pos = pos;
+ return 0;
+}
+
void lttng_msgpack_writer_init(struct lttng_msgpack_writer *writer,
uint8_t *buffer, size_t size)
{
void lttng_msgpack_writer_init(struct lttng_msgpack_writer *writer,
uint8_t *buffer, size_t size)
{
*/
ret = lttng_msgpack_begin_map(writer, 2);
if (ret) {
*/
ret = lttng_msgpack_begin_map(writer, 2);
if (ret) {
goto end;
}
ret = lttng_msgpack_write_str(writer, "type");
if (ret) {
goto end;
}
ret = lttng_msgpack_write_str(writer, "type");
if (ret) {
goto end;
}
ret = lttng_msgpack_write_str(writer, "enum");
if (ret) {
goto end;
}
ret = lttng_msgpack_write_str(writer, "enum");
if (ret) {
goto end;
}
ret = lttng_msgpack_write_str(writer, "value");
if (ret) {
goto end;
}
ret = lttng_msgpack_write_str(writer, "value");
if (ret) {
case LTTNG_INTERPRETER_TYPE_SIGNED_ENUM:
ret = lttng_msgpack_write_signed_integer(writer, output->u.s);
if (ret) {
case LTTNG_INTERPRETER_TYPE_SIGNED_ENUM:
ret = lttng_msgpack_write_signed_integer(writer, output->u.s);
if (ret) {
goto end;
}
break;
case LTTNG_INTERPRETER_TYPE_UNSIGNED_ENUM:
ret = lttng_msgpack_write_signed_integer(writer, output->u.u);
if (ret) {
goto end;
}
break;
case LTTNG_INTERPRETER_TYPE_UNSIGNED_ENUM:
ret = lttng_msgpack_write_signed_integer(writer, output->u.u);
if (ret) {
goto end;
}
break;
default:
goto end;
}
break;
default:
}
ret = lttng_msgpack_end_map(writer);
}
ret = lttng_msgpack_end_map(writer);
- if (ret)
- WARN_ON_ONCE(1);
-
ret = lttng_msgpack_begin_array(writer, output->u.sequence.nr_elem);
if (ret) {
ret = lttng_msgpack_begin_array(writer, output->u.sequence.nr_elem);
if (ret) {
break;
default:
/* Capture of array of non-integer are not supported. */
break;
default:
/* Capture of array of non-integer are not supported. */
+ WARN_ON_ONCE(1);
+ ret = -1;
+ goto end;
}
signedness = integer_type->signedness;
for (i = 0; i < output->u.sequence.nr_elem; i++) {
}
signedness = integer_type->signedness;
for (i = 0; i < output->u.sequence.nr_elem; i++) {
ret = lttng_msgpack_write_signed_integer(writer,
capture_sequence_element_signed(ptr, integer_type));
if (ret) {
ret = lttng_msgpack_write_signed_integer(writer,
capture_sequence_element_signed(ptr, integer_type));
if (ret) {
goto end;
}
} else {
ret = lttng_msgpack_write_unsigned_integer(writer,
capture_sequence_element_unsigned(ptr, integer_type));
if (ret) {
goto end;
}
} else {
ret = lttng_msgpack_write_unsigned_integer(writer,
capture_sequence_element_unsigned(ptr, integer_type));
if (ret) {
* take into account that the next element might be further
* away.
*/
* take into account that the next element might be further
* away.
*/
- WARN_ON(integer_type->alignment > integer_type->size);
+ WARN_ON_ONCE(integer_type->alignment > integer_type->size);
/* Size is in number of bits. */
ptr += (integer_type->size / CHAR_BIT) ;
}
ret = lttng_msgpack_end_array(writer);
/* Size is in number of bits. */
ptr += (integer_type->size / CHAR_BIT) ;
}
ret = lttng_msgpack_end_array(writer);
- if (ret)
- WARN_ON_ONCE(1);
switch (output->type) {
case LTTNG_INTERPRETER_TYPE_S64:
ret = lttng_msgpack_write_signed_integer(writer, output->u.s);
switch (output->type) {
case LTTNG_INTERPRETER_TYPE_S64:
ret = lttng_msgpack_write_signed_integer(writer, output->u.s);
- if (ret) {
- WARN_ON_ONCE(1);
- goto end;
- }
break;
case LTTNG_INTERPRETER_TYPE_U64:
ret = lttng_msgpack_write_unsigned_integer(writer, output->u.u);
break;
case LTTNG_INTERPRETER_TYPE_U64:
ret = lttng_msgpack_write_unsigned_integer(writer, output->u.u);
- if (ret) {
- WARN_ON_ONCE(1);
- goto end;
- }
break;
case LTTNG_INTERPRETER_TYPE_STRING:
if (output->u.str.user) {
break;
case LTTNG_INTERPRETER_TYPE_STRING:
if (output->u.str.user) {
} else {
ret = lttng_msgpack_write_str(writer, output->u.str.str);
}
} else {
ret = lttng_msgpack_write_str(writer, output->u.str.str);
}
- if (ret) {
- WARN_ON_ONCE(1);
- goto end;
- }
break;
case LTTNG_INTERPRETER_TYPE_SEQUENCE:
ret = capture_sequence(writer, output);
break;
case LTTNG_INTERPRETER_TYPE_SEQUENCE:
ret = capture_sequence(writer, output);
- if (ret) {
- WARN_ON_ONCE(1);
- goto end;
- }
break;
case LTTNG_INTERPRETER_TYPE_SIGNED_ENUM:
case LTTNG_INTERPRETER_TYPE_UNSIGNED_ENUM:
ret = capture_enum(writer, output);
break;
case LTTNG_INTERPRETER_TYPE_SIGNED_ENUM:
case LTTNG_INTERPRETER_TYPE_UNSIGNED_ENUM:
ret = capture_enum(writer, output);
- if (ret) {
- WARN_ON_ONCE(1);
- goto end;
- }
break;
default:
ret = -1;
break;
default:
ret = -1;
int notification_append_empty_capture(
struct lttng_event_notifier_notification *notif)
{
int notification_append_empty_capture(
struct lttng_event_notifier_notification *notif)
{
- int ret = lttng_msgpack_write_nil(¬if->writer);
- if (ret)
- WARN_ON_ONCE(1);
-
- return ret;
+ return lttng_msgpack_write_nil(¬if->writer);
ret = lttng_msgpack_begin_array(writer, event_notifier->priv->num_captures);
if (ret) {
ret = lttng_msgpack_begin_array(writer, event_notifier->priv->num_captures);
if (ret) {
struct lttng_kernel_notification_ctx *notif_ctx)
{
struct lttng_event_notifier_notification notif = { 0 };
struct lttng_kernel_notification_ctx *notif_ctx)
{
struct lttng_event_notifier_notification notif = { 0 };
if (unlikely(!READ_ONCE(event_notifier->parent.enabled)))
return;
if (unlikely(!READ_ONCE(event_notifier->parent.enabled)))
return;
- ret = notification_init(¬if, event_notifier);
- if (ret) {
- WARN_ON_ONCE(1);
+ if (notification_init(¬if, event_notifier)) {
+ record_error(event_notifier);
list_for_each_entry_rcu(capture_bc_runtime,
&event_notifier->priv->capture_bytecode_runtime_head, node) {
struct lttng_interpreter_output output;
list_for_each_entry_rcu(capture_bc_runtime,
&event_notifier->priv->capture_bytecode_runtime_head, node) {
struct lttng_interpreter_output output;
+ uint8_t *save_pos;
+ int ret;
+ lttng_msgpack_save_writer_pos(¬if.writer, &save_pos);
if (capture_bc_runtime->interpreter_func(capture_bc_runtime,
stack_data, probe_ctx, &output) == LTTNG_KERNEL_BYTECODE_INTERPRETER_OK)
ret = notification_append_capture(¬if, &output);
else
ret = notification_append_empty_capture(¬if);
if (capture_bc_runtime->interpreter_func(capture_bc_runtime,
stack_data, probe_ctx, &output) == LTTNG_KERNEL_BYTECODE_INTERPRETER_OK)
ret = notification_append_capture(¬if, &output);
else
ret = notification_append_empty_capture(¬if);
-
- if (ret)
- printk(KERN_WARNING "Error appending capture to notification");
+ if (ret) {
+ /*
+ * On append capture error, skip the field
+ * capture by restoring the msgpack writer
+ * position.
+ */
+ lttng_msgpack_restore_writer_pos(¬if.writer, save_pos);
+ }