Skip to content

Commit

Permalink
afs: Implement network namespacing
Browse files Browse the repository at this point in the history
Implement network namespacing within AFS, but don't yet let mounts occur
outside the init namespace.  An additional patch will be required propagate
the network namespace across automounts.

Signed-off-by: David Howells <[email protected]>
  • Loading branch information
dhowells committed May 23, 2018
1 parent 1588def commit 5b86d4f
Show file tree
Hide file tree
Showing 8 changed files with 173 additions and 295 deletions.
4 changes: 2 additions & 2 deletions fs/afs/cell.c
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,7 @@ static int afs_activate_cell(struct afs_net *net, struct afs_cell *cell)
NULL, 0,
cell, 0, true);
#endif
ret = afs_proc_cell_setup(net, cell);
ret = afs_proc_cell_setup(cell);
if (ret < 0)
return ret;
spin_lock(&net->proc_cells_lock);
Expand All @@ -544,7 +544,7 @@ static void afs_deactivate_cell(struct afs_net *net, struct afs_cell *cell)
{
_enter("%s", cell->name);

afs_proc_cell_remove(net, cell);
afs_proc_cell_remove(cell);

spin_lock(&net->proc_cells_lock);
list_del_init(&cell->proc_link);
Expand Down
2 changes: 1 addition & 1 deletion fs/afs/cmservice.c
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ static void SRXAFSCB_TellMeAboutYourself(struct work_struct *work)
nifs = 0;
ifs = kcalloc(32, sizeof(*ifs), GFP_KERNEL);
if (ifs) {
nifs = afs_get_ipv4_interfaces(ifs, 32, false);
nifs = afs_get_ipv4_interfaces(call->net, ifs, 32, false);
if (nifs < 0) {
kfree(ifs);
ifs = NULL;
Expand Down
43 changes: 24 additions & 19 deletions fs/afs/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#include <linux/backing-dev.h>
#include <linux/uuid.h>
#include <net/net_namespace.h>
#include <net/netns/generic.h>
#include <net/sock.h>
#include <net/af_rxrpc.h>

#include "afs.h"
Expand All @@ -40,7 +42,8 @@ struct afs_mount_params {
afs_voltype_t type; /* type of volume requested */
int volnamesz; /* size of volume name */
const char *volname; /* name of volume to mount */
struct afs_net *net; /* Network namespace in effect */
struct net *net_ns; /* Network namespace in effect */
struct afs_net *net; /* the AFS net namespace stuff */
struct afs_cell *cell; /* cell in which to find volume */
struct afs_volume *volume; /* volume record */
struct key *key; /* key to use for secure mounting */
Expand Down Expand Up @@ -189,7 +192,7 @@ struct afs_read {
* - there's one superblock per volume
*/
struct afs_super_info {
struct afs_net *net; /* Network namespace */
struct net *net_ns; /* Network namespace */
struct afs_cell *cell; /* The cell in which the volume resides */
struct afs_volume *volume; /* volume record */
bool dyn_root; /* True if dynamic root */
Expand All @@ -210,14 +213,14 @@ struct afs_sysnames {
char *subs[AFS_NR_SYSNAME];
refcount_t usage;
unsigned short nr;
short error;
char blank[1];
};

/*
* AFS network namespace record.
*/
struct afs_net {
struct net *net; /* Backpointer to the owning net namespace */
struct afs_uuid uuid;
bool live; /* F if this namespace is being removed */

Expand Down Expand Up @@ -280,7 +283,6 @@ struct afs_net {
};

extern const char afs_init_sysname[];
extern struct afs_net __afs_net;// Dummy AFS network namespace; TODO: replace with real netns

enum afs_cell_state {
AFS_CELL_UNSET,
Expand Down Expand Up @@ -787,34 +789,36 @@ extern int afs_drop_inode(struct inode *);
* main.c
*/
extern struct workqueue_struct *afs_wq;
extern int afs_net_id;

static inline struct afs_net *afs_d2net(struct dentry *dentry)
static inline struct afs_net *afs_net(struct net *net)
{
return &__afs_net;
return net_generic(net, afs_net_id);
}

static inline struct afs_net *afs_i2net(struct inode *inode)
static inline struct afs_net *afs_sb2net(struct super_block *sb)
{
return &__afs_net;
return afs_net(AFS_FS_S(sb)->net_ns);
}

static inline struct afs_net *afs_v2net(struct afs_vnode *vnode)
static inline struct afs_net *afs_d2net(struct dentry *dentry)
{
return &__afs_net;
return afs_sb2net(dentry->d_sb);
}

static inline struct afs_net *afs_sock2net(struct sock *sk)
static inline struct afs_net *afs_i2net(struct inode *inode)
{
return &__afs_net;
return afs_sb2net(inode->i_sb);
}

static inline struct afs_net *afs_get_net(struct afs_net *net)
static inline struct afs_net *afs_v2net(struct afs_vnode *vnode)
{
return net;
return afs_i2net(&vnode->vfs_inode);
}

static inline void afs_put_net(struct afs_net *net)
static inline struct afs_net *afs_sock2net(struct sock *sk)
{
return net_generic(sock_net(sk), afs_net_id);
}

static inline void __afs_stat(atomic_t *s)
Expand Down Expand Up @@ -842,15 +846,16 @@ extern void afs_mntpt_kill_timer(void);
/*
* netdevices.c
*/
extern int afs_get_ipv4_interfaces(struct afs_interface *, size_t, bool);
extern int afs_get_ipv4_interfaces(struct afs_net *, struct afs_interface *,
size_t, bool);

/*
* proc.c
*/
extern int __net_init afs_proc_init(struct afs_net *);
extern void __net_exit afs_proc_cleanup(struct afs_net *);
extern int afs_proc_cell_setup(struct afs_net *, struct afs_cell *);
extern void afs_proc_cell_remove(struct afs_net *, struct afs_cell *);
extern int afs_proc_cell_setup(struct afs_cell *);
extern void afs_proc_cell_remove(struct afs_cell *);
extern void afs_put_sysnames(struct afs_sysnames *);

/*
Expand Down Expand Up @@ -983,7 +988,7 @@ extern bool afs_annotate_server_list(struct afs_server_list *, struct afs_server
* super.c
*/
extern int __init afs_fs_init(void);
extern void __exit afs_fs_exit(void);
extern void afs_fs_exit(void);

/*
* vlclient.c
Expand Down
33 changes: 27 additions & 6 deletions fs/afs/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <linux/completion.h>
#include <linux/sched.h>
#include <linux/random.h>
#include <linux/proc_fs.h>
#define CREATE_TRACE_POINTS
#include "internal.h"

Expand All @@ -32,7 +33,7 @@ module_param(rootcell, charp, 0);
MODULE_PARM_DESC(rootcell, "root AFS cell name and VL server IP addr list");

struct workqueue_struct *afs_wq;
struct afs_net __afs_net;
static struct proc_dir_entry *afs_proc_symlink;

#if defined(CONFIG_ALPHA)
const char afs_init_sysname[] = "alpha_linux26";
Expand Down Expand Up @@ -67,11 +68,13 @@ const char afs_init_sysname[] = "unknown_linux26";
/*
* Initialise an AFS network namespace record.
*/
static int __net_init afs_net_init(struct afs_net *net)
static int __net_init afs_net_init(struct net *net_ns)
{
struct afs_sysnames *sysnames;
struct afs_net *net = afs_net(net_ns);
int ret;

net->net = net_ns;
net->live = true;
generate_random_uuid((unsigned char *)&net->uuid);

Expand Down Expand Up @@ -142,8 +145,10 @@ static int __net_init afs_net_init(struct afs_net *net)
/*
* Clean up and destroy an AFS network namespace record.
*/
static void __net_exit afs_net_exit(struct afs_net *net)
static void __net_exit afs_net_exit(struct net *net_ns)
{
struct afs_net *net = afs_net(net_ns);

net->live = false;
afs_cell_purge(net);
afs_purge_servers(net);
Expand All @@ -152,6 +157,13 @@ static void __net_exit afs_net_exit(struct afs_net *net)
afs_put_sysnames(net->sysnames);
}

static struct pernet_operations afs_net_ops = {
.init = afs_net_init,
.exit = afs_net_exit,
.id = &afs_net_id,
.size = sizeof(struct afs_net),
};

/*
* initialise the AFS client FS module
*/
Expand All @@ -178,7 +190,7 @@ static int __init afs_init(void)
goto error_cache;
#endif

ret = afs_net_init(&__afs_net);
ret = register_pernet_subsys(&afs_net_ops);
if (ret < 0)
goto error_net;

Expand All @@ -187,10 +199,18 @@ static int __init afs_init(void)
if (ret < 0)
goto error_fs;

afs_proc_symlink = proc_symlink("fs/afs", NULL, "../self/net/afs");
if (IS_ERR(afs_proc_symlink)) {
ret = PTR_ERR(afs_proc_symlink);
goto error_proc;
}

return ret;

error_proc:
afs_fs_exit();
error_fs:
afs_net_exit(&__afs_net);
unregister_pernet_subsys(&afs_net_ops);
error_net:
#ifdef CONFIG_AFS_FSCACHE
fscache_unregister_netfs(&afs_cache_netfs);
Expand Down Expand Up @@ -219,8 +239,9 @@ static void __exit afs_exit(void)
{
printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 unregistering.\n");

proc_remove(afs_proc_symlink);
afs_fs_exit();
afs_net_exit(&__afs_net);
unregister_pernet_subsys(&afs_net_ops);
#ifdef CONFIG_AFS_FSCACHE
fscache_unregister_netfs(&afs_cache_netfs);
#endif
Expand Down
6 changes: 3 additions & 3 deletions fs/afs/netdevices.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
* - maxbufs must be at least 1
* - returns the number of interface records in the buffer
*/
int afs_get_ipv4_interfaces(struct afs_interface *bufs, size_t maxbufs,
bool wantloopback)
int afs_get_ipv4_interfaces(struct afs_net *net, struct afs_interface *bufs,
size_t maxbufs, bool wantloopback)
{
struct net_device *dev;
struct in_device *idev;
Expand All @@ -27,7 +27,7 @@ int afs_get_ipv4_interfaces(struct afs_interface *bufs, size_t maxbufs,
ASSERT(maxbufs > 0);

rtnl_lock();
for_each_netdev(&init_net, dev) {
for_each_netdev(net->net, dev) {
if (dev->type == ARPHRD_LOOPBACK && !wantloopback)
continue;
idev = __in_dev_get_rtnl(dev);
Expand Down
Loading

0 comments on commit 5b86d4f

Please sign in to comment.