diff options
Diffstat (limited to 'fs/jbd/commit.c')
| -rw-r--r-- | fs/jbd/commit.c | 25 | 
1 files changed, 22 insertions, 3 deletions
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index 86b39b167c2..11bb11f48b3 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c @@ -162,8 +162,17 @@ static void journal_do_submit_data(struct buffer_head **wbuf, int bufs,  	for (i = 0; i < bufs; i++) {  		wbuf[i]->b_end_io = end_buffer_write_sync; -		/* We use-up our safety reference in submit_bh() */ -		submit_bh(write_op, wbuf[i]); +		/* +		 * Here we write back pagecache data that may be mmaped. Since +		 * we cannot afford to clean the page and set PageWriteback +		 * here due to lock ordering (page lock ranks above transaction +		 * start), the data can change while IO is in flight. Tell the +		 * block layer it should bounce the bio pages if stable data +		 * during write is required. +		 * +		 * We use up our safety reference in submit_bh(). +		 */ +		_submit_bh(write_op, wbuf[i], 1 << BIO_SNAP_STABLE);  	}  } @@ -667,7 +676,17 @@ start_journal_io:  				clear_buffer_dirty(bh);  				set_buffer_uptodate(bh);  				bh->b_end_io = journal_end_buffer_io_sync; -				submit_bh(write_op, bh); +				/* +				 * In data=journal mode, here we can end up +				 * writing pagecache data that might be +				 * mmapped. Since we can't afford to clean the +				 * page and set PageWriteback (see the comment +				 * near the other use of _submit_bh()), the +				 * data can change while the write is in +				 * flight.  Tell the block layer to bounce the +				 * bio pages if stable pages are required. +				 */ +				_submit_bh(write_op, bh, 1 << BIO_SNAP_STABLE);  			}  			cond_resched();  |