]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - fs/jbd2/commit.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
[linux.git] / fs / jbd2 / commit.c
index 6396fe70085b488a94f9163e0b5fddb297345ba9..27373f5792a4f7a5a846742cb44e624ad56f5377 100644 (file)
@@ -985,12 +985,29 @@ void jbd2_journal_commit_transaction(journal_t *journal)
                 * pagesize and it is attached to the last partial page.
                 */
                if (buffer_freed(bh) && !jh->b_next_transaction) {
+                       struct address_space *mapping;
+
                        clear_buffer_freed(bh);
                        clear_buffer_jbddirty(bh);
-                       clear_buffer_mapped(bh);
-                       clear_buffer_new(bh);
-                       clear_buffer_req(bh);
-                       bh->b_bdev = NULL;
+
+                       /*
+                        * Block device buffers need to stay mapped all the
+                        * time, so it is enough to clear buffer_jbddirty and
+                        * buffer_freed bits. For the file mapping buffers (i.e.
+                        * journalled data) we need to unmap buffer and clear
+                        * more bits. We also need to be careful about the check
+                        * because the data page mapping can get cleared under
+                        * out hands, which alse need not to clear more bits
+                        * because the page and buffers will be freed and can
+                        * never be reused once we are done with them.
+                        */
+                       mapping = READ_ONCE(bh->b_page->mapping);
+                       if (mapping && !sb_is_blkdev_sb(mapping->host->i_sb)) {
+                               clear_buffer_mapped(bh);
+                               clear_buffer_new(bh);
+                               clear_buffer_req(bh);
+                               bh->b_bdev = NULL;
+                       }
                }
 
                if (buffer_jbddirty(bh)) {