[lkml]   [1999]   [Dec]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
Messages in this thread
SubjectRace in truncate in 2.3 kernels?


Consider following situation:

Process1: Wants to read some page in file. So do_generic_file_read() is
called. It gets page but founds it's not uptodate. So we go on page_not_
_uptodate and block.
Process2: Calls truncate on the file. It will capture the i_sem, lower
the size and do vmtruncate() which calls truncate_inode_pages(). This
function will shamelessly delete the page from inode even if it has
holders... Then ext2_truncate() blocks.
Process1: Wakes up - it finds out that page is still not uptodate and
so calls readpage() on it. Readpage() will recreate the buffers() and
happily maps it.

So as the result we have page with mapped buffers (and freed space
under them) going to free_page...

Similar race would be:
Process1: Wants to read some page in file -> do_generic_file_read(). Page
not in memory -> page_cache_alloc() - blocks (I suppose it can block
as otherwise we are dropping spinlocks without reason...).
Process2: Truncate - lower size, vmtruncate(), blocks in ext2_truncate().
Process1: Wakes up - adds page to pagecache and to inode, calls readpage()
which will create buffers and map them.

As the result we have page after i_size and with mapped buffer and
freed blocks under those buffers. Funny things happen when we grow the
file again...

Am I missing something?

The second case can be easily fixed by rechecking the inode size
after blocking. The first case is a bit harder to fix. We might probably
wait for other users of the page to drop it in truncate_inode_pages()
but it might slow down things noticably...


To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to
Please read the FAQ at

 \ /
  Last update: 2005-03-22 13:55    [W:0.019 / U:27.648 seconds]
©2003-2018 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site