]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - tools/xfsbuflock.py
cc15f582c4efb87e01ae82b010beeea6e2ba2021
3 # Read ftrace input, looking for XFS buffer deadlocks.
5 # Copyright (C) 2016 Oracle. All Rights Reserved.
7 # Author: Darrick J. Wong <darrick.wong@oracle.com>
9 # This program is free software; you can redistribute it and/or
10 # modify it under the terms of the GNU General Public License
11 # as published by the Free Software Foundation; either version 2
12 # of the License, or (at your option) any later version.
14 # This program is distributed in the hope that it would be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
19 # You should have received a copy of the GNU General Public License
20 # along with this program; if not, write the Free Software Foundation,
21 # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
23 # Rough guide to using this script:
24 # Collect ftrace data from a deadlock:
26 # # trace-cmd record -e 'xfs_buf_*lock*' <other traces> &
27 # <run command, hang system>^Z
28 # # killall -INT trace-cmd
29 # <wait for trace-cmd to spit out trace.dat>
31 # Now analyze the captured trace data:
33 # # trace-cmd report | xfsbuflock.py
36 # 3732.005575: xfs_buf_trylock_fail: dev 8:16 bno 0x1 nblks 0x1 hold 4 \
37 # pincount 1 lock 0 flags DONE|KMEM caller 0xc009af36s
39 # dev 8:16 bno 0x64c371 nblks 0x1 lock 1 owner fsx-14956@3732.005567
41 # dev 8:16 bno 0x64c380 nblks 0x8 lock 1 owner fsx-14956@3732.005571
42 # dev 8:16 bno 0x64c378 nblks 0x8 lock 1 owner fsx-14956@3732.005570
45 # 3732.005592: xfs_buf_trylock_fail: dev 8:16 bno 0x64c371 nblks 0x1 hold 4 \
46 # pincount 1 lock 0 flags ASYNC|DONE|KMEM caller 0xc009af36s
48 # dev 8:16 bno 0x8 nblks 0x8 lock 1 owner fsx-14954@3732.005583
49 # dev 8:16 bno 0x1 nblks 0x1 lock 1 owner fsx-14954@3732.005574
53 # dev 8:16 bno 0x10 nblks 0x8 lock 1 owner fsx-14954@3732.005585
55 # As you can see, fsx-14596 is locking AGFs in violation of the locking
60 from collections
import namedtuple
65 def __init__(self
, pid
):
68 self
.locked_bufs
= set()
72 print('=== %s ===' % self
.pid
)
73 for bt
in self
.backtrace
:
74 print('%f: %s' % (bt
.time
, bt
.descr
))
75 print('Locked buffers:')
76 for buf
in self
.locked_bufs
:
80 def __init__(self
, dev
, bno
, blen
):
82 self
.bno
= int(bno
, 0)
83 self
.blen
= int(blen
, 0)
89 def trylock(self
, process
, time
):
91 self
.lockdone(process
, time
)
93 def lockdone(self
, process
, time
):
95 print('Buffer already locked on line %d?!' % nr
)
99 if process
in self
.waiters
:
100 self
.waiters
.remove(process
)
104 process
.locked_bufs
.add(self
)
105 process
.bufs
.add(self
)
106 locked_buffers
.add(self
)
108 def waitlock(self
, process
):
109 self
.waiters
.add(process
)
113 if self
in locked_buffers
:
114 locked_buffers
.remove(self
)
115 if self
.owner
is not None and \
116 self
in self
.owner
.locked_bufs
:
117 self
.owner
.locked_bufs
.remove(self
)
120 if self
.owner
is not None:
121 pid
= '%s@%f' % (self
.owner
.pid
, self
.locktime
)
124 print('dev %s bno 0x%x nblks 0x%x lock %d owner %s' % \
125 (self
.dev
, self
.bno
, self
.blen
, self
.locked
, \
127 for proc
in self
.waiters
:
128 print(' waiting: %s' % proc
.pid
)
130 Event
= namedtuple('Event', 'time descr')
132 # Read ftrace input, looking for events and for buffer lock info
135 locked_buffers
= set()
138 if int(toks
[7], 0) == 18446744073709551615:
140 bufkey
= ' '.join(toks
[4:10])
141 if bufkey
in buffers
:
142 return buffers
[bufkey
]
143 buf
= Buffer(toks
[5], toks
[7], toks
[9])
144 buffers
[bufkey
] = buf
148 for line
in fileinput
.input():
155 time
= float(toks
[2][:-1])
161 proc
= processes
[pid
]
164 processes
[pid
] = proc
166 if fn
== 'xfs_buf_unlock' or fn
== 'xfs_buf_item_unlock_stale':
170 elif fn
== 'xfs_buf_lock_done':
173 buf
.lockdone(proc
, time
)
174 elif fn
== 'xfs_buf_lock':
178 elif fn
== 'xfs_buf_trylock':
181 buf
.trylock(proc
, time
)
182 elif fn
== 'xfs_buf_item_unlock':
185 e
= Event(time
, ' '.join(toks
[3:]))
186 proc
.backtrace
.append(e
)
187 if len(proc
.backtrace
) > NR_BACKTRACE
:
188 proc
.backtrace
.pop(0)
191 for buf
in locked_buffers
:
192 deadlocked
.add(buf
.owner
)
194 for proc
in deadlocked
:
202 print('dev %s bno 0x%x len 0x%x owner %s' % (buf
.dev
, buf
.bno
, buf
.blen
, buf
.owner
.pid
))
204 print('dev %s bno 0x%x len 0x%x' % (buf
.dev
, buf
.bno
, buf
.blen
))
208 for pid
in processes
:
209 proc
= processes
[pid
]