tux3: Support mmap write: Fix race of mmap write with write(2) for copy_from_user()
mmap write and write(2) can race.
cpu0 cpu1
write(2)
delta-1 = get_delta()
remove_suid()
update_timestamp()
write_begin()
delta++
mmap write
lock_page()
delta-2 = get_delta()
page-B = pagefork(page-A)
unlock_page()
get_delta_if_need()
lock_page()
page-B = find_get_page();
pagefork(page-B)
write_end()
put_delta()
If mmap write and write(2) run in above order, cpu0 see dirty page-B
for delta-2, while write(2) is using delta-1. We should guarantee one
doesn't see data in future delta.
To fix this race, this (re)takes delta while holding lock_page(). With
this change, we guarantee to use latest delta, and fix race.
FIXME: But this way separates transactions of
update_timestamp()/remove_suid()/etc. and first modification to
page. We would be better to modify data and metadata in same delta
though (to make app's modification and on-disk state more atomic).
Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>