JBD2: Clear buffer_ordered flag for barried IO request on success

In JBD2 jbd2_journal_write_commit_record(), clear the buffer_ordered
flag for the bh after barried IO has succeed. This prevents later, if
the same buffer head were submitted to the underlying device, which has
been reconfigured to not support barrier request, the JBD2 commit code
could treat it as a normal IO (without barrier).

This is a port from JBD/ext3 fix from Neil Brown.

More details from Neil:

Some devices - notably dm and md - can change their behaviour in
response to BIO_RW_BARRIER requests. They might start out accepting
such requests but on reconfiguration, they find out that they cannot
any more. JBD2 deal with this by always testing if BIO_RW_BARRIER
requests fail with EOPNOTSUPP, and retrying the write
requests without the barrier (probably after waiting for any pending
writes to complete).

However there is a bug in the handling this in JBD2 for ext4 .

When ext4/JBD2 to submit a BIO_RW_BARRIER request,
it sets the buffer_ordered flag on the buffer head.
If the request completes successfully, the flag STAYS SET.

Other code might then write the same buffer_head after the device has
been reconfigured to not accept barriers. This write will then fail,
but the "other code" is not ready to handle EOPNOTSUPP errors and the
error will be treated as fatal.

Cc: Neil Brown <neilb@suse.de>
Signed-off-by: Dave Kleikamp <shaggy@linux.vnet.ibm.com>
Signed-off-by: Mingming Cao <cmm@us.ibm.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>

authored by Dave Kleikamp and committed by Theodore Ts'o c4e35e07 7fb5409d

+2 -1
+2 -1
fs/jbd2/commit.c
··· 148 148 barrier_done = 1; 149 149 } 150 150 ret = submit_bh(WRITE, bh); 151 + if (barrier_done) 152 + clear_buffer_ordered(bh); 151 153 152 154 /* is it possible for another commit to fail at roughly 153 155 * the same time as this one? If so, we don't want to ··· 168 166 spin_unlock(&journal->j_state_lock); 169 167 170 168 /* And try again, without the barrier */ 171 - clear_buffer_ordered(bh); 172 169 set_buffer_uptodate(bh); 173 170 set_buffer_dirty(bh); 174 171 ret = submit_bh(WRITE, bh);