afs: Make /afs/.<cell> as well as /afs/<cell> mountpoints
JIRA: https://issues.redhat.com/browse/RHEL-78217 commit 92f08e9d3cf0f8005ac6fcb931e3c388efc3ac49 Author: David Howells <dhowells@redhat.com> Date: Tue Jan 7 18:34:49 2025 +0000 afs: Make /afs/.<cell> as well as /afs/<cell> mountpoints When a cell is instantiated, automatically create an /afs/.<cell> mountpoint to match the /afs/<cell> mountpoint to match other AFS clients. Signed-off-by: David Howells <dhowells@redhat.com> Link: https://lore.kernel.org/r/20250107183454.608451-2-dhowells@redhat.com cc: Marc Dionne <marc.dionne@auristor.com> cc: linux-afs@lists.infradead.org Signed-off-by: Christian Brauner <brauner@kernel.org> Signed-off-by: Marc Dionne <mdionne@redhat.com>
This commit is contained in:
parent
43f4348ae2
commit
02c98f073f
|
@ -146,18 +146,20 @@ static struct afs_cell *afs_alloc_cell(struct afs_net *net,
|
|||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
cell->name = kmalloc(namelen + 1, GFP_KERNEL);
|
||||
cell->name = kmalloc(1 + namelen + 1, GFP_KERNEL);
|
||||
if (!cell->name) {
|
||||
kfree(cell);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
cell->net = net;
|
||||
cell->name[0] = '.';
|
||||
cell->name++;
|
||||
cell->name_len = namelen;
|
||||
for (i = 0; i < namelen; i++)
|
||||
cell->name[i] = tolower(name[i]);
|
||||
cell->name[i] = 0;
|
||||
|
||||
cell->net = net;
|
||||
refcount_set(&cell->ref, 1);
|
||||
atomic_set(&cell->active, 0);
|
||||
INIT_WORK(&cell->manager, afs_manage_cell_work);
|
||||
|
@ -211,7 +213,7 @@ parse_failed:
|
|||
if (ret == -EINVAL)
|
||||
printk(KERN_ERR "kAFS: bad VL server IP address\n");
|
||||
error:
|
||||
kfree(cell->name);
|
||||
kfree(cell->name - 1);
|
||||
kfree(cell);
|
||||
_leave(" = %d", ret);
|
||||
return ERR_PTR(ret);
|
||||
|
@ -502,7 +504,7 @@ static void afs_cell_destroy(struct rcu_head *rcu)
|
|||
afs_put_vlserverlist(net, rcu_access_pointer(cell->vl_servers));
|
||||
afs_unuse_cell(net, cell->alias_of, afs_cell_trace_unuse_alias);
|
||||
key_put(cell->anonymous_key);
|
||||
kfree(cell->name);
|
||||
kfree(cell->name - 1);
|
||||
kfree(cell);
|
||||
|
||||
afs_dec_cells_outstanding(net);
|
||||
|
@ -710,7 +712,8 @@ static void afs_deactivate_cell(struct afs_net *net, struct afs_cell *cell)
|
|||
afs_proc_cell_remove(cell);
|
||||
|
||||
mutex_lock(&net->proc_cells_lock);
|
||||
hlist_del_rcu(&cell->proc_link);
|
||||
if (!hlist_unhashed(&cell->proc_link))
|
||||
hlist_del_rcu(&cell->proc_link);
|
||||
afs_dynroot_rmdir(net, cell);
|
||||
mutex_unlock(&net->proc_cells_lock);
|
||||
|
||||
|
|
|
@ -271,7 +271,8 @@ const struct dentry_operations afs_dynroot_dentry_operations = {
|
|||
int afs_dynroot_mkdir(struct afs_net *net, struct afs_cell *cell)
|
||||
{
|
||||
struct super_block *sb = net->dynroot_sb;
|
||||
struct dentry *root, *subdir;
|
||||
struct dentry *root, *subdir, *dsubdir;
|
||||
char *dotname = cell->name - 1;
|
||||
int ret;
|
||||
|
||||
if (!sb || atomic_read(&sb->s_active) == 0)
|
||||
|
@ -286,34 +287,31 @@ int afs_dynroot_mkdir(struct afs_net *net, struct afs_cell *cell)
|
|||
goto unlock;
|
||||
}
|
||||
|
||||
/* Note that we're retaining an extra ref on the dentry */
|
||||
dsubdir = lookup_one_len(dotname, root, cell->name_len + 1);
|
||||
if (IS_ERR(dsubdir)) {
|
||||
ret = PTR_ERR(dsubdir);
|
||||
dput(subdir);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/* Note that we're retaining extra refs on the dentries. */
|
||||
subdir->d_fsdata = (void *)1UL;
|
||||
dsubdir->d_fsdata = (void *)1UL;
|
||||
ret = 0;
|
||||
unlock:
|
||||
inode_unlock(root->d_inode);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove a manually added cell mount directory.
|
||||
* - The caller must hold net->proc_cells_lock
|
||||
*/
|
||||
void afs_dynroot_rmdir(struct afs_net *net, struct afs_cell *cell)
|
||||
static void afs_dynroot_rm_one_dir(struct dentry *root, const char *name, size_t name_len)
|
||||
{
|
||||
struct super_block *sb = net->dynroot_sb;
|
||||
struct dentry *root, *subdir;
|
||||
|
||||
if (!sb || atomic_read(&sb->s_active) == 0)
|
||||
return;
|
||||
|
||||
root = sb->s_root;
|
||||
inode_lock(root->d_inode);
|
||||
struct dentry *subdir;
|
||||
|
||||
/* Don't want to trigger a lookup call, which will re-add the cell */
|
||||
subdir = try_lookup_one_len(cell->name, root, cell->name_len);
|
||||
subdir = try_lookup_one_len(name, root, name_len);
|
||||
if (IS_ERR_OR_NULL(subdir)) {
|
||||
_debug("lookup %ld", PTR_ERR(subdir));
|
||||
goto no_dentry;
|
||||
return;
|
||||
}
|
||||
|
||||
_debug("rmdir %pd %u", subdir, d_count(subdir));
|
||||
|
@ -324,8 +322,24 @@ void afs_dynroot_rmdir(struct afs_net *net, struct afs_cell *cell)
|
|||
dput(subdir);
|
||||
}
|
||||
dput(subdir);
|
||||
no_dentry:
|
||||
inode_unlock(root->d_inode);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove a manually added cell mount directory.
|
||||
* - The caller must hold net->proc_cells_lock
|
||||
*/
|
||||
void afs_dynroot_rmdir(struct afs_net *net, struct afs_cell *cell)
|
||||
{
|
||||
struct super_block *sb = net->dynroot_sb;
|
||||
char *dotname = cell->name - 1;
|
||||
|
||||
if (!sb || atomic_read(&sb->s_active) == 0)
|
||||
return;
|
||||
|
||||
inode_lock(sb->s_root->d_inode);
|
||||
afs_dynroot_rm_one_dir(sb->s_root, cell->name, cell->name_len);
|
||||
afs_dynroot_rm_one_dir(sb->s_root, dotname, cell->name_len + 1);
|
||||
inode_unlock(sb->s_root->d_inode);
|
||||
_leave("");
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue