Re: [PATCH] Documentation: fs: fix directory locking proofs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Al Viro <viro@xxxxxxxxxxxxxxxxxx> 于2023年10月11日周三 14:46写道:
>
> On Wed, Oct 11, 2023 at 01:28:15PM +0800, Mo Zou wrote:
> > Commit 28eceeda130f ("fs: Lock moved directories") acquires locks also for
> > directories when they are moved and updates the deadlock-freedom proof
> > to claim "a linear ordering of the objects - A < B iff (A is an ancestor
> > of B) or (B is an ancestor of A and ptr(A) < ptr(B))". This claim,
> > however, is not correct. Because cross-directory rename may acquire two
> > parents (old parent and new parent) and two child directories (source
> > and target) and the ordering between old parent and target (or new parent
> > and source) may not fall into the above cases, i.e. ptr(old parent) <
> > ptr(target) may not hold. We should revert to previous description that
> > "at any moment we have a partial ordering of the objects - A < B iff A is
> > an ancestor of B".
>
> Not quite.  I agree that the proof needs fixing, but your change doesn't
> do it.
>
> The thing is, the ordering in "neither is an ancestor of another" case
> of lock_two_directories() does, unfortunately, matter.  That's new,
> subtle and not adequately discussed.
>
> Another thing is that callers of lock_two_nondirectories() are not
> covered at all.
>
> I'll put something together and post it; it's 2:45am here at the moment,
> and I'd rather get some sleep first.

When trying to write a fix for the proof, I seem to encounter a corner
case that could lead to deadlocks. The key problem is that the code
introduces more inode-pointer orders between directories (originally,
there is at most one such order for cross-directory rename) and
inode-pointer orders are not compatible with ancestor orders, i.e.
they do not give a linear order!

Consider directories objects A, B, C. The pointer orders are that A < B
and C < A. And B is ancestor to C, so B < C. Thus we have A < B < C
< A!

A concrete deadlock  example can be constructed as follows. Suppose
the tree has following edges /A and /B/C and A < B and C < A. There are
three operations forming a deadlock.

rename(/A, /B) executes: lock /; lock A; (about to lock B)
unlink(/B/C) executes: lock B; (about to lock C)
rename(/A/x, /C/y) executes: lock C; (about to lock A)





[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux