[PATCH] backing a little bit out of Rik v. riel's vm

From: Frank Dekervel (Frank.dekervel@student.kuleuven.ac.be)
Date: Fri Sep 22 2000 - 19:39:43 EDT

  • Next message: Vitaly Luban: "Re: cPCI development"

    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);

    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    Please read the FAQ at http://www.tux.org/lkml/



    This archive was generated by hypermail 2b29 : Fri Sep 22 2000 - 19:41:56 EDT