Fix: kernel consumer: get next subbuffer EAGAIN handling
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Fri, 30 Apr 2021 16:02:47 +0000 (12:02 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Fri, 30 Apr 2021 23:07:03 +0000 (19:07 -0400)
The caller of get next subbuffer (data and metadata) callbacks only
expects -ENODATA when there is no data to read. However, the kernel
tracer distinguishes between no data for a finalized stream (-ENODATA)
and no data for a non-finalized stream (-EAGAIN).

Given that the consumer daemon uses the POLLHUP returned by epoll to
detect stream end of life, it does not care about the distinction
between -EAGAIN and -ENODATA when streaming.

However, taking a snapshot of a metadata stream uses the distinction
between nodata and again. Change this so it considers a return value of
0 from lttng_consumer_read_subbuffer to mean there is no more data to
read, so we can combine -EAGAIN and -ENODATA within get next subbuffer
callbacks and return -ENODATA for both.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
Change-Id: I30786985c2389570dd342e55d4faf7c552532f8b

src/common/kernel-consumer/kernel-consumer.c

index 46a9f52c0ac2406787f2743213da3380b2a503d4..5464822aaa58678377869a30d7c8bd9dbae1c6ba 100644 (file)
@@ -403,16 +403,12 @@ static int lttng_kconsumer_snapshot_metadata(
 
                ret_read = lttng_consumer_read_subbuffer(metadata_stream, ctx, true);
                if (ret_read < 0) {
-                       if (ret_read != -EAGAIN) {
-                               ERR("Kernel snapshot reading metadata subbuffer (ret: %zd)",
-                                               ret_read);
-                               ret = ret_read;
-                               goto error_snapshot;
-                       }
-                       /* ret_read is negative at this point so we will exit the loop. */
-                       continue;
+                       ERR("Kernel snapshot reading metadata subbuffer (ret: %zd)",
+                                       ret_read);
+                       ret = ret_read;
+                       goto error_snapshot;
                }
-       } while (ret_read >= 0);
+       } while (ret_read > 0);
 
        if (use_relayd) {
                close_relayd_stream(metadata_stream);
@@ -1594,6 +1590,17 @@ int get_subbuffer_common(struct lttng_consumer_stream *stream,
 
        ret = kernctl_get_next_subbuf(stream->wait_fd);
        if (ret) {
+               /*
+                * The caller only expects -ENODATA when there is no data to
+                * read, but the kernel tracer returns -EAGAIN when there is
+                * currently no data for a non-finalized stream, and -ENODATA
+                * when there is no data for a finalized stream. Those can be
+                * combined into a -ENODATA return value.
+                */
+               if (ret == -EAGAIN) {
+                       ret = -ENODATA;
+               }
+
                goto end;
        }
 
@@ -1675,6 +1682,16 @@ int get_next_subbuffer_metadata_check(struct lttng_consumer_stream *stream,
                        subbuffer->info.metadata.padded_subbuf_size,
                        coherent ? "true" : "false");
 end:
+       /*
+        * The caller only expects -ENODATA when there is no data to read, but
+        * the kernel tracer returns -EAGAIN when there is currently no data
+        * for a non-finalized stream, and -ENODATA when there is no data for a
+        * finalized stream. Those can be combined into a -ENODATA return value.
+        */
+       if (ret == -EAGAIN) {
+               ret = -ENODATA;
+       }
+
        return ret;
 }
 
This page took 0.02689 seconds and 4 git commands to generate.