]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 15 Jan 2013 13:33:07 +0000 (05:33 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 15 Jan 2013 13:33:07 +0000 (05:33 -0800)
added patches:
gfs2-test-bufdata-with-buffer-locked-and-gfs2_log_lock-held.patch

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

diff --git a/queue-3.4/gfs2-test-bufdata-with-buffer-locked-and-gfs2_log_lock-held.patch b/queue-3.4/gfs2-test-bufdata-with-buffer-locked-and-gfs2_log_lock-held.patch
new file mode 100644 (file)
index 0000000..a77a0ea
--- /dev/null
@@ -0,0 +1,115 @@
+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>
+[bwh: Backported to 3.2: adjust context]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/gfs2/lops.c  |   18 ++++--------------
+ fs/gfs2/trans.c |    8 ++++++++
+ 2 files changed, 12 insertions(+), 14 deletions(-)
+
+--- a/fs/gfs2/lops.c
++++ b/fs/gfs2/lops.c
+@@ -258,16 +258,14 @@ 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);
+       if (!list_empty(&bd->bd_list_tr))
+-              goto out;
++              return;
+       tr = current->journal_info;
+       tr->tr_touched = 1;
+       tr->tr_num_buf++;
+       list_add(&bd->bd_list_tr, &tr->tr_list_buf);
+       if (!list_empty(&le->le_list))
+-              goto out;
++              return;
+       set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);
+       set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);
+       gfs2_meta_check(sdp, bd->bd_bh);
+@@ -278,9 +276,6 @@ static void buf_lo_add(struct gfs2_sbd *
+       sdp->sd_log_num_buf++;
+       list_add(&le->le_list, &sdp->sd_log_le_buf);
+       tr->tr_num_buf_new++;
+-out:
+-      gfs2_log_unlock(sdp);
+-      unlock_buffer(bd->bd_bh);
+ }
+ static void buf_lo_before_commit(struct gfs2_sbd *sdp)
+@@ -611,11 +606,9 @@ 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) {
+               if (!list_empty(&bd->bd_list_tr))
+-                      goto out;
++                      return;
+               tr->tr_touched = 1;
+               if (gfs2_is_jdata(ip)) {
+                       tr->tr_num_buf++;
+@@ -623,7 +616,7 @@ static void databuf_lo_add(struct gfs2_s
+               }
+       }
+       if (!list_empty(&le->le_list))
+-              goto out;
++              return;
+       set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);
+       set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);
+@@ -635,9 +628,6 @@ static void databuf_lo_add(struct gfs2_s
+       } else {
+               list_add_tail(&le->le_list, &sdp->sd_log_le_ordered);
+       }
+-out:
+-      gfs2_log_unlock(sdp);
+-      unlock_buffer(bd->bd_bh);
+ }
+ static void gfs2_check_magic(struct buffer_head *bh)
+--- a/fs/gfs2/trans.c
++++ b/fs/gfs2/trans.c
+@@ -145,14 +145,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->bd_le);
++      gfs2_log_unlock(sdp);
++      unlock_buffer(bh);
+ }
+ void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
index a0d5f6fa3fa15a36019ad9df47e3ffc42c60de92..6ba87a87ef5e0f29258a85f060dfcda5d51ab65f 100644 (file)
@@ -106,3 +106,4 @@ usb-handle-warm-reset-failure-on-empty-port.patch
 xhci-avoid-dead-ports-add-roothub-port-polling.patch
 usb-hub-handle-claim-of-enabled-remote-wakeup-after-reset.patch
 xhci-handle-hs-bulk-ctrl-endpoints-that-don-t-nak.patch
+gfs2-test-bufdata-with-buffer-locked-and-gfs2_log_lock-held.patch