From 042d62050b799f563e5a1f1a7c535dacc6b02e0f Mon Sep 17 00:00:00 2001 From: pschwan Date: Tue, 18 Jun 2002 03:12:12 +0000 Subject: [PATCH] - Fixed a DLM deadlock bug - Added the leak finding script --- lustre/ldlm/ldlm_lock.c | 16 +++++++++++--- lustre/tests/leak_finder.pl | 53 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 lustre/tests/leak_finder.pl diff --git a/lustre/ldlm/ldlm_lock.c b/lustre/ldlm/ldlm_lock.c index 94df819..66cc28b 100644 --- a/lustre/ldlm/ldlm_lock.c +++ b/lustre/ldlm/ldlm_lock.c @@ -512,12 +512,22 @@ ldlm_error_t ldlm_local_lock_enqueue(struct lustre_handle *lockh, /* policies are not executed on the client */ if (!local && (policy = ldlm_res_policy_table[res->lr_type])) { - int rc = policy(lock, cookie, lock->l_req_mode, NULL); + int rc; + + /* We do this dancing with refcounts and locks because the + * policy function could send an RPC */ + res->lr_refcount++; + spin_unlock(&res->lr_lock); + + rc = policy(lock, cookie, lock->l_req_mode, NULL); + + spin_lock(&res->lr_lock); + ldlm_resource_put(res); + if (rc == ELDLM_LOCK_CHANGED) { res = lock->l_resource; *flags |= LDLM_FL_LOCK_CHANGED; - } - if (rc == ELDLM_LOCK_ABORTED) { + } else if (rc == ELDLM_LOCK_ABORTED) { /* Abort. */ ldlm_resource_put(lock->l_resource); ldlm_lock_free(lock); diff --git a/lustre/tests/leak_finder.pl b/lustre/tests/leak_finder.pl new file mode 100644 index 0000000..99a0f67 --- /dev/null +++ b/lustre/tests/leak_finder.pl @@ -0,0 +1,53 @@ +#!/usr/bin/perl -w + +my ($line, $memory); +my $debug_line = 0; + +while ($line = <>) { + $debug_line++; + my ($file, $func, $lno, $name, $size, $addr, $type); + if ($line =~ m/^.*\(@\d+ (.*):(.*)\,l\. (\d+) .* k(.*) '(.*)': (\d+) at (.*) \(tot .*$/) { + $file = $1; + $func = $2; + $lno = $3; + $type = $4; + $name = $5; + $size = $6; + $addr = $7; + printf("%8s %6d bytes at %s called %s (%s:%s:%d)\n", $type, $size, + $addr, $name, $file, $func, $lno); + } else { + next; + } + + if ($type eq 'malloced') { + $memory->{$addr}->{name} = $name; + $memory->{$addr}->{size} = $size; + $memory->{$addr}->{file} = $file; + $memory->{$addr}->{func} = $func; + $memory->{$addr}->{lno} = $lno; + $memory->{$addr}->{debug_line} = $debug_line; + } else { + if (!defined($memory->{$addr})) { + print "*** Free without malloc ($size bytes at $addr, $file:$func:$lno)\n"; + next; + } + my ($oldname, $oldsize, $oldfile, $oldfunc, $oldlno) = $memory->{$addr}; + + if ($memory->{$addr}->{size} != $size) { + print "*** Free different size ($memory->{$addr}->{size} alloced, $size freed).\n"; + print " malloc at $memory->{$addr}->{file}:$memory->{$addr}->{func}:$memory->{$addr}->{lno}, free at $file:$func:$lno\n"; + next; + } + + delete $memory->{$addr}; + } +} + +my $key; +foreach $key (keys(%{$memory})) { + my ($oldname, $oldsize, $oldfile, $oldfunc, $oldlno) = $memory->{$key}; + print "*** Leak: $memory->{$key}->{size} bytes allocated at $key ($memory->{$key}->{file}:$memory->{$key}->{func}:$memory->{$key}->{lno}, debug file line $memory->{$key}->{debug_line})\n"; +} + +print "Done.\n"; -- 1.8.3.1