remarkable-linux/fs/xfs
Nick Piggin d00806b183 mm: fix fault vs invalidate race for linear mappings
Fix the race between invalidate_inode_pages and do_no_page.

Andrea Arcangeli identified a subtle race between invalidation of pages from
pagecache with userspace mappings, and do_no_page.

The issue is that invalidation has to shoot down all mappings to the page,
before it can be discarded from the pagecache.  Between shooting down ptes to
a particular page, and actually dropping the struct page from the pagecache,
do_no_page from any process might fault on that page and establish a new
mapping to the page just before it gets discarded from the pagecache.

The most common case where such invalidation is used is in file truncation.
This case was catered for by doing a sort of open-coded seqlock between the
file's i_size, and its truncate_count.

Truncation will decrease i_size, then increment truncate_count before
unmapping userspace pages; do_no_page will read truncate_count, then find the
page if it is within i_size, and then check truncate_count under the page
table lock and back out and retry if it had subsequently been changed (ptl
will serialise against unmapping, and ensure a potentially updated
truncate_count is actually visible).

Complexity and documentation issues aside, the locking protocol fails in the
case where we would like to invalidate pagecache inside i_size.  do_no_page
can come in anytime and filemap_nopage is not aware of the invalidation in
progress (as it is when it is outside i_size).  The end result is that
dangling (->mapping == NULL) pages that appear to be from a particular file
may be mapped into userspace with nonsense data.  Valid mappings to the same
place will see a different page.

Andrea implemented two working fixes, one using a real seqlock, another using
a page->flags bit.  He also proposed using the page lock in do_no_page, but
that was initially considered too heavyweight.  However, it is not a global or
per-file lock, and the page cacheline is modified in do_no_page to increment
_count and _mapcount anyway, so a further modification should not be a large
performance hit.  Scalability is not an issue.

This patch implements this latter approach.  ->nopage implementations return
with the page locked if it is possible for their underlying file to be
invalidated (in that case, they must set a special vm_flags bit to indicate
so).  do_no_page only unlocks the page after setting up the mapping
completely.  invalidation is excluded because it holds the page lock during
invalidation of each page (and ensures that the page is not mapped while
holding the lock).

This also allows significant simplifications in do_no_page, because we have
the page locked in the right place in the pagecache from the start.

