Hello,
I'm a computer science undergraduate student studying Linux kernel USB device drivers.
While analyzing the skel_read() function in usb-skeleton.c, I noticed what seems like inconsistent retry logic. I'd appreciate your insights.
Current Behavior Analysis
The skeleton code operates as follows:
retry:
if (dev->ongoing_read) {
// Check O_NONBLOCK and wait
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
wait_event_interruptible(dev->bulk_in_wait, (!dev->ongoing_read));
}
// Copy data
chunk = min(available, count);
copy_to_user(buffer, dev->bulk_in_buffer, chunk);
// When data is insufficient
if (available < count) {
usb_do_read_io(dev, count - chunk);
// No goto retry here!
}
return chunk;
The Inconsistency
On entry: Waits for ongoing_read (or returns -EAGAIN if O_NONBLOCK)
When data < count: Submits URB but returns immediately without waiting
These two behaviors seem inconsistent.
Proposed Modification
if (available < count) {
usb_do_read_io(dev, count - chunk);
goto retry; // <- Add this
}
This would:
- Handle O_NONBLOCK consistently at the retry label
- Attempt to fulfill the requested count in blocking I/O mode
- Allow signal interruption via
wait_event_interruptible
Questions
- Is the current behavior intentional, or is it simplified for educational purposes?
- Am I missing any negative side effects of adding
goto retry? - Is there a USB Bulk transfer characteristic that requires enforcing Short Reads?
I appreciate any advice. Thank you!