Re: [PATCH v1 01/12] VFS: don't count references through ->d_parent
NeilBrown <[email protected]>
| Newsgroups | gmane.linux.nfs,gmane.linux.kernel.autofs,gmane.linux.kernel,gmane.comp.file-systems.ceph.devel,gmane.comp.file-systems.coda.general,gmane.linux.file-systems |
|---|---|
| Message-ID | <[email protected]> |
On Mon, 10 Aug 2026, Miklos Szeredi wrote: > On Mon, 3 Aug 2026 at 03:37, NeilBrown <[email protected]> wrote: > > > When a DCACHE_CURSOR dentry is added to d_children, it is only ever > > added "before" or "behind" an existing child, so it will never be the > > first and so never needs to adjust the refcount on the parent. If it > > remains on the list until dput() it could be the last child to be > > removed, in which case normal handling applies in dentry_unlist() (where > > it has been moved from dentry_kill(). > > Not handling the parent refcount together with cursor removal can > result in inconsistency, e.g: > > - add cursor (seek between two positive dentries) > - remove all real children (parent refcount not touched, since cursor > is still on d_children) > - remove cursor (seek to zero offset) > - close directory (dentry_unlist() will skip parent refcount update > since dentry->d_sib is no longer linked) > > Repro attached, produces "BUG: Dentry ffff888107ef75d0{i=143e,n=dir} > still in use (1) [unm > ount of hugetlbfs hugetlbfs]". > > Thanks, > Milklos > Thanks for the review. I realised that when I was doing patch 11 which changes d_for_each_positive_child() to use a cursor, but I didn't think the apply that understand back at this patch. There is only on user of cursors so it can be easily fixed as follows. Thanks, NeilBrown index 5a0d276379d1..91f535192ee2 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -169,6 +169,8 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int whence) hlist_del_init(&cursor->d_sib); if (to) hlist_add_behind(&cursor->d_sib, &to->d_sib); + else if (hlist_empty(&dentry->d_children) + dput_dlock(dentry); spin_unlock(&dentry->d_lock); dput(to); @@ -213,6 +215,8 @@ int dcache_readdir(struct file *file, struct dir_context *ctx) hlist_del_init(&cursor->d_sib); if (next) hlist_add_before(&cursor->d_sib, &next->d_sib); + else if (hlist_empty(&dentry->d_children)) + dput_dlock(dentry); spin_unlock(&dentry->d_lock); dput(next);