aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
authorAl Viro <viro@zeniv.linux.org.uk>2026-04-24 22:29:06 +0900
committerNamjae Jeon <linkinjeon@kernel.org>2026-05-23 13:24:14 +0900
commit9fb8a7fed397f19807f3dfebd25a698eb6e8765b (patch)
treeccb514a806dd2e2124976dd244373817d950f094 /fs
parent9514cf5e2f34017155563c68cca66e6eb175bce2 (diff)
downloadlinux-next-history-9fb8a7fed397f19807f3dfebd25a698eb6e8765b.tar.gz
exfat: simplify exfat_lookup()
1) d_splice_alias() handles ERR_PTR() for inode just fine 2) no need to even look for existing aliases in case of directory inodes; just punt to d_splice_alias(), it'll do the right thing 3) no need to bother with 'd_unhashed(alias)' case - d_find_alias() would've returned that only in case of a directory, and d_splice_alias() will handle that just fine on its own. 4) exfat_d_anon_disconn() is entirely pointless now - we only get to evaluating it in case dentry->d_parent == alias->d_parent and alias being a non-directory. But in that case IS_ROOT(alias) can't possibly be true - that would've reqiured alias == alias->d_parent, i.e alias == dentry->d_parent and dentry->d_parent is guaranteed to be a directory. So exfat_d_anon_disconn() would always return false when it's called, which makes && !exfat_d_anon_disconn(alias) a no-op. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Reviewed-by: Sungjong Seo <sj1557.seo@samsung.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/exfat/namei.c56
1 files changed, 13 insertions, 43 deletions
diff --git a/fs/exfat/namei.c b/fs/exfat/namei.c
index 2c5636634b4a4..27db6ebad57db 100644
--- a/fs/exfat/namei.c
+++ b/fs/exfat/namei.c
@@ -705,71 +705,44 @@ static int exfat_find(struct inode *dir, const struct qstr *qname,
return 0;
}
-static int exfat_d_anon_disconn(struct dentry *dentry)
-{
- return IS_ROOT(dentry) && (dentry->d_flags & DCACHE_DISCONNECTED);
-}
-
static struct dentry *exfat_lookup(struct inode *dir, struct dentry *dentry,
unsigned int flags)
{
struct super_block *sb = dir->i_sb;
- struct inode *inode;
+ struct inode *inode = NULL;
struct dentry *alias;
struct exfat_dir_entry info;
int err;
loff_t i_pos;
- mode_t i_mode;
mutex_lock(&EXFAT_SB(sb)->s_lock);
err = exfat_find(dir, &dentry->d_name, &info);
if (err) {
- if (err == -ENOENT) {
- inode = NULL;
- goto out;
- }
- goto unlock;
+ if (unlikely(err != -ENOENT))
+ inode = ERR_PTR(err);
+ goto out;
}
i_pos = exfat_make_i_pos(&info);
inode = exfat_build_inode(sb, &info, i_pos);
- err = PTR_ERR_OR_ZERO(inode);
- if (err)
- goto unlock;
+ if (IS_ERR(inode) || S_ISDIR(inode->i_mode))
+ goto out;
- i_mode = inode->i_mode;
alias = d_find_alias(inode);
/*
* Checking "alias->d_parent == dentry->d_parent" to make sure
* FS is not corrupted (especially double linked dir).
*/
- if (alias && alias->d_parent == dentry->d_parent &&
- !exfat_d_anon_disconn(alias)) {
-
+ if (alias && alias->d_parent == dentry->d_parent) {
/*
- * Unhashed alias is able to exist because of revalidate()
- * called by lookup_fast. You can easily make this status
- * by calling create and lookup concurrently
- * In such case, we reuse an alias instead of new dentry
+ * This inode has a hashed alias dentry with different
+ * name. This means, the user did ->lookup() by an
+ * another name (longname vs 8.3 alias of it) in past.
+ *
+ * Switch to new one for reason of locality if possible.
*/
- if (d_unhashed(alias)) {
- WARN_ON(alias->d_name.hash_len !=
- dentry->d_name.hash_len);
- exfat_info(sb, "rehashed a dentry(%p) in read lookup",
- alias);
- d_drop(dentry);
- d_rehash(alias);
- } else if (!S_ISDIR(i_mode)) {
- /*
- * This inode has non anonymous-DCACHE_DISCONNECTED
- * dentry. This means, the user did ->lookup() by an
- * another name (longname vs 8.3 alias of it) in past.
- *
- * Switch to new one for reason of locality if possible.
- */
- d_move(alias, dentry);
- }
+ d_move(alias, dentry);
iput(inode);
mutex_unlock(&EXFAT_SB(sb)->s_lock);
return alias;
@@ -781,9 +754,6 @@ out:
exfat_d_version_set(dentry, inode_query_iversion(dir));
return d_splice_alias(inode, dentry);
-unlock:
- mutex_unlock(&EXFAT_SB(sb)->s_lock);
- return ERR_PTR(err);
}
/* remove an entry, BUT don't truncate */