All of lore.kernel.org
 help / color / mirror / Atom feed
From: Al Viro <viro@zeniv.linux.org.uk>
To: linux-cifs@vger.kernel.org
Cc: Steve French <sfrench@samba.org>, linux-fsdevel@vger.kernel.org
Subject: [PATCH 7/7] cifs: switch build_path_from_dentry() to using dentry_path_raw()
Date: Sat, 20 Mar 2021 04:33:04 +0000	[thread overview]
Message-ID: <20210320043304.1803623-7-viro@zeniv.linux.org.uk> (raw)
In-Reply-To: <20210320043304.1803623-1-viro@zeniv.linux.org.uk>

The cost is that we might need to flip '/' to '\\' in more than
just the prefix.  Needs profiling, but I suspect that we won't
get slowdown on that.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 fs/cifs/dir.c | 83 +++++++++++++++--------------------------------------------
 1 file changed, 21 insertions(+), 62 deletions(-)

diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 6e855f004f50..3febf667d119 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -93,20 +93,16 @@ char *
 build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
 				       bool prefix)
 {
-	struct dentry *temp;
-	int namelen;
 	int dfsplen;
 	int pplen = 0;
-	char *full_path = page;
-	char dirsep;
 	struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
 	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
-	unsigned seq;
+	char dirsep = CIFS_DIR_SEP(cifs_sb);
+	char *s;
 
 	if (unlikely(!page))
 		return ERR_PTR(-ENOMEM);
 
-	dirsep = CIFS_DIR_SEP(cifs_sb);
 	if (prefix)
 		dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
 	else
@@ -115,74 +111,37 @@ build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
 		pplen = cifs_sb->prepath ? strlen(cifs_sb->prepath) + 1 : 0;
 
-cifs_bp_rename_retry:
-	namelen = dfsplen + pplen;
-	seq = read_seqbegin(&rename_lock);
-	rcu_read_lock();
-	for (temp = direntry; !IS_ROOT(temp);) {
-		namelen += (1 + temp->d_name.len);
-		temp = temp->d_parent;
-	}
-	rcu_read_unlock();
-
-	if (namelen >= PAGE_SIZE)
+	s = dentry_path_raw(direntry, page, PAGE_SIZE);
+	if (IS_ERR(s))
+		return s;
+	if (s < (char *)page + pplen + dfsplen)
 		return ERR_PTR(-ENAMETOOLONG);
-
-	full_path[namelen] = 0;	/* trailing null */
-	rcu_read_lock();
-	for (temp = direntry; !IS_ROOT(temp);) {
-		spin_lock(&temp->d_lock);
-		namelen -= 1 + temp->d_name.len;
-		if (namelen < 0) {
-			spin_unlock(&temp->d_lock);
-			break;
-		} else {
-			full_path[namelen] = dirsep;
-			strncpy(full_path + namelen + 1, temp->d_name.name,
-				temp->d_name.len);
-			cifs_dbg(FYI, "name: %s\n", full_path + namelen);
-		}
-		spin_unlock(&temp->d_lock);
-		temp = temp->d_parent;
-	}
-	rcu_read_unlock();
-	if (namelen != dfsplen + pplen || read_seqretry(&rename_lock, seq)) {
-		cifs_dbg(FYI, "did not end path lookup where expected. namelen=%ddfsplen=%d\n",
-			 namelen, dfsplen);
-		/* presumably this is only possible if racing with a rename
-		of one of the parent directories  (we can not lock the dentries
-		above us to prevent this, but retrying should be harmless) */
-		goto cifs_bp_rename_retry;
-	}
-	/* DIR_SEP already set for byte  0 / vs \ but not for
-	   subsequent slashes in prepath which currently must
-	   be entered the right way - not sure if there is an alternative
-	   since the '\' is a valid posix character so we can not switch
-	   those safely to '/' if any are found in the middle of the prepath */
-	/* BB test paths to Windows with '/' in the midst of prepath */
-
 	if (pplen) {
-		int i;
-
 		cifs_dbg(FYI, "using cifs_sb prepath <%s>\n", cifs_sb->prepath);
-		memcpy(full_path+dfsplen+1, cifs_sb->prepath, pplen-1);
-		full_path[dfsplen] = dirsep;
-		for (i = 0; i < pplen-1; i++)
-			if (full_path[dfsplen+1+i] == '/')
-				full_path[dfsplen+1+i] = CIFS_DIR_SEP(cifs_sb);
+		s -= pplen;
+		memcpy(s + 1, cifs_sb->prepath, pplen - 1);
+		*s = '/';
 	}
+	if (dirsep != '/') {
+		/* BB test paths to Windows with '/' in the midst of prepath */
+		char *p;
 
+		for (p = s; *p; p++)
+			if (*p == '/')
+				*p = dirsep;
+	}
 	if (dfsplen) {
-		strncpy(full_path, tcon->treeName, dfsplen);
+		s -= dfsplen;
+		memcpy(page, tcon->treeName, dfsplen);
 		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
 			int i;
 			for (i = 0; i < dfsplen; i++) {
-				if (full_path[i] == '\\')
-					full_path[i] = '/';
+				if (s[i] == '\\')
+					s[i] = '/';
 			}
 		}
 	}
-	return full_path;
+	return s;
 }
 
 /*
-- 
2.11.0


  parent reply	other threads:[~2021-03-20  4:36 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-20  4:31 [RFC][PATCHSET] hopefully saner handling of pathnames in cifs Al Viro
2021-03-20  4:32 ` [PATCH 1/7] cifs: don't cargo-cult strndup() Al Viro
2021-03-20  4:32   ` [PATCH 2/7] cifs: constify get_normalized_path() properly Al Viro
2021-03-20  4:33   ` [PATCH 3/7] cifs: constify path argument of ->make_node() Al Viro
2021-03-20  4:33   ` [PATCH 4/7] cifs: constify pathname arguments in a bunch of helpers Al Viro
2021-03-20  4:33   ` [PATCH 5/7] cifs: make build_path_from_dentry() return const char * Al Viro
2021-03-20  4:33   ` [PATCH 6/7] cifs: allocate buffer in the caller of build_path_from_dentry() Al Viro
2021-03-20  4:33   ` Al Viro [this message]
2021-03-21 19:58 ` [RFC][PATCHSET] hopefully saner handling of pathnames in cifs Steve French
2021-03-22  2:19   ` Steve French
2021-03-22  2:38     ` Al Viro
2021-03-22  3:36       ` Steve French
2021-03-22  3:38         ` Steve French
2021-03-22 13:15           ` Aurélien Aptel
2021-03-23  5:04       ` Steve French
2021-03-24 15:28         ` Al Viro
2021-03-22 12:25 ` Jeff Layton

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210320043304.1803623-7-viro@zeniv.linux.org.uk \
    --to=viro@zeniv.linux.org.uk \
    --cc=linux-cifs@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=sfrench@samba.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.