From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 8AA54CA0EC4 for ; Wed, 13 Aug 2025 00:05:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=Qr+IqnRuSlDkHyFoN/sJwPITYwHJggwkYv4hfZlQ2Yg=; b=1ZM9E9LPJ1Rg3lK6Q/iPNPUiEG xPWcE1lYTmNI7AnCbFx7709ai6Qq/Ju57sF0JcYnEnM51HNqK+oGx8dX/B9cvrdlB0FGBad+zpd4e lb8d9VLdqWOVzAbBplTTf+sO63jkqv8AfjQmRKA9frcxOmdBFQcf9MVleepKtRljJo9R9EReQwIN8 POmv9+40u7Vmd42TcsF91+xpjBSFh0kHoXgrxz7LtEdUXUMaENBwuHiFv79QDKpVxi0ylM8V3Yqxp UlLSDfxSk4KUKEcefcZ8diCqBRxLZAvL8Ou9Yl1rzkXGPphPch+5S9XYAWrUUTP5pE/DNTmVe1wGw 84dsubDQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.2 #2 (Red Hat Linux)) id 1ulyzI-0000000CG7D-1PyK; Wed, 13 Aug 2025 00:05:04 +0000 Received: from casper.infradead.org ([2001:8b0:10b:1236::1]) by bombadil.infradead.org with esmtps (Exim 4.98.2 #2 (Red Hat Linux)) id 1ulyzG-0000000CG6M-3JYz; Wed, 13 Aug 2025 00:05:02 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Sender:Reply-To: Content-Type:Content-ID:Content-Description; bh=Qr+IqnRuSlDkHyFoN/sJwPITYwHJggwkYv4hfZlQ2Yg=; b=LnUCT/j+0txLywIEIH7hI0cZp9 YqGykkmZZczYfXuZa7WxclT8rbBkIJYJ7ymQkb+0k7CcP950zQD81X839j64lj5iCUNV5aunF0Ezs /7VG/K9+cC6220ELUbl0gft5dQ8qfNXonHmF6Xnzo+CV94ZWWEmywdqU4lhrMvn3EE6ZUiPmcSD9W lk3b6dsUqks1ur0F1r22xwlZAfwfl1eX+2LyEt6OfDruBPJ7kUdDyIKMbthh9bt4VK+SYFeAxWXf4 FyErOY9iYNJRpj/gQHOSKEXK3+xTBfD6ycnqtha7Q5ca24ro2QQdPrO1SXa6VBgRWnwXMOJ0boz6K he8732wQ==; Received: from neil.brown.name ([103.29.64.221]) by casper.infradead.org with esmtps (Exim 4.98.2 #2 (Red Hat Linux)) id 1ulyzC-00000003U7S-1XKD; Wed, 13 Aug 2025 00:05:01 +0000 Received: from 196.186.233.220.static.exetel.com.au ([220.233.186.196] helo=home.neil.brown.name) by neil.brown.name with esmtp (Exim 4.95) (envelope-from ) id 1ulynO-005Y29-KL; Tue, 12 Aug 2025 23:52:48 +0000 From: NeilBrown To: Alexander Viro , Christian Brauner , Jan Kara Cc: David Howells , Marc Dionne , Xiubo Li , Ilya Dryomov , Tyler Hicks , Miklos Szeredi , Richard Weinberger , Anton Ivanov , Johannes Berg , Trond Myklebust , Anna Schumaker , Chuck Lever , Jeff Layton , Amir Goldstein , Steve French , Namjae Jeon , Carlos Maiolino , linux-fsdevel@vger.kernel.org, linux-afs@lists.infradead.org, netfs@lists.linux.dev, ceph-devel@vger.kernel.org, ecryptfs@vger.kernel.org, linux-um@lists.infradead.org, linux-nfs@vger.kernel.org, linux-unionfs@vger.kernel.org, linux-cifs@vger.kernel.org, linux-xfs@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 08/11] VFS: allow d_splice_alias() and d_add() to work on hashed dentries. Date: Tue, 12 Aug 2025 12:25:11 +1000 Message-ID: <20250812235228.3072318-9-neil@brown.name> X-Mailer: git-send-email 2.50.0.107.gf914562f5916.dirty In-Reply-To: <20250812235228.3072318-1-neil@brown.name> References: <20250812235228.3072318-1-neil@brown.name> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250813_010459_522412_B84974D5 X-CRM114-Status: GOOD ( 15.77 ) X-BeenThere: linux-um@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-um" Errors-To: linux-um-bounces+linux-um=archiver.kernel.org@lists.infradead.org Proposed locking changes will require a dentry to remain hashed during all directory operations which are currently protected by i_rwsem, or for there to be a controlled transition from one hashed dentry to another which maintains the lock - which will then be on the dentry. The current practice of dropping (unhashing) a dentry before calling d_splice_alias() and d_add() defeats this need. This patch changes d_splice_alias() and d_add() to accept a hashed dentry and to only drop it when necessary immediately before an alternate dentry is hashed. These functions will, in a subsequent patch, transfer the dentry locking across so that the name remains locked in the directory. Signed-off-by: NeilBrown --- Documentation/filesystems/vfs.rst | 4 ++-- fs/ceph/file.c | 2 -- fs/ceph/inode.c | 3 --- fs/dcache.c | 8 +++++--- fs/fuse/dir.c | 1 - fs/hostfs/hostfs_kern.c | 1 - fs/nfs/dir.c | 5 +---- fs/nfs/nfs4proc.c | 1 - fs/smb/client/dir.c | 1 - 9 files changed, 8 insertions(+), 18 deletions(-) diff --git a/Documentation/filesystems/vfs.rst b/Documentation/filesystems/vfs.rst index 486a91633474..642dd6afb139 100644 --- a/Documentation/filesystems/vfs.rst +++ b/Documentation/filesystems/vfs.rst @@ -580,8 +580,8 @@ otherwise noted. dentry before the first mkdir returns. If there is any chance this could happen, then the new inode - should be d_drop()ed and attached with d_splice_alias(). The - returned dentry (if any) should be returned by ->mkdir(). + should be attached with d_splice_alias(). The returned dentry + (if any) should be returned by ->mkdir(). ``rmdir`` called by the rmdir(2) system call. Only required if you want diff --git a/fs/ceph/file.c b/fs/ceph/file.c index c02f100f8552..27eb1ac06177 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -755,8 +755,6 @@ static int ceph_finish_async_create(struct inode *dir, struct inode *inode, unlock_new_inode(inode); } if (d_in_lookup(dentry) || d_really_is_negative(dentry)) { - if (!d_unhashed(dentry)) - d_drop(dentry); dn = d_splice_alias(inode, dentry); WARN_ON_ONCE(dn && dn != dentry); } diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index fc543075b827..7acd6ac0d50f 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -1480,9 +1480,6 @@ static int splice_dentry(struct dentry **pdn, struct inode *in) } } - /* dn must be unhashed */ - if (!d_unhashed(dn)) - d_drop(dn); realdn = d_splice_alias(in, dn); if (IS_ERR(realdn)) { pr_err_client(cl, "error %ld %p inode %p ino %llx.%llx\n", diff --git a/fs/dcache.c b/fs/dcache.c index 60046ae23d51..0db256098adb 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -2709,7 +2709,11 @@ static inline void __d_add(struct dentry *dentry, struct inode *inode, raw_write_seqcount_end(&dentry->d_seq); fsnotify_update_flags(dentry); } - __d_rehash(dentry); + if (d_unhashed(dentry)) + __d_rehash(dentry); + else if (inode && (dentry->d_flags & + (DCACHE_LRU_LIST|DCACHE_SHRINK_LIST)) == DCACHE_LRU_LIST) + this_cpu_dec(nr_dentry_negative); if (dir) end_dir_add(dir, n, d_wait); spin_unlock(&dentry->d_lock); @@ -2990,8 +2994,6 @@ struct dentry *d_splice_alias_ops(struct inode *inode, struct dentry *dentry, if (IS_ERR(inode)) return ERR_CAST(inode); - BUG_ON(!d_unhashed(dentry)); - if (!inode) goto out; diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 2d817d7cab26..60e7763da8c8 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -834,7 +834,6 @@ static struct dentry *create_new_entry(struct mnt_idmap *idmap, struct fuse_moun } kfree(forget); - d_drop(entry); d = d_splice_alias(inode, entry); if (IS_ERR(d)) return d; diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 01e516175bcd..8e51fc623301 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -700,7 +700,6 @@ static struct dentry *hostfs_mkdir(struct mnt_idmap *idmap, struct inode *ino, dentry = ERR_PTR(err); } else { inode = hostfs_iget(dentry->d_sb, file); - d_drop(dentry); dentry = d_splice_alias(inode, dentry); } __putname(file); diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index d81217923936..250a826d5480 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -2136,7 +2136,6 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, err = PTR_ERR(inode); trace_nfs_atomic_open_exit(dir, ctx, open_flags, err); put_nfs_open_context(ctx); - d_drop(dentry); switch (err) { case -ENOENT: d_splice_alias(NULL, dentry); @@ -2157,6 +2156,7 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, default: break; } + d_drop(dentry); goto out; } file->f_mode |= FMODE_CAN_ODIRECT; @@ -2304,8 +2304,6 @@ nfs_add_or_obtain(struct dentry *dentry, struct nfs_fh *fhandle, struct dentry *d; int error; - d_drop(dentry); - if (fhandle->size == 0) { error = NFS_PROTO(dir)->lookup(dir, dentry, &dentry->d_name, fhandle, fattr); @@ -2652,7 +2650,6 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) old_dentry, dentry); trace_nfs_link_enter(inode, dir, dentry); - d_drop(dentry); if (S_ISREG(inode->i_mode)) nfs_sync_inode(inode); error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name); diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 7d2b67e06cc3..d8739c286a99 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -3175,7 +3175,6 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata, dentry = opendata->dentry; if (d_really_is_negative(dentry)) { struct dentry *alias; - d_drop(dentry); alias = d_splice_alias(igrab(state->inode), dentry); /* d_splice_alias() can't fail here - it's a non-directory */ if (alias) { diff --git a/fs/smb/client/dir.c b/fs/smb/client/dir.c index 5223edf6d11a..8cbc284c5005 100644 --- a/fs/smb/client/dir.c +++ b/fs/smb/client/dir.c @@ -439,7 +439,6 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned goto out_err; } - d_drop(direntry); d_add(direntry, newinode); out: -- 2.50.0.107.gf914562f5916.dirty