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>
This commit is contained in:
parent
1ac8362977
commit
11f779421a
|
@ -220,6 +220,7 @@ static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size)
|
||||||
struct sockaddr *sap = (struct sockaddr *)&address;
|
struct sockaddr *sap = (struct sockaddr *)&address;
|
||||||
size_t salen = sizeof(address);
|
size_t salen = sizeof(address);
|
||||||
char *fo_path;
|
char *fo_path;
|
||||||
|
struct net *net = file->f_dentry->d_sb->s_fs_info;
|
||||||
|
|
||||||
/* sanity check */
|
/* sanity check */
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
|
@ -232,7 +233,7 @@ static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size)
|
||||||
if (qword_get(&buf, fo_path, size) < 0)
|
if (qword_get(&buf, fo_path, size) < 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (rpc_pton(&init_net, fo_path, size, sap, salen) == 0)
|
if (rpc_pton(net, fo_path, size, sap, salen) == 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
return nlmsvc_unlock_all_by_ip(sap);
|
return nlmsvc_unlock_all_by_ip(sap);
|
||||||
|
@ -317,6 +318,7 @@ static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
|
||||||
int len;
|
int len;
|
||||||
struct auth_domain *dom;
|
struct auth_domain *dom;
|
||||||
struct knfsd_fh fh;
|
struct knfsd_fh fh;
|
||||||
|
struct net *net = file->f_dentry->d_sb->s_fs_info;
|
||||||
|
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -352,7 +354,7 @@ static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
|
||||||
if (!dom)
|
if (!dom)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
len = exp_rootfh(&init_net, dom, path, &fh, maxsize);
|
len = exp_rootfh(net, dom, path, &fh, maxsize);
|
||||||
auth_domain_put(dom);
|
auth_domain_put(dom);
|
||||||
if (len)
|
if (len)
|
||||||
return len;
|
return len;
|
||||||
|
@ -396,7 +398,7 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size)
|
||||||
{
|
{
|
||||||
char *mesg = buf;
|
char *mesg = buf;
|
||||||
int rv;
|
int rv;
|
||||||
struct net *net = &init_net;
|
struct net *net = file->f_dentry->d_sb->s_fs_info;
|
||||||
|
|
||||||
if (size > 0) {
|
if (size > 0) {
|
||||||
int newthreads;
|
int newthreads;
|
||||||
|
@ -447,7 +449,7 @@ static ssize_t write_pool_threads(struct file *file, char *buf, size_t size)
|
||||||
int len;
|
int len;
|
||||||
int npools;
|
int npools;
|
||||||
int *nthreads;
|
int *nthreads;
|
||||||
struct net *net = &init_net;
|
struct net *net = file->f_dentry->d_sb->s_fs_info;
|
||||||
|
|
||||||
mutex_lock(&nfsd_mutex);
|
mutex_lock(&nfsd_mutex);
|
||||||
npools = nfsd_nrpools(net);
|
npools = nfsd_nrpools(net);
|
||||||
|
@ -510,7 +512,7 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size)
|
||||||
unsigned minor;
|
unsigned minor;
|
||||||
ssize_t tlen = 0;
|
ssize_t tlen = 0;
|
||||||
char *sep;
|
char *sep;
|
||||||
struct net *net = &init_net;
|
struct net *net = file->f_dentry->d_sb->s_fs_info;
|
||||||
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
||||||
|
|
||||||
if (size>0) {
|
if (size>0) {
|
||||||
|
@ -792,7 +794,7 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size,
|
||||||
static ssize_t write_ports(struct file *file, char *buf, size_t size)
|
static ssize_t write_ports(struct file *file, char *buf, size_t size)
|
||||||
{
|
{
|
||||||
ssize_t rv;
|
ssize_t rv;
|
||||||
struct net *net = &init_net;
|
struct net *net = file->f_dentry->d_sb->s_fs_info;
|
||||||
|
|
||||||
mutex_lock(&nfsd_mutex);
|
mutex_lock(&nfsd_mutex);
|
||||||
rv = __write_ports(file, buf, size, net);
|
rv = __write_ports(file, buf, size, net);
|
||||||
|
@ -827,7 +829,7 @@ int nfsd_max_blksize;
|
||||||
static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
|
static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
|
||||||
{
|
{
|
||||||
char *mesg = buf;
|
char *mesg = buf;
|
||||||
struct net *net = &init_net;
|
struct net *net = file->f_dentry->d_sb->s_fs_info;
|
||||||
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
||||||
|
|
||||||
if (size > 0) {
|
if (size > 0) {
|
||||||
|
@ -923,7 +925,8 @@ static ssize_t nfsd4_write_time(struct file *file, char *buf, size_t size,
|
||||||
*/
|
*/
|
||||||
static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
|
static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
|
||||||
{
|
{
|
||||||
struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
|
struct net *net = file->f_dentry->d_sb->s_fs_info;
|
||||||
|
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
||||||
return nfsd4_write_time(file, buf, size, &nn->nfsd4_lease, nn);
|
return nfsd4_write_time(file, buf, size, &nn->nfsd4_lease, nn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -939,7 +942,8 @@ static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
|
||||||
*/
|
*/
|
||||||
static ssize_t write_gracetime(struct file *file, char *buf, size_t size)
|
static ssize_t write_gracetime(struct file *file, char *buf, size_t size)
|
||||||
{
|
{
|
||||||
struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
|
struct net *net = file->f_dentry->d_sb->s_fs_info;
|
||||||
|
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
||||||
return nfsd4_write_time(file, buf, size, &nn->nfsd4_grace, nn);
|
return nfsd4_write_time(file, buf, size, &nn->nfsd4_grace, nn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -995,7 +999,8 @@ static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size,
|
||||||
static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
|
static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
|
||||||
{
|
{
|
||||||
ssize_t rv;
|
ssize_t rv;
|
||||||
struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
|
struct net *net = file->f_dentry->d_sb->s_fs_info;
|
||||||
|
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
||||||
|
|
||||||
mutex_lock(&nfsd_mutex);
|
mutex_lock(&nfsd_mutex);
|
||||||
rv = __write_recoverydir(file, buf, size, nn);
|
rv = __write_recoverydir(file, buf, size, nn);
|
||||||
|
@ -1037,20 +1042,35 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
|
||||||
#endif
|
#endif
|
||||||
/* last one */ {""}
|
/* last one */ {""}
|
||||||
};
|
};
|
||||||
return simple_fill_super(sb, 0x6e667364, nfsd_files);
|
struct net *net = data;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = simple_fill_super(sb, 0x6e667364, nfsd_files);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
sb->s_fs_info = get_net(net);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct dentry *nfsd_mount(struct file_system_type *fs_type,
|
static struct dentry *nfsd_mount(struct file_system_type *fs_type,
|
||||||
int flags, const char *dev_name, void *data)
|
int flags, const char *dev_name, void *data)
|
||||||
{
|
{
|
||||||
return mount_single(fs_type, flags, data, nfsd_fill_super);
|
return mount_ns(fs_type, flags, current->nsproxy->net_ns, nfsd_fill_super);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nfsd_umount(struct super_block *sb)
|
||||||
|
{
|
||||||
|
struct net *net = sb->s_fs_info;
|
||||||
|
|
||||||
|
kill_litter_super(sb);
|
||||||
|
put_net(net);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct file_system_type nfsd_fs_type = {
|
static struct file_system_type nfsd_fs_type = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.name = "nfsd",
|
.name = "nfsd",
|
||||||
.mount = nfsd_mount,
|
.mount = nfsd_mount,
|
||||||
.kill_sb = kill_litter_super,
|
.kill_sb = nfsd_umount,
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
|
|
|
@ -702,8 +702,7 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
|
||||||
int nfsd_pool_stats_open(struct inode *inode, struct file *file)
|
int nfsd_pool_stats_open(struct inode *inode, struct file *file)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct net *net = &init_net;
|
struct nfsd_net *nn = net_generic(inode->i_sb->s_fs_info, nfsd_net_id);
|
||||||
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
|
||||||
|
|
||||||
mutex_lock(&nfsd_mutex);
|
mutex_lock(&nfsd_mutex);
|
||||||
if (nn->nfsd_serv == NULL) {
|
if (nn->nfsd_serv == NULL) {
|
||||||
|
@ -720,7 +719,7 @@ int nfsd_pool_stats_open(struct inode *inode, struct file *file)
|
||||||
int nfsd_pool_stats_release(struct inode *inode, struct file *file)
|
int nfsd_pool_stats_release(struct inode *inode, struct file *file)
|
||||||
{
|
{
|
||||||
int ret = seq_release(inode, file);
|
int ret = seq_release(inode, file);
|
||||||
struct net *net = &init_net;
|
struct net *net = inode->i_sb->s_fs_info;
|
||||||
|
|
||||||
mutex_lock(&nfsd_mutex);
|
mutex_lock(&nfsd_mutex);
|
||||||
/* this function really, really should have been called svc_put() */
|
/* this function really, really should have been called svc_put() */
|
||||||
|
|
Loading…
Reference in New Issue