Re: d_splice_alias() problem.

Nikita Danilov
2004-04-26T12:45:11Z

Andrew Morton writes:
> Nikita Danilov <Nikita@Namesys.COM> wrote:
> >
> > for some time I am observing that during stress tests over NFS
> >
> > shrink_slab->...->prune_dcache()->prune_one_dentry()->...->iput()
> >
> > is called on inode with ->i_nlink == 0 which results in truncate and
> > file deletion. This is wrong in general (file system is re-entered), and
> > deadlock prone on some file systems.
>
> The filesystem is only reentered if the caller of __alloc_pages() passed in
> __GFP_FS, in which case the bug is in the caller, not in shrink_slab().

Well, I always thought that the only file system IO that GFP_FS is
expected to do is one issued by ->writepage. Doing truncate from within
VM scanner looks... wrong. But that's not the point, actually. Current
d_splice_alias leads to the following problems with NFS (and may be
other remote file systems also):

* there are more dentries than nlinks for a given file, as a result

* file (not opened by user) is not truncated when its last name is
removed. inode is pinned in the memory indefinitely by remaining
disconnected dentries.

* sequence "touch x; rm x" always creates _two_ dentries for "x": one
disconnected (by ->decode_fh) and one connected (by lookup_one_len
from nfs unlink request).

I think that d_splice_alias() should be changed to scan inode->i_dentry
list and d_move() any disconnected dentry found into new one.

>

Nikita.