On Monday 10 December 2007 13:31, Jonathan Corbet wrote: > Hey, Daniel, > > I'm just getting around to looking at this. One thing jumped out at me: > > + if (bio->bi_throttle) { > > + struct request_queue *q = bio->bi_queue; > > + bio->bi_throttle = 0; /* or detect multiple endio and err? */ > > + atomic_add(bio->bi_throttle, &q->available); > > + wake_up(&q->throttle_wait); > > + } > > I'm feeling like I must be really dumb, but...how can that possibly > work? You're zeroing >bi_throttle before adding it back into > q->available, so the latter will never increase... Hi Jon, Don't you know? These days we optimize all our code for modern processors with tunnelling instructions and metaphysical cache. On such processors, setting a register to zero does not entirely destroy all the data that used to be in the register, so subsequent instructions can make further use of the overwritten data by reconstructing it from remnants of bits left attached to the edges of the register. Um, yeah, that's it. Actually, I fat-fingered it in the merge to -mm. Thanks for the catch, corrected patch attached. The offending line isn't even a functional part of the algorithm, it is just supposed to defend against the possibility that, somehow, ->bi_endio gets called multiple times. Probably it should really be something like: BUG_ON(bio->bi_throttle == -1); if (bio->bi_throttle) { ... bio->bi_throttle = -1; Or perhaps we should just rely on nobody ever making that mistake and let somebody else catch it if it does. Regards, Daniel