]> 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 2494095e0340b6c30c450a01c575304b3f4fa4f3..27373f5792a4f7a5a846742cb44e624ad56f5377 100644 (file)
@@ -976,29 +976,33 @@ void jbd2_journal_commit_transaction(journal_t *journal)
                 * it. */
 
                /*
-               * A buffer which has been freed while still being journaled by
-               * a previous transaction.
-               */
-               if (buffer_freed(bh)) {
+                * A buffer which has been freed while still being journaled
+                * by a previous transaction, refile the buffer to BJ_Forget of
+                * the running transaction. If the just committed transaction
+                * contains "add to orphan" operation, we can completely
+                * invalidate the buffer now. We are rather through in that
+                * since the buffer may be still accessible when blocksize <
+                * 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);
+
                        /*
-                        * If the running transaction is the one containing
-                        * "add to orphan" operation (b_next_transaction !=
-                        * NULL), we have to wait for that transaction to
-                        * commit before we can really get rid of the buffer.
-                        * So just clear b_modified to not confuse transaction
-                        * credit accounting and refile the buffer to
-                        * BJ_Forget of the running transaction. If the just
-                        * committed transaction contains "add to orphan"
-                        * operation, we can completely invalidate the buffer
-                        * now. We are rather through in that since the
-                        * buffer may be still accessible when blocksize <
-                        * pagesize and it is attached to the last partial
-                        * page.
+                        * 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.
                         */
-                       jh->b_modified = 0;
-                       if (!jh->b_next_transaction) {
-                               clear_buffer_freed(bh);
-                               clear_buffer_jbddirty(bh);
+                       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);