ext4: fix BUG_ON in mb_free_blocks()
[firefly-linux-kernel-4.4.55.git] / fs / ext4 / ext4_jbd2.c
index 7058975e3a5505a9b19d082f4d6ba627919432ff..1be3996b5942f7c4dd6706bf93e3bac69cc36123 100644 (file)
@@ -43,6 +43,8 @@ handle_t *__ext4_journal_start_sb(struct super_block *sb, unsigned int line,
 {
        journal_t *journal;
 
+       might_sleep();
+
        trace_ext4_journal_start(sb, nblocks, _RET_IP_);
        if (sb->s_flags & MS_RDONLY)
                return ERR_PTR(-EROFS);
@@ -113,6 +115,8 @@ int __ext4_journal_get_write_access(const char *where, unsigned int line,
 {
        int err = 0;
 
+       might_sleep();
+
        if (ext4_handle_valid(handle)) {
                err = jbd2_journal_get_write_access(handle, bh);
                if (err)
@@ -209,12 +213,25 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
 {
        int err = 0;
 
+       might_sleep();
+
+       set_buffer_meta(bh);
+       set_buffer_prio(bh);
        if (ext4_handle_valid(handle)) {
                err = jbd2_journal_dirty_metadata(handle, bh);
-               if (err) {
-                       /* Errors can only happen if there is a bug */
-                       handle->h_err = err;
-                       __ext4_journal_stop(where, line, handle);
+               /* Errors can only happen if there is a bug */
+               if (WARN_ON_ONCE(err)) {
+                       ext4_journal_abort_handle(where, line, __func__, bh,
+                                                 handle, err);
+                       ext4_error_inode(inode, where, line,
+                                        bh->b_blocknr,
+                                        "journal_dirty_metadata failed: "
+                                        "handle type %u started at line %u, "
+                                        "credits %u/%u, errcode %d",
+                                        handle->h_type,
+                                        handle->h_line_no,
+                                        handle->h_requested_credits,
+                                        handle->h_buffer_credits, err);
                }
        } else {
                if (inode)