Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

PROBLEM: flock system call can confuse current->locks and return spurious ENOLCK errno.

1 view
Skip to first unread message

Pat Knight

unread,
Apr 10, 2002, 11:29:58 AM4/10/02
to
[1.] One line summary of the problem:
flock system call can confuse current->locks and return spurious ENOLCK errno.

[2.] Full description of the problem/report:
We had a (largish) program that opens a file and then forks() two children. The
children loop rapidly writing to the file, using flock() locks to maintain
consistency. Note - the fork means that both child processes are sharing a
filp. We found that we would sometimes get ENOLCK failures.

We tracked this down to the value of current->locks going to unsigned 32 bit
max int (and thus equalling RLIMIT_LOCKS). This was caused by locks_free_lock
decrementing current->locks when it was zero.

We eventually determined that this was due to (correct) flock behaviour of
sharing locks held by processes inheriting an open file from a common ancestor.
We know we shouldn't be using flock in these circumstances, and have stopped.

The "search" loop in flock_lock_file checks to see if the requested lock is
already held by that file pointer. If child A has done flock(f,LOCK_EX) and
child B does flock(f,LOCK_EX) before A unlocks, the requested lock is found.
flock_lock_file breaks out of the "search" loop with 'goto out'. The code at
the 'out' label does a locks_free_lock on the new_fl that was allocated "just
in case". B now thinks it has the lock (both A and B have it). However, its
current->locks wasn't incremented as the lock already existed. If B now unlocks
before A, B's value for current->locks decrements "below" 0. Later on, A tries
to free and doesn't find the lock, so never decrements its current->locks.

If current->locks was only used by flock I wouldn't mind if the value was
corrupted by bad use of flock. However, fcntl locks also use current->locks. Is
there a danger that the corrupt values set by flock could affect fcntl? Also, I
think this is a case of user level process behaviour shouldn't "upset" the
kernel.

[3.] Keywords (i.e., modules, networking, kernel):
FILE LOCKING, fs, locks.c

[4.] Kernel version (from /proc/version):
Linux version 2.4.17PK (root@budvar) (gcc version 2.95.3 20010315 (SuSE)) #8
Mon Apr 8 14:49:51 BST 2002

But note that we reproduced the problem in 2.4.18-ac1. The bug is in the
fs/locks.c file and that is identical in both versions of the kernel.

[5.] Output of Oops.. message (if applicable) with symbolic information
resolved (see Documentation/oops-tracing.txt)
No oops.

[6.] A small shell script or example program which triggers the
problem (if possible)

[7.] Environment

[7.1.] Software
Linux budvar 2.4.17PK #8 Mon Apr 8 14:49:51 BST 2002 i686 unknown

Gnu C 2.95.3
Gnu make 3.79.1
binutils 2.11.90.0.29
util-linux 2.11i
mount 2.11i
modutils 2.4.8
e2fsprogs 1.24a
reiserfsprogs 3.x.0k-pre9
Linux C Library x 1 root root 1384168 Sep 20 2001 /lib/libc.so.6
Dynamic linker (ldd) 2.2.4
Procps 2.0.7
Net-tools 1.60
Kbd 1.04
Sh-utils 2.0
Modules Loaded NVdriver vmnet vmmon serial 3c59x

[7.2.] Processor information (from /proc/cpuinfo):
Not relevant - this is CPU independent and deterministic.

[7.3.] Module information (from /proc/modules):
Not a module related bug.

[7.4.] Loaded driver and hardware information (/proc/ioports, /proc/iomem)
Not hardware related.

[7.5.] PCI information ('lspci -vvv' as root)
Not hardware related.

[7.6.] SCSI information (from /proc/scsi/scsi)
Not SCSI related.

[7.7.] Other information that might be relevant to the problem
(please look in /proc and include all information that you
think to be relevant):

[X.] Other notes, patches, fixes, workarounds:
Timeline showing the bug. 1060 and 1061 are the siblings. Functions are in
fs/locks.c.

flock_lock_file (PID 1060) - enter LOCK_EX
locks_alloc_lock (PID 1060): current->locks ++ to 2 // allocate new_fl
flock_lock_file (PID 1060) - new_fl cfe6c3e0
flock_lock_file (PID 1060) - change 0 unlock 0
flock_lock_file (PID 1060) - return 0 // 1060 has created lock cfe6c3e0

flock_lock_file (PID 1061) - enter LOCK_EX
locks_alloc_lock (PID 1061): current->locks ++ to 1 // allocate new_fl
flock_lock_file (PID 1061) - new_fl cfe6c1b8
flock_lock_file (PID 1061) - existing cfe6c3e0 // found existing lock
locks_free_lock (PID 1061) (caller flock_lock_file) - current->locks -- to 0
flock_lock_file (PID 1061) - return 0 // 1061 uses existing lock, frees new_fl

flock_lock_file (PID 1061) - enter LOCK_UN
flock_lock_file (PID 1061) - change 1 unlock 1
locks_free_lock (PID 1061) - locks 0 called by _delete_lock // frees cfe6c3e0
locks_free_lock (PID 1061) - (caller _delete_lock) - current->locks -- to
4294967295 // free lock we didn't allocate!!!
flock_lock_file (PID 1061) - return 0

flock_lock_file (PID 1061) - enter LOCK_EX
locks_alloc_lock (PID 1061): locks 4294967295 >= RLIMIT_LOCKS 4294967295
flock_lock_file (PID 1061) - new_fl NULL, return ENOLCK

flock_lock_file (PID 1060) - enter LOCK_UN
flock_lock_file (PID 1060) - change 0 unlock 1 // no lock found
flock_lock_file (PID 1060) - return 0 // nothing to do, but locks too high.

-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majo...@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

0 new messages