]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.6-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 13 Nov 2012 23:53:34 +0000 (15:53 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 13 Nov 2012 23:53:34 +0000 (15:53 -0800)
added patches:
gfs2-test-bufdata-with-buffer-locked-and-gfs2_log_lock-held.patch

queue-3.6/gfs2-test-bufdata-with-buffer-locked-and-gfs2_log_lock-held.patch [new file with mode: 0644]
queue-3.6/series

diff --git a/queue-3.6/gfs2-test-bufdata-with-buffer-locked-and-gfs2_log_lock-held.patch b/queue-3.6/gfs2-test-bufdata-with-buffer-locked-and-gfs2_log_lock-held.patch
new file mode 100644 (file)
index 0000000..abe5c50
--- /dev/null
@@ -0,0 +1,102 @@
+From 96e5d1d3adf56f1c7eeb07258f6a1a0a7ae9c489 Mon Sep 17 00:00:00 2001
+From: Benjamin Marzinski <bmarzins@redhat.com>
+Date: Wed, 7 Nov 2012 00:38:06 -0600
+Subject: GFS2: Test bufdata with buffer locked and gfs2_log_lock held
+
+From: Benjamin Marzinski <bmarzins@redhat.com>
+
+commit 96e5d1d3adf56f1c7eeb07258f6a1a0a7ae9c489 upstream.
+
+In gfs2_trans_add_bh(), gfs2 was testing if a there was a bd attached to the
+buffer without having the gfs2_log_lock held. It was then assuming it would
+stay attached for the rest of the function. However, without either the log
+lock being held of the buffer locked, __gfs2_ail_flush() could detach bd at any
+time.  This patch moves the locking before the test.  If there isn't a bd
+already attached, gfs2 can safely allocate one and attach it before locking.
+There is no way that the newly allocated bd could be on the ail list,
+and thus no way for __gfs2_ail_flush() to detach it.
+
+Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
+Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/gfs2/lops.c  |   14 ++------------
+ fs/gfs2/trans.c |    8 ++++++++
+ 2 files changed, 10 insertions(+), 12 deletions(-)
+
+--- a/fs/gfs2/lops.c
++++ b/fs/gfs2/lops.c
+@@ -393,12 +393,10 @@ static void buf_lo_add(struct gfs2_sbd *
+       struct gfs2_meta_header *mh;
+       struct gfs2_trans *tr;
+-      lock_buffer(bd->bd_bh);
+-      gfs2_log_lock(sdp);
+       tr = current->journal_info;
+       tr->tr_touched = 1;
+       if (!list_empty(&bd->bd_list))
+-              goto out;
++              return;
+       set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);
+       set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);
+       mh = (struct gfs2_meta_header *)bd->bd_bh->b_data;
+@@ -414,9 +412,6 @@ static void buf_lo_add(struct gfs2_sbd *
+       sdp->sd_log_num_buf++;
+       list_add(&bd->bd_list, &sdp->sd_log_le_buf);
+       tr->tr_num_buf_new++;
+-out:
+-      gfs2_log_unlock(sdp);
+-      unlock_buffer(bd->bd_bh);
+ }
+ static void gfs2_check_magic(struct buffer_head *bh)
+@@ -777,12 +772,10 @@ static void databuf_lo_add(struct gfs2_s
+       struct address_space *mapping = bd->bd_bh->b_page->mapping;
+       struct gfs2_inode *ip = GFS2_I(mapping->host);
+-      lock_buffer(bd->bd_bh);
+-      gfs2_log_lock(sdp);
+       if (tr)
+               tr->tr_touched = 1;
+       if (!list_empty(&bd->bd_list))
+-              goto out;
++              return;
+       set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);
+       set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);
+       if (gfs2_is_jdata(ip)) {
+@@ -793,9 +786,6 @@ static void databuf_lo_add(struct gfs2_s
+       } else {
+               list_add_tail(&bd->bd_list, &sdp->sd_log_le_ordered);
+       }
+-out:
+-      gfs2_log_unlock(sdp);
+-      unlock_buffer(bd->bd_bh);
+ }
+ /**
+--- a/fs/gfs2/trans.c
++++ b/fs/gfs2/trans.c
+@@ -155,14 +155,22 @@ void gfs2_trans_add_bh(struct gfs2_glock
+       struct gfs2_sbd *sdp = gl->gl_sbd;
+       struct gfs2_bufdata *bd;
++      lock_buffer(bh);
++      gfs2_log_lock(sdp);
+       bd = bh->b_private;
+       if (bd)
+               gfs2_assert(sdp, bd->bd_gl == gl);
+       else {
++              gfs2_log_unlock(sdp);
++              unlock_buffer(bh);
+               gfs2_attach_bufdata(gl, bh, meta);
+               bd = bh->b_private;
++              lock_buffer(bh);
++              gfs2_log_lock(sdp);
+       }
+       lops_add(sdp, bd);
++      gfs2_log_unlock(sdp);
++      unlock_buffer(bh);
+ }
+ void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
index d9d1fc5ea9feecc5c171bd5c68d304db9f5048e9..e875195f5ec7249f66b1cd9feadc8c3203d2f60f 100644 (file)
@@ -62,3 +62,4 @@ drm-vmwgfx-fix-hibernation-device-reset.patch
 drm-vmwgfx-fix-a-case-where-the-code-would-bug-when-trying-to-pin-gmr-memory.patch
 drm-radeon-cayman-add-some-missing-regs-to-the-vm-reg-checker.patch
 drm-radeon-si-add-some-missing-regs-to-the-vm-reg-checker.patch
+gfs2-test-bufdata-with-buffer-locked-and-gfs2_log_lock-held.patch