|
@@ -2754,13 +2754,36 @@ retry:
|
|
|
done = true;
|
|
|
}
|
|
|
}
|
|
|
- ext4_journal_stop(handle);
|
|
|
+ /*
|
|
|
+ * Caution: If the handle is synchronous,
|
|
|
+ * ext4_journal_stop() can wait for transaction commit
|
|
|
+ * to finish which may depend on writeback of pages to
|
|
|
+ * complete or on page lock to be released. In that
|
|
|
+ * case, we have to wait until after after we have
|
|
|
+ * submitted all the IO, released page locks we hold,
|
|
|
+ * and dropped io_end reference (for extent conversion
|
|
|
+ * to be able to complete) before stopping the handle.
|
|
|
+ */
|
|
|
+ if (!ext4_handle_valid(handle) || handle->h_sync == 0) {
|
|
|
+ ext4_journal_stop(handle);
|
|
|
+ handle = NULL;
|
|
|
+ }
|
|
|
/* Submit prepared bio */
|
|
|
ext4_io_submit(&mpd.io_submit);
|
|
|
/* Unlock pages we didn't use */
|
|
|
mpage_release_unused_pages(&mpd, give_up_on_write);
|
|
|
- /* Drop our io_end reference we got from init */
|
|
|
- ext4_put_io_end(mpd.io_submit.io_end);
|
|
|
+ /*
|
|
|
+ * Drop our io_end reference we got from init. We have
|
|
|
+ * to be careful and use deferred io_end finishing if
|
|
|
+ * we are still holding the transaction as we can
|
|
|
+ * release the last reference to io_end which may end
|
|
|
+ * up doing unwritten extent conversion.
|
|
|
+ */
|
|
|
+ if (handle) {
|
|
|
+ ext4_put_io_end_defer(mpd.io_submit.io_end);
|
|
|
+ ext4_journal_stop(handle);
|
|
|
+ } else
|
|
|
+ ext4_put_io_end(mpd.io_submit.io_end);
|
|
|
|
|
|
if (ret == -ENOSPC && sbi->s_journal) {
|
|
|
/*
|