This is a note to let you know that I've just added the patch titled cifs: fix dentry lookups in directory handle cache to the 6.2-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: cifs-fix-dentry-lookups-in-directory-handle-cache.patch and it can be found in the queue-6.2 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. >From be4fde79812f02914e350bde0bc4cfeae8429378 Mon Sep 17 00:00:00 2001 From: Paulo Alcantara <pc@xxxxxxxxxxxxx> Date: Fri, 24 Mar 2023 13:56:33 -0300 Subject: cifs: fix dentry lookups in directory handle cache From: Paulo Alcantara <pc@xxxxxxxxxxxxx> commit be4fde79812f02914e350bde0bc4cfeae8429378 upstream. Get rid of any prefix paths in @path before lookup_positive_unlocked() as it will call ->lookup() which already adds those prefix paths through build_path_from_dentry(). This has caused a performance regression when mounting shares with a prefix path where readdir(2) would end up retrying several times to open bad directory names that contained duplicate prefix paths. Fix this by skipping any prefix paths in @path before calling lookup_positive_unlocked(). Fixes: e4029e072673 ("cifs: find and use the dentry for cached non-root directories also") Cc: stable@xxxxxxxxxxxxxxx # 6.1+ Signed-off-by: Paulo Alcantara (SUSE) <pc@xxxxxxxxxxxxx> Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- fs/cifs/cached_dir.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) --- a/fs/cifs/cached_dir.c +++ b/fs/cifs/cached_dir.c @@ -99,6 +99,23 @@ path_to_dentry(struct cifs_sb_info *cifs return dentry; } +static const char *path_no_prefix(struct cifs_sb_info *cifs_sb, + const char *path) +{ + size_t len = 0; + + if (!*path) + return path; + + if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) && + cifs_sb->prepath) { + len = strlen(cifs_sb->prepath) + 1; + if (unlikely(len > strlen(path))) + return ERR_PTR(-EINVAL); + } + return path + len; +} + /* * Open the and cache a directory handle. * If error then *cfid is not initialized. @@ -125,6 +142,7 @@ int open_cached_dir(unsigned int xid, st struct dentry *dentry = NULL; struct cached_fid *cfid; struct cached_fids *cfids; + const char *npath; if (tcon == NULL || tcon->cfids == NULL || tcon->nohandlecache || is_smb1_server(tcon->ses->server)) @@ -161,6 +179,20 @@ int open_cached_dir(unsigned int xid, st } /* + * Skip any prefix paths in @path as lookup_positive_unlocked() ends up + * calling ->lookup() which already adds those through + * build_path_from_dentry(). Also, do it earlier as we might reconnect + * below when trying to send compounded request and then potentially + * having a different prefix path (e.g. after DFS failover). + */ + npath = path_no_prefix(cifs_sb, path); + if (IS_ERR(npath)) { + rc = PTR_ERR(npath); + kfree(utf16_path); + return rc; + } + + /* * We do not hold the lock for the open because in case * SMB2_open needs to reconnect. * This is safe because no other thread will be able to get a ref @@ -252,10 +284,10 @@ int open_cached_dir(unsigned int xid, st (char *)&cfid->file_all_info)) cfid->file_all_info_is_valid = true; - if (!path[0]) + if (!npath[0]) dentry = dget(cifs_sb->root); else { - dentry = path_to_dentry(cifs_sb, path); + dentry = path_to_dentry(cifs_sb, npath); if (IS_ERR(dentry)) { rc = -ENOENT; goto oshr_free; Patches currently in stable-queue which might be from pc@xxxxxxxxxxxxx are queue-6.2/cifs-lock-chan_lock-outside-match_session.patch queue-6.2/smb3-lower-default-deferred-close-timeout-to-address-perf-regression.patch queue-6.2/cifs-do-not-poll-server-interfaces-too-regularly.patch queue-6.2/cifs-dump-pending-mids-for-all-channels-in-debugdata.patch queue-6.2/smb3-fix-unusable-share-after-force-unmount-failure.patch queue-6.2/cifs-empty-interface-list-when-server-doesn-t-support-query-interfaces.patch queue-6.2/cifs-print-session-id-while-listing-open-files.patch queue-6.2/cifs-fix-dentry-lookups-in-directory-handle-cache.patch queue-6.2/cifs-append-path-to-open_enter-trace-event.patch