Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 34286d66 authored by Nick Piggin's avatar Nick Piggin
Browse files

fs: rcu-walk aware d_revalidate method



Require filesystems be aware of .d_revalidate being called in rcu-walk
mode (nd->flags & LOOKUP_RCU). For now do a simple push down, returning
-ECHILD from all implementations.

Signed-off-by: default avatarNick Piggin <npiggin@kernel.dk>
parent 44a7d7a8
Loading
Loading
Loading
Loading
+9 −9
Original line number Diff line number Diff line
@@ -9,7 +9,7 @@ be able to use diff(1).

--------------------------- dentry_operations --------------------------
prototypes:
	int (*d_revalidate)(struct dentry *, int);
	int (*d_revalidate)(struct dentry *, struct nameidata *);
	int (*d_hash)(const struct dentry *, const struct inode *,
			struct qstr *);
	int (*d_compare)(const struct dentry *, const struct inode *,
@@ -21,14 +21,14 @@ prototypes:
	char *(*d_dname)((struct dentry *dentry, char *buffer, int buflen);

locking rules:
		rename_lock	->d_lock	may block
d_revalidate:	no		no		yes
d_hash		no		no		no
d_compare:	yes		no		no
d_delete:	no		yes		no
d_release:	no		no		yes
d_iput:		no		no		yes
d_dname:	no		no		no
		rename_lock	->d_lock	may block	rcu-walk
d_revalidate:	no		no		yes (ref-walk)	maybe
d_hash		no		no		no		maybe
d_compare:	yes		no		no		maybe
d_delete:	no		yes		no		no
d_release:	no		no		yes		no
d_iput:		no		no		yes		no
d_dname:	no		no		no		no

--------------------------- inode_operations --------------------------- 
prototypes:
+2 −3
Original line number Diff line number Diff line
@@ -317,11 +317,10 @@ The detailed design for rcu-walk is like this:
The cases where rcu-walk cannot continue are:
* NULL dentry (ie. any uncached path element)
* parent with d_inode->i_op->permission or ACLs
* dentries with d_revalidate
* Following links

In future patches, permission checks and d_revalidate become rcu-walk aware. It
may be possible eventually to make following links rcu-walk aware.
In future patches, permission checks become rcu-walk aware. It may be possible
eventually to make following links rcu-walk aware.

Uncached path elements will always require dropping to ref-walk mode, at the
very least because i_mutex needs to be grabbed, and objects allocated.
+20 −0
Original line number Diff line number Diff line
@@ -360,3 +360,23 @@ i_dentry to be reinitialized before it is freed, so an:
  INIT_LIST_HEAD(&inode->i_dentry);

must be done in the RCU callback.

--
[recommended]
	vfs now tries to do path walking in "rcu-walk mode", which avoids
atomic operations and scalability hazards on dentries and inodes (see
Documentation/filesystems/path-walk.txt). d_hash and d_compare changes (above)
are examples of the changes required to support this. For more complex
filesystem callbacks, the vfs drops out of rcu-walk mode before the fs call, so
no changes are required to the filesystem. However, this is costly and loses
the benefits of rcu-walk mode. We will begin to add filesystem callbacks that
are rcu-walk aware, shown below. Filesystems should take advantage of this
where possible.

--
[mandatory]
	d_revalidate is a callback that is made on every path element (if
the filesystem provides it), which requires dropping out of rcu-walk mode. This
may now be called in rcu-walk mode (nd->flags & LOOKUP_RCU). -ECHILD should be
returned if the filesystem cannot handle rcu-walk. See
Documentation/filesystems/vfs.txt for more details.
+9 −0
Original line number Diff line number Diff line
@@ -863,6 +863,15 @@ struct dentry_operations {
	dcache. Most filesystems leave this as NULL, because all their
	dentries in the dcache are valid

	d_revalidate may be called in rcu-walk mode (nd->flags & LOOKUP_RCU).
	If in rcu-walk mode, the filesystem must revalidate the dentry without
	blocking or storing to the dentry, d_parent and d_inode should not be
	used without care (because they can go NULL), instead nd->inode should
	be used.

	If a situation is encountered that rcu-walk cannot handle, return
	-ECHILD and it will be called again in ref-walk mode.

  d_hash: called when the VFS adds a dentry to the hash table. The first
	dentry passed to d_hash is the parent directory that the name is
	to be hashed into. The inode is the dentry's inode.
+4 −1
Original line number Diff line number Diff line
@@ -161,6 +161,9 @@ static int autofs_revalidate(struct dentry * dentry, struct nameidata *nd)
	struct autofs_dir_ent *ent;
	int res;

	if (nd->flags & LOOKUP_RCU)
		return -ECHILD;

	lock_kernel();
	dir = dentry->d_parent->d_inode;
	sbi = autofs_sbi(dir->i_sb);
Loading