| Kernel v2.4.12-ac3 /mm/highmem.c |
|---|
 2.4.12-ac3
 mm
 highmem.c
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/mm/highmem.c linux.ac/mm/highmem.c
--- linux.vanilla/mm/highmem.c Tue Sep 18 22:10:43 2001
+++ linux.ac/mm/highmem.c Wed Oct 10 01:48:38 2001
@@ -46,7 +46,7 @@
for (i = 0; i < LAST_PKMAP; i++) {
struct page *page;
-
+ pte_t pte;
/*
* zero means we don't have anything to do,
* >1 means that it is still in use. Only
@@ -56,21 +56,10 @@
if (pkmap_count[i] != 1)
continue;
pkmap_count[i] = 0;
-
- /* sanity check */
- if (pte_none(pkmap_page_table[i]))
+ pte = ptep_get_and_clear(pkmap_page_table+i);
+ if (pte_none(pte))
BUG();
-
- /*
- * Don't need an atomic fetch-and-clear op here;
- * no-one has the page mapped, and cannot get at
- * its virtual address (and hence PTE) without first
- * getting the kmap_lock (which is held here).
- * So no dangers, even with speculative execution.
- */
- page = pte_page(pkmap_page_table[i]);
- pte_clear(&pkmap_page_table[i]);
-
+ page = pte_page(pte);
page->virtual = NULL;
}
flush_tlb_all();
@@ -150,7 +139,6 @@
{
unsigned long vaddr;
unsigned long nr;
- int need_wakeup;
spin_lock(&kmap_lock);
vaddr = (unsigned long) page->virtual;
@@ -162,28 +150,13 @@
* A count must never go down to zero
* without a TLB flush!
*/
- need_wakeup = 0;
switch (--pkmap_count[nr]) {
case 0:
BUG();
case 1:
- /*
- * Avoid an unnecessary wake_up() function call.
- * The common case is pkmap_count[] == 1, but
- * no waiters.
- * The tasks queued in the wait-queue are guarded
- * by both the lock in the wait-queue-head and by
- * the kmap_lock. As the kmap_lock is held here,
- * no need for the wait-queue-head's lock. Simply
- * test if the queue is empty.
- */
- need_wakeup = waitqueue_active(&pkmap_map_wait);
+ wake_up(&pkmap_map_wait);
}
spin_unlock(&kmap_lock);
-
- /* do wake-up, if needed, race-free outside of the spin lock */
- if (need_wakeup)
- wake_up(&pkmap_map_wait);
}
#define POOL_SIZE 32
@@ -209,12 +182,20 @@
{
struct page *p_from;
char *vfrom;
+ unsigned long flags;
p_from = from->b_page;
- vfrom = kmap_atomic(p_from, KM_USER0);
+ /*
+ * Since this can be executed from IRQ context, reentrance
+ * on the same CPU must be avoided:
+ */
+ __save_flags(flags);
+ __cli();
+ vfrom = kmap_atomic(p_from, KM_BOUNCE_WRITE);
memcpy(to->b_data, vfrom + bh_offset(from), to->b_size);
- kunmap_atomic(vfrom, KM_USER0);
+ kunmap_atomic(vfrom, KM_BOUNCE_WRITE);
+ __restore_flags(flags);
}
static inline void copy_to_high_bh_irq (struct buffer_head *to,
@@ -328,14 +309,14 @@
struct page *page;
repeat_alloc:
- page = alloc_page(GFP_NOHIGHIO);
+ page = alloc_page(GFP_NOIO);
if (page)
return page;
/*
* No luck. First, kick the VM so it doesnt idle around while
* we are using up our emergency rations.
*/
- wakeup_bdflush();
+ wakeup_bdflush(0);
/*
* Try to allocate from the emergency pool.
@@ -366,14 +347,14 @@
struct buffer_head *bh;
repeat_alloc:
- bh = kmem_cache_alloc(bh_cachep, SLAB_NOHIGHIO);
+ bh = kmem_cache_alloc(bh_cachep, SLAB_NOIO);
if (bh)
return bh;
/*
* No luck. First, kick the VM so it doesnt idle around while
* we are using up our emergency rations.
*/
- wakeup_bdflush();
+ wakeup_bdflush(0);
/*
* Try to allocate from the emergency pool.
|