In the Linux kernel pathname lookup can be done in either RCU or REF mode. The documentation says that:
No ``inode->i_rwsem`` or even ``rename_lock``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<...>. If some other thread does
take ``i_rwsem`` and modifies the directory in a way that RCU-walk needs
to notice, the result will be either that RCU-walk fails to find the
dentry that it is looking for, or it will find a dentry which
``read_seqretry()`` won't validate. In either case it will drop down to
REF-walk mode which can take whatever locks are needed.
From chmod source code:
int chmod_common(const struct path *path, umode_t mode)
{
...
inode_lock(inode);
error = security_path_chmod(path, mode);
if (error)
goto out_unlock;
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
error = notify_change(mnt_idmap(path->mnt), path->dentry,
&newattrs, &delegated_inode);
out_unlock:
inode_unlock(inode);
...
}
it does take inode->i_rwsem
by calling inode_{lock|unlock}
, so if one thread was doing chmod
and another was performing lookup
(it first must try RCU mode, let’s say that dentry
is already cached). To be able to fall back to REF mode and use locks or drop to filesystem specific code it needs to invalidate dentry
by calling d_invalidate
(I’m not sure in this part, maybe there are other mechanism to do so), but in case of chmod
it will call fsnotify_dentry
, but it doesn’t seem to invalidate or to remove the dentry
from the dcache
(I can be wrong here).
So, how exactly does chmod
notify lookup
that inode
has been changed?
4