From: NeilBrown <[email protected]> 1/ exfat_d_anon_disconn() serves no purpose. It is only called (on alias) when alias->d_parent == dentry->d_parent and in that case IS_ROOT(dentry) will return false, so the whole function will return false. So we can remove it.
2/ When an alias for the inode is found in the same parent it is always sufficient to d_move() the alias to the new name. This will keep just one dentry around when there are multiple effective names, and it will always show the most recently used name, which appears to be the intention. Signed-off-by: NeilBrown <[email protected]> --- fs/exfat/namei.c | 36 +++++++----------------------------- 1 file changed, 7 insertions(+), 29 deletions(-) diff --git a/fs/exfat/namei.c b/fs/exfat/namei.c index 670116ae9ec8..e04cda7425da 100644 --- a/fs/exfat/namei.c +++ b/fs/exfat/namei.c @@ -711,11 +711,6 @@ 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) { @@ -750,32 +745,15 @@ static struct dentry *exfat_lookup(struct inode *dir, struct dentry *dentry, * 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 + * As EXFAT does not support hard-links this must + * be an alternate name for the same file, + * possibly longname vs 8.3 alias. + * Rather than allocating a new dentry, use the old + * one but keep the most recently used name. */ - 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; -- 2.50.0.107.gf914562f5916.dirty
