diff options
| author | Andrew Morton <akpm@osdl.org> | 2004-04-12 00:15:51 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-04-12 00:15:51 -0700 |
| commit | 6d27f67bf6ee2b9ad0c8814118264bc273d916a1 (patch) | |
| tree | 061ebd5a38b7ba938bae27c66ff574d90764a7c3 /kernel | |
| parent | 3749bf2c1fb31ffd3f95b9843890a7132fa06c06 (diff) | |
[PATCH] per-backing dev unplugging
From: Jens Axboe <axboe@suse.de>,
Chris Mason,
me, others.
The global unplug list causes horrid spinlock contention on many-disk
many-CPU setups - throughput is worse than halved.
The other problem with the global unplugging is of course that it will cause
the unplugging of queues which are unrelated to the I/O upon which the caller
is about to wait.
So what we do to solve these problems is to remove the global unplug and set
up the infrastructure under which the VFS can tell the block layer to unplug
only those queues which are relevant to the page or buffer_head whcih is
about to be waited upon.
We do this via the very appropriate address_space->backing_dev_info structure.
Most of the complexity is in devicemapper, MD and swapper_space, because for
these backing devices, multiple queues may need to be unplugged to complete a
page/buffer I/O. In each case we ensure that data structures are in place to
permit us to identify all the lower-level queues which contribute to the
higher-level backing_dev_info. Each contributing queue is told to unplug in
response to a higher-level unplug.
To simplify things in various places we also introduce the concept of a
"synchronous BIO": it is tagged with BIO_RW_SYNC. The block layer will
perform an immediate unplug when it sees one of these go past.
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/power/disk.c | 1 | ||||
| -rw-r--r-- | kernel/power/pmdisk.c | 3 | ||||
| -rw-r--r-- | kernel/power/swsusp.c | 5 |
3 files changed, 1 insertions, 8 deletions
diff --git a/kernel/power/disk.c b/kernel/power/disk.c index 7e035a9b42d1..6abcf99b7ada 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c @@ -84,7 +84,6 @@ static void free_some_memory(void) while (shrink_all_memory(10000)) printk("."); printk("|\n"); - blk_run_queues(); } diff --git a/kernel/power/pmdisk.c b/kernel/power/pmdisk.c index d54147214bea..22855abbdd6e 100644 --- a/kernel/power/pmdisk.c +++ b/kernel/power/pmdisk.c @@ -859,7 +859,6 @@ static int end_io(struct bio * bio, unsigned int num, int err) static void wait_io(void) { - blk_run_queues(); while(atomic_read(&io_done)) io_schedule(); } @@ -898,7 +897,7 @@ static int submit(int rw, pgoff_t page_off, void * page) if (rw == WRITE) bio_set_pages_dirty(bio); start_io(); - submit_bio(rw,bio); + submit_bio(rw | (1 << BIO_RW_SYNC), bio); wait_io(); Done: bio_put(bio); diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index 20134ab8e0b2..ae748a467af5 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c @@ -707,11 +707,6 @@ int software_suspend(void) free_some_memory(); - /* No need to invalidate any vfsmnt list -- - * they will be valid after resume, anyway. - */ - blk_run_queues(); - /* Save state of all device drivers, and stop them. */ if ((res = device_suspend(4))==0) /* If stopping device drivers worked, we proceed basically into |
