* [Cluster-devel] [PATCH] GFS2: Test bufdata with buffer locked and gfs2_log_lock held
@ 2012-11-07 6:38 Benjamin Marzinski
2012-11-07 10:27 ` Steven Whitehouse
0 siblings, 1 reply; 2+ messages in thread
From: Benjamin Marzinski @ 2012-11-07 6:38 UTC (permalink / raw)
To: cluster-devel.redhat.com
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>
---
fs/gfs2/lops.c | 14 ++------------
fs/gfs2/trans.c | 8 ++++++++
2 files changed, 10 insertions(+), 12 deletions(-)
Index: gfs2-3.0-nmw/fs/gfs2/lops.c
===================================================================
--- gfs2-3.0-nmw.orig/fs/gfs2/lops.c
+++ gfs2-3.0-nmw/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)
@@ -775,12 +770,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)) {
@@ -791,9 +784,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);
}
/**
Index: gfs2-3.0-nmw/fs/gfs2/trans.c
===================================================================
--- gfs2-3.0-nmw.orig/fs/gfs2/trans.c
+++ gfs2-3.0-nmw/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)
^ permalink raw reply [flat|nested] 2+ messages in thread
* [Cluster-devel] [PATCH] GFS2: Test bufdata with buffer locked and gfs2_log_lock held
2012-11-07 6:38 [Cluster-devel] [PATCH] GFS2: Test bufdata with buffer locked and gfs2_log_lock held Benjamin Marzinski
@ 2012-11-07 10:27 ` Steven Whitehouse
0 siblings, 0 replies; 2+ messages in thread
From: Steven Whitehouse @ 2012-11-07 10:27 UTC (permalink / raw)
To: cluster-devel.redhat.com
Hi,
Now in the -nmw tree - thanks for fixing this. Also I'm sorting out a
-fixes tree too, so that I can send the collected bug fixes to Linus
ahead of the next merge window,
Steve.
On Wed, 2012-11-07 at 00:38 -0600, Benjamin Marzinski wrote:
> 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>
> ---
> fs/gfs2/lops.c | 14 ++------------
> fs/gfs2/trans.c | 8 ++++++++
> 2 files changed, 10 insertions(+), 12 deletions(-)
>
> Index: gfs2-3.0-nmw/fs/gfs2/lops.c
> ===================================================================
> --- gfs2-3.0-nmw.orig/fs/gfs2/lops.c
> +++ gfs2-3.0-nmw/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)
> @@ -775,12 +770,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)) {
> @@ -791,9 +784,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);
> }
>
> /**
> Index: gfs2-3.0-nmw/fs/gfs2/trans.c
> ===================================================================
> --- gfs2-3.0-nmw.orig/fs/gfs2/trans.c
> +++ gfs2-3.0-nmw/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)
>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2012-11-07 10:27 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-11-07 6:38 [Cluster-devel] [PATCH] GFS2: Test bufdata with buffer locked and gfs2_log_lock held Benjamin Marzinski
2012-11-07 10:27 ` Steven Whitehouse
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).