From: Miklos S. <mi...@sz...> - 2012-01-20 14:40:45
|
Anand Avati <av...@re...> writes: > Problem: > create("filename") => 0 > link("filename", "linkname") => 0 > unlink("filename") => 0 > link("linkname", "filename") => -ENOENT ### BUG ### > > This is a test case link section of the Poix compliance test suite from > ntfs-3g project. > > Cause: > fuse_unlink() clears i_nlink of the inode. If the inode has > hardlinks (and hence aliases) they kept fresh (within the entry > timeout bounds.) A link() call happening right after unlink now checks > for i_nlink == 0 (since patch aae8a97d3ec30788790d1720b71d76fd8eb44b73) > and fails the syscall for security reasons. > > Fix: > Instead of marking the just-unlinked entry as stale, mark all > the aliases as stale so that a revalidation of the alias is done during > path resolution. This is only a partial fix: the entry may still be referenced and used: linkat(..., AT_EMPTY_PATH). There are also several other places where i_nlink is cheked without refreshing the attributes. So how about changing that clear_nlink() to drop_nlink()? I don't quite understand what that comment above clear_nlink() is saying but I suspect it comes from before ->drop_inode was used. Now the inode will go away if no dentry is referencing it regardless of the value of i_nlink. Untested patch below. Does that work for you? Thanks, Miklos diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 2066328..517a7f5 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -645,12 +645,7 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry) if (!err) { struct inode *inode = entry->d_inode; - /* - * Set nlink to zero so the inode can be cleared, if the inode - * does have more links this will be discovered at the next - * lookup/getattr. - */ - clear_nlink(inode); + drop_nlink(inode); fuse_invalidate_attr(inode); fuse_invalidate_attr(dir); fuse_invalidate_entry_cache(entry); |