From: Mike Anderson Performance optimization for high contention of the q->queue_lock in dm_table_unplug_all under certain workloads. A OLTP type workload on a 16core Intel box using a volume containing 48 logical drives across 3 dual port fiber adapters showed some high oprofile values. A high oprofile sampling value was seen in dm_table_unplug_all coming from high contention of the q->queue_lock. Since dm_table_unplug_all will unplug all devices in the table it can cause contention on the queue_lock with processes trying to pull requests off the queue even on devices that are not plugged. As dm_table_unplug_all is coded now blk_unplug will result in the queue_lock being taken for all checks of the queue_flags +(blk_remove_plug). The change lead to a ~16 percent performance improvement on a Red Hat distro kernel. It appears to be a fairly safe change as the worst case if dm missed a queue to unplug, the queue will get unplugged when the number of requests exceed (unplug_thresh (4) or unplug_delay (3 ms). It can also be the case that if post getting the queue_lock and checking for the queue to be plugged that once the lock is dropped plugging can occur. [AGK: Some doubts have been expressed about this patch now - it can hit performance in some cases (stacking). A better solution is being sought.] Signed-off-by: Mike Anderson Signed-off-by: Alasdair G Kergon --- drivers/md/dm-table.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletion(-) Index: linux-2.6.25/drivers/md/dm-table.c =================================================================== --- linux-2.6.25.orig/drivers/md/dm-table.c 2008-04-18 12:40:15.000000000 +0100 +++ linux-2.6.25/drivers/md/dm-table.c 2008-04-18 12:40:20.000000000 +0100 @@ -974,7 +974,8 @@ void dm_table_unplug_all(struct dm_table list_for_each_entry(dd, devices, list) { struct request_queue *q = bdev_get_queue(dd->bdev); - blk_unplug(q); + if (blk_queue_plugged(q)) + blk_unplug(q); } }