switch-linux/include/linux
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
..
amba
byteorder
dvb
hdlc
isdn
lockd knfsd: lockd: nfsd4: use same grace period for lockd and nfsd4 2007-07-17 10:23:07 -07:00
mlx4
mmc
mtd
netfilter
netfilter_arp
netfilter_bridge
netfilter_ipv4 [NETFILTER]: ipt_iprange.h must #include <linux/types.h> 2007-07-18 02:21:50 -07:00
netfilter_ipv6
nfsd knfsd: nfsd: enforce per-flavor id squashing 2007-07-17 10:23:08 -07:00
raid md: change bitmap_unplug and others to void functions 2007-07-17 10:23:15 -07:00
rtc rtc: add support for the ST M48T59 RTC 2007-07-17 10:23:09 -07:00
spi SPI: tle620x power switch driver 2007-07-17 10:23:05 -07:00
sunrpc knfsd: nfsd4: secinfo handling without secinfo= option 2007-07-17 10:23:08 -07:00
tc_act
tc_ematch
usb
8250_pci.h
a.out.h
ac97_codec.h
acct.h
acpi.h
acpi_pmtmr.h
adb.h
adfs_fs.h
adfs_fs_i.h
adfs_fs_sb.h
aer.h
affs_hardblocks.h
agp_backend.h
agpgart.h
aio.h
aio_abi.h
amifd.h
amifdreg.h
amigaffs.h
anon_inodes.h
apm-emulation.h
apm_bios.h
arcdevice.h
arcfb.h
async_tx.h
ata.h
atalk.h
atm.h
atm_eni.h
atm_he.h
atm_idt77105.h
atm_nicstar.h
atm_suni.h
atm_tcp.h
atm_zatm.h
atmapi.h
atmarp.h
atmbr2684.h
atmclip.h
atmdev.h
atmel_pdc.h
atmioc.h
atmlec.h
atmmpc.h
atmppp.h
atmsap.h
atmsvc.h
attribute_container.h
audit.h
auto_fs.h
auto_fs4.h
auxvec.h
ax25.h
b1lli.h
b1pcmcia.h
backing-dev.h
backlight.h
baycom.h
bcd.h
bfs_fs.h
binfmts.h
bio.h
bit_spinlock.h
bitmap.h
bitops.h
bitrev.h
blkdev.h
blkpg.h
blktrace_api.h
blockgroup_lock.h
bootmem.h
bottom_half.h
bpqether.h
bsg.h
buffer_head.h
bug.h
cache.h
calc64.h
capability.h
capi.h
cciss_ioctl.h
cd1400.h
cdev.h
cdk.h
cdrom.h
cfag12864b.h
chio.h
circ_buf.h
clk.h
clockchips.h
clocksource.h
cm4000_cs.h
cn_proc.h
coda.h
coda_cache.h
coda_fs_i.h
coda_linux.h
coda_proc.h
coda_psdev.h
coff.h
com20020.h
compat.h
compiler-gcc.h
compiler-gcc3.h
compiler-gcc4.h
compiler-intel.h
compiler.h
completion.h
comstats.h
concap.h
configfs.h
connector.h
console.h
console_struct.h
consolemap.h
const.h
cpu.h
cpufreq.h
cpumask.h
cpuset.h
cramfs_fs.h
cramfs_fs_sb.h
crash_dump.h
crc-ccitt.h
crc-itu-t.h
crc7.h CRC7 support 2007-07-17 10:23:04 -07:00
crc16.h
crc32.h
crc32c.h
crypto.h
cryptohash.h
ctype.h
cuda.h
cyclades.h
cyclomx.h
cycx_cfm.h
cycx_drv.h
cycx_x25.h
dcache.h
dccp.h
dcookies.h
debug_locks.h
debugfs.h
delay.h
delayacct.h
device-mapper.h
device.h dev_vdbg(), available with -DVERBOSE_DEBUG 2007-07-18 15:49:50 -07:00
devpts_fs.h
dio.h
dirent.h
display.h
dlm.h
dlm_device.h
dlm_netlink.h
dm-ioctl.h
dm9000.h
dma-mapping.h
dmaengine.h
dmapool.h
dmi.h
dn.h
dnotify.h
dqblk_v1.h
dqblk_v2.h
dqblk_xfs.h
ds1wm.h
ds1286.h
ds17287rtc.h
dtlk.h
edd.h
eeprom_93cx6.h
efi.h
efs_dir.h
efs_fs.h knfsd: exportfs: remove iget abuse 2007-07-17 10:23:06 -07:00
efs_fs_i.h
efs_fs_sb.h
efs_vh.h
eisa.h
elevator.h
elf-em.h
elf-fdpic.h
elf.h
elfcore.h
elfnote.h use elfnote.h to generate vsyscall notes. 2007-07-18 08:47:40 -07:00
err.h
errno.h
errqueue.h
etherdevice.h
ethtool.h
eventfd.h
eventpoll.h
exportfs.h knfsd: exportfs: add procedural interface for NFSD 2007-07-17 10:23:06 -07:00
ext2_fs.h
ext2_fs_sb.h
ext3_fs.h
ext3_fs_i.h
ext3_fs_sb.h
ext3_jbd.h
ext4_fs.h ext4: Expand extra_inodes space per the s_{want,min}_extra_isize fields 2007-07-18 09:19:57 -04:00
ext4_fs_extents.h Change on-disk format to support 2^15 uninitialized extents 2007-07-18 09:02:56 -04:00
ext4_fs_i.h ext4: Add nanosecond timestamps 2007-07-18 09:15:20 -04:00
ext4_fs_sb.h ext4: Add nanosecond timestamps 2007-07-18 09:15:20 -04:00
ext4_jbd2.h
fadvise.h
falloc.h sys_fallocate() implementation on i386, x86_64 and powerpc 2007-07-17 21:42:44 -04:00
fault-inject.h
fb.h OMAP: add TI OMAP1610 accelerator entry. 2007-07-17 10:23:13 -07:00
fcdevice.h
fcntl.h
fd.h
fd1772.h
fddidevice.h
fdreg.h
fib_rules.h
file.h
filter.h
firewire-cdev.h
firewire-constants.h
firmware.h
flat.h
font.h
freezer.h
fs.h Merge branch 'for-linus' of git://linux-nfs.org/~bfields/linux 2007-07-18 18:27:00 -07:00
fs_enet_pd.h
fs_stack.h
fs_struct.h
fs_uart_pd.h
fsl_devices.h Fix RGMII-ID handling in gianfar 2007-07-18 18:29:37 -04:00
fsnotify.h
fuse.h
futex.h
gameport.h
gen_stats.h
genalloc.h
generic_acl.h
generic_serial.h
genetlink.h
genhd.h
getcpu.h
gfp.h
gfs2_ondisk.h
gigaset_dev.h
gpio_keys.h
gpio_mouse.h
hardirq.h
harrier_defs.h
hash.h
hayesesp.h
hdlc.h
hdlcdrv.h
hdpu_features.h
hdreg.h
hdsmart.h
hid-debug.h
hid.h
hiddev.h
highmem.h
highuid.h
hil.h
hil_mlc.h
hippidevice.h
hp_sdc.h
hpet.h
hrtimer.h
htirq.h
hugetlb.h
hw_random.h
hwmon-sysfs.h
hwmon-vid.h
hwmon.h
hysdn_if.h
i2c-algo-bit.h
i2c-algo-pca.h
i2c-algo-pcf.h
i2c-algo-sgi.h
i2c-dev.h
i2c-gpio.h
i2c-id.h
i2c-isa.h
i2c-ocores.h
i2c-pnx.h
i2c-pxa.h
i2c.h
i2o-dev.h
i2o.h
i8k.h
ibmtr.h
icmp.h
icmpv6.h
ide.h
idr.h
ieee80211.h
if.h
if_addr.h
if_arcnet.h
if_arp.h
if_bonding.h
if_bridge.h
if_cablemodem.h
if_ec.h
if_eql.h
if_ether.h
if_fc.h
if_fddi.h
if_frad.h
if_hippi.h
if_infiniband.h
if_link.h
if_ltalk.h
if_macvlan.h
if_packet.h
if_plip.h
if_ppp.h
if_pppol2tp.h
if_pppox.h
if_shaper.h
if_slip.h
if_strip.h
if_tr.h
if_tun.h
if_tunnel.h
if_vlan.h
if_wanpipe.h
igmp.h
in.h
in6.h
in_route.h
inet.h
inet_diag.h
inetdevice.h
init.h
init_task.h
initrd.h
inotify.h
input-polldev.h
input.h
interrupt.h
io.h
ioc3.h
ioc4.h
ioctl.h
ioport.h
ioprio.h
ip.h
ip6_tunnel.h
ipc.h
ipmi.h
ipmi_msgdefs.h
ipmi_smi.h
ipsec.h
ipv6.h
ipv6_route.h
ipx.h
irda.h
irq.h
irq_cpustat.h
irqflags.h
irqreturn.h
isa.h
isapnp.h
isdn.h
isdn_divertif.h
isdn_ppp.h
isdnif.h
isicom.h
iso_fs.h
istallion.h
ixjuser.h
jbd.h
jbd2.h jbd2: Fix CONFIG_JBD_DEBUG ifdef to be CONFIG_JBD2_DEBUG 2007-07-18 08:57:06 -04:00
jffs2.h
jhash.h
jiffies.h
journal-head.h
joystick.h
kallsyms.h kallsyms: make KSYM_NAME_LEN include space for trailing '\0' 2007-07-17 10:23:03 -07:00
kbd_diacr.h
kbd_kern.h
Kbuild
kd.h
kdebug.h
kdev_t.h
kernel.h
kernel_stat.h
kernelcapi.h Use mutex instead of semaphore in CAPI 2.0 driver 2007-07-17 10:23:05 -07:00
kexec.h
key-ui.h
key.h
keyboard.h
keyctl.h
kfifo.h
klist.h
kmalloc_sizes.h
kmod.h usermodehelper: Tidy up waiting 2007-07-18 08:47:40 -07:00
kobj_map.h
kobject.h Driver core: accept all valid action-strings in uevent-trigger 2007-07-18 15:49:49 -07:00
kprobes.h
kref.h
ks0108.h
kthread.h
ktime.h
kvm.h
kvm_para.h
lapb.h
latency.h
lcd.h
leds.h
libata.h
libps2.h
license.h
limits.h Remove CHILD_MAX 2007-07-17 10:23:03 -07:00
linkage.h
linux_logo.h fbdev: Add fb_append_extra_logo() 2007-07-17 10:23:13 -07:00
list.h
llc.h
lm_interface.h
lock_dlm_plock.h
lockdep.h
log2.h
loop.h
lp.h
lzo.h
m41t00.h
m48t86.h
magic.h
major.h xen: add virtual block device driver. 2007-07-18 08:47:45 -07:00
matroxfb.h
mbcache.h
mc6821.h
mc146818rtc.h
mca-legacy.h
mca.h
memory.h
memory_hotplug.h
mempolicy.h
mempool.h
meye.h
migrate.h
mii.h
minix_fs.h
miscdevice.h
mm.h mm: fix fault vs invalidate race for linear mappings 2007-07-19 10:04:41 -07:00
mm_inline.h
mm_types.h
mman.h
mmtimer.h
mmzone.h
mnt_namespace.h
mod_devicetable.h
module.h
moduleloader.h
moduleparam.h
mount.h
mpage.h
mqueue.h
mroute.h
msdos_fs.h
msg.h
msi.h
mtio.h
mutex-debug.h
mutex.h
mv643xx.h
n_r3964.h
namei.h
nbd.h
ncp.h
ncp_fs.h
ncp_fs_i.h
ncp_fs_sb.h
ncp_mount.h
ncp_no.h
neighbour.h
net.h
netdevice.h [NET]: move dev_mc_discard from dev_mcast.c to dev.c 2007-07-18 02:10:54 -07:00
netfilter.h
netfilter_arp.h
netfilter_bridge.h
netfilter_decnet.h
netfilter_ipv4.h
netfilter_ipv6.h
netlink.h
netpoll.h
netrom.h
nfs.h
nfs2.h
nfs3.h
nfs4.h
nfs4_acl.h
nfs4_mount.h
nfs_fs.h
nfs_fs_i.h
nfs_fs_sb.h
nfs_idmap.h
nfs_mount.h
nfs_page.h
nfs_xdr.h
nfsacl.h
nfsd_idmap.h
nl80211.h
nls.h
nmi.h
node.h
nodemask.h
notifier.h
nsc_gpio.h
nsproxy.h
nubus.h
numa.h
nvram.h
oom.h
oprofile.h
page-flags.h xen: add pinned page flag 2007-07-18 08:47:43 -07:00
pagemap.h
pagevec.h
param.h
parport.h
parport_pc.h
parser.h
pata_platform.h
patchkey.h
pci-acpi.h
pci.h
pci_hotplug.h
pci_ids.h
pci_regs.h
pcieport_if.h
pda_power.h
percpu.h
percpu_counter.h
personality.h
pfkeyv2.h
pfn.h
pg.h
phantom.h
phonedev.h
phy.h
pid.h
pid_namespace.h
pipe_fs_i.h
pkt_cls.h
pkt_sched.h
pktcdvd.h
platform_device.h
plist.h
pm.h PM: remove deprecated dpm_runtime_* routines 2007-07-18 15:49:49 -07:00
pm_legacy.h
pmu.h
pnp.h
pnpbios.h
poison.h
poll.h
posix-timers.h
posix_acl.h
posix_acl_xattr.h
posix_types.h
power_supply.h
ppdev.h
ppp-comp.h
ppp_channel.h
ppp_defs.h
prctl.h
preempt.h
prefetch.h
prio_tree.h
proc_fs.h
profile.h
ps2esdi.h
ptrace.h PTRACE_POKEDATA consolidation 2007-07-17 10:23:03 -07:00
qnx4_fs.h
qnxtypes.h
quicklist.h
quota.h
quotaio_v1.h
quotaio_v2.h
quotaops.h
radeonfb.h
radix-tree.h
raid_class.h
ramfs.h
random.h
raw.h
rbtree.h
rcupdate.h
reboot.h Add common orderly_poweroff() 2007-07-18 08:47:40 -07:00
reciprocal_div.h
reiserfs_acl.h
reiserfs_fs.h
reiserfs_fs_i.h
reiserfs_fs_sb.h
reiserfs_xattr.h
relay.h
resource.h
resume-trace.h
rfkill.h
rio.h
rio_drv.h
rio_ids.h
rio_regs.h
rmap.h
romfs_fs.h
root_dev.h
rose.h
route.h
rslib.h
rtc-v3020.h
rtc.h
rtmutex.h
rtnetlink.h
rwsem-spinlock.h
rwsem.h
rxrpc.h
sc26198.h
scatterlist.h
scc.h
sched.h
screen_info.h
sctp.h
scx200.h
scx200_gpio.h
sdla.h
seccomp.h
securebits.h
security.h
selection.h
selinux.h
selinux_netlink.h
sem.h
seq_file.h
seqlock.h
serial.h
serial167.h
serial_8250.h serial: add early_serial_setup() back to header file 2007-07-18 08:38:22 -07:00
serial_core.h zs: move to the serial subsystem 2007-07-18 08:38:22 -07:00
serial_pnx8xxx.h
serial_reg.h
serialP.h
serio.h
shm.h
shmem_fs.h
signal.h
signalfd.h
skbuff.h
slab.h
slab_def.h
slob_def.h slob: Kill off duplicate kzalloc() definition. 2007-07-17 17:26:43 -07:00
slub_def.h
sm501-regs.h
sm501.h
smb.h
smb_fs.h
smb_fs_i.h
smb_fs_sb.h
smb_mount.h
smbno.h
smp.h smp_call_function_single() should be a macro on UP 2007-07-17 14:39:19 -07:00
smp_lock.h
snmp.h
socket.h
sockios.h
som.h
sonet.h
sony-laptop.h
sonypi.h
sort.h
sound.h
soundcard.h
spinlock.h
spinlock_api_smp.h
spinlock_api_up.h
spinlock_types.h
spinlock_types_up.h
spinlock_up.h
splice.h
srcu.h
stacktrace.h
stallion.h
start_kernel.h
stat.h
statfs.h
stddef.h
stop_machine.h
string.h add argv_split() 2007-07-18 08:47:40 -07:00
stringify.h
superhyway.h
suspend.h
svga.h
swap.h
swapops.h
synclink.h
sys.h
syscalls.h sys_fallocate() implementation on i386, x86_64 and powerpc 2007-07-17 21:42:44 -04:00
sysctl.h
sysdev.h
sysfs.h
sysrq.h
sysv_fs.h
task_io_accounting.h
task_io_accounting_ops.h
taskstats.h
taskstats_kern.h
tc.h
tcp.h
telephony.h
termios.h
textsearch.h
textsearch_fsm.h
tfrc.h
thread_info.h
threads.h
ticable.h
tick.h
tifm.h
time.h make timespec_equal() take const arguments 2007-07-17 10:23:03 -07:00
timer.h
timerfd.h
times.h
timex.h
tiocl.h
tipc.h
tipc_config.h
topology.h
toshiba.h
transport_class.h
trdevice.h
tsacct_kern.h
tty.h
tty_driver.h
tty_flip.h
tty_ldisc.h
types.h
uaccess.h
udf_fs.h
udf_fs_i.h
udf_fs_sb.h
udp.h
ufs_fs.h
ufs_fs_i.h
ufs_fs_sb.h
uinput.h
uio.h
uio_driver.h UIO: Add the User IO core code 2007-07-18 15:57:15 -07:00
ultrasound.h
umem.h
un.h
unistd.h
unwind.h
usb.h
usb_gadget.h
usb_sl811.h
usb_usual.h
usbdevice_fs.h
user.h
user_namespace.h
utime.h
uts.h
utsname.h
vermagic.h
vfs.h
via.h
video_decoder.h
video_encoder.h
video_output.h
videodev.h
videodev2.h
videotext.h
vmalloc.h Allocate and free vmalloc areas 2007-07-18 08:47:41 -07:00
vmstat.h
vt.h
vt_buffer.h
vt_kern.h vt: add comment for unbind_con_driver() 2007-07-17 10:23:11 -07:00
wait.h
wanrouter.h
watchdog.h
wireless.h
workqueue.h
writeback.h
x25.h
xattr.h
xfrm.h
yam.h
zconf.h
zlib.h
zorro.h
zorro_ids.h
zutil.h