diff options
| author | Stanislav Kinsbursky <skinsbursky@parallels.com> | 2013-02-01 07:56:12 -0500 |
|---|---|---|
| committer | J. Bruce Fields <bfields@redhat.com> | 2013-02-15 11:21:00 -0500 |
| commit | 11f779421a39b86da8a523d97e5fd3477878d44f (patch) | |
| tree | 5a2c01f75d57a1ff23dd0ecec56a378e2b34bb8d | |
| parent | 1ac8362977b9ec75779170ac3074c7b36ab19b82 (diff) | |
nfsd: containerize NFSd filesystem
This patch makes NFSD file system superblock to be created per net.
This makes possible to get proper network namespace from superblock instead of
using hard-coded "init_net".
Note: NFSd fs super-block holds network namespace. This garantees, that
network namespace won't disappear from underneath of it.
This, obviously, means, that in case of kill of a container's "init" (which is not a mount
namespace, but network namespace creator) netowrk namespace won't be
destroyed.
Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
| -rw-r--r-- | fs/nfsd/nfsctl.c | 46 | ||||
| -rw-r--r-- | fs/nfsd/nfssvc.c | 5 |
2 files changed, 35 insertions, 16 deletions
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 29c3f0d25469..f6d448e6eb28 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c | |||
| @@ -220,6 +220,7 @@ static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size) | |||
| 220 | struct sockaddr *sap = (struct sockaddr *)&address; | 220 | struct sockaddr *sap = (struct sockaddr *)&address; |
| 221 | size_t salen = sizeof(address); | 221 | size_t salen = sizeof(address); |
| 222 | char *fo_path; | 222 | char *fo_path; |
| 223 | struct net *net = file->f_dentry->d_sb->s_fs_info; | ||
| 223 | 224 | ||
| 224 | /* sanity check */ | 225 | /* sanity check */ |
| 225 | if (size == 0) | 226 | if (size == 0) |
| @@ -232,7 +233,7 @@ static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size) | |||
| 232 | if (qword_get(&buf, fo_path, size) < 0) | 233 | if (qword_get(&buf, fo_path, size) < 0) |
| 233 | return -EINVAL; | 234 | return -EINVAL; |
| 234 | 235 | ||
| 235 | if (rpc_pton(&init_net, fo_path, size, sap, salen) == 0) | 236 | if (rpc_pton(net, fo_path, size, sap, salen) == 0) |
| 236 | return -EINVAL; | 237 | return -EINVAL; |
| 237 | 238 | ||
| 238 | return nlmsvc_unlock_all_by_ip(sap); | 239 | return nlmsvc_unlock_all_by_ip(sap); |
| @@ -317,6 +318,7 @@ static ssize_t write_filehandle(struct file *file, char *buf, size_t size) | |||
| 317 | int len; | 318 | int len; |
| 318 | struct auth_domain *dom; | 319 | struct auth_domain *dom; |
| 319 | struct knfsd_fh fh; | 320 | struct knfsd_fh fh; |
| 321 | struct net *net = file->f_dentry->d_sb->s_fs_info; | ||
| 320 | 322 | ||
| 321 | if (size == 0) | 323 | if (size == 0) |
| 322 | return -EINVAL; | 324 | return -EINVAL; |
| @@ -352,7 +354,7 @@ static ssize_t write_filehandle(struct file *file, char *buf, size_t size) | |||
| 352 | if (!dom) | 354 | if (!dom) |
| 353 | return -ENOMEM; | 355 | return -ENOMEM; |
| 354 | 356 | ||
| 355 | len = exp_rootfh(&init_net, dom, path, &fh, maxsize); | 357 | len = exp_rootfh(net, dom, path, &fh, maxsize); |
| 356 | auth_domain_put(dom); | 358 | auth_domain_put(dom); |
| 357 | if (len) | 359 | if (len) |
| 358 | return len; | 360 | return len; |
| @@ -396,7 +398,7 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size) | |||
| 396 | { | 398 | { |
| 397 | char *mesg = buf; | 399 | char *mesg = buf; |
| 398 | int rv; | 400 | int rv; |
| 399 | struct net *net = &init_net; | 401 | struct net *net = file->f_dentry->d_sb->s_fs_info; |
| 400 | 402 | ||
| 401 | if (size > 0) { | 403 | if (size > 0) { |
| 402 | int newthreads; | 404 | int newthreads; |
| @@ -447,7 +449,7 @@ static ssize_t write_pool_threads(struct file *file, char *buf, size_t size) | |||
| 447 | int len; | 449 | int len; |
| 448 | int npools; | 450 | int npools; |
| 449 | int *nthreads; | 451 | int *nthreads; |
| 450 | struct net *net = &init_net; | 452 | struct net *net = file->f_dentry->d_sb->s_fs_info; |
| 451 | 453 | ||
| 452 | mutex_lock(&nfsd_mutex); | 454 | mutex_lock(&nfsd_mutex); |
| 453 | npools = nfsd_nrpools(net); | 455 | npools = nfsd_nrpools(net); |
| @@ -510,7 +512,7 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size) | |||
| 510 | unsigned minor; | 512 | unsigned minor; |
| 511 | ssize_t tlen = 0; | 513 | ssize_t tlen = 0; |
| 512 | char *sep; | 514 | char *sep; |
| 513 | struct net *net = &init_net; | 515 | struct net *net = file->f_dentry->d_sb->s_fs_info; |
| 514 | struct nfsd_net *nn = net_generic(net, nfsd_net_id); | 516 | struct nfsd_net *nn = net_generic(net, nfsd_net_id); |
| 515 | 517 | ||
| 516 | if (size>0) { | 518 | if (size>0) { |
| @@ -792,7 +794,7 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size, | |||
| 792 | static ssize_t write_ports(struct file *file, char *buf, size_t size) | 794 | static ssize_t write_ports(struct file *file, char *buf, size_t size) |
| 793 | { | 795 | { |
| 794 | ssize_t rv; | 796 | ssize_t rv; |
| 795 | struct net *net = &init_net; | 797 | struct net *net = file->f_dentry->d_sb->s_fs_info; |
| 796 | 798 | ||
| 797 | mutex_lock(&nfsd_mutex); | 799 | mutex_lock(&nfsd_mutex); |
| 798 | rv = __write_ports(file, buf, size, net); | 800 | rv = __write_ports(file, buf, size, net); |
| @@ -827,7 +829,7 @@ int nfsd_max_blksize; | |||
| 827 | static ssize_t write_maxblksize(struct file *file, char *buf, size_t size) | 829 | static ssize_t write_maxblksize(struct file *file, char *buf, size_t size) |
| 828 | { | 830 | { |
| 829 | char *mesg = buf; | 831 | char *mesg = buf; |
| 830 | struct net *net = &init_net; | 832 | struct net *net = file->f_dentry->d_sb->s_fs_info; |
| 831 | struct nfsd_net *nn = net_generic(net, nfsd_net_id); | 833 | struct nfsd_net *nn = net_generic(net, nfsd_net_id); |
| 832 | 834 | ||
| 833 | if (size > 0) { | 835 | if (size > 0) { |
| @@ -923,7 +925,8 @@ static ssize_t nfsd4_write_time(struct file *file, char *buf, size_t size, | |||
| 923 | */ | 925 | */ |
| 924 | static ssize_t write_leasetime(struct file *file, char *buf, size_t size) | 926 | static ssize_t write_leasetime(struct file *file, char *buf, size_t size) |
| 925 | { | 927 | { |
| 926 | struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); | 928 | struct net *net = file->f_dentry->d_sb->s_fs_info; |
| 929 | struct nfsd_net *nn = net_generic(net, nfsd_net_id); | ||
| 927 | return nfsd4_write_time(file, buf, size, &nn->nfsd4_lease, nn); | 930 | return nfsd4_write_time(file, buf, size, &nn->nfsd4_lease, nn); |
| 928 | } | 931 | } |
| 929 | 932 | ||
| @@ -939,7 +942,8 @@ static ssize_t write_leasetime(struct file *file, char *buf, size_t size) | |||
| 939 | */ | 942 | */ |
| 940 | static ssize_t write_gracetime(struct file *file, char *buf, size_t size) | 943 | static ssize_t write_gracetime(struct file *file, char *buf, size_t size) |
| 941 | { | 944 | { |
| 942 | struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); | 945 | struct net *net = file->f_dentry->d_sb->s_fs_info; |
| 946 | struct nfsd_net *nn = net_generic(net, nfsd_net_id); | ||
| 943 | return nfsd4_write_time(file, buf, size, &nn->nfsd4_grace, nn); | 947 | return nfsd4_write_time(file, buf, size, &nn->nfsd4_grace, nn); |
| 944 | } | 948 | } |
| 945 | 949 | ||
| @@ -995,7 +999,8 @@ static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size, | |||
| 995 | static ssize_t write_recoverydir(struct file *file, char *buf, size_t size) | 999 | static ssize_t write_recoverydir(struct file *file, char *buf, size_t size) |
| 996 | { | 1000 | { |
| 997 | ssize_t rv; | 1001 | ssize_t rv; |
| 998 | struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); | 1002 | struct net *net = file->f_dentry->d_sb->s_fs_info; |
| 1003 | struct nfsd_net *nn = net_generic(net, nfsd_net_id); | ||
| 999 | 1004 | ||
| 1000 | mutex_lock(&nfsd_mutex); | 1005 | mutex_lock(&nfsd_mutex); |
| 1001 | rv = __write_recoverydir(file, buf, size, nn); | 1006 | rv = __write_recoverydir(file, buf, size, nn); |
| @@ -1037,20 +1042,35 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent) | |||
| 1037 | #endif | 1042 | #endif |
| 1038 | /* last one */ {""} | 1043 | /* last one */ {""} |
| 1039 | }; | 1044 | }; |
| 1040 | return simple_fill_super(sb, 0x6e667364, nfsd_files); | 1045 | struct net *net = data; |
| 1046 | int ret; | ||
| 1047 | |||
| 1048 | ret = simple_fill_super(sb, 0x6e667364, nfsd_files); | ||
| 1049 | if (ret) | ||
| 1050 | return ret; | ||
| 1051 | sb->s_fs_info = get_net(net); | ||
| 1052 | return 0; | ||
| 1041 | } | 1053 | } |
| 1042 | 1054 | ||
| 1043 | static struct dentry *nfsd_mount(struct file_system_type *fs_type, | 1055 | static struct dentry *nfsd_mount(struct file_system_type *fs_type, |
| 1044 | int flags, const char *dev_name, void *data) | 1056 | int flags, const char *dev_name, void *data) |
| 1045 | { | 1057 | { |
| 1046 | return mount_single(fs_type, flags, data, nfsd_fill_super); | 1058 | return mount_ns(fs_type, flags, current->nsproxy->net_ns, nfsd_fill_super); |
| 1059 | } | ||
| 1060 | |||
| 1061 | static void nfsd_umount(struct super_block *sb) | ||
| 1062 | { | ||
| 1063 | struct net *net = sb->s_fs_info; | ||
| 1064 | |||
| 1065 | kill_litter_super(sb); | ||
| 1066 | put_net(net); | ||
| 1047 | } | 1067 | } |
| 1048 | 1068 | ||
| 1049 | static struct file_system_type nfsd_fs_type = { | 1069 | static struct file_system_type nfsd_fs_type = { |
| 1050 | .owner = THIS_MODULE, | 1070 | .owner = THIS_MODULE, |
| 1051 | .name = "nfsd", | 1071 | .name = "nfsd", |
| 1052 | .mount = nfsd_mount, | 1072 | .mount = nfsd_mount, |
| 1053 | .kill_sb = kill_litter_super, | 1073 | .kill_sb = nfsd_umount, |
| 1054 | }; | 1074 | }; |
| 1055 | 1075 | ||
| 1056 | #ifdef CONFIG_PROC_FS | 1076 | #ifdef CONFIG_PROC_FS |
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 40cb1cbaba4e..6cee5db72047 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c | |||
| @@ -702,8 +702,7 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp) | |||
| 702 | int nfsd_pool_stats_open(struct inode *inode, struct file *file) | 702 | int nfsd_pool_stats_open(struct inode *inode, struct file *file) |
| 703 | { | 703 | { |
| 704 | int ret; | 704 | int ret; |
| 705 | struct net *net = &init_net; | 705 | struct nfsd_net *nn = net_generic(inode->i_sb->s_fs_info, nfsd_net_id); |
| 706 | struct nfsd_net *nn = net_generic(net, nfsd_net_id); | ||
| 707 | 706 | ||
| 708 | mutex_lock(&nfsd_mutex); | 707 | mutex_lock(&nfsd_mutex); |
| 709 | if (nn->nfsd_serv == NULL) { | 708 | if (nn->nfsd_serv == NULL) { |
| @@ -720,7 +719,7 @@ int nfsd_pool_stats_open(struct inode *inode, struct file *file) | |||
| 720 | int nfsd_pool_stats_release(struct inode *inode, struct file *file) | 719 | int nfsd_pool_stats_release(struct inode *inode, struct file *file) |
| 721 | { | 720 | { |
| 722 | int ret = seq_release(inode, file); | 721 | int ret = seq_release(inode, file); |
| 723 | struct net *net = &init_net; | 722 | struct net *net = inode->i_sb->s_fs_info; |
| 724 | 723 | ||
| 725 | mutex_lock(&nfsd_mutex); | 724 | mutex_lock(&nfsd_mutex); |
| 726 | /* this function really, really should have been called svc_put() */ | 725 | /* this function really, really should have been called svc_put() */ |
