diff options
author | Stanislav Kinsbursky <skinsbursky@parallels.com> | 2012-01-23 12:26:05 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-02-06 18:48:02 -0500 |
commit | 6b13168b36b6a7f603d962c232f1f2f325705832 (patch) | |
tree | e524fb58428a8c128dcad8cf00cbd2692be9c6ad /fs/nfs/client.c | |
parent | a602bea3e7ccc5ce3da61d2c18245c4058983926 (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.c | 38 |
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 | ||
55 | DEFINE_SPINLOCK(nfs_client_lock); | 58 | DEFINE_SPINLOCK(nfs_client_lock); |
56 | LIST_HEAD(nfs_client_list); | ||
57 | static LIST_HEAD(nfs_volume_list); | 59 | static LIST_HEAD(nfs_volume_list); |
58 | static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq); | 60 | static 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 */ |
532 | install_client: | 533 | install_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 | ||
1762 | void 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 |
1761 | static struct proc_dir_entry *proc_fs_nfs; | 1770 | static 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 | */ |
1827 | static void *nfs_server_list_start(struct seq_file *m, loff_t *_pos) | 1838 | static 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 | */ |
1837 | static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos) | 1850 | static 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) | |||
1853 | static int nfs_server_list_show(struct seq_file *m, void *v) | 1868 | static 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 | } |