]> www.infradead.org Git - users/hch/misc.git/commitdiff
firewire: core: call handler for exclusive regions outside RCU read-side critical...
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>
Sun, 3 Aug 2025 12:20:13 +0000 (21:20 +0900)
committerTakashi Sakamoto <o-takashi@sakamocchi.jp>
Sun, 3 Aug 2025 12:20:13 +0000 (21:20 +0900)
The previous commit added reference counting to ensure safe invocations of
address handlers.

This commit moves the invocation of handlers for exclusive regions outside
of the RCU read-side critical section. The address handler for the
requested region is selected within the critical section, then invoked
outside of it.

Link: https://lore.kernel.org/r/20250803122015.236493-3-o-takashi@sakamocchi.jp
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
drivers/firewire/core-transaction.c

index 29ca9f3f14ceb048d3aa4b822512b8f8c87cf3c4..a742971c65fa6d0b25b634733749843ac2e0736b 100644 (file)
@@ -935,17 +935,19 @@ static void handle_exclusive_region_request(struct fw_card *card,
        scoped_guard(rcu) {
                handler = lookup_enclosing_address_handler(&address_handler_list, offset,
                                                           request->length);
-               if (handler) {
+               if (handler)
                        get_address_handler(handler);
-                       handler->address_callback(card, request, tcode, destination, source,
-                                                 p->generation, offset, request->data,
-                                                 request->length, handler->callback_data);
-                       put_address_handler(handler);
-               }
        }
 
-       if (!handler)
+       if (!handler) {
                fw_send_response(card, request, RCODE_ADDRESS_ERROR);
+               return;
+       }
+
+       // Outside the RCU read-side critical section. Without spinlock. With reference count.
+       handler->address_callback(card, request, tcode, destination, source, p->generation, offset,
+                                 request->data, request->length, handler->callback_data);
+       put_address_handler(handler);
 }
 
 static void handle_fcp_region_request(struct fw_card *card,