Messages in this thread | | | Date | Tue, 15 May 2018 15:53:33 +0200 | From | Christoph Hellwig <> | Subject | Re: [PATCH 3/3] afs: Implement namespacing |
| |
So the real question here is why afs needs a write callback as the first user of /proc/net ever in a day and time were we've deprecated adding new proc files. This is a discussion that should be had with linux-fsdevel and netdev in Cc.
On Tue, May 01, 2018 at 12:20:39AM +0100, David Howells wrote: > Implement 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 <dhowells@redhat.com> > --- > > fs/afs/cell.c | 4 > fs/afs/cmservice.c | 2 > fs/afs/internal.h | 43 +++-- > fs/afs/main.c | 33 +++- > fs/afs/netdevices.c | 6 - > fs/afs/proc.c | 414 +++++++++++++-------------------------------------- > fs/afs/rxrpc.c | 2 > fs/afs/super.c | 20 +- > 8 files changed, 176 insertions(+), 348 deletions(-) > > diff --git a/fs/afs/cell.c b/fs/afs/cell.c > index fdf4c36cff79..a98a8a3d5544 100644 > --- a/fs/afs/cell.c > +++ b/fs/afs/cell.c > @@ -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); > @@ -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); > diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c > index 357de908df3a..4c89b1f4c02b 100644 > --- a/fs/afs/cmservice.c > +++ b/fs/afs/cmservice.c > @@ -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; > diff --git a/fs/afs/internal.h b/fs/afs/internal.h > index f8086ec95e24..58f4de6390d0 100644 > --- a/fs/afs/internal.h > +++ b/fs/afs/internal.h > @@ -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" > @@ -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 */ > @@ -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 */ > @@ -210,7 +213,6 @@ struct afs_sysnames { > char *subs[AFS_NR_SYSNAME]; > refcount_t usage; > unsigned short nr; > - short error; > char blank[1]; > }; > > @@ -218,6 +220,7 @@ struct afs_sysnames { > * 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 */ > > @@ -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, > @@ -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) > @@ -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 *); > > /* > @@ -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 > diff --git a/fs/afs/main.c b/fs/afs/main.c > index d7560168b3bf..7d2c1354e2ca 100644 > --- a/fs/afs/main.c > +++ b/fs/afs/main.c > @@ -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" > > @@ -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"; > @@ -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); > > @@ -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); > @@ -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 > */ > @@ -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; > > @@ -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); > @@ -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 > diff --git a/fs/afs/netdevices.c b/fs/afs/netdevices.c > index 50bd5bb1c4fb..2a009d1939d7 100644 > --- a/fs/afs/netdevices.c > +++ b/fs/afs/netdevices.c > @@ -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; > @@ -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); > diff --git a/fs/afs/proc.c b/fs/afs/proc.c > index 363383e9961f..9f748687d2c2 100644 > --- a/fs/afs/proc.c > +++ b/fs/afs/proc.c > @@ -17,14 +17,14 @@ > #include <linux/uaccess.h> > #include "internal.h" > > -static inline struct afs_net *afs_proc2net(struct file *f) > +static inline struct afs_net *afs_seq2net(struct seq_file *m) > { > - return &__afs_net; > + return afs_net(seq_file_net(m)); > } > > -static inline struct afs_net *afs_seq2net(struct seq_file *m) > +static inline struct afs_net *afs_seq2net_single(struct seq_file *m) > { > - return &__afs_net; // TODO: use seq_file_net(m) > + return afs_net(seq_file_single_net(m)); > } > > /* > @@ -75,28 +75,20 @@ static const struct seq_operations afs_proc_cells_ops = { > * handle writes to /proc/fs/afs/cells > * - to add cells: echo "add <cellname> <IP>[:<IP>][:<IP>]" > */ > -static ssize_t afs_proc_cells_write(struct file *file, const char __user *buf, > - size_t size, loff_t *_pos) > +static int afs_proc_cells_write(struct file *file, char *buf, size_t size) > { > - struct afs_net *net = afs_proc2net(file); > - char *kbuf, *name, *args; > + struct seq_file *m = file->private_data; > + struct afs_net *net = afs_seq2net(m); > + char *name, *args; > int ret; > > - /* start by dragging the command into memory */ > - if (size <= 1 || size >= PAGE_SIZE) > - return -EINVAL; > - > - kbuf = memdup_user_nul(buf, size); > - if (IS_ERR(kbuf)) > - return PTR_ERR(kbuf); > - > /* trim to first NL */ > - name = memchr(kbuf, '\n', size); > + name = memchr(buf, '\n', size); > if (name) > *name = 0; > > /* split into command, name and argslist */ > - name = strchr(kbuf, ' '); > + name = strchr(buf, ' '); > if (!name) > goto inval; > do { > @@ -115,9 +107,9 @@ static ssize_t afs_proc_cells_write(struct file *file, const char __user *buf, > goto inval; > > /* determine command to perform */ > - _debug("cmd=%s name=%s args=%s", kbuf, name, args); > + _debug("cmd=%s name=%s args=%s", buf, name, args); > > - if (strcmp(kbuf, "add") == 0) { > + if (strcmp(buf, "add") == 0) { > struct afs_cell *cell; > > cell = afs_lookup_cell(net, name, strlen(name), args, true); > @@ -133,10 +125,9 @@ static ssize_t afs_proc_cells_write(struct file *file, const char __user *buf, > goto inval; > } > > - ret = size; > + ret = 0; > > done: > - kfree(kbuf); > _leave(" = %d", ret); > return ret; > > @@ -146,68 +137,23 @@ static ssize_t afs_proc_cells_write(struct file *file, const char __user *buf, > goto done; > } > > -static int afs_proc_cells_open(struct inode *inode, struct file *file) > -{ > - struct seq_file *m; > - int ret; > - > - ret = seq_open(file, &afs_proc_cells_ops); > - if (ret < 0) > - return ret; > - > - m = file->private_data; > - m->private = PDE_DATA(inode); > - return 0; > -} > - > -static const struct file_operations afs_proc_cells_fops = { > - .open = afs_proc_cells_open, > - .read = seq_read, > - .write = afs_proc_cells_write, > - .llseek = seq_lseek, > - .release = seq_release, > -}; > - > /* > - * Read the name of the current workstation cell. > + * Display the name of the current workstation cell. > */ > -static ssize_t afs_proc_rootcell_read(struct file *file, char __user *buf, > - size_t size, loff_t *_pos) > +static int afs_proc_rootcell_show(struct seq_file *m, void *v) > { > struct afs_cell *cell; > - struct afs_net *net = afs_proc2net(file); > - unsigned int seq = 0; > - char name[AFS_MAXCELLNAME + 1]; > - int len; > - > - if (*_pos > 0) > - return 0; > - if (!net->ws_cell) > - return 0; > - > - rcu_read_lock(); > - do { > - read_seqbegin_or_lock(&net->cells_lock, &seq); > - len = 0; > - cell = rcu_dereference_raw(net->ws_cell); > - if (cell) { > - len = cell->name_len; > - memcpy(name, cell->name, len); > - } > - } while (need_seqretry(&net->cells_lock, seq)); > - done_seqretry(&net->cells_lock, seq); > - rcu_read_unlock(); > - > - if (!len) > - return 0; > - > - name[len++] = '\n'; > - if (len > size) > - len = size; > - if (copy_to_user(buf, name, len) != 0) > - return -EFAULT; > - *_pos = 1; > - return len; > + struct afs_net *net; > + > + net = afs_seq2net_single(m); > + if (net->ws_cell) { > + rcu_read_lock(); > + cell = rcu_dereference(net->ws_cell); > + if (cell) > + seq_printf(m, "%s\n", cell->name); > + rcu_read_unlock(); > + } > + return 0; > } > > /* > @@ -216,52 +162,34 @@ static ssize_t afs_proc_rootcell_read(struct file *file, char __user *buf, > * > * echo "cell.name:192.168.231.14" >/proc/fs/afs/rootcell > */ > -static ssize_t afs_proc_rootcell_write(struct file *file, > - const char __user *buf, > - size_t size, loff_t *_pos) > +static int afs_proc_rootcell_write(struct file *file, char *buf, size_t size) > { > - struct afs_net *net = afs_proc2net(file); > - char *kbuf, *s; > + struct seq_file *m = file->private_data; > + struct afs_net *net = afs_seq2net_single(m); > + char *s; > int ret; > > - /* start by dragging the command into memory */ > - if (size <= 1 || size >= PAGE_SIZE) > - return -EINVAL; > - > - kbuf = memdup_user_nul(buf, size); > - if (IS_ERR(kbuf)) > - return PTR_ERR(kbuf); > - > ret = -EINVAL; > - if (kbuf[0] == '.') > + if (buf[0] == '.') > goto out; > - if (memchr(kbuf, '/', size)) > + if (memchr(buf, '/', size)) > goto out; > > /* trim to first NL */ > - s = memchr(kbuf, '\n', size); > + s = memchr(buf, '\n', size); > if (s) > *s = 0; > > /* determine command to perform */ > - _debug("rootcell=%s", kbuf); > + _debug("rootcell=%s", buf); > > - ret = afs_cell_init(net, kbuf); > - if (ret >= 0) > - ret = size; /* consume everything, always */ > + ret = afs_cell_init(net, buf); > > out: > - kfree(kbuf); > _leave(" = %d", ret); > return ret; > } > > -static const struct file_operations afs_proc_rootcell_fops = { > - .read = afs_proc_rootcell_read, > - .write = afs_proc_rootcell_write, > - .llseek = no_llseek, > -}; > - > static const char afs_vol_types[3][3] = { > [AFSVL_RWVOL] = "RW", > [AFSVL_ROVOL] = "RO", > @@ -273,8 +201,8 @@ static const char afs_vol_types[3][3] = { > */ > static int afs_proc_cell_volumes_show(struct seq_file *m, void *v) > { > - struct afs_cell *cell = m->private; > struct afs_volume *vol = list_entry(v, struct afs_volume, proc_link); > + struct afs_cell *cell = PDE_DATA(file_inode(m->file)); > > /* Display header on line 1 */ > if (v == &cell->proc_volumes) { > @@ -292,24 +220,24 @@ static int afs_proc_cell_volumes_show(struct seq_file *m, void *v) > static void *afs_proc_cell_volumes_start(struct seq_file *m, loff_t *_pos) > __acquires(cell->proc_lock) > { > - struct afs_cell *cell = m->private; > + struct afs_cell *cell = PDE_DATA(file_inode(m->file)); > > read_lock(&cell->proc_lock); > return seq_list_start_head(&cell->proc_volumes, *_pos); > } > > -static void *afs_proc_cell_volumes_next(struct seq_file *p, void *v, > +static void *afs_proc_cell_volumes_next(struct seq_file *m, void *v, > loff_t *_pos) > { > - struct afs_cell *cell = p->private; > + struct afs_cell *cell = PDE_DATA(file_inode(m->file)); > > return seq_list_next(v, &cell->proc_volumes, _pos); > } > > -static void afs_proc_cell_volumes_stop(struct seq_file *p, void *v) > +static void afs_proc_cell_volumes_stop(struct seq_file *m, void *v) > __releases(cell->proc_lock) > { > - struct afs_cell *cell = p->private; > + struct afs_cell *cell = PDE_DATA(file_inode(m->file)); > > read_unlock(&cell->proc_lock); > } > @@ -321,33 +249,6 @@ static const struct seq_operations afs_proc_cell_volumes_ops = { > .show = afs_proc_cell_volumes_show, > }; > > -static int afs_proc_cell_volumes_open(struct inode *inode, struct file *file) > -{ > - struct afs_cell *cell; > - struct seq_file *m; > - int ret; > - > - cell = PDE_DATA(inode); > - if (!cell) > - return -ENOENT; > - > - ret = seq_open(file, &afs_proc_cell_volumes_ops); > - if (ret < 0) > - return ret; > - > - m = file->private_data; > - m->private = cell; > - > - return 0; > -} > - > -static const struct file_operations afs_proc_cell_volumes_fops = { > - .open = afs_proc_cell_volumes_open, > - .read = seq_read, > - .llseek = seq_lseek, > - .release = seq_release, > -}; > - > /* > * Display the list of Volume Location servers we're using for a cell. > */ > @@ -370,7 +271,7 @@ static void *afs_proc_cell_vlservers_start(struct seq_file *m, loff_t *_pos) > __acquires(rcu) > { > struct afs_addr_list *alist; > - struct afs_cell *cell = m->private; > + struct afs_cell *cell = PDE_DATA(file_inode(m->file)); > loff_t pos = *_pos; > > rcu_read_lock(); > @@ -388,11 +289,11 @@ static void *afs_proc_cell_vlservers_start(struct seq_file *m, loff_t *_pos) > return alist->addrs + pos; > } > > -static void *afs_proc_cell_vlservers_next(struct seq_file *p, void *v, > +static void *afs_proc_cell_vlservers_next(struct seq_file *m, void *v, > loff_t *_pos) > { > struct afs_addr_list *alist; > - struct afs_cell *cell = p->private; > + struct afs_cell *cell = PDE_DATA(file_inode(m->file)); > loff_t pos; > > alist = rcu_dereference(cell->vl_addrs); > @@ -405,7 +306,7 @@ static void *afs_proc_cell_vlservers_next(struct seq_file *p, void *v, > return alist->addrs + pos; > } > > -static void afs_proc_cell_vlservers_stop(struct seq_file *p, void *v) > +static void afs_proc_cell_vlservers_stop(struct seq_file *m, void *v) > __releases(rcu) > { > rcu_read_unlock(); > @@ -418,33 +319,6 @@ static const struct seq_operations afs_proc_cell_vlservers_ops = { > .show = afs_proc_cell_vlservers_show, > }; > > -static int afs_proc_cell_vlservers_open(struct inode *inode, struct file *file) > -{ > - struct afs_cell *cell; > - struct seq_file *m; > - int ret; > - > - cell = PDE_DATA(inode); > - if (!cell) > - return -ENOENT; > - > - ret = seq_open(file, &afs_proc_cell_vlservers_ops); > - if (ret<0) > - return ret; > - > - m = file->private_data; > - m->private = cell; > - > - return 0; > -} > - > -static const struct file_operations afs_proc_cell_vlservers_fops = { > - .open = afs_proc_cell_vlservers_open, > - .read = seq_read, > - .llseek = seq_lseek, > - .release = seq_release, > -}; > - > /* > * Display the list of fileservers we're using within a namespace. > */ > @@ -479,7 +353,7 @@ static void *afs_proc_servers_next(struct seq_file *m, void *v, loff_t *_pos) > return seq_hlist_next_rcu(v, &afs_seq2net(m)->fs_proc, _pos); > } > > -static void afs_proc_servers_stop(struct seq_file *p, void *v) > +static void afs_proc_servers_stop(struct seq_file *m, void *v) > __releases(rcu) > { > rcu_read_unlock(); > @@ -492,18 +366,6 @@ static const struct seq_operations afs_proc_servers_ops = { > .show = afs_proc_servers_show, > }; > > -static int afs_proc_servers_open(struct inode *inode, struct file *file) > -{ > - return seq_open(file, &afs_proc_servers_ops); > -} > - > -static const struct file_operations afs_proc_servers_fops = { > - .open = afs_proc_servers_open, > - .read = seq_read, > - .llseek = seq_lseek, > - .release = seq_release, > -}; > - > /* > * Display the list of strings that may be substituted for the @sys pathname > * macro. > @@ -523,10 +385,11 @@ static void *afs_proc_sysname_start(struct seq_file *m, loff_t *pos) > __acquires(&net->sysnames_lock) > { > struct afs_net *net = afs_seq2net(m); > - struct afs_sysnames *names = net->sysnames; > + struct afs_sysnames *names; > > read_lock(&net->sysnames_lock); > > + names = net->sysnames; > if (*pos >= names->nr) > return NULL; > return (void *)(unsigned long)(*pos + 1); > @@ -561,35 +424,21 @@ static const struct seq_operations afs_proc_sysname_ops = { > /* > * Allow the @sys substitution to be configured. > */ > -static ssize_t afs_proc_sysname_write(struct file *file, > - const char __user *buf, > - size_t size, loff_t *_pos) > +static int afs_proc_sysname_write(struct file *file, char *buf, size_t size) > { > - struct afs_sysnames *sysnames; > + struct afs_sysnames *sysnames, *kill; > struct seq_file *m = file->private_data; > - char *kbuf = NULL, *s, *p, *sub; > + struct afs_net *net = afs_seq2net(m); > + char *s, *p, *sub; > int ret, len; > > - sysnames = m->private; > + sysnames = kzalloc(sizeof(*sysnames), GFP_KERNEL); > if (!sysnames) > - return -EINVAL; > - if (sysnames->error) > - return sysnames->error; > - > - if (size >= PAGE_SIZE - 1) { > - sysnames->error = -EINVAL; > - return -EINVAL; > - } > - if (size == 0) > - return 0; > - > - kbuf = memdup_user_nul(buf, size); > - if (IS_ERR(kbuf)) > - return PTR_ERR(kbuf); > - > - inode_lock(file_inode(file)); > + return -ENOMEM; > + refcount_set(&sysnames->usage, 1); > + kill = sysnames; > > - p = kbuf; > + p = buf; > while ((s = strsep(&p, " \t\n"))) { > len = strlen(s); > if (len == 0) > @@ -630,16 +479,23 @@ static ssize_t afs_proc_sysname_write(struct file *file, > sysnames->nr++; > } > > - ret = size; /* consume everything, always */ > + if (sysnames->nr == 0) { > + sysnames->subs[0] = sysnames->blank; > + sysnames->nr++; > + } > + > + write_lock(&net->sysnames_lock); > + kill = net->sysnames; > + net->sysnames = sysnames; > + write_unlock(&net->sysnames_lock); > + ret = 0; > out: > - inode_unlock(file_inode(file)); > - kfree(kbuf); > + afs_put_sysnames(kill); > return ret; > > invalid: > ret = -EINVAL; > error: > - sysnames->error = ret; > goto out; > } > > @@ -655,75 +511,12 @@ void afs_put_sysnames(struct afs_sysnames *sysnames) > } > } > > -static int afs_proc_sysname_release(struct inode *inode, struct file *file) > -{ > - struct afs_sysnames *sysnames, *kill = NULL; > - struct seq_file *m = file->private_data; > - struct afs_net *net = afs_seq2net(m); > - > - sysnames = m->private; > - if (sysnames) { > - if (!sysnames->error) { > - kill = sysnames; > - if (sysnames->nr == 0) { > - sysnames->subs[0] = sysnames->blank; > - sysnames->nr++; > - } > - write_lock(&net->sysnames_lock); > - kill = net->sysnames; > - net->sysnames = sysnames; > - write_unlock(&net->sysnames_lock); > - } > - afs_put_sysnames(kill); > - } > - > - return seq_release(inode, file); > -} > - > -/* > - * Handle opening of /proc/fs/afs/sysname. If it is opened for writing, we > - * assume the caller wants to change the substitution list and we allocate a > - * buffer to hold the list. > - */ > -static int afs_proc_sysname_open(struct inode *inode, struct file *file) > -{ > - struct afs_sysnames *sysnames; > - struct seq_file *m; > - int ret; > - > - ret = seq_open(file, &afs_proc_sysname_ops); > - if (ret < 0) > - return ret; > - > - if (file->f_mode & FMODE_WRITE) { > - sysnames = kzalloc(sizeof(*sysnames), GFP_KERNEL); > - if (!sysnames) { > - seq_release(inode, file); > - return -ENOMEM; > - } > - > - refcount_set(&sysnames->usage, 1); > - m = file->private_data; > - m->private = sysnames; > - } > - > - return 0; > -} > - > -static const struct file_operations afs_proc_sysname_fops = { > - .open = afs_proc_sysname_open, > - .read = seq_read, > - .llseek = seq_lseek, > - .release = afs_proc_sysname_release, > - .write = afs_proc_sysname_write, > -}; > - > /* > * Display general per-net namespace statistics. > */ > static int afs_proc_stats_show(struct seq_file *m, void *v) > { > - struct afs_net *net = afs_seq2net(m); > + struct afs_net *net = afs_seq2net_single(m); > > seq_puts(m, "kAFS statistics\n"); > > @@ -749,38 +542,28 @@ static int afs_proc_stats_show(struct seq_file *m, void *v) > return 0; > } > > -/* > - * Open "/proc/fs/afs/stats" to allow reading of the stat counters. > - */ > -static int afs_proc_stats_open(struct inode *inode, struct file *file) > -{ > - return single_open(file, afs_proc_stats_show, NULL); > -} > - > -static const struct file_operations afs_proc_stats_fops = { > - .open = afs_proc_stats_open, > - .read = seq_read, > - .llseek = seq_lseek, > - .release = single_release, > -}; > - > /* > * initialise /proc/fs/afs/<cell>/ > */ > -int afs_proc_cell_setup(struct afs_net *net, struct afs_cell *cell) > +int afs_proc_cell_setup(struct afs_cell *cell) > { > struct proc_dir_entry *dir; > + struct afs_net *net = cell->net; > > _enter("%p{%s},%p", cell, cell->name, net->proc_afs); > > - dir = proc_mkdir(cell->name, net->proc_afs); > + dir = proc_net_mkdir(net->net, cell->name, net->proc_afs); > if (!dir) > goto error_dir; > > - if (!proc_create_data("vlservers", 0, dir, > - &afs_proc_cell_vlservers_fops, cell) || > - !proc_create_data("volumes", 0, dir, > - &afs_proc_cell_volumes_fops, cell)) > + if (!proc_create_net_data("vlservers", 0444, dir, > + &afs_proc_cell_vlservers_ops, > + sizeof(struct seq_net_private), > + cell) || > + !proc_create_net_data("volumes", 0444, dir, > + &afs_proc_cell_volumes_ops, > + sizeof(struct seq_net_private), > + cell)) > goto error_tree; > > _leave(" = 0"); > @@ -796,12 +579,12 @@ int afs_proc_cell_setup(struct afs_net *net, struct afs_cell *cell) > /* > * remove /proc/fs/afs/<cell>/ > */ > -void afs_proc_cell_remove(struct afs_net *net, struct afs_cell *cell) > +void afs_proc_cell_remove(struct afs_cell *cell) > { > - _enter(""); > + struct afs_net *net = cell->net; > > + _enter(""); > remove_proc_subtree(cell->name, net->proc_afs); > - > _leave(""); > } > > @@ -810,24 +593,39 @@ void afs_proc_cell_remove(struct afs_net *net, struct afs_cell *cell) > */ > int afs_proc_init(struct afs_net *net) > { > + struct proc_dir_entry *p; > + > _enter(""); > > - net->proc_afs = proc_mkdir("fs/afs", NULL); > - if (!net->proc_afs) > + p = proc_net_mkdir(net->net, "afs", net->net->proc_net); > + if (!p) > goto error_dir; > > - if (!proc_create("cells", 0644, net->proc_afs, &afs_proc_cells_fops) || > - !proc_create("rootcell", 0644, net->proc_afs, &afs_proc_rootcell_fops) || > - !proc_create("servers", 0644, net->proc_afs, &afs_proc_servers_fops) || > - !proc_create("stats", 0644, net->proc_afs, &afs_proc_stats_fops) || > - !proc_create("sysname", 0644, net->proc_afs, &afs_proc_sysname_fops)) > + if (!proc_create_net_data_write("cells", 0644, p, > + &afs_proc_cells_ops, > + afs_proc_cells_write, > + sizeof(struct seq_net_private), > + NULL) || > + !proc_create_net_single_write("rootcell", 0644, p, > + afs_proc_rootcell_show, > + afs_proc_rootcell_write, > + NULL) || > + !proc_create_net("servers", 0444, p, &afs_proc_servers_ops, > + sizeof(struct seq_net_private)) || > + !proc_create_net_single("stats", 0444, p, afs_proc_stats_show, NULL) || > + !proc_create_net_data_write("sysname", 0644, p, > + &afs_proc_sysname_ops, > + afs_proc_sysname_write, > + sizeof(struct seq_net_private), > + NULL)) > goto error_tree; > > + net->proc_afs = p; > _leave(" = 0"); > return 0; > > error_tree: > - proc_remove(net->proc_afs); > + proc_remove(p); > error_dir: > _leave(" = -ENOMEM"); > return -ENOMEM; > diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c > index 5c6263972ec9..e58fa0e15798 100644 > --- a/fs/afs/rxrpc.c > +++ b/fs/afs/rxrpc.c > @@ -45,7 +45,7 @@ int afs_open_socket(struct afs_net *net) > > _enter(""); > > - ret = sock_create_kern(&init_net, AF_RXRPC, SOCK_DGRAM, PF_INET6, &socket); > + ret = sock_create_kern(net->net, AF_RXRPC, SOCK_DGRAM, PF_INET6, &socket); > if (ret < 0) > goto error_1; > > diff --git a/fs/afs/super.c b/fs/afs/super.c > index 65081ec3c36e..593820372848 100644 > --- a/fs/afs/super.c > +++ b/fs/afs/super.c > @@ -48,6 +48,8 @@ struct file_system_type afs_fs_type = { > }; > MODULE_ALIAS_FS("afs"); > > +int afs_net_id; > + > static const struct super_operations afs_super_ops = { > .statfs = afs_statfs, > .alloc_inode = afs_alloc_inode, > @@ -117,7 +119,7 @@ int __init afs_fs_init(void) > /* > * clean up the filesystem > */ > -void __exit afs_fs_exit(void) > +void afs_fs_exit(void) > { > _enter(""); > > @@ -351,7 +353,7 @@ static int afs_test_super(struct super_block *sb, void *data) > struct afs_super_info *as1 = data; > struct afs_super_info *as = AFS_FS_S(sb); > > - return (as->net == as1->net && > + return (as->net_ns == as1->net_ns && > as->volume && > as->volume->vid == as1->volume->vid); > } > @@ -437,7 +439,7 @@ static struct afs_super_info *afs_alloc_sbi(struct afs_mount_params *params) > > as = kzalloc(sizeof(struct afs_super_info), GFP_KERNEL); > if (as) { > - as->net = afs_get_net(params->net); > + as->net_ns = get_net(params->net_ns); > if (params->dyn_root) > as->dyn_root = true; > else > @@ -450,8 +452,8 @@ static void afs_destroy_sbi(struct afs_super_info *as) > { > if (as) { > afs_put_volume(as->cell, as->volume); > - afs_put_cell(as->net, as->cell); > - afs_put_net(as->net); > + afs_put_cell(afs_net(as->net_ns), as->cell); > + put_net(as->net_ns); > kfree(as); > } > } > @@ -472,12 +474,13 @@ static struct dentry *afs_mount(struct file_system_type *fs_type, > _enter(",,%s,%p", dev_name, options); > > memset(¶ms, 0, sizeof(params)); > - params.net = &__afs_net; > > ret = -EINVAL; > if (current->nsproxy->net_ns != &init_net) > goto error; > - > + params.net_ns = current->nsproxy->net_ns; > + params.net = afs_net(params.net_ns); > + > /* parse the options and device name */ > if (options) { > ret = afs_parse_options(¶ms, options, &dev_name); > @@ -571,7 +574,8 @@ static void afs_kill_super(struct super_block *sb) > * deactivating the superblock. > */ > if (as->volume) > - afs_clear_callback_interests(as->net, as->volume->servers); > + afs_clear_callback_interests(afs_net(as->net_ns), > + as->volume->servers); > kill_anon_super(sb); > if (as->volume) > afs_deactivate_volume(as->volume); ---end quoted text---
| |