Re: [PATCH RFC] ib_uverbs: atomically flush and mark closed the comp event queue

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Sep 10, 2018 at 02:24:03PM -0500, Steve Wise wrote:
> 
> 
> On 9/1/2018 3:45 PM, Jason Gunthorpe wrote:
> > On Fri, Aug 31, 2018 at 07:16:03AM -0700, Steve Wise wrote:
> >> Currently a uverbs completion event queue is flushed of events in
> >> ib_uverbs_comp_event_close() with the queue spinlock held and then
> >> released.  Yet setting ev_queue->is_closed is not set until later in
> >> uverbs_hot_unplug_completion_event_file().
> >>
> >> In between the time ib_uverbs_comp_event_close() releases the lock
> >> and uverbs_hot_unplug_completion_event_file() acquires the lock, a
> >> completion event can arrive and be inserted into the event queue by
> >> ib_uverbs_comp_handler().
> >>
> >> This can cause a "double add" list_add warning or crash depending on
> >> the kernel configuration, or a memory leak because the event is never
> >> dequeued since the queue is already closed down.
> >>
> >> So move the setting of ev_queue->is_closed to
> >> ib_uverbs_comp_event_close().
> >>
> >> Cc: stable@xxxxxxxxxxxxxxx
> >> Fixes: 1e7710f3f656 ("IB/core: Change completion channel to use the reworked objects schema")
> >> Signed-off-by: Steve Wise <swise@xxxxxxxxxxxxxxxxxxxxx>
> >>
> >> I added the RFC tag because I'm not sure removing setting
> >> is_closed in uverbs_hot_unplug_completion_event_file() is correct.
> >> Can uverbs_hot_unplug_completion_event_file() be called w/o
> >> ib_uverbs_comp_event_close() being called first?  Should is_closed be
> >> set in both places?
> >>
> >>  drivers/infiniband/core/uverbs_main.c      | 1 +
> >>  drivers/infiniband/core/uverbs_std_types.c | 4 ----
> >>  2 files changed, 1 insertion(+), 4 deletions(-)
> >>
> >> diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
> >> index 823beca448e1..b3ef7db68bde 100644
> >> +++ b/drivers/infiniband/core/uverbs_main.c
> >> @@ -440,6 +440,7 @@ static int ib_uverbs_comp_event_close(struct inode *inode, struct file *filp)
> >>  			list_del(&entry->obj_list);
> >>  		kfree(entry);
> >>  	}
> >> +	file->ev_queue.is_closed = 1;
> >>  	spin_unlock_irq(&file->ev_queue.lock);
> > 
> > Since event_close is essentially the release function of a kref, it is
> > definately wrong to set is_closed here, as there can be nothing to
> > read it.
> 
> Hey Jason,
> 
> Question:  Why is there similar logic in ib_uverbs_async_event_close()
> to set ev_queue.is_closed for the async ev_queue?:

Presumably because those functions use a different refcounting scheme
for their event queue..

Oh, but they don't! ib_uverbs_lookup_comp_file() drops the kref on the
file * and just retains on the uobject! Why!? 

That creates the possibility of a half destructed uobject!!

Everytime I look at this stuff I end up in tears :P

So, yes, it does look helpfull to move the is_closed like this..

But better would be to just not have something so insane in the first
place :(

Jason



[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux