On Sun, 28 Jan 2001, Marcelo Tosatti wrote:
> > 
> > This is the smoking gun here, I bet, but I'd like to make sure I see the
> > whole thing. I don't see _why_ we'd have deadlocked on __wait_on_page(),
> > but I think this is the thread that hangs on to the mm semaphore.
> 
> I was able to reproduce it here with dbench. 
> 
> Nothing is locked except this dbench thread (the only dbench thread):
> 
> dbench    D C1C9FE64  5200  1013      1        (L-TLB)    1370   785 
> Call Trace: [___wait_on_page+130/160] [truncate_list_pages+100/404] 
>[truncate_inode_pages+93/128] [iput+162/360] [dput+262/356] [fput+121/232] 
>[exit_mmap+218/292]  
> [mmput+56/80] [do_exit+208/680] [do_signal+566/656] [dput+25/356] 
>[path_release+13/60] [sys_newstat+100/112] [sys_read+188/196] [signal_return+20/24]  

Ok, this definitely seems to be the pattern.

I don't see _what_ is going on, though.

I know of one "known bug" in pre10: if you run out of swap-space with
shared memory segments, it will do the wrong thing (return 1 without
unlocking the page). xmms might trigger this, but I didn't think that
dbench used shared memory?

There's also an ugliness in the truncate ordering. I don't think it should
matter, but I do believe it's conceptually wrong as-is.

Does this patch make any difference at all?

                Linus

-----
diff -u --recursive --new-file pre10/linux/mm/memory.c linux/mm/memory.c
--- pre10/linux/mm/memory.c     Sat Jan 27 10:53:39 2001
+++ linux/mm/memory.c   Sat Jan 27 19:12:35 2001
@@ -945,7 +945,6 @@
        if (inode->i_size < offset)
                goto do_expand;
        inode->i_size = offset;
-       truncate_inode_pages(mapping, offset);
        spin_lock(&mapping->i_shared_lock);
        if (!mapping->i_mmap && !mapping->i_mmap_shared)
                goto out_unlock;
@@ -960,8 +959,7 @@
 
 out_unlock:
        spin_unlock(&mapping->i_shared_lock);
-       /* this should go into ->truncate */
-       inode->i_size = offset;
+       truncate_inode_pages(mapping, offset);
        if (inode->i_op && inode->i_op->truncate)
                inode->i_op->truncate(inode);
        return;
diff -u --recursive --new-file pre10/linux/mm/shmem.c linux/mm/shmem.c
--- pre10/linux/mm/shmem.c      Sat Jan 27 10:53:39 2001
+++ linux/mm/shmem.c    Sat Jan 27 19:50:08 2001
@@ -217,8 +217,11 @@
 
        info = &page->mapping->host->u.shmem_i;
        swap = __get_swap_page(2);
-       if (!swap.val)
-               return 1;
+       if (!swap.val) {
+               set_page_dirty(page);
+               UnlockPage(page);
+               return -ENOMEM;
+       }
 
        spin_lock(&info->lock);
        shmem_recalc_inode(page->mapping->host);

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

Reply via email to