Home / Alt manpages / proc_locks(5)

  • proc_locks(5)
  • File format
  • linux

Read /proc/locks Without Guessing Which Process Owns It

You will finish with a repeatable way to inspect the file locks currently visible to your Linux process namespace, interpret the fields in /proc/locks, and use lslocks when you need paths and command names. The examples use the installed Linux man-pages 6.7 description of /proc/locks, a 6.8 kernel, and lslocks from util-linux 2.41.3 on this machine.

Allow about fifteen minutes. You need a shell and a lock that is currently held if you want to reproduce the examples. Reading the proc file and running lslocks are normally unprivileged. Do not stop or kill a process merely because it appears in this list: a lock may protect active writes, and /proc/locks does not tell you whether terminating the owner is safe.

1. Confirm which tools you are using

Check the command path and version first. This avoids a common distraction: a distribution can provide one lslocks while a locally installed copy appears earlier in PATH.

$ command -v lslocks
/home/linuxbrew/.linuxbrew/bin/lslocks
$ lslocks --version
lslocks from util-linux 2.41.3
$ man --version | head -1
man 2.12.0

The version of the proc_locks(5) manpage is separate from the util-linux command version. On this host the installed proc_locks(5) page is Linux man-pages 6.7, dated 19 November 2023. Keep those facts separate when comparing another host's output.

Checkpoint: if command -v lslocks points somewhere unexpected, inspect that binary before trusting its options. The proc file itself is supplied by the kernel, not by the manpages package.

2. Read the kernel's raw lock list

Start with the source of truth described by the manpage:

$ sed -n '1,20p' /proc/locks
1: POSIX  ADVISORY  WRITE 3726740 00:41:241959159 1073741824 1073742335
2: POSIX  ADVISORY  WRITE 3726740 00:41:241959147 1073741824 1073742335
3: FLOCK  ADVISORY  WRITE 3726067 09:02:164652492 0 EOF

Your list will change while programs open, close and lock files. The first number is only the lock's ordinal position in the current list. It is not a stable identifier and should not be saved for later. Take a fresh reading before acting on a finding.

The next fields tell you what kind of lock exists. POSIX is a byte-range lock made with fcntl(2); FLOCK is a BSD lock made with flock(2); and OFDLCK is an open file description lock made with fcntl(2). ADVISORY means cooperating programs must check the lock themselves. A MANDATORY entry has different enforcement semantics and deserves closer investigation before you diagnose an application failure.

3. Decode the owner and byte range

After the lock mode, the next value is normally the owning process ID. For an OFD lock it is -1, because the lock belongs to an open file description that can be shared by more than one process. Do not turn that value into a fake PID or try to inspect process -1.

The device and inode field has three colon-separated parts: major device number, minor device number, and inode number. That identifies the locked file at the filesystem level, but it is not a pathname. The final two fields are the first and last byte offsets. 0 EOF means a BSD lock covering the whole file. A numeric end offset describes an inclusive byte range in the proc representation.

For example, the following entry is a POSIX read lock held by process 3548 over bytes 1826 through 2335 on inode 7865567:

7: POSIX  ADVISORY  READ  3548 08:01:7865567 1826 2335

That interpretation is deliberately narrow. It tells you the kernel's lock record, not why the program took the lock, whether another process is waiting, or whether the associated file is safe to edit.

4. Use lslocks when you need a pathname

lslocks reads the kernel lock information and adds details such as the command and a resolved path where it can find one:

$ lslocks -o COMMAND,PID,TYPE,MODE,PATH,START,END | head
COMMAND             PID  TYPE MODE   PATH  START  END
master          1700053 FLOCK WRITE  ...       0    0
chrome          3720930 POSIX WRITE  ... 1073741824 1073742335

Exact rows are host-specific. A path can be shortened with an ellipsis, unavailable because the current user cannot read it, or represented by the filesystem mount point. Add --notruncate when the full path matters:

$ lslocks --notruncate -o COMMAND,PID,TYPE,MODE,PATH,START,END

If you only need a machine-readable snapshot, use JSON:

$ lslocks --json > locks.json
$ test -s locks.json && echo 'lock snapshot written'
lock snapshot written

Redirection creates or replaces locks.json. Choose a new filename if an existing snapshot is valuable. No kernel lock is changed by either command, and deleting the snapshot later does not release any lock.

5. Narrow the search without changing state

If you already have a suspected PID, ask lslocks to show that process's locks:

$ lslocks --pid 3726067 -o COMMAND,PID,TYPE,MODE,PATH,START,END
COMMAND       PID  TYPE MODE PATH  START END
chrome    3726067  FLOCK WRITE ...      0 EOF

Replace the example PID with a current value from your own output. A blank result means that the process has no lock visible to this invocation, or that the lock disappeared between the two reads. It is not proof that the process never held a lock.

For an unambiguous raw view, omit the heading:

$ lslocks --noheadings --raw -o PID,TYPE,MODE,START,END,PATH

Do not parse the human-readable /proc/locks list as if its ordinal were a process ID. Use the explicit PID field, and expect the list to change while you are investigating.

6. Check namespace and permission boundaries

Since Linux 4.9, /proc/locks is filtered according to the PID namespace in which the proc filesystem was mounted. In the initial PID namespace, the list is not filtered in that way. A container can therefore show a different set of locks from the host, even when both commands are run at the same time.

Read-only visibility is also affected by how /proc and the locked files are mounted. If lslocks cannot resolve a path, try:

$ lslocks --notruncate -o PID,TYPE,PATH
$ findmnt /proc

Use sudo only when your system reports that the relevant proc entries or paths cannot be read by the current user:

$ sudo lslocks --notruncate -o COMMAND,PID,TYPE,MODE,PATH,START,END

This is still an observation. Elevated privileges do not release a lock, repair a stale application, or make an advisory lock mandatory. If a service is blocked, inspect its logs and lock protocol before changing ownership or restarting it.

7. Choose a safe next action

After identifying a candidate, map the PID to its current command without changing it:

$ ps -p 3726067 -o pid=,comm=,args=
3726067 chrome /usr/bin/chrome ...

Confirm the PID and path again because processes exit and PIDs can eventually be reused. Do not remove a lock file to clear a blocked operation: the kernel lock is held by a process, not by a magic file that can safely be deleted. If a service really must be stopped, follow its documented shutdown and recovery procedure, take a backup where data loss is possible, and record how to restart or roll back the change.

Done means

  • You checked the actual lslocks binary and version on the host.
  • You can distinguish POSIX, BSD and OFD locks, and advisory from mandatory records.
  • You read PID, device and inode, start offset, and end offset without treating the ordinal as an ID.
  • You used lslocks for command names and paths, with --notruncate when required.
  • You accounted for changing output, PID namespaces and path permissions.
  • You have not killed a process, deleted a lock file, restarted a service or altered kernel state just to inspect the list.