aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jbd/commit.c
diff options
context:
space:
mode:
authorPawit Pornkitprasan <p.pawit@gmail.com>2012-11-20 19:27:29 +0700
committerPawit Pornkitprasan <p.pawit@gmail.com>2012-11-20 19:27:29 +0700
commitcc7f0ca4b92d7da9d3a7bd674bfd454cc69e7780 (patch)
tree6ffdbe4122642c18f7dbf3eecd93794d49987dcb /fs/jbd/commit.c
parent67196921fba94cf21b6c2de7da422d536fc9471d (diff)
parent89d2d133c6947c04a8ab539b997f266535beaafe (diff)
downloadkernel_samsung_aries-cc7f0ca4b92d7da9d3a7bd674bfd454cc69e7780.zip
kernel_samsung_aries-cc7f0ca4b92d7da9d3a7bd674bfd454cc69e7780.tar.gz
kernel_samsung_aries-cc7f0ca4b92d7da9d3a7bd674bfd454cc69e7780.tar.bz2
Merge 3.0.52
Merge branch 'linux-3.0.y' of git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable into jellybean-next Conflicts: drivers/net/tun.c kernel/time/timekeeping.c Change-Id: Iba7fc59ca05114d9e7bade8dfc5bb45229ebf075
Diffstat (limited to 'fs/jbd/commit.c')
-rw-r--r--fs/jbd/commit.c45
1 files changed, 34 insertions, 11 deletions
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index 72ffa97..dcd23f8 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -85,7 +85,12 @@ nope:
static void release_data_buffer(struct buffer_head *bh)
{
if (buffer_freed(bh)) {
+ WARN_ON_ONCE(buffer_dirty(bh));
clear_buffer_freed(bh);
+ clear_buffer_mapped(bh);
+ clear_buffer_new(bh);
+ clear_buffer_req(bh);
+ bh->b_bdev = NULL;
release_buffer_page(bh);
} else
put_bh(bh);
@@ -840,17 +845,35 @@ restart_loop:
* there's no point in keeping a checkpoint record for
* it. */
- /* A buffer which has been freed while still being
- * journaled by a previous transaction may end up still
- * being dirty here, but we want to avoid writing back
- * that buffer in the future after the "add to orphan"
- * operation been committed, That's not only a performance
- * gain, it also stops aliasing problems if the buffer is
- * left behind for writeback and gets reallocated for another
- * use in a different page. */
- if (buffer_freed(bh) && !jh->b_next_transaction) {
- clear_buffer_freed(bh);
- clear_buffer_jbddirty(bh);
+ /*
+ * A buffer which has been freed while still being journaled by
+ * a previous transaction.
+ */
+ if (buffer_freed(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 throughout in that since the
+ * buffer may be still accessible when blocksize <
+ * pagesize and it is attached to the last partial
+ * page.
+ */
+ jh->b_modified = 0;
+ if (!jh->b_next_transaction) {
+ clear_buffer_freed(bh);
+ clear_buffer_jbddirty(bh);
+ clear_buffer_mapped(bh);
+ clear_buffer_new(bh);
+ clear_buffer_req(bh);
+ bh->b_bdev = NULL;
+ }
}
if (buffer_jbddirty(bh)) {