lkml.org 
[lkml]   [2000]   [Sep]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Hello,

since for me , the VM deadlocks were introduced only after
test8-rielvm2, i diff'd a bit between test8-rielvm2 and test9-pre5.
It gave me a little patch that made me run mmap002 without locking up,
so probably some people could use this little patch as a
temporarily fix for the recent VM-related deadlocks.
Maybe with a temp. fix we don't have to hurry that much , and people
ain't getting that nervous and might get a clue on the real bug.
The vm, now a bit older , still works really okay for me (much better
than 'old' 2.4 vm).
Please take in account i am a clueless non-kernel-hacker, and the patch
might contain some absurd things, i don't know.

I hope this helps a bit...

Greets,
Frank Dekervel

--- linux-t9p5/fs/buffer.c Sat Sep 23 00:32:55 2000
+++ linux-t8riel2/fs/buffer.c Sat Sep 23 00:35:04 2000
@@ -410,9 +410,8 @@
*/
#define _hashfn(dev,block) \
((((dev)<<(bh_hash_shift - 6)) ^ ((dev)<<(bh_hash_shift - 9))) ^ \
+ (((block)<<(bh_hash_shift - 6)) ^ ((block) >> 13) ^ ((block) << (bh_hash_shift - 12))))
+#define hash(dev,block) hash_table[(_hashfn(dev,block) & bh_hash_mask)]
- (((block)<<(bh_hash_shift - 6)) ^ ((block) >> 13) ^ \
- ((block) << (bh_hash_shift - 12))))
-#define hash(dev,block) hash_table[(_hashfn(HASHDEV(dev),block) & bh_hash_mask)]

