Thread (20 messages) 20 messages, 5 authors, 2025-08-13

Re: [RFC PATCH 1/6] fs/9p: Add ability to identify inode by path for .L

From: Mickaël Salaün <mic@digikod.net>
Date: 2025-08-13 07:54:48
Also in: linux-fsdevel, v9fs

On Wed, Aug 13, 2025 at 12:57:49AM +0100, Tingmao Wang wrote:
Thanks for the review :)  I will try to send a v2 in the coming weeks with
the two changes you suggested and the changes to cached mode as suggested
by Dominique (plus rename handling).  (will also try to figure out how to
test with xfstests)

On 8/8/25 09:32, Mickaël Salaün wrote:
quoted
[...]
quoted
On 7/5/25 01:25, Al Viro wrote:
quoted
On Sun, Apr 06, 2025 at 09:43:02PM +0100, Tingmao Wang wrote:
quoted
+bool ino_path_compare(struct v9fs_ino_path *ino_path,
+			     struct dentry *dentry)
+{
+	struct dentry *curr = dentry;
+	struct qstr *curr_name;
+	struct name_snapshot *compare;
+	ssize_t i;
+
+	lockdep_assert_held_read(&v9fs_dentry2v9ses(dentry)->rename_sem);
+
+	rcu_read_lock();
+	for (i = ino_path->nr_components - 1; i >= 0; i--) {
+		if (curr->d_parent == curr) {
+			/* We're supposed to have more components to walk */
+			rcu_read_unlock();
+			return false;
+		}
+		curr_name = &curr->d_name;
+		compare = &ino_path->names[i];
+		/*
+		 * We can't use hash_len because it is salted with the parent
+		 * dentry pointer.  We could make this faster by pre-computing our
+		 * own hashlen for compare and ino_path outside, probably.
+		 */
+		if (curr_name->len != compare->name.len) {
+			rcu_read_unlock();
+			return false;
+		}
+		if (strncmp(curr_name->name, compare->name.name,
+			    curr_name->len) != 0) {
... without any kind of protection for curr_name.  Incidentally,
what about rename()?  Not a cross-directory one, just one that
changes the name of a subdirectory within the same parent?
As far as I can tell, in v9fs_vfs_rename, v9ses->rename_sem is taken for
both same-parent and different parent renames, so I think we're safe here
(and hopefully for any v9fs dentries, nobody should be causing d_name to
change except for ourselves when we call d_move in v9fs_vfs_rename?  If
yes then because we also take v9ses->rename_sem, in theory we should be
fine here...?)
A lockdep_assert_held() or similar and a comment would make this clear.
I can add a comment, but there is already a lockdep_assert_held_read of
the v9fs rename sem at the top of this function.
I wrote this comment before reading your new version beneath, which
already have this lockdep, so no need to change anything. :)
quoted hunk ↗ jump to hunk
quoted
[...]
quoted
/*
 * Must hold rename_sem due to traversing parents
 */
bool ino_path_compare(struct v9fs_ino_path *ino_path, struct dentry *dentry)
{
	struct dentry *curr = dentry;
	struct name_snapshot *compare;
	ssize_t i;

	lockdep_assert_held_read(&v9fs_dentry2v9ses(dentry)->rename_sem);

	rcu_read_lock();
	for (i = ino_path->nr_components - 1; i >= 0; i--) {
		if (curr->d_parent == curr) {
			/* We're supposed to have more components to walk */
			rcu_read_unlock();
			return false;
		}
		compare = &ino_path->names[i];
		if (!d_same_name(curr, curr->d_parent, &compare->name)) {
			rcu_read_unlock();
			return false;
		}
		curr = curr->d_parent;
	}
	rcu_read_unlock();
	if (curr != curr->d_parent) {
Looking at this again I think this check probably needs to be done inside
RCU, will fix as below:
quoted
quoted
		/* dentry is deeper than ino_path */
		return false;
	}
	return true;
}
diff --git a/fs/9p/ino_path.c b/fs/9p/ino_path.c
index 0000b4964df0..7264003cb087 100644
--- a/fs/9p/ino_path.c
+++ b/fs/9p/ino_path.c
@@ -77,13 +77,15 @@ void free_ino_path(struct v9fs_ino_path *path)
 }
 
 /*
- * Must hold rename_sem due to traversing parents
+ * Must hold rename_sem due to traversing parents.  Returns whether
+ * ino_path matches with the path of a v9fs dentry.
  */
 bool ino_path_compare(struct v9fs_ino_path *ino_path, struct dentry *dentry)
 {
 	struct dentry *curr = dentry;
 	struct name_snapshot *compare;
 	ssize_t i;
+	bool ret;
 
 	lockdep_assert_held_read(&v9fs_dentry2v9ses(dentry)->rename_sem);
 
@@ -101,10 +103,8 @@ bool ino_path_compare(struct v9fs_ino_path *ino_path, struct dentry *dentry)
 		}
 		curr = curr->d_parent;
 	}
+	/* Comparison fails if dentry is deeper than ino_path */
+	ret = (curr == curr->d_parent);
 	rcu_read_unlock();
-	if (curr != curr->d_parent) {
-		/* dentry is deeper than ino_path */
-		return false;
-	}
-	return true;
+	return ret;
 }
Looks good
quoted
I like this new version.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help