diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-05-07 02:55:41 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-05-07 02:55:41 +0000 |
commit | dcec8a13bf565e47942a1751a9cec21bec5648fe (patch) | |
tree | 548b69625b18cc2e88c3e68d0923be546c9ebb03 /mm/page_io.c | |
parent | 2e0f55e79c49509b7ff70ff1a10e1e9e90a3dfd4 (diff) |
o Merge with Linux 2.1.99.
o Fix ancient bug in the ELF loader making ldd crash.
o Fix ancient bug in the keyboard code for SGI, SNI and Jazz.
Diffstat (limited to 'mm/page_io.c')
-rw-r--r-- | mm/page_io.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/mm/page_io.c b/mm/page_io.c index e02565def..eb436f7b7 100644 --- a/mm/page_io.c +++ b/mm/page_io.c @@ -28,6 +28,8 @@ #include <asm/bitops.h> #include <asm/pgtable.h> +static struct wait_queue * lock_queue = NULL; + /* * Reads or writes a swap page. * wait=1: start I/O and wait for completion. wait=0: start asynchronous I/O. @@ -87,6 +89,12 @@ void rw_swap_page(int rw, unsigned long entry, char * buf, int wait) return; } + /* Make sure we are the only process doing I/O with this swap page. */ + while (test_and_set_bit(offset,p->swap_lockmap)) { + run_task_queue(&tq_disk); + sleep_on(&lock_queue); + } + if (rw == READ) { clear_bit(PG_uptodate, &page->flags); kstat.pswpin++; @@ -115,6 +123,7 @@ void rw_swap_page(int rw, unsigned long entry, char * buf, int wait) if (!wait) { set_bit(PG_free_after, &page->flags); set_bit(PG_decr_after, &page->flags); + set_bit(PG_swap_unlock_after, &page->flags); atomic_inc(&nr_async_pages); } ll_rw_page(rw,p->swap_device,offset,buf); @@ -173,6 +182,9 @@ void rw_swap_page(int rw, unsigned long entry, char * buf, int wait) printk("rw_swap_page: no swap file or device\n"); atomic_dec(&page->count); + if (offset && !test_and_clear_bit(offset,p->swap_lockmap)) + printk("rw_swap_page: lock already cleared\n"); + wake_up(&lock_queue); #ifdef DEBUG_SWAP printk ("DebugVM: %s_swap_page finished on page %p (count %d)\n", (rw == READ) ? "read" : "write", @@ -180,6 +192,28 @@ void rw_swap_page(int rw, unsigned long entry, char * buf, int wait) #endif } +/* This is run when asynchronous page I/O has completed. */ +void swap_after_unlock_page (unsigned long entry) +{ + unsigned long type, offset; + struct swap_info_struct * p; + + type = SWP_TYPE(entry); + if (type >= nr_swapfiles) { + printk("swap_after_unlock_page: bad swap-device\n"); + return; + } + p = &swap_info[type]; + offset = SWP_OFFSET(entry); + if (offset >= p->max) { + printk("swap_after_unlock_page: weirdness\n"); + return; + } + if (!test_and_clear_bit(offset,p->swap_lockmap)) + printk("swap_after_unlock_page: lock already cleared\n"); + wake_up(&lock_queue); +} + /* * Setting up a new swap file needs a simple wrapper just to read the * swap signature. SysV shared memory also needs a simple wrapper. |