LWN.net Logo

A new way of block queue plugging

Jens Axboe has posted a patch which, once again, changes some of the main assumptions underlying the block I/O subsystem. It is worth a look at what is going on.

A longstanding feature of the block layer has been "queue plugging." If the request queue for a particular block device has been plugged, that device's driver will not be invoked to execute the operations in the queue. The main reason for plugging has been to allow the block layer to build up a backlog of requests, so that adjacent operations can be merged. By sometimes waiting a little longer to start an operation, the block layer can often achieve better performance overall.

With the 2.5 block layer, however, there is less need for this sort of plugging. The code works harder at not splitting large requests in the first place, so it is not necessary to merge them again. The new plugging code actually serves a different purpose: it is a mechanism by which a block driver can indicate that it is busy and can not handle any more requests at the moment.

As Jens points out in his patch, the block code is starting to look a little (a little!) bit more like the networking subsystem. Like network interfaces, block devices can have multiple requests outstanding. When the device has been given all the simultaneous requests that it can handle, there is no point in further troubling the driver until some of those requests complete. Thus the new plugging code: block devices, too, can ask to be allowed to work in peace for a while.

There's a couple of other, incidental changes in this patch. One is that the venerable tq_disk task queue has been removed. Slowly, the set of standard task queues is shrinking. A block driver's request ("strategy") function is also now called out of a tasklet. The block layer that shows up in 2.6 will be vastly different from what has been seen in previous stable kernels.


(Log in to post comments)

strategy call context

Posted Jun 6, 2002 17:18 UTC (Thu) by axboe (subscriber, #904) [Link]

Some minor changes have been made to the plugging mechanism since the original patch was posted, and one of them was to move the call of the request_fn back into process context. There are basically two reasons for doing that -- the first is that request_fn can take a significant time which we don't want to do inside what is essentially a soft interrupt. The second is that while sleeping/blocking inside the request_fn is generally discouraged [1], it still does happen in some drivers. This is illegal inside tasklet context.

Internally, the block layer now simply provides its own simple task queue mechanism for controlling unplugging.

[1] What used to be run_task_queue(&tq_disk) and is now blk_run_queues(), the calling of request_fn's is serialized. So one blocking request_fn will stall the execution of other pending plugs.

Copyright © 2002, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds