aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/client.c
diff options
context:
space:
mode:
authorStanislav Kinsbursky <skinsbursky@parallels.com>2012-01-23 12:26:05 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-02-06 18:48:02 -0500
commit6b13168b36b6a7f603d962c232f1f2f325705832 (patch)
treee524fb58428a8c128dcad8cf00cbd2692be9c6ad /fs/nfs/client.c
parenta602bea3e7ccc5ce3da61d2c18245c4058983926 (diff)
NFS: make nfs_client_list per net ns
This patch splits global list of NFS clients into per-net-ns array of lists. This looks more strict and clearer. BTW, this patch also makes "/proc/fs/nfsfs/servers" entry content depends on /proc mount owner pid namespace. See below for details. NOTE: few words about how was /proc/fs/nfsfs/ entries content show per network namespace done. This is a little bit tricky and not the best is could be. But it's cheap (proper fix for /proc conteinerization is a hard nut to crack). The idea is simple: take proper network namespace from pid namespace child reaper nsproxy of /proc/ mount creator. This actually means, that if there are 2 containers with different net namespace sharing pid namespace, then read of /proc/fs/nfsfs/ entries will always return content, taken from net namespace of pid namespace creator task (and thus second namespace set wil be unvisible). Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/client.c')
-rw-r--r--fs/nfs/client.c38
1 files changed, 27 insertions, 11 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 98af1cb28ee3..058eb9bcfa9d 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -39,6 +39,8 @@
39#include <net/ipv6.h> 39#include <net/ipv6.h>
40#include <linux/nfs_xdr.h> 40#include <linux/nfs_xdr.h>
41#include <linux/sunrpc/bc_xprt.h> 41#include <linux/sunrpc/bc_xprt.h>
42#include <linux/nsproxy.h>
43#include <linux/pid_namespace.h>
42 44
43#include <asm/system.h> 45#include <asm/system.h>
44 46
@@ -49,11 +51,11 @@
49#include "internal.h" 51#include "internal.h"
50#include "fscache.h" 52#include "fscache.h"
51#include "pnfs.h" 53#include "pnfs.h"
54#include "netns.h"
52 55
53#define NFSDBG_FACILITY NFSDBG_CLIENT 56#define NFSDBG_FACILITY NFSDBG_CLIENT
54 57
55DEFINE_SPINLOCK(nfs_client_lock); 58DEFINE_SPINLOCK(nfs_client_lock);
56LIST_HEAD(nfs_client_list);
57static LIST_HEAD(nfs_volume_list); 59static LIST_HEAD(nfs_volume_list);
58static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq); 60static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq);
59#ifdef CONFIG_NFS_V4 61#ifdef CONFIG_NFS_V4
@@ -464,8 +466,9 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat
464{ 466{
465 struct nfs_client *clp; 467 struct nfs_client *clp;
466 const struct sockaddr *sap = data->addr; 468 const struct sockaddr *sap = data->addr;
469 struct nfs_net *nn = net_generic(data->net, nfs_net_id);
467 470
468 list_for_each_entry(clp, &nfs_client_list, cl_share_link) { 471 list_for_each_entry(clp, &nn->nfs_client_list, cl_share_link) {
469 const struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr; 472 const struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr;
470 /* Don't match clients that failed to initialise properly */ 473 /* Don't match clients that failed to initialise properly */
471 if (clp->cl_cons_state < 0) 474 if (clp->cl_cons_state < 0)
@@ -483,9 +486,6 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat
483 /* Match the full socket address */ 486 /* Match the full socket address */
484 if (!nfs_sockaddr_cmp(sap, clap)) 487 if (!nfs_sockaddr_cmp(sap, clap))
485 continue; 488 continue;
486 /* Match network namespace */
487 if (clp->net != data->net)
488 continue;
489 489
490 atomic_inc(&clp->cl_count); 490 atomic_inc(&clp->cl_count);
491 return clp; 491 return clp;
@@ -506,6 +506,7 @@ nfs_get_client(const struct nfs_client_initdata *cl_init,
506{ 506{
507 struct nfs_client *clp, *new = NULL; 507 struct nfs_client *clp, *new = NULL;
508 int error; 508 int error;
509 struct nfs_net *nn = net_generic(cl_init->net, nfs_net_id);
509 510
510 dprintk("--> nfs_get_client(%s,v%u)\n", 511 dprintk("--> nfs_get_client(%s,v%u)\n",
511 cl_init->hostname ?: "", cl_init->rpc_ops->version); 512 cl_init->hostname ?: "", cl_init->rpc_ops->version);
@@ -531,7 +532,7 @@ nfs_get_client(const struct nfs_client_initdata *cl_init,
531 /* install a new client and return with it unready */ 532 /* install a new client and return with it unready */
532install_client: 533install_client:
533 clp = new; 534 clp = new;
534 list_add(&clp->cl_share_link, &nfs_client_list); 535 list_add(&clp->cl_share_link, &nn->nfs_client_list);
535 spin_unlock(&nfs_client_lock); 536 spin_unlock(&nfs_client_lock);
536 537
537 error = cl_init->rpc_ops->init_client(clp, timeparms, ip_addr, 538 error = cl_init->rpc_ops->init_client(clp, timeparms, ip_addr,
@@ -1227,9 +1228,10 @@ nfs4_find_client_sessionid(const struct sockaddr *addr,
1227 struct nfs4_sessionid *sid) 1228 struct nfs4_sessionid *sid)
1228{ 1229{
1229 struct nfs_client *clp; 1230 struct nfs_client *clp;
1231 struct nfs_net *nn = net_generic(&init_net, nfs_net_id);
1230 1232
1231 spin_lock(&nfs_client_lock); 1233 spin_lock(&nfs_client_lock);
1232 list_for_each_entry(clp, &nfs_client_list, cl_share_link) { 1234 list_for_each_entry(clp, &nn->nfs_client_list, cl_share_link) {
1233 if (nfs4_cb_match_client(addr, clp, 1) == false) 1235 if (nfs4_cb_match_client(addr, clp, 1) == false)
1234 continue; 1236 continue;
1235 1237
@@ -1757,6 +1759,13 @@ out_free_server:
1757 return ERR_PTR(error); 1759 return ERR_PTR(error);
1758} 1760}
1759 1761
1762void nfs_clients_init(struct net *net)
1763{
1764 struct nfs_net *nn = net_generic(net, nfs_net_id);
1765
1766 INIT_LIST_HEAD(&nn->nfs_client_list);
1767}
1768
1760#ifdef CONFIG_PROC_FS 1769#ifdef CONFIG_PROC_FS
1761static struct proc_dir_entry *proc_fs_nfs; 1770static struct proc_dir_entry *proc_fs_nfs;
1762 1771
@@ -1810,13 +1819,15 @@ static int nfs_server_list_open(struct inode *inode, struct file *file)
1810{ 1819{
1811 struct seq_file *m; 1820 struct seq_file *m;
1812 int ret; 1821 int ret;
1822 struct pid_namespace *pid_ns = file->f_dentry->d_sb->s_fs_info;
1823 struct net *net = pid_ns->child_reaper->nsproxy->net_ns;
1813 1824
1814 ret = seq_open(file, &nfs_server_list_ops); 1825 ret = seq_open(file, &nfs_server_list_ops);
1815 if (ret < 0) 1826 if (ret < 0)
1816 return ret; 1827 return ret;
1817 1828
1818 m = file->private_data; 1829 m = file->private_data;
1819 m->private = PDE(inode)->data; 1830 m->private = net;
1820 1831
1821 return 0; 1832 return 0;
1822} 1833}
@@ -1826,9 +1837,11 @@ static int nfs_server_list_open(struct inode *inode, struct file *file)
1826 */ 1837 */
1827static void *nfs_server_list_start(struct seq_file *m, loff_t *_pos) 1838static void *nfs_server_list_start(struct seq_file *m, loff_t *_pos)
1828{ 1839{
1840 struct nfs_net *nn = net_generic(m->private, nfs_net_id);
1841
1829 /* lock the list against modification */ 1842 /* lock the list against modification */
1830 spin_lock(&nfs_client_lock); 1843 spin_lock(&nfs_client_lock);
1831 return seq_list_start_head(&nfs_client_list, *_pos); 1844 return seq_list_start_head(&nn->nfs_client_list, *_pos);
1832} 1845}
1833 1846
1834/* 1847/*
@@ -1836,7 +1849,9 @@ static void *nfs_server_list_start(struct seq_file *m, loff_t *_pos)
1836 */ 1849 */
1837static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos) 1850static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos)
1838{ 1851{
1839 return seq_list_next(v, &nfs_client_list, pos); 1852 struct nfs_net *nn = net_generic(p->private, nfs_net_id);
1853
1854 return seq_list_next(v, &nn->nfs_client_list, pos);
1840} 1855}
1841 1856
1842/* 1857/*
@@ -1853,9 +1868,10 @@ static void nfs_server_list_stop(struct seq_file *p, void *v)
1853static int nfs_server_list_show(struct seq_file *m, void *v) 1868static int nfs_server_list_show(struct seq_file *m, void *v)
1854{ 1869{
1855 struct nfs_client *clp; 1870 struct nfs_client *clp;
1871 struct nfs_net *nn = net_generic(m->private, nfs_net_id);
1856 1872
1857 /* display header on line 1 */ 1873 /* display header on line 1 */
1858 if (v == &nfs_client_list) { 1874 if (v == &nn->nfs_client_list) {
1859 seq_puts(m, "NV SERVER PORT USE HOSTNAME\n"); 1875 seq_puts(m, "NV SERVER PORT USE HOSTNAME\n");
1860 return 0; 1876 return 0;
1861 } 1877 }