[Ocfs2-devel] [PATCH] ocfs2: fix __ocfs2_cluster_lock() dead lock
Wengang Wang
wen.gang.wang at oracle.com
Tue Jan 12 23:08:47 PST 2010
On 10-01-13 11:20, Wengang Wang wrote:
> Hi Joel and David,
>
> I think the patch to fix the deadlock(or livelock) is not good enough
> yet.
> my original patch is based on that when we have requested the lock, we
> don't allow to downconvert it before we release it.
> but per the communications with Joel and Sunil, I found my base is
> wrong. so my original patch is not good. and Joel's patch has problem
> either.
>
> On 10-01-11 17:59, Joel Becker wrote:
> > [Cc'd Mark and Dave]
> > Signed-off-by: Joel Becker <joel.becker at oracle.com>
> > ---
> > fs/ocfs2/dlmglue.c | 29 +++++++++++++++++++++++++++++
> > 1 files changed, 29 insertions(+), 0 deletions(-)
> >
> > diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
> > index 90682a0..eabe53e 100644
> > --- a/fs/ocfs2/dlmglue.c
> > +++ b/fs/ocfs2/dlmglue.c
> > @@ -1313,6 +1313,7 @@ static int __ocfs2_cluster_lock(struct ocfs2_super *osb,
> > unsigned long flags;
> > unsigned int gen;
> > int noqueue_attempted = 0;
> > + int lock_attempted = 0;
> >
> > mlog_entry_void();
> >
> > @@ -1347,6 +1348,25 @@ again:
> > goto unlock;
> > }
> >
> > + if (lock_attempted && (lockres->l_level >= level)) {
> > + /*
> > + * We've attempted to upconvert, and the lock now has
> > + * a level we can work with. If we fell through to the
> > + * next checks, we could spin in an upconvert->downconvert
> > + * cycle as other nodes pounded us. Instead, we jump
> > + * out and let the caller do some work. If a downconvert
> > + * has come in, it will do its thing as soon as the caller
> > + * is done.
> > + */
> > + goto update_holders;
> > + }
>
> before update_holders, the lock could be DCed(since no BUSY flag set by
> here).
>
> and even after update_holders, the lock could be DCed too.
>
> so that we get ocfs2_cluster_lock()(with holders increased) returned sucessfully
> but actually we don't hold the dlm lock. --thus more than one node is
> considering that they have the (EX) lock.
>
> that's could be the cause of what is happening observed by David.
I think the main problem is that though the lock is got, the holders
is not updated in time(within BUSY flag protection).
a BUSY flag protects a single ocfs2_dlm_lock(). if a BUSY_INC_HD(also busy with
updating holders) is used to protect a single ocfs2_dlm_lock() + holders
updates against dc thread, so far I think it's the fix. comments?
#patch attached.
-------------- next part --------------
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index c3ee146..d172c5f 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -1360,6 +1360,8 @@ again:
goto update_holders;
}
+ lockres_clear_flags(lockres, OCFS2_LOCK_BUSY_INC_HD);
+
/*
* This is either the first pass or our level wasn't good enough.
* Treat both cases as a first pass.
@@ -1403,7 +1405,7 @@ again:
}
lockres->l_requested = level;
- lockres_or_flags(lockres, OCFS2_LOCK_BUSY);
+ lockres_or_flags(lockres, OCFS2_LOCK_BUSY|OCFS2_LOCK_BUSY_INC_HD);
gen = lockres_set_pending(lockres);
spin_unlock_irqrestore(&lockres->l_lock, flags);
@@ -1447,6 +1449,8 @@ again:
update_holders:
/* Ok, if we get here then we're good to go. */
ocfs2_inc_holders(lockres, level);
+ /* no harm even double clear OCFS2_LOCK_BUSY_INC_HD */
+ lockres_clear_flags(lockres, OCFS2_LOCK_BUSY_INC_HD);
ret = 0;
unlock:
@@ -3392,7 +3396,7 @@ static int ocfs2_unblock_lock(struct ocfs2_super *osb,
BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BLOCKED));
recheck:
- if (lockres->l_flags & OCFS2_LOCK_BUSY) {
+ if (lockres->l_flags & (OCFS2_LOCK_BUSY|OCFS2_LOCK_BUSY_INC_HD)) {
/* XXX
* This is a *big* race. The OCFS2_LOCK_PENDING flag
* exists entirely for one reason - another thread has set
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index d963d86..a3d23ef 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -136,6 +136,7 @@ enum ocfs2_unlock_action {
#define OCFS2_LOCK_PENDING (0x00000400) /* This lockres is pending a
call to dlm_lock. Only
exists with BUSY set. */
+#define OCFS2_LOCK_BUSY_INC_HD (0x00000800) /* busy with increase holders */
struct ocfs2_lock_res_ops;
More information about the Ocfs2-devel
mailing list