7c8b3ddfed
.sync and fsync used unnecessarily restrictive locking type .fsync violated locking order by obtaining a vmnt lock after a filp lock .fsync contained a TOCTOU bug .new_node violated locking rules (didn't upgrade lock upon file creation) .do_pipe used unnecessarily restrictive locking type .always lock pipes exclusively; even a read operation might require to do a write on a vnode object (update pipe size) .when opening a file with O_TRUNC, upgrade vnode lock when truncating .utime used unnecessarily restrictive locking type .path parsing: .always acquire VMNT_WRITE or VMNT_EXCL on vmnt and downgrade to VMNT_READ if that was what was actually requested. This prevents the following deadlock scenario: thread A: lock_vmnt(vmp, TLL_READSER); lock_vnode(vp, TLL_READSER); upgrade_vmnt_lock(vmp, TLL_WRITE); thread B: lock_vmnt(vmp, TLL_READ); lock_vnode(vp, TLL_READSER); thread A will be stuck in upgrade_vmnt_lock and thread B is stuck in lock_vnode. This happens when, for example, thread A tries create a new node (open.c:new_node) and thread B tries to do eat_path to change dir (stadir.c:do_chdir). When the path is being resolved, a vnode is always locked with VNODE_OPCL (TLL_READSER) and then downgraded to VNODE_READ if read-only is actually requested. Thread A locks the vmnt with VMNT_WRITE (TLL_READSER) which still allows VMNT_READ locks. Thread B can't acquire a lock on the vnode because thread A has it; Thread A can't upgrade its vmnt lock to VMNT_WRITE (TLL_WRITE) because thread B has a VMNT_READ lock on it. By serializing vmnt locks during path parsing, thread B can only acquire a lock on vmp when thread A has completely finished its operation. |
||
---|---|---|
.. | ||
comm.c | ||
comm.h | ||
const.h | ||
coredump.c | ||
device.c | ||
dmap.c | ||
dmap.h | ||
exec.c | ||
file.h | ||
filedes.c | ||
fproc.h | ||
fs.h | ||
gcov.c | ||
glo.h | ||
job.h | ||
link.c | ||
lock.c | ||
lock.h | ||
main.c | ||
Makefile | ||
misc.c | ||
mount.c | ||
open.c | ||
param.h | ||
path.c | ||
path.h | ||
pipe.c | ||
protect.c | ||
proto.h | ||
read.c | ||
request.c | ||
request.h | ||
scratchpad.h | ||
select.c | ||
stadir.c | ||
table.c | ||
threads.h | ||
time.c | ||
tll.c | ||
tll.h | ||
utility.c | ||
vmnt.c | ||
vmnt.h | ||
vnode.c | ||
vnode.h | ||
worker.c | ||
write.c |