On Tue, Jan 07, 2025 at 02:25:09PM +0000, David Howells wrote: > @@ -247,9 +285,13 @@ static struct dentry *afs_dynroot_lookup(struct inode *dir, struct dentry *dentr > return ERR_PTR(-ENAMETOOLONG); > } > > - if (dentry->d_name.len == 5 && > - memcmp(dentry->d_name.name, "@cell", 5) == 0) > - return afs_lookup_atcell(dentry); > + if (dentry->d_name.len == sizeof(afs_atcell) - 1 && > + memcmp(dentry->d_name.name, afs_atcell, sizeof(afs_atcell) - 1) == 0) > + return afs_lookup_atcell(dentry, false); > + > + if (dentry->d_name.len == sizeof(afs_dotatcell) - 1 && > + memcmp(dentry->d_name.name, afs_dotatcell, sizeof(afs_dotatcell) - 1) == 0) > + return afs_lookup_atcell(dentry, true); Ow... That looks just painful. > return d_splice_alias(afs_try_auto_mntpt(dentry, dir), dentry); > } > @@ -343,6 +385,40 @@ void afs_dynroot_rmdir(struct afs_net *net, struct afs_cell *cell) > +static int afs_dynroot_symlink(struct afs_net *net) > +{ > + struct super_block *sb = net->dynroot_sb; > + struct dentry *root, *symlink, *dsymlink; > + int ret; > + > + /* Let the ->lookup op do the creation */ > + root = sb->s_root; > + inode_lock(root->d_inode); > + symlink = lookup_one_len(afs_atcell, root, sizeof(afs_atcell) - 1); > + if (IS_ERR(symlink)) { > + ret = PTR_ERR(symlink); > + goto unlock; > + } > + > + dsymlink = lookup_one_len(afs_dotatcell, root, sizeof(afs_dotatcell) - 1); > + if (IS_ERR(dsymlink)) { > + ret = PTR_ERR(dsymlink); > + dput(symlink); > + goto unlock; > + } Just allocate those child dentries and call your afs_lookup_atcell() for them. No need to keep that mess in ->lookup() - you are keeping those suckers cached now, so...