Re: general protection fault in __queue_work (2)

From: Jens Axboe
Date: Sun Mar 08 2020 - 22:17:15 EST


On 3/8/20 8:09 PM, Hillf Danton wrote:
>
> On Sun, 8 Mar 2020 10:17:33 -0600 Jens Axboe wrote:
>> On 3/8/20 3:44 AM, Hillf Danton wrote:
>>> @@ -1208,8 +1211,16 @@ static int __loop_clr_fd(struct loop_dev
>>> *
>>> * 3) unlock, del_timer_sync so if timer raced it will be a no-op
>>> */
>>> - loop_unprepare_queue(lo);
>>> spin_lock_irq(&lo->lo_lock);
>>> + do {
>>> + struct workqueue_struct *wq = lo->workqueue;
>>> +
>>> + lo->workqueue = ERR_PTR(-EINVAL);
>>> + spin_unlock_irq(&lo->lo_lock);
>>> + destroy_workqueue(wq);
>>> + spin_lock_irq(&lo->lo_lock);
>>> + } while (0);
>>
>> This looks highly suspicious, what's the point of this loop?
>
> It is a while(0) loop that just gives me the chance for adding the
> transient local variable wq.

I think that adds more confusion than what is necessary, and I don't think
the approach is great to begin with as you now need various checks as well
for the workqueue pointer.

We're freezing the queue right after anyway, which will ensure that
nobody is going to hit an invalid workqueue pointer in terms of queueing.
This looks more like an ordering issue.

>> Also think this series a) might not be fully cooked, and b) really
>> should have gone through the block tree.
>
> Gavel in your hand, Sir.

Andrew, can you please drop this series so we can work out the kinks and
get it properly queued up after?

--
Jens Axboe