diff options
author | Stanislav Kinsbursky <skinsbursky@parallels.com> | 2012-01-23 12:26:14 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-02-06 18:48:02 -0500 |
commit | c25d32b26361ce0814fef2281f164866c18c8692 (patch) | |
tree | 8429f6b0bc9deeab4a74792eb43e62d65dd57082 | |
parent | 6b13168b36b6a7f603d962c232f1f2f325705832 (diff) |
NFS: make nfs_volume_list per net ns
This patch splits global list of NFS servers into per-net-ns array of lists.
This looks more strict and clearer.
BTW, this patch also makes "/proc/fs/nfsfs/volumes" 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>
-rw-r--r-- | fs/nfs/client.c | 20 | ||||
-rw-r--r-- | fs/nfs/netns.h | 1 |
2 files changed, 15 insertions, 6 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 058eb9bcfa9d..d58e8386e6bc 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -56,7 +56,6 @@ | |||
56 | #define NFSDBG_FACILITY NFSDBG_CLIENT | 56 | #define NFSDBG_FACILITY NFSDBG_CLIENT |
57 | 57 | ||
58 | DEFINE_SPINLOCK(nfs_client_lock); | 58 | DEFINE_SPINLOCK(nfs_client_lock); |
59 | static LIST_HEAD(nfs_volume_list); | ||
60 | static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq); | 59 | static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq); |
61 | #ifdef CONFIG_NFS_V4 | 60 | #ifdef CONFIG_NFS_V4 |
62 | static DEFINE_IDR(cb_ident_idr); /* Protected by nfs_client_lock */ | 61 | static DEFINE_IDR(cb_ident_idr); /* Protected by nfs_client_lock */ |
@@ -1036,10 +1035,11 @@ static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_serve | |||
1036 | static void nfs_server_insert_lists(struct nfs_server *server) | 1035 | static void nfs_server_insert_lists(struct nfs_server *server) |
1037 | { | 1036 | { |
1038 | struct nfs_client *clp = server->nfs_client; | 1037 | struct nfs_client *clp = server->nfs_client; |
1038 | struct nfs_net *nn = net_generic(clp->net, nfs_net_id); | ||
1039 | 1039 | ||
1040 | spin_lock(&nfs_client_lock); | 1040 | spin_lock(&nfs_client_lock); |
1041 | list_add_tail_rcu(&server->client_link, &clp->cl_superblocks); | 1041 | list_add_tail_rcu(&server->client_link, &clp->cl_superblocks); |
1042 | list_add_tail(&server->master_link, &nfs_volume_list); | 1042 | list_add_tail(&server->master_link, &nn->nfs_volume_list); |
1043 | clear_bit(NFS_CS_STOP_RENEW, &clp->cl_res_state); | 1043 | clear_bit(NFS_CS_STOP_RENEW, &clp->cl_res_state); |
1044 | spin_unlock(&nfs_client_lock); | 1044 | spin_unlock(&nfs_client_lock); |
1045 | 1045 | ||
@@ -1764,6 +1764,7 @@ void nfs_clients_init(struct net *net) | |||
1764 | struct nfs_net *nn = net_generic(net, nfs_net_id); | 1764 | struct nfs_net *nn = net_generic(net, nfs_net_id); |
1765 | 1765 | ||
1766 | INIT_LIST_HEAD(&nn->nfs_client_list); | 1766 | INIT_LIST_HEAD(&nn->nfs_client_list); |
1767 | INIT_LIST_HEAD(&nn->nfs_volume_list); | ||
1767 | } | 1768 | } |
1768 | 1769 | ||
1769 | #ifdef CONFIG_PROC_FS | 1770 | #ifdef CONFIG_PROC_FS |
@@ -1900,13 +1901,15 @@ static int nfs_volume_list_open(struct inode *inode, struct file *file) | |||
1900 | { | 1901 | { |
1901 | struct seq_file *m; | 1902 | struct seq_file *m; |
1902 | int ret; | 1903 | int ret; |
1904 | struct pid_namespace *pid_ns = file->f_dentry->d_sb->s_fs_info; | ||
1905 | struct net *net = pid_ns->child_reaper->nsproxy->net_ns; | ||
1903 | 1906 | ||
1904 | ret = seq_open(file, &nfs_volume_list_ops); | 1907 | ret = seq_open(file, &nfs_volume_list_ops); |
1905 | if (ret < 0) | 1908 | if (ret < 0) |
1906 | return ret; | 1909 | return ret; |
1907 | 1910 | ||
1908 | m = file->private_data; | 1911 | m = file->private_data; |
1909 | m->private = PDE(inode)->data; | 1912 | m->private = net; |
1910 | 1913 | ||
1911 | return 0; | 1914 | return 0; |
1912 | } | 1915 | } |
@@ -1916,9 +1919,11 @@ static int nfs_volume_list_open(struct inode *inode, struct file *file) | |||
1916 | */ | 1919 | */ |
1917 | static void *nfs_volume_list_start(struct seq_file *m, loff_t *_pos) | 1920 | static void *nfs_volume_list_start(struct seq_file *m, loff_t *_pos) |
1918 | { | 1921 | { |
1922 | struct nfs_net *nn = net_generic(m->private, nfs_net_id); | ||
1923 | |||
1919 | /* lock the list against modification */ | 1924 | /* lock the list against modification */ |
1920 | spin_lock(&nfs_client_lock); | 1925 | spin_lock(&nfs_client_lock); |
1921 | return seq_list_start_head(&nfs_volume_list, *_pos); | 1926 | return seq_list_start_head(&nn->nfs_volume_list, *_pos); |
1922 | } | 1927 | } |
1923 | 1928 | ||
1924 | /* | 1929 | /* |
@@ -1926,7 +1931,9 @@ static void *nfs_volume_list_start(struct seq_file *m, loff_t *_pos) | |||
1926 | */ | 1931 | */ |
1927 | static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos) | 1932 | static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos) |
1928 | { | 1933 | { |
1929 | return seq_list_next(v, &nfs_volume_list, pos); | 1934 | struct nfs_net *nn = net_generic(p->private, nfs_net_id); |
1935 | |||
1936 | return seq_list_next(v, &nn->nfs_volume_list, pos); | ||
1930 | } | 1937 | } |
1931 | 1938 | ||
1932 | /* | 1939 | /* |
@@ -1945,9 +1952,10 @@ static int nfs_volume_list_show(struct seq_file *m, void *v) | |||
1945 | struct nfs_server *server; | 1952 | struct nfs_server *server; |
1946 | struct nfs_client *clp; | 1953 | struct nfs_client *clp; |
1947 | char dev[8], fsid[17]; | 1954 | char dev[8], fsid[17]; |
1955 | struct nfs_net *nn = net_generic(m->private, nfs_net_id); | ||
1948 | 1956 | ||
1949 | /* display header on line 1 */ | 1957 | /* display header on line 1 */ |
1950 | if (v == &nfs_volume_list) { | 1958 | if (v == &nn->nfs_volume_list) { |
1951 | seq_puts(m, "NV SERVER PORT DEV FSID FSC\n"); | 1959 | seq_puts(m, "NV SERVER PORT DEV FSID FSC\n"); |
1952 | return 0; | 1960 | return 0; |
1953 | } | 1961 | } |
diff --git a/fs/nfs/netns.h b/fs/nfs/netns.h index feb33c3f9a56..0fbd4e017d27 100644 --- a/fs/nfs/netns.h +++ b/fs/nfs/netns.h | |||
@@ -8,6 +8,7 @@ struct nfs_net { | |||
8 | struct cache_detail *nfs_dns_resolve; | 8 | struct cache_detail *nfs_dns_resolve; |
9 | struct rpc_pipe *bl_device_pipe; | 9 | struct rpc_pipe *bl_device_pipe; |
10 | struct list_head nfs_client_list; | 10 | struct list_head nfs_client_list; |
11 | struct list_head nfs_volume_list; | ||
11 | }; | 12 | }; |
12 | 13 | ||
13 | extern int nfs_net_id; | 14 | extern int nfs_net_id; |