afs: Display manually added cells in dynamic root mount

Alter the dynroot mount so that cells created by manipulation of
/proc/fs/afs/cells and /proc/fs/afs/rootcell and by specification of a root
cell as a module parameter will cause directories for those cells to be
created in the dynamic root superblock for the network namespace[*].

To this end:

 (1) Only one dynamic root superblock is now created per network namespace
     and this is shared between all attempts to mount it.  This makes it
     easier to find the superblock to modify.

 (2) When a dynamic root superblock is created, the list of cells is walked
     and directories created for each cell already defined.

 (3) When a new cell is added, if a dynamic root superblock exists, a
     directory is created for it.

 (4) When a cell is destroyed, the directory is removed.

 (5) These directories are created by calling lookup_one_len() on the root
     dir which automatically creates them if they don't exist.

[*] Inasmuch as network namespaces are currently supported here.

Signed-off-by: David Howells <dhowells@redhat.com>
This commit is contained in:
David Howells
2018-06-15 15:19:22 +01:00
parent c88d5a7fff
commit 0da0b7fd73
7 changed files with 200 additions and 27 deletions

View File

@@ -355,12 +355,17 @@ static int afs_test_super(struct super_block *sb, void *data)
return (as->net_ns == as1->net_ns &&
as->volume &&
as->volume->vid == as1->volume->vid);
as->volume->vid == as1->volume->vid &&
!as->dyn_root);
}
static int afs_dynroot_test_super(struct super_block *sb, void *data)
{
return false;
struct afs_super_info *as1 = data;
struct afs_super_info *as = AFS_FS_S(sb);
return (as->net_ns == as1->net_ns &&
as->dyn_root);
}
static int afs_set_super(struct super_block *sb, void *data)
@@ -420,10 +425,14 @@ static int afs_fill_super(struct super_block *sb,
if (!sb->s_root)
goto error;
if (params->dyn_root)
if (as->dyn_root) {
sb->s_d_op = &afs_dynroot_dentry_operations;
else
ret = afs_dynroot_populate(sb);
if (ret < 0)
goto error;
} else {
sb->s_d_op = &afs_fs_dentry_operations;
}
_leave(" = 0");
return 0;
@@ -458,6 +467,25 @@ static void afs_destroy_sbi(struct afs_super_info *as)
}
}
static void afs_kill_super(struct super_block *sb)
{
struct afs_super_info *as = AFS_FS_S(sb);
struct afs_net *net = afs_net(as->net_ns);
if (as->dyn_root)
afs_dynroot_depopulate(sb);
/* Clear the callback interests (which will do ilookup5) before
* deactivating the superblock.
*/
if (as->volume)
afs_clear_callback_interests(net, as->volume->servers);
kill_anon_super(sb);
if (as->volume)
afs_deactivate_volume(as->volume);
afs_destroy_sbi(as);
}
/*
* get an AFS superblock
*/
@@ -566,22 +594,6 @@ error:
return ERR_PTR(ret);
}
static void afs_kill_super(struct super_block *sb)
{
struct afs_super_info *as = AFS_FS_S(sb);
/* Clear the callback interests (which will do ilookup5) before
* deactivating the superblock.
*/
if (as->volume)
afs_clear_callback_interests(afs_net(as->net_ns),
as->volume->servers);
kill_anon_super(sb);
if (as->volume)
afs_deactivate_volume(as->volume);
afs_destroy_sbi(as);
}
/*
* Initialise an inode cache slab element prior to any use. Note that
* afs_alloc_inode() *must* reset anything that could incorrectly leak from one