static __inline__ void __hash_link(struct buffer_head *bh, struct buffer_head **head)
{
@@ -706,9 +705,9 @@
static void refill_freelist(int size)
{
if (!grow_buffers(size)) {
+ //wakeup_bdflush(1);
balance_dirty(NODEV);
+ wakeup_kswapd(1);
- wakeup_kswapd(0); /* We can't wait because of __GFP_IO */
- schedule();
}
}

@@ -864,14 +863,15 @@

dirty = size_buffers_type[BUF_DIRTY] >> PAGE_SHIFT;
tot = nr_free_buffer_pages();
+// tot -= size_buffers_type[BUF_PROTECTED] >> PAGE_SHIFT;

dirty *= 200;
soft_dirty_limit = tot * bdf_prm.b_un.nfract;
hard_dirty_limit = soft_dirty_limit * 2;

/* First, check for the "real" dirty limit. */
+ if (dirty > soft_dirty_limit || inactive_shortage()) {
+ if (dirty > hard_dirty_limit)
- if (dirty > soft_dirty_limit) {
- if (dirty > hard_dirty_limit || inactive_shortage())
return 1;
return 0;
}
@@ -1393,19 +1393,6 @@
}

/*
- * NOTE! All mapped/uptodate combinations are valid:
- *
- * Mapped Uptodate Meaning
- *
- * No No "unknown" - must do get_block()
- * No Yes "hole" - zero-filled
- * Yes No "allocated" - allocated on disk, not read in
- * Yes Yes "valid" - allocated and up-to-date in memory.
- *
- * "Dirty" is valid only with the last case (mapped+uptodate).
- */
-
-/*
* block_write_full_page() is SMP-safe - currently it's still
* being called with the kernel lock held, but the code is ready.
*/
@@ -1497,10 +1484,6 @@
goto out;
if (buffer_new(bh)) {
unmap_underlying_metadata(bh);
- if (Page_Uptodate(page)) {
- set_bit(BH_Uptodate, &bh->b_state);
- continue;
- }
if (block_end > to)
memset(kaddr+to, 0, block_end-to);
if (block_start < from)
@@ -1510,10 +1493,6 @@
continue;
}
}
- if (Page_Uptodate(page)) {
- set_bit(BH_Uptodate, &bh->b_state);
- continue;
- }
if (!buffer_uptodate(bh) &&
(block_start < from || block_end > to)) {
ll_rw_block(READ, 1, &bh);
@@ -1608,10 +1587,8 @@
continue;

if (!buffer_mapped(bh)) {
+ if (iblock < lblock)
+ get_block(inode, iblock, bh, 0);
- if (iblock < lblock) {
- if (get_block(inode, iblock, bh, 0))
- continue;
- }
if (!buffer_mapped(bh)) {
if (!kaddr)
kaddr = kmap(page);
@@ -1796,25 +1773,15 @@

err = 0;
if (!buffer_mapped(bh)) {
- /* Hole? Nothing to do */
- if (buffer_uptodate(bh))
- goto unlock;
get_block(inode, iblock, bh, 0);
- /* Still unmapped? Nothing to do */
if (!buffer_mapped(bh))
goto unlock;
}
-
- /* Ok, it's mapped. Make sure it's up-to-date */
- if (Page_Uptodate(page))
- set_bit(BH_Uptodate, &bh->b_state);
-
if (!buffer_uptodate(bh)) {
err = -EIO;
bh->b_end_io = end_buffer_io_sync;
ll_rw_block(READ, 1, &bh);
wait_on_buffer(bh);
- /* Uhhuh. Read error. Complain and punt. */
if (!buffer_uptodate(bh))
goto unlock;
}
@@ -2292,9 +2259,7 @@
{
struct buffer_head * tmp, * bh = page->buffers;
int index = BUFSIZE_INDEX(bh->b_size);
- int loop = 0;

-cleaned_buffers_try_again:
spin_lock(&lru_list_lock);
write_lock(&hash_table_lock);
spin_lock(&free_list[index].lock);
@@ -2340,14 +2305,8 @@
spin_unlock(&free_list[index].lock);
write_unlock(&hash_table_lock);
spin_unlock(&lru_list_lock);
+ if (wait)
- if (wait) {
sync_page_buffers(bh, wait);
- /* We waited synchronously, so we can free the buffers. */
- if (wait > 1 && !loop) {
- loop = 1;
- goto cleaned_buffers_try_again;
- }
- }
return 0;
}

--- linux-t9p5/fs/proc/proc_misc.c Sat Sep 23 00:32:55 2000
+++ linux-t8riel2/fs/proc/proc_misc.c Sat Sep 23 00:35:04 2000
@@ -160,10 +160,10 @@
"MemFree: %8lu kB\n"
"MemShared: %8lu kB\n"
"Buffers: %8lu kB\n"
+ "Cached: %8lu kB\n"
+ "Active: %8lu kB\n"
+ "Inact_dirty: %8lu kB\n"
+ "Inact_clean: %8lu kB\n"
- "Cached: %8u kB\n"
- "Active: %8u kB\n"
- "Inact_dirty: %8u kB\n"
- "Inact_clean: %8u kB\n"
"Inact_target: %8lu kB\n"
"HighTotal: %8lu kB\n"
"HighFree: %8lu kB\n"
@@ -336,14 +336,14 @@

for (major = 0; major < DK_MAX_MAJOR; major++) {
for (disk = 0; disk < DK_MAX_DISK; disk++) {
+ int active = kstat.dk_drive_rio[major][disk] +
- int active = kstat.dk_drive[major][disk] +
kstat.dk_drive_rblk[major][disk] +
+ kstat.dk_drive_wio[major][disk] +
kstat.dk_drive_wblk[major][disk];
if (active)
len += sprintf(page + len,
+ "(%u,%u):(%u,%u,%u,%u) ",
- "(%u,%u):(%u,%u,%u,%u,%u) ",
major, disk,
- kstat.dk_drive[major][disk],
kstat.dk_drive_rio[major][disk],
kstat.dk_drive_rblk[major][disk],
kstat.dk_drive_wio[major][disk],
--- linux-t9p5/mm/swap.c Sat Sep 23 00:32:59 2000
+++ linux-t8riel2/mm/swap.c Sat Sep 23 00:35:05 2000
@@ -161,19 +161,14 @@
* Don't touch it if it's not on the active list.
* (some pages aren't on any list at all)
*/
+ if (PageActive(page) && (page_count(page) == 1 || page->buffers) &&
- if (PageActive(page) && (page_count(page) <= 2 || page->buffers) &&
!page_ramdisk(page)) {

/*
* We can move the page to the inactive_dirty list
* if we know there is backing store available.
- *
- * We also move pages here that we cannot free yet,
- * but may be able to free later - because most likely
- * we're holding an extra reference on the page which
- * will be dropped right after deactivate_page().
*/
+ if (page->buffers) {
- if (page->buffers || page_count(page) == 2) {
del_page_from_active_list(page);
add_page_to_inactive_dirty_list(page);
/*
@@ -186,7 +181,8 @@
add_page_to_inactive_clean_list(page);
}
/*
+ * ELSE: no backing store available, leave it on
+ * the active list.
- * OK, we cannot free the page. Leave it alone.
*/
}
}
--- linux-t9p5/mm/vmscan.c Sat Sep 23 00:32:59 2000
+++ linux-t8riel2/mm/vmscan.c Sat Sep 23 00:35:05 2000
@@ -103,8 +103,8 @@
UnlockPage(page);
vma->vm_mm->rss--;
flush_tlb_page(vma, address);
+ page_cache_release(page);
deactivate_page(page);
- page_cache_release(page);
goto out_failed;
}

@@ -572,9 +572,6 @@
maxlaunder = 0;
cleaned_pages = 0;

- if (!(gfp_mask & __GFP_IO))
- return 0;
-
dirty_page_rescan:
spin_lock(&pagemap_lru_lock);
maxscan = nr_inactive_dirty_pages;
@@ -684,26 +681,19 @@
if (freed_page && !free_shortage())
break;
continue;
- } else if (page->mapping && !PageDirty(page)) {
- /*
- * If a page had an extra reference in
- * deactivate_page(), we will find it here.
- * Now the page is really freeable, so we
- * move it to the inactive_clean list.
- */
- UnlockPage(page);
- del_page_from_inactive_dirty_list(page);
- add_page_to_inactive_clean_list(page);
- cleaned_pages++;
} else {
/*
+ * Somebody else freed the bufferheads for us?
+ * This really shouldn't happen, but we check
+ * for it anyway.
- * OK, we don't know what to do with the page.
- * It's no use keeping it here, so we move it to
- * the active list.
*/
+ printk("VM: page_launder, found pre-cleaned page ?!\n");
UnlockPage(page);
+ if (page->mapping && !PageDirty(page)) {
+ del_page_from_inactive_dirty_list(page);
+ add_page_to_inactive_clean_list(page);
+ cleaned_pages++;
+ }
- del_page_from_inactive_dirty_list(page);
- add_page_to_active_list(page);
}
}
spin_unlock(&pagemap_lru_lock);
@@ -727,6 +717,8 @@
maxlaunder = MAX_LAUNDER;
/* Kflushd takes care of the rest. */
wakeup_bdflush(0);
+ current->policy |= SCHED_YIELD;
+ schedule();
goto dirty_page_rescan;
}

@@ -746,7 +738,7 @@
{
struct list_head * page_lru;
struct page * page;
+ int maxscan;
- int maxscan, page_active = 0;
int ret = 0;

/* Take the lock while messing with the list... */
@@ -766,17 +758,17 @@
/* Do aging on the pages. */
if (PageTestandClearReferenced(page)) {
age_page_up_nolock(page);
+ goto must_be_active;
- page_active = 1;
} else {
age_page_down_nolock(page);
- page_active = 0;
}
/*
* If the page is still on the active list, move it
* to the other end of the list. Otherwise it was
* deactivated by age_page_down and we exit successfully.
*/
+ if (PageActive(page)) {
+must_be_active:
- if (page_active || PageActive(page)) {
list_del(page_lru);
list_add(page_lru, &active_list);
} else {
@@ -873,8 +865,10 @@
do {
made_progress = 0;

+ if (!inactive_shortage() && !free_shortage())
+ goto done;
+
if (current->need_resched) {
- __set_current_state(TASK_RUNNING);
schedule();
}

@@ -920,14 +914,6 @@
}

/*
- * If we either have enough free memory, or if
- * page_launder() will be able to make enough
- * free memory, then stop.
- */
- if (!inactive_shortage() || !free_shortage())
- goto done;
-
- /*
* Only switch to a lower "priority" if we
* didn't make any useful progress in the
* last loop.
@@ -972,14 +958,10 @@
* the inode and dentry cache whenever we do this.
*/
if (free_shortage() || inactive_shortage()) {
+ ret += shrink_dcache_memory(6, gfp_mask);
+ ret += shrink_icache_memory(6, gfp_mask);
- if (gfp_mask & __GFP_IO) {
- ret += shrink_dcache_memory(6, gfp_mask);
- ret += shrink_icache_memory(6, gfp_mask);
- }

ret += refill_inactive(gfp_mask, user);
- } else {
- ret = 1;
}

return ret;
@@ -1077,7 +1059,8 @@
* We go to sleep for one second, but if it's needed
* we'll be woken up earlier...
*/
+ if (!free_shortage() ||
+ inactive_shortage() <= inactive_target / 3)
- if (!free_shortage() || !inactive_shortage())
interruptible_sleep_on_timeout(&kswapd_wait, HZ);
}
}
@@ -1090,8 +1073,7 @@
return;

if (!block) {
+ wake_up(&kswapd_wait);
- if (waitqueue_active(&kswapd_wait))
- wake_up(&kswapd_wait);
return;
}

@@ -1128,13 +1110,12 @@
*/
int try_to_free_pages(unsigned int gfp_mask)
{
- int ret = 1;
-
if (gfp_mask & __GFP_WAIT) {
+ balance_dirty(NODEV);
+ wakeup_kswapd(1);
- ret = do_try_to_free_pages(gfp_mask, 1);
}

+ return 1;
- return ret;
}

DECLARE_WAIT_QUEUE_HEAD(kreclaimd_wait);
\
 
 \ /
  Last update: 2005-03-22 12:39    [W:0.047 / U:0.492 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site