On Mon, 17 May 2004, Oliver Neukum wrote:

> Am Montag, 17. Mai 2004 18:56 schrieb Greg KH:
> > On Mon, May 17, 2004 at 12:41:42PM -0400, Alan Stern wrote:
> > > +void usb_kill_urb(struct urb *urb)
> > > +{
> > > + if (!(urb->dev && urb->dev->bus && urb->dev->bus->op))
> > > +         return;
> > > + urb->reject = 1;
> > > + urb->dev->bus->op->unlink_urb(urb, -ENOENT);
> > > + wait_event(usb_kill_urb_queue, atomic_read(&urb->kref.refcount) <= 1);
> > > + urb->reject = 0;
> > >  }
> > 
> > Heh, no, you can't just sit and spin on the refcount, because that will
> > not work if I do:
> >     usb_free_urb(urb);
> >     usb_kill_urb(urb);
> 
> Arguably you must not kill what you've freed, as you have no reference.
> 
> > And that last urb->reject = 0 will oops if I do that :)
> > (and yes, some drivers do that already today with a call to
> > usb_submit_urb() followed by a call to usb_free_urb().)

I agree with Oliver here.  Once you've freed the URB, you have no business 
trying to do anything with the pointer.  I trust that the drivers today do 
_not_ do usb_free_urb() followed by usb_unlink_urb() -- that could oops 
almost as easily as your example.

> > Or what if I do:
> >     usb_get_urb(urb);
> >     usb_get_urb(urb);
> >     usb_get_urb(urb);
> >     usb_kill_urb(urb);
> > which will cause this function to deadlock.

Yes, and that is mentioned in the kerneldoc at the start of
usb_kill_urb(). I did a quick search through all the USB drivers, and
_none_ of them call usb_get_urb().  Only the core uses that function.  So
for now there isn't a problem.

> > You need to grab a reference to the urb at the beginning of the call,
> > and decrement it at the end of it.  But in the middle there, you can't
> > count on a paticular refcount value, so you will have to trigger off of
> > something else.
> 
> Right. However, you need a _submission_ counter only if giveback_urb()
> can be reentered. If we are ready to ban resubmission to another device
> in completion handlers, a single bit will do.

If the two of you feel strongly that the existing reference counter 
shouldn't be used, I will change it.  The new counter and the new "reject" 
field could easily fit into two shorts.

> Alan wrote:
> >You are right.  There's no choice but to add another field for the Reject 
> >flag.
> 
> But there is. Use urb->lock to protect transfer_flags.

You mean, require every completion handler to do that.  I would prefer to
add a new field.  And whether this means adding 2 shorts or 2 bits doesn't
matter much, because _any_ addition will cause the structure to grow by a
minimum of 4 bytes (on x86).

Alan Stern



-------------------------------------------------------
This SF.Net email is sponsored by: SourceForge.net Broadband
Sign-up now for SourceForge Broadband and get the fastest
6.0/768 connection for only $19.95/mo for the first 3 months!
http://ads.osdn.com/?ad_id=2562&alloc_id=6184&op=click
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to