Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (Brite)
  • No Skin
Collapse

Linux Kernel Meet

Z

zerohexer

@zerohexer
About
Posts
1
Topics
0
Shares
0
Groups
0
Followers
0
Following
0

Posts

Recent Best Controversial

  • Question about retry logic in usb-skeleton.c skel_read()
    Z zerohexer

    Hi, The behavior is intentional, not inconsistent.

    Looking at the actual source code, the driver handles three cases differently:

    1. No data at all → goto retry (must wait, can't return 0 which means EOF)
    2. Buffer exhausted → goto retry (same reason)
    3. Some data available → return it immediately, prefetch the rest

    Why no goto retry in case 3?

    • Returning 0 from read() signals EOF to userspace
    • When there's no data, the driver must wait—otherwise it would falsely indicate EOF
    • When there is data, returning a short read is standard POSIX behavior
    • The prefetch (skel_do_read_io) is an optimization for the next read call

    Standard Unix read() semantics:

    • read() may return fewer bytes than requested—this is normal
    • Userspace is expected to loop if it needs exactly N bytes
    • This applies to sockets, pipes, and character devices alike

    Adding goto retry would work but would change the driver from "return data as soon as available" to "block until buffer is full"—which increases latency unnecessarily.

    Because it would need to wait for full buffer.

    //Userspace is expected to handle short reads:
    
      // Standard pattern - userspace loops, not the driver
      ssize_t read_full(int fd, void *buf, size_t count)
      {
          size_t total = 0;
          while (total < count) {
              ssize_t ret = read(fd, buf + total, count - total);
              if (ret < 0)  return ret;   // error
              if (ret == 0) break;        // EOF
              total += ret;
          }
          return total;
      }
    
    
    The problem:
    
     User calls: read(fd, buf, 100)
     Buffer has: 30 bytes
    
      First iteration:
        - Copy 30 bytes to buf[0..29]
        - rv = 30
        - goto retry...
    
      Second iteration (after new data arrives):
        - Copy to 'buffer' again (buf[0..??])  ← OVERWRITES first 30 bytes!
        - rv = new_chunk                        ← loses the original 30
    
      The userspace buffer pointer is never advanced. So goto retry would overwrite data already copied.
     
      copy_to_user(buffer, ...);  // First copy: buf[0]
      goto retry;
      copy_to_user(buffer, ...);  // Second copy: buf[0] again! Data corrupted.
    

    Even if you fixed the buffer pointer issue (by advancing it on each iteration), the modified behavior would still be undesirable because it changes the driver's semantics from "return data as available" to "block until full"

    General Discussion
  • Login

  • Don't have an account? Register

  • Login or register to search.
Powered by NodeBB Contributors
  • First post
    Last post
0
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups