diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2026-04-24 22:29:06 +0900 |
|---|---|---|
| committer | Namjae Jeon <linkinjeon@kernel.org> | 2026-05-23 13:24:14 +0900 |
| commit | 9fb8a7fed397f19807f3dfebd25a698eb6e8765b (patch) | |
| tree | ccb514a806dd2e2124976dd244373817d950f094 /fs | |
| parent | 9514cf5e2f34017155563c68cca66e6eb175bce2 (diff) | |
| download | linux-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.c | 56 |
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 */ |
