Re: [RFC][PATCH v2 20/31] timers: usb: Use del_timer_shutdown() before freeing timer

From: Steven Rostedt
Date: Fri Oct 28 2022 - 10:00:48 EST


On Fri, 28 Oct 2022 06:14:22 -0400
Steven Rostedt <rostedt@xxxxxxxxxxx> wrote:

> On Thu, 27 Oct 2022 22:23:06 -0700
> Guenter Roeck <linux@xxxxxxxxxxxx> wrote:
>
> > A similar call to INIT_DELAYED_WORK() around line 1085 needs the same change.
> >
> > It would be great if that can somehow be hidden in INIT_DELAYED_WORK().
>
> I agree, but the delayed work is such a special case, I'm struggling to
> find something that works sensibly. :-/
>

OK, I diagnosed the issue here. The problem is that delayed work also has no
"shutdown" method when it's done. Which means there's no generic way to
call the work->timer shutdown method. So we have two options to handle
delayed work timers:

1) Add special initialization for delayed work so that it can just go back
to the old checking (activating on arming, deactivating by any
del_timer*).

2) Implement a shutdown state for the work queues as well. There could
definitely be the same types of bugs as with timers, where a delayed
work could be pending on something that's been freed. That's probably
why there's a DEBUG_OBJECTS_WORK too.

Ideally, I would like to have #2, but realistically, I'm going for #1 for
now. We could always add the work queue shutdown state later if we want.

The problem with timers with respect to delayed work queues, is that there's
no place to add the "shutdown" before its no longer in use. Worse yet,
there's code that caches descriptors that have delayed work instead of
freeing them. (See block/blk-mq.c and drivers/scsi/scsi_lib.c with the queuelist).
Where it just calls del_timer(), and then sends it back to the free store
for reuse later. Perhaps we should add DEBUG_OBJECTS checking to these too?

Anyway, I'll make it where the INIT_DELAYED_WORK will call
__timer_init_work() that will set the debug state in the timer to
TIMER_DEBUG_WORK, were it will activate and deactivate the debug object on
add_timer() and del_timer() and hope that it's not one of the bugs we are
hitting :-/

-- Steve