greybus: operation: fix response-cancellation race
authorJohan Hovold <johan@hovoldconsulting.com>
Tue, 14 Jul 2015 13:43:34 +0000 (15:43 +0200)
committerGreg Kroah-Hartman <gregkh@google.com>
Wed, 15 Jul 2015 19:39:13 +0000 (12:39 -0700)
Make sure the request handler has submitted the response before
cancelling it during operation cancellation.

This prevents cancelling not-yet-submitted messages. It currently also
avoids us ending up with an active message on a stalled connection (e.g.
due to E2EFC).

Note that the call to gb_operation_result_set() is now redundant but is
kept as a precaution to guarantee that a response has indeed been
allocated as part of response submission.

Signed-off-by: Johan Hovold <johan@hovoldconsulting.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
drivers/staging/greybus/operation.c

index f7b0aa970bbcdd70e3182516f8b43e6ee3515c09..0576f197f58e9fd99d4d95b5e6a6c1d3570b32c0 100644 (file)
@@ -928,10 +928,14 @@ void gb_connection_recv(struct gb_connection *connection,
 void gb_operation_cancel(struct gb_operation *operation, int errno)
 {
        if (gb_operation_is_incoming(operation)) {
-               /* Cancel response if it has been allocated */
-               if (!gb_operation_result_set(operation, errno) &&
-                               !gb_operation_is_unidirectional(operation)) {
-                       gb_message_cancel(operation->response);
+               if (!gb_operation_is_unidirectional(operation)) {
+                       /*
+                        * Make sure the request handler has submitted the
+                        * response before cancelling it.
+                        */
+                       flush_work(&operation->work);
+                       if (!gb_operation_result_set(operation, errno))
+                               gb_message_cancel(operation->response);
                }
        } else {
                if (gb_operation_result_set(operation, errno)) {