On Tue, Jan 08, 2019 at 01:07:16PM -0800, Darrick J. Wong wrote: > On Tue, Jan 08, 2019 at 03:54:23PM -0500, Jeff Moyer wrote: > > "Darrick J. Wong" <darrick.wong@xxxxxxxxxx> writes: > > > > > It looks like we're issuing two bios to satisfy a particular dio. > > > However, the first bio completes before the submitter calls finish_plug?? > > > > > > I guess this means that blk_start_plug no longer plugs up io requests, > > > which means that the end_io function tries to wake up the submitter > > > before it's even had a chance to issue the second bio. > > > > blk_start_plug was always a hint. If you exceed a certain number of > > requests (BLK_MAX_REQUEST_COUNT, which is 16) or a certain size of > > request (BLK_PLUG_FLUSH_SIZE, which is 128k), the block layer will flush > > the plug list. > > > > > This is surprising to me, because I was under the impression that > > > blk_{start,finish}_plug held all the bios so there was no chance that > > > any of them would issue (let alone call end_io) before finish_plug. > > > > Definitely not the case. The plug list is just a performance > > optimization. > > Ahh, fun! I had not realized that it was merely a suggestion. > > $ git grep blk_start_plug Documentation/ > $ echo $? > 1 > > In that case we definitely need something to prevent the endio from > trying to wake up a submitter that's still submitting. Below is the > amended patch I'm using to run generic/013 and generic/323 in a loop. > No crashes so far. Bloody ugly having to take /two/ submission context reference counts, but.... /me sees this in the block device dio path: if (!dio->multi_bio) { /* * AIO needs an extra reference to ensure the dio * structure which is embedded into the first bio * stays around. */ if (!is_sync) bio_get(bio); dio->multi_bio = true; atomic_set(&dio->ref, 2); } else { atomic_inc(&dio->ref); } This code was derived from the iomap direct IO code, but unlike the iomap code it takes two references to the first bio in the submission set and sets a flag to indicate there are multiple bios in the set. because the extra bio reference is not dropped until all the IO is completed, the struct dio is valid until everything is done and it is no longer being referenced. The other thing to note here is that "dio->ref" is actually an "io remaining" counter, and it is /pre-incremented/. That is, when we submit the first bio, the ref count is set to 2 so that if the IO completes before the second bio is submitted the count will not go to zero and the IO won't be completed. So, this is /quite different/ to the iomap code it was derived from. i.e. dio->ref is an IO counter, not a structure lifetime controller, and the struct dio lifetime is handled by a bio reference counter rather than an internal counter. That makes a bunch of stuff much simpler. OK, I'll rework the patch with this in mind.... Cheers, Dave. -- Dave Chinner david@xxxxxxxxxxxxx