Signed-off-by: Nick Piggin <npiggin@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-07-19 10:04:41 -07:00
..
linux-2.6 mm: fix fault vs invalidate race for linear mappings 2007-07-19 10:04:41 -07:00
quota mm: clean up and kernelify shrinker registration 2007-07-17 10:23:00 -07:00
support [XFS] reducing the number of random number functions. 2007-05-08 13:49:03 +10:00
Kbuild
Kconfig
Makefile
Makefile-linux-2.6 [XFS] Concurrent Multi-File Data Streams 2007-07-14 15:40:53 +10:00
xfs.h [XFS] Concurrent Multi-File Data Streams 2007-07-14 15:40:53 +10:00
xfs_acl.c [XFS] Remove unused header files for MAC and CAP checking functionality. 2007-02-10 18:37:28 +11:00
xfs_acl.h
xfs_ag.h [XFS] Concurrent Multi-File Data Streams 2007-07-14 15:40:53 +10:00
xfs_alloc.c [XFS] Clean up function name handling in tracing code 2007-07-14 15:41:24 +10:00
xfs_alloc.h [XFS] Lazy Superblock Counters 2007-07-14 15:28:50 +10:00
xfs_alloc_btree.c [XFS] Lazy Superblock Counters 2007-07-14 15:28:50 +10:00
xfs_alloc_btree.h [XFS] Remove unused arguments from the XFS_BTREE_*_ADDR macros. 2007-02-10 18:37:33 +11:00
xfs_arch.h
xfs_attr.c [XFS] The last argument "lsn" of xfs_trans_commit() is always called with 2007-05-08 13:48:42 +10:00
xfs_attr.h
xfs_attr_leaf.c [XFS] The last argument "lsn" of xfs_trans_commit() is always called with 2007-05-08 13:48:42 +10:00
xfs_attr_leaf.h
xfs_attr_sf.h
xfs_behavior.c
xfs_behavior.h
xfs_bit.c [XFS] Kill off xfs_count_bits 2007-07-14 15:36:43 +10:00
xfs_bit.h [XFS] Kill off xfs_count_bits 2007-07-14 15:36:43 +10:00
xfs_bmap.c [XFS] Clean up function name handling in tracing code 2007-07-14 15:41:24 +10:00
xfs_bmap.h [XFS] Clean up function name handling in tracing code 2007-07-14 15:41:24 +10:00
xfs_bmap_btree.c [XFS] Clean up function name handling in tracing code 2007-07-14 15:41:24 +10:00
xfs_bmap_btree.h [XFS] Remove a bunch of unused functions from XFS. 2007-02-10 18:37:40 +11:00
xfs_btree.c
xfs_btree.h [XFS] Simplify XFS min/max macros. 2007-07-14 15:36:53 +10:00
xfs_buf_item.c [XFS] Kill off xfs_count_bits 2007-07-14 15:36:43 +10:00
xfs_buf_item.h [XFS] Get rid of old 5.3/6.1 v1 log items. Cleanup patch sent in by Eric 2007-02-10 18:35:02 +11:00
xfs_clnt.h [XFS] Concurrent Multi-File Data Streams 2007-07-14 15:40:53 +10:00
xfs_da_btree.c [XFS] Remove a bunch of unused functions from XFS. 2007-02-10 18:37:40 +11:00
xfs_da_btree.h [XFS] Remove a bunch of unused functions from XFS. 2007-02-10 18:37:40 +11:00
xfs_dfrag.c [XFS] propogate return codes from flush routines 2007-05-08 13:49:27 +10:00
xfs_dfrag.h
xfs_dinode.h [XFS] Concurrent Multi-File Data Streams 2007-07-14 15:40:53 +10:00
xfs_dir2.c [XFS] Reduce shouting by removing unnecessary macros from dir2 code. 2007-07-14 15:37:02 +10:00
xfs_dir2.h
xfs_dir2_block.c [XFS] Reduce shouting by removing unnecessary macros from dir2 code. 2007-07-14 15:37:02 +10:00
xfs_dir2_block.h [XFS] Reduce shouting by removing unnecessary macros from dir2 code. 2007-07-14 15:37:02 +10:00
xfs_dir2_data.c [XFS] Reduce shouting by removing unnecessary macros from dir2 code. 2007-07-14 15:37:02 +10:00
xfs_dir2_data.h [XFS] Reduce shouting by removing unnecessary macros from dir2 code. 2007-07-14 15:37:02 +10:00
xfs_dir2_leaf.c [XFS] Reduce shouting by removing unnecessary macros from dir2 code. 2007-07-14 15:37:02 +10:00
xfs_dir2_leaf.h [XFS] Reduce shouting by removing unnecessary macros from dir2 code. 2007-07-14 15:37:02 +10:00
xfs_dir2_node.c [XFS] Reduce shouting by removing unnecessary macros from dir2 code. 2007-07-14 15:37:02 +10:00
xfs_dir2_node.h [XFS] Reduce shouting by removing unnecessary macros from dir2 code. 2007-07-14 15:37:02 +10:00
xfs_dir2_sf.c [XFS] Reduce shouting by removing unnecessary macros from dir2 code. 2007-07-14 15:37:02 +10:00
xfs_dir2_sf.h [XFS] Reduce shouting by removing unnecessary macros from dir2 code. 2007-07-14 15:37:02 +10:00
xfs_dir2_trace.c
xfs_dir2_trace.h
xfs_dmapi.h
xfs_dmops.c
xfs_error.c [XFS] reducing the number of random number functions. 2007-05-08 13:49:03 +10:00
xfs_error.h [XFS] Remove a bunch of unused functions from XFS. 2007-02-10 18:37:40 +11:00
xfs_extfree_item.c [XFS] Keep stack usage down for 4k stacks by using noinline. 2007-02-10 18:34:56 +11:00
xfs_extfree_item.h
xfs_filestream.c [XFS] Concurrent Multi-File Data Streams 2007-07-14 15:40:53 +10:00
xfs_filestream.h [XFS] Concurrent Multi-File Data Streams 2007-07-14 15:40:53 +10:00
xfs_fs.h [XFS] Concurrent Multi-File Data Streams 2007-07-14 15:40:53 +10:00
xfs_fsops.c [XFS] Concurrent Multi-File Data Streams 2007-07-14 15:40:53 +10:00
xfs_fsops.h
xfs_ialloc.c [XFS] Lazy Superblock Counters 2007-07-14 15:28:50 +10:00
xfs_ialloc.h [XFS] Lazy Superblock Counters 2007-07-14 15:28:50 +10:00
xfs_ialloc_btree.c
xfs_ialloc_btree.h [XFS] Remove unused arguments from the XFS_BTREE_*_ADDR macros. 2007-02-10 18:37:33 +11:00
xfs_iget.c [XFS] Add lockdep support for XFS 2007-05-08 13:50:19 +10:00
xfs_imap.h
xfs_inode.c [XFS] Clean up function name handling in tracing code 2007-07-14 15:41:24 +10:00
xfs_inode.h [XFS] Fix lockdep annotations for xfs_lock_inodes 2007-07-14 18:09:42 +10:00
xfs_inode_item.c [XFS] Keep stack usage down for 4k stacks by using noinline. 2007-02-10 18:34:56 +11:00
xfs_inode_item.h
xfs_inum.h
xfs_iocore.c [XFS] Fix to prevent the notorious 'NULL files' problem after a crash. 2007-05-08 13:49:46 +10:00
xfs_iomap.c [XFS] Cleanup inode extent size hint extraction 2007-07-14 15:35:36 +10:00
xfs_iomap.h [XFS] Fix to prevent the notorious 'NULL files' problem after a crash. 2007-05-08 13:49:46 +10:00
xfs_itable.c [XFS] Fix XFS_IOC_FSBULKSTAT{,_SINGLE} & XFS_IOC_FSINUMBERS in compat mode 2007-07-14 15:42:50 +10:00
xfs_itable.h [XFS] Fix XFS_IOC_FSBULKSTAT{,_SINGLE} & XFS_IOC_FSINUMBERS in compat mode 2007-07-14 15:42:50 +10:00
xfs_log.c [XFS] Lazy Superblock Counters 2007-07-14 15:28:50 +10:00
xfs_log.h
xfs_log_priv.h
xfs_log_recover.c [XFS] Lazy Superblock Counters 2007-07-14 15:28:50 +10:00
xfs_log_recover.h
xfs_mount.c [XFS] Use do_div() on 64 bit types. 2007-07-14 15:36:08 +10:00
xfs_mount.h [XFS] Concurrent Multi-File Data Streams 2007-07-14 15:40:53 +10:00
xfs_mru_cache.c [XFS] Concurrent Multi-File Data Streams 2007-07-14 15:40:53 +10:00
xfs_mru_cache.h [XFS] Concurrent Multi-File Data Streams 2007-07-14 15:40:53 +10:00
xfs_qmops.c [XFS] The last argument "lsn" of xfs_trans_commit() is always called with 2007-05-08 13:48:42 +10:00
xfs_quota.h [XFS] Fix uquota and oquota enforcement problems. 2007-05-08 13:49:33 +10:00
xfs_refcache.h
xfs_rename.c [XFS] The last argument "lsn" of xfs_trans_commit() is always called with 2007-05-08 13:48:42 +10:00
xfs_rtalloc.c [XFS] Don't grow filesystems past the size they can index. 2007-07-14 15:21:29 +10:00
xfs_rtalloc.h [XFS] Remove a bunch of unused functions from XFS. 2007-02-10 18:37:40 +11:00
xfs_rw.c [XFS] The last argument "lsn" of xfs_trans_commit() is always called with 2007-05-08 13:48:42 +10:00
xfs_rw.h [XFS] Cleanup inode extent size hint extraction 2007-07-14 15:35:36 +10:00
xfs_sb.h [XFS] Lazy Superblock Counters 2007-07-14 15:28:50 +10:00
xfs_trans.c [XFS] Apply transaction delta counts atomically to incore counters 2007-07-14 15:32:09 +10:00
xfs_trans.h [XFS] Lazy Superblock Counters 2007-07-14 15:28:50 +10:00
xfs_trans_ail.c [XFS] Workaround log space issue by increasing XFS_TRANS_PUSH_AIL_RESTARTS 2007-02-10 18:35:52 +11:00
xfs_trans_buf.c
xfs_trans_extfree.c
xfs_trans_inode.c
xfs_trans_item.c
xfs_trans_priv.h
xfs_trans_space.h
xfs_types.h
xfs_utils.c [XFS] propogate return codes from flush routines 2007-05-08 13:49:27 +10:00
xfs_utils.h
xfs_vfsops.c [XFS] Concurrent Multi-File Data Streams 2007-07-14 15:40:53 +10:00
xfs_vnodeops.c [XFS] Fix lockdep annotations for xfs_lock_inodes 2007-07-14 18:09:42 +10:00