Listing file locks on Solaris 10

September 14, 2009

Suppose that you want to find out what files are locked on your Solaris
10 machine, perhaps because it is an NFS server and you really want a
global view of what locks you have. On a
Linux machine (or a sufficiently old Solaris one) you could use lslk,
but it's never been ported to Solaris 10; instead you need to use 'mdb
-k', the kernel debugger.

We need the sort -u because it's reasonably common for our servers to
have multiple locks (presumably non-overlapping) against the same file.
Your situation may differ.

The mdb ::lminfo command gives you somewhat more information about all
of the locks, but it has the drawback that it truncates filenames. What
I know about the various fields it prints:

the bits of the FLAG field come from flock_impl.h,
specifically the section about the l_status field.
Note that the FLAG field is printed in hex.

the PID and COMM fields are not necessarily meaningful for
client locks on an NFS server.
Locks from clients sometimes have a PID of 0 (which shows
as as a COMM of <kernel>), sometimes have impossible
PIDs (which show as <defunct>, because there's no such
PID on the NFS server), and if you're unlucky have the PID
(and COMM) of an actual process on your NFS server.

I believe that you can spot file locks from NFS clients
by a FLAG value that includes 0x2000 (aka LOCKMGR_LOCK).

Further digging (to, for example, find the name of the client that
theoretically holds the lock) is hampered by the NFS lock manager code
unfortunately not being part of the OpenSolaris code base because it's
not open source. (Allegedly Sun can't share it because it contains
third-party code.)

Possibly, even ideally, there's a better way to get this sort of
information. If so, I've been unable to find it.

Sidebar: what the mdb command does

This is a sufficiently complicated mdb command sequence that I feel
like breaking it down (if only so that I'll remember how it works
later).

::walk lock_graph

Iterate over the 'locking graph', which has
all file locks in the system. This yields a
series of addresses of lock_descriptor_t
structures.

::print lock_descriptor_t l_vnode

Print the l_vnode pointer from each lock
descriptor. You can guess what this points to.

::vnode2path

Get the pathname given the vnode pointer.

If you're doing this inside an interactive mdb session, you can
append '! sort -u' to sort it too.