Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=cb5f7b9a47963d9238398cd0c2676473e3c6896d
Commit:     cb5f7b9a47963d9238398cd0c2676473e3c6896d
Parent:     a0ee5ec520ede1dc8e2194623bcebfd9fab408f2
Author:     Hugh Dickins <[EMAIL PROTECTED]>
AuthorDate: Mon Feb 4 22:28:52 2008 -0800
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Tue Feb 5 09:44:15 2008 -0800

    tmpfs: make shmem_unuse more preemptible
    
    shmem_unuse is at present an unbroken search through every swap vector page 
of
    every tmpfs file which might be swapped, all under shmem_swaplist_lock.  
This
    dates from long ago, when the caller held mmlist_lock over it all too: long
    gone, but there's never been much pressure for preemptible swapoff.
    
    Make it a little more preemptible, replacing shmem_swaplist_lock by
    shmem_swaplist_mutex, inserting a cond_resched in the main loop, and a
    cond_resched_lock (on info->lock) at one convenient point in the
    shmem_unuse_inode loop, where it has no outstanding kmap_atomic.
    
    If we're serious about preemptible swapoff, there's much further to go e.g.
    I'm stupid to let the kmap_atomics of the decreasingly significant HIGHMEM
    case dictate preemptiblility for other configs.  But as in the earlier patch
    to make swapoff scan ptes preemptibly, my hidden agenda is really towards
    making memcgroups work, hardly about preemptibility at all.
    
    Signed-off-by: Hugh Dickins <[EMAIL PROTECTED]>
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 mm/shmem.c |   23 ++++++++++++++++-------
 1 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/mm/shmem.c b/mm/shmem.c
index c919ed5..2e03d60 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -193,7 +193,7 @@ static struct backing_dev_info shmem_backing_dev_info  
__read_mostly = {
 };
 
 static LIST_HEAD(shmem_swaplist);
-static DEFINE_SPINLOCK(shmem_swaplist_lock);
+static DEFINE_MUTEX(shmem_swaplist_mutex);
 
 static void shmem_free_blocks(struct inode *inode, long pages)
 {
@@ -796,9 +796,9 @@ static void shmem_delete_inode(struct inode *inode)
                inode->i_size = 0;
                shmem_truncate(inode);
                if (!list_empty(&info->swaplist)) {
-                       spin_lock(&shmem_swaplist_lock);
+                       mutex_lock(&shmem_swaplist_mutex);
                        list_del_init(&info->swaplist);
-                       spin_unlock(&shmem_swaplist_lock);
+                       mutex_unlock(&shmem_swaplist_mutex);
                }
        }
        BUG_ON(inode->i_blocks);
@@ -851,6 +851,14 @@ static int shmem_unuse_inode(struct shmem_inode_info 
*info, swp_entry_t entry, s
        for (idx = SHMEM_NR_DIRECT; idx < limit; idx += ENTRIES_PER_PAGE, 
dir++) {
                if (unlikely(idx == stage)) {
                        shmem_dir_unmap(dir-1);
+                       if (cond_resched_lock(&info->lock)) {
+                               /* check it has not been truncated */
+                               if (limit > info->next_index) {
+                                       limit = info->next_index;
+                                       if (idx >= limit)
+                                               goto lost2;
+                               }
+                       }
                        dir = shmem_dir_map(info->i_indirect) +
                            ENTRIES_PER_PAGE/2 + idx/ENTRIES_PER_PAGEPAGE;
                        while (!*dir) {
@@ -924,7 +932,7 @@ int shmem_unuse(swp_entry_t entry, struct page *page)
        struct shmem_inode_info *info;
        int found = 0;
 
-       spin_lock(&shmem_swaplist_lock);
+       mutex_lock(&shmem_swaplist_mutex);
        list_for_each_safe(p, next, &shmem_swaplist) {
                info = list_entry(p, struct shmem_inode_info, swaplist);
                if (!info->swapped)
@@ -935,8 +943,9 @@ int shmem_unuse(swp_entry_t entry, struct page *page)
                        found = 1;
                        break;
                }
+               cond_resched();
        }
-       spin_unlock(&shmem_swaplist_lock);
+       mutex_unlock(&shmem_swaplist_mutex);
        return found;
 }
 
@@ -996,10 +1005,10 @@ static int shmem_writepage(struct page *page, struct 
writeback_control *wbc)
                shmem_swp_unmap(entry);
                spin_unlock(&info->lock);
                if (list_empty(&info->swaplist)) {
-                       spin_lock(&shmem_swaplist_lock);
+                       mutex_lock(&shmem_swaplist_mutex);
                        /* move instead of add in case we're racing */
                        list_move_tail(&info->swaplist, &shmem_swaplist);
-                       spin_unlock(&shmem_swaplist_lock);
+                       mutex_unlock(&shmem_swaplist_mutex);
                }
                swap_duplicate(swap);
                BUG_ON(page_mapped(page));
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to