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>
4 files changed