mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
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>
This commit is contained in:
parent
3f5f8ee991
commit
623f0aa1ec
|
|
@ -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 @@ static struct dentry *exfat_lookup(struct inode *dir, struct dentry *dentry,
|
|||
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 */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user