[PATCH] tmpfs 2/3 swapoff-truncate race

From: Hugh Dickins (hugh@veritas.com)
Date: Tue Jun 10 2003 - 12:00:54 EST


Dissatisfied with earlier fix to race where swapoff sneaks page into
tmpfs page cache after truncate_inode_pages cleaned it: calling it a
second time can be too heavy, instead fix shmem_unuse_inode to check
i_size. (Actually, one part of this fix is in the previous patch:
shmem_file_write now has a hold on the page when it raises i_size.)

--- tmpfs1/mm/shmem.c Fri Jun 6 19:20:21 2003
+++ tmpfs2/mm/shmem.c Fri Jun 6 19:24:34 2003
@@ -488,16 +488,6 @@
         }
 done2:
         BUG_ON(info->swapped > info->next_index);
- if (inode->i_mapping->nrpages) {
- /*
- * Call truncate_inode_pages again: racing shmem_unuse_inode
- * may have swizzled a page in from swap since vmtruncate or
- * generic_delete_inode did it, before we lowered next_index.
- */
- spin_unlock(&info->lock);
- truncate_inode_pages(inode->i_mapping, inode->i_size);
- spin_lock(&info->lock);
- }
         shmem_recalc_inode(inode);
         spin_unlock(&info->lock);
 }
@@ -579,6 +569,7 @@
 
 static int shmem_unuse_inode(struct shmem_inode_info *info, swp_entry_t entry, struct page *page)
 {
+ struct inode *inode;
         unsigned long idx;
         unsigned long size;
         unsigned long limit;
@@ -643,8 +634,15 @@
         spin_unlock(&info->lock);
         return 0;
 found:
- if (move_from_swap_cache(page, idx + offset,
- info->vfs_inode.i_mapping) == 0)
+ idx += offset;
+ inode = &info->vfs_inode;
+
+ /* Racing against delete or truncate? Must leave out of page cache */
+ limit = (inode->i_state & I_FREEING)? 0:
+ (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+
+ if (idx >= limit ||
+ move_from_swap_cache(page, idx, inode->i_mapping) == 0)
                 shmem_swp_set(info, ptr + offset, 0);
         shmem_swp_unmap(ptr);
         spin_unlock(&info->lock);
@@ -653,7 +651,7 @@
          * try_to_unuse will skip over mms, then reincrement count.
          */
         swap_free(entry);
- return 1;
+ return idx < limit;
 }
 
 /*

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



This archive was generated by hypermail 2b29 : Sun Jun 15 2003 - 22:00:24 EST