ChangeSet@1.1136.1.73 2003-12-07 15:10:38-02:00 mikulas at cuni.cz [PATCH] from -aa tree: Fix potential fsync() race condition > 00_ll_rw_block-sync-race-1 first appeared in 2.4.21pre4aa3 - 470 bytes > > Add lock_page in ll_rw_block to fix a fs race > condition. Fix suggested by Mikulas Patocka. Yes. You have two inodes placed in the same buffer. Process 1 modifies inode 1 and calls fsync on it. fsync initiates write of the block. ll_rw_block returns, write is in progress. Process 2 modifies inode 2 and calls fsync on it. Filesystem calls ll_rw_block write on the same buffer. ll_rw_block immediatelly returns, because it sees there is already IO on the buffer (there used to be something like if (buffer_locked(bh)) return;). Process 2 waits on buffer. The write finished. Both processes are waken up. Both processes return out of fsync function. Process 2 returns from fsync while it did not write its inode modification to disk --- it waited on process 1's write. --- linux-2.4.23/drivers/block/ll_rw_blk.c~ Tue Dec 9 00:17:12 2003 +++ linux-2.4.23/drivers/block/ll_rw_blk.c Tue Dec 9 00:17:12 2003 @@ -1377,9 +1377,7 @@ for (i = 0; i < nr; i++) { struct buffer_head *bh = bhs[i]; - /* Only one thread can actually submit the I/O. */ - if (test_and_set_bit(BH_Lock, &bh->b_state)) - continue; + lock_buffer(bh); /* We have the buffer lock */ atomic_inc(&bh->b_count);