--- linux-2.6.0-test10-mm1.ddm/fs/direct-io.c 2003-12-05 17:14:57.704920048 -0800 +++ linux-2.6.0-test10-mm1.ddm.DIO/fs/direct-io.c 2003-12-05 16:55:56.000000000 -0800 @@ -909,6 +909,7 @@ direct_io_worker(int rw, struct kiocb *i int ret = 0; int ret2; size_t bytes; + loff_t i_size; dio->bio = NULL; dio->inode = inode; @@ -1017,9 +1018,15 @@ direct_io_worker(int rw, struct kiocb *i * All block lookups have been performed. For READ requests * we can let i_sem go now that its achieved its purpose * of protecting us from looking up uninitialized blocks. + * + * We also need sample i_size before we release i_sem to prevent + * a racing write from changing i_size causing us to return + * uninitialized data. */ - if ((rw == READ) && dio->needs_locking) + if ((rw == READ) && dio->needs_locking) { + i_size = i_size_read(inode); up(&dio->inode->i_sem); + } /* * OK, all BIOs are submitted, so we can decrement bio_count to truly @@ -1064,7 +1071,6 @@ direct_io_worker(int rw, struct kiocb *i if (ret == 0) ret = dio->page_errors; if (ret == 0 && dio->result) { - loff_t i_size = i_size_read(inode); ret = dio->result; /*