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.
The route
Jump straight to the step you need, or tick off Done means at the end.
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
lslocksbinary 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
lslocksfor command names and paths, with--notruncatewhen 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.