[Cluster-devel] cluster/group/dlm_controld deadlock.c
teigland at sourceware.org
teigland at sourceware.org
Thu Aug 23 19:08:12 UTC 2007
CVSROOT: /cvs/cluster
Module name: cluster
Changes by: teigland at sourceware.org 2007-08-23 19:08:11
Modified files:
group/dlm_controld: deadlock.c
Log message:
needed to be a little more thorough in taking a canceled transaction
out of the dependency graph for cases where multiple locks were blocked
between the same two transactions
Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/group/dlm_controld/deadlock.c.diff?cvsroot=cluster&r1=1.6&r2=1.7
--- cluster/group/dlm_controld/deadlock.c 2007/08/17 21:17:53 1.6
+++ cluster/group/dlm_controld/deadlock.c 2007/08/23 19:08:11 1.7
@@ -73,6 +73,8 @@
struct dlm_rsb *rsb; /* lock is on resource */
struct trans *trans; /* lock owned by this transaction */
struct list_head trans_list; /* tr->locks */
+ struct trans *waitfor_trans; /* the trans that's holding the
+ lock that's blocking us */
};
/* waitfor pointers alloc'ed 4 at at time */
@@ -87,7 +89,9 @@
waitfor */
int waitfor_alloc;
int waitfor_count; /* count of in-use
- waitfor slots */
+ waitfor slots and
+ num of trans's we're
+ waiting on */
struct trans **waitfor; /* waitfor_alloc trans
pointers */
};
@@ -765,8 +769,6 @@
goto out_it;
}
- log_group(ls, "read_checkpoint: ckpt read %llu bytes",
- (unsigned long long)iov.readSize);
section_len = iov.readSize;
if (!section_len)
@@ -1598,6 +1600,7 @@
tr->waitfor[tr->waitfor_count++] = granted_lkb->trans;
granted_lkb->trans->others_waiting_on_us++;
+ waiting_lkb->waitfor_trans = granted_lkb->trans;
}
/* for each trans, for each waiting lock, go to rsb of the lock,
@@ -1742,14 +1745,32 @@
if (lkb->lock.status == DLM_LKSTS_GRANTED)
continue;
send_cancel_lock(ls, tr, lkb);
- tr->waitfor_count--;
- }
- if (tr->waitfor_count)
- log_group(ls, "canceled trans has non-zero waitfor_count %d",
- tr->waitfor_count);
+ /* When this canceled trans has multiple locks all blocked by
+ locks held by one other trans, that other trans is only
+ added to tr->waitfor once, and only one of these waiting
+ locks will have waitfor_trans set. So, the lkb with
+ non-null waitfor_trans was the first one responsible
+ for adding waitfor_trans to tr->waitfor.
+
+ We could potentially forget about keeping track of lkb->
+ waitfor_trans, forget about calling remove_waitfor()
+ here and just set tr->waitfor_count = 0 after this loop.
+ The loss would be that waitfor_trans->others_waiting_on_us
+ would not get decremented. */
+
+ if (lkb->waitfor_trans)
+ remove_waitfor(tr, lkb->waitfor_trans);
+ }
+
+ /* this shouldn't happen, if it does something's not working right */
+ if (tr->waitfor_count) {
+ log_group(ls, "cancel_trans: %llx non-zero waitfor_count %d",
+ (unsigned long long)tr->xid, tr->waitfor_count);
+ }
- /* this should now remove the canceled trans */
+ /* this should now remove the canceled trans since it now has a zero
+ waitfor_count */
removed = reduce_waitfor_graph(ls);
if (!removed)
@@ -1772,11 +1793,12 @@
log_group(ls, "locks:");
list_for_each_entry(lkb, &tr->locks, trans_list) {
- log_group(ls, " %s: id %08x gr %s rq %s pid %u \"%s\"",
+ log_group(ls, " %s: id %08x gr %s rq %s pid %u:%u \"%s\"",
status_str(lkb->lock.status),
lkb->lock.id,
dlm_mode_str(lkb->lock.grmode),
dlm_mode_str(lkb->lock.rqmode),
+ lkb->home,
lkb->lock.ownpid,
lkb->rsb->name);
}
More information about the Cluster-devel
mailing list