diff options
author | Stanislav Kinsbursky <skinsbursky@parallels.com> | 2012-01-23 12:26:22 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-02-06 18:48:03 -0500 |
commit | 28cd1b3f262dba56b5e335ba668e342d530f6129 (patch) | |
tree | 7ae24e43fe054042800118edb266287125ba34f8 /fs/nfs | |
parent | c25d32b26361ce0814fef2281f164866c18c8692 (diff) |
NFS: make cb_ident_idr per net ns
This patch makes ID's infrastructure network namespace aware. This was done
mainly because of nfs_client_lock, which is desired to be per network
namespace, but protects NFS clients ID's.
NOTE: NFS client's net pointer have to be set prior to ID initialization,
proper assignment was moved.
Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/callback_xdr.c | 2 | ||||
-rw-r--r-- | fs/nfs/client.c | 28 | ||||
-rw-r--r-- | fs/nfs/inode.c | 2 | ||||
-rw-r--r-- | fs/nfs/internal.h | 4 | ||||
-rw-r--r-- | fs/nfs/netns.h | 3 |
5 files changed, 25 insertions, 14 deletions
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c index 2f45aa717423..e14af46bd2c6 100644 --- a/fs/nfs/callback_xdr.c +++ b/fs/nfs/callback_xdr.c | |||
@@ -876,7 +876,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r | |||
876 | return rpc_garbage_args; | 876 | return rpc_garbage_args; |
877 | 877 | ||
878 | if (hdr_arg.minorversion == 0) { | 878 | if (hdr_arg.minorversion == 0) { |
879 | cps.clp = nfs4_find_client_ident(hdr_arg.cb_ident); | 879 | cps.clp = nfs4_find_client_ident(rqstp->rq_xprt->xpt_net, hdr_arg.cb_ident); |
880 | if (!cps.clp || !check_gss_callback_principal(cps.clp, rqstp)) | 880 | if (!cps.clp || !check_gss_callback_principal(cps.clp, rqstp)) |
881 | return rpc_drop_reply; | 881 | return rpc_drop_reply; |
882 | } | 882 | } |
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index d58e8386e6bc..f51b2795ce07 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -58,7 +58,6 @@ | |||
58 | DEFINE_SPINLOCK(nfs_client_lock); | 58 | DEFINE_SPINLOCK(nfs_client_lock); |
59 | static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq); | 59 | static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq); |
60 | #ifdef CONFIG_NFS_V4 | 60 | #ifdef CONFIG_NFS_V4 |
61 | static DEFINE_IDR(cb_ident_idr); /* Protected by nfs_client_lock */ | ||
62 | 61 | ||
63 | /* | 62 | /* |
64 | * Get a unique NFSv4.0 callback identifier which will be used | 63 | * Get a unique NFSv4.0 callback identifier which will be used |
@@ -67,14 +66,15 @@ static DEFINE_IDR(cb_ident_idr); /* Protected by nfs_client_lock */ | |||
67 | static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion) | 66 | static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion) |
68 | { | 67 | { |
69 | int ret = 0; | 68 | int ret = 0; |
69 | struct nfs_net *nn = net_generic(clp->net, nfs_net_id); | ||
70 | 70 | ||
71 | if (clp->rpc_ops->version != 4 || minorversion != 0) | 71 | if (clp->rpc_ops->version != 4 || minorversion != 0) |
72 | return ret; | 72 | return ret; |
73 | retry: | 73 | retry: |
74 | if (!idr_pre_get(&cb_ident_idr, GFP_KERNEL)) | 74 | if (!idr_pre_get(&nn->cb_ident_idr, GFP_KERNEL)) |
75 | return -ENOMEM; | 75 | return -ENOMEM; |
76 | spin_lock(&nfs_client_lock); | 76 | spin_lock(&nfs_client_lock); |
77 | ret = idr_get_new(&cb_ident_idr, clp, &clp->cl_cb_ident); | 77 | ret = idr_get_new(&nn->cb_ident_idr, clp, &clp->cl_cb_ident); |
78 | spin_unlock(&nfs_client_lock); | 78 | spin_unlock(&nfs_client_lock); |
79 | if (ret == -EAGAIN) | 79 | if (ret == -EAGAIN) |
80 | goto retry; | 80 | goto retry; |
@@ -173,6 +173,7 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_ | |||
173 | clp->cl_rpcclient = ERR_PTR(-EINVAL); | 173 | clp->cl_rpcclient = ERR_PTR(-EINVAL); |
174 | 174 | ||
175 | clp->cl_proto = cl_init->proto; | 175 | clp->cl_proto = cl_init->proto; |
176 | clp->net = cl_init->net; | ||
176 | 177 | ||
177 | #ifdef CONFIG_NFS_V4 | 178 | #ifdef CONFIG_NFS_V4 |
178 | err = nfs_get_cb_ident_idr(clp, cl_init->minorversion); | 179 | err = nfs_get_cb_ident_idr(clp, cl_init->minorversion); |
@@ -191,7 +192,6 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_ | |||
191 | if (!IS_ERR(cred)) | 192 | if (!IS_ERR(cred)) |
192 | clp->cl_machine_cred = cred; | 193 | clp->cl_machine_cred = cred; |
193 | nfs_fscache_get_client_cookie(clp); | 194 | nfs_fscache_get_client_cookie(clp); |
194 | clp->net = cl_init->net; | ||
195 | 195 | ||
196 | return clp; | 196 | return clp; |
197 | 197 | ||
@@ -236,16 +236,20 @@ static void nfs4_shutdown_client(struct nfs_client *clp) | |||
236 | } | 236 | } |
237 | 237 | ||
238 | /* idr_remove_all is not needed as all id's are removed by nfs_put_client */ | 238 | /* idr_remove_all is not needed as all id's are removed by nfs_put_client */ |
239 | void nfs_cleanup_cb_ident_idr(void) | 239 | void nfs_cleanup_cb_ident_idr(struct net *net) |
240 | { | 240 | { |
241 | idr_destroy(&cb_ident_idr); | 241 | struct nfs_net *nn = net_generic(net, nfs_net_id); |
242 | |||
243 | idr_destroy(&nn->cb_ident_idr); | ||
242 | } | 244 | } |
243 | 245 | ||
244 | /* nfs_client_lock held */ | 246 | /* nfs_client_lock held */ |
245 | static void nfs_cb_idr_remove_locked(struct nfs_client *clp) | 247 | static void nfs_cb_idr_remove_locked(struct nfs_client *clp) |
246 | { | 248 | { |
249 | struct nfs_net *nn = net_generic(clp->net, nfs_net_id); | ||
250 | |||
247 | if (clp->cl_cb_ident) | 251 | if (clp->cl_cb_ident) |
248 | idr_remove(&cb_ident_idr, clp->cl_cb_ident); | 252 | idr_remove(&nn->cb_ident_idr, clp->cl_cb_ident); |
249 | } | 253 | } |
250 | 254 | ||
251 | static void pnfs_init_server(struct nfs_server *server) | 255 | static void pnfs_init_server(struct nfs_server *server) |
@@ -263,7 +267,7 @@ static void nfs4_shutdown_client(struct nfs_client *clp) | |||
263 | { | 267 | { |
264 | } | 268 | } |
265 | 269 | ||
266 | void nfs_cleanup_cb_ident_idr(void) | 270 | void nfs_cleanup_cb_ident_idr(struct net *net) |
267 | { | 271 | { |
268 | } | 272 | } |
269 | 273 | ||
@@ -1203,12 +1207,13 @@ error: | |||
1203 | * Find a client by callback identifier | 1207 | * Find a client by callback identifier |
1204 | */ | 1208 | */ |
1205 | struct nfs_client * | 1209 | struct nfs_client * |
1206 | nfs4_find_client_ident(int cb_ident) | 1210 | nfs4_find_client_ident(struct net *net, int cb_ident) |
1207 | { | 1211 | { |
1208 | struct nfs_client *clp; | 1212 | struct nfs_client *clp; |
1213 | struct nfs_net *nn = net_generic(net, nfs_net_id); | ||
1209 | 1214 | ||
1210 | spin_lock(&nfs_client_lock); | 1215 | spin_lock(&nfs_client_lock); |
1211 | clp = idr_find(&cb_ident_idr, cb_ident); | 1216 | clp = idr_find(&nn->cb_ident_idr, cb_ident); |
1212 | if (clp) | 1217 | if (clp) |
1213 | atomic_inc(&clp->cl_count); | 1218 | atomic_inc(&clp->cl_count); |
1214 | spin_unlock(&nfs_client_lock); | 1219 | spin_unlock(&nfs_client_lock); |
@@ -1765,6 +1770,9 @@ void nfs_clients_init(struct net *net) | |||
1765 | 1770 | ||
1766 | INIT_LIST_HEAD(&nn->nfs_client_list); | 1771 | INIT_LIST_HEAD(&nn->nfs_client_list); |
1767 | INIT_LIST_HEAD(&nn->nfs_volume_list); | 1772 | INIT_LIST_HEAD(&nn->nfs_volume_list); |
1773 | #ifdef CONFIG_NFS_V4 | ||
1774 | idr_init(&nn->cb_ident_idr); | ||
1775 | #endif | ||
1768 | } | 1776 | } |
1769 | 1777 | ||
1770 | #ifdef CONFIG_PROC_FS | 1778 | #ifdef CONFIG_PROC_FS |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 0365b84cc2c7..6c662598f885 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -1565,6 +1565,7 @@ static int nfs_net_init(struct net *net) | |||
1565 | static void nfs_net_exit(struct net *net) | 1565 | static void nfs_net_exit(struct net *net) |
1566 | { | 1566 | { |
1567 | nfs_dns_resolver_cache_destroy(net); | 1567 | nfs_dns_resolver_cache_destroy(net); |
1568 | nfs_cleanup_cb_ident_idr(net); | ||
1568 | } | 1569 | } |
1569 | 1570 | ||
1570 | static struct pernet_operations nfs_net_ops = { | 1571 | static struct pernet_operations nfs_net_ops = { |
@@ -1674,7 +1675,6 @@ static void __exit exit_nfs_fs(void) | |||
1674 | #ifdef CONFIG_PROC_FS | 1675 | #ifdef CONFIG_PROC_FS |
1675 | rpc_proc_unregister(&init_net, "nfs"); | 1676 | rpc_proc_unregister(&init_net, "nfs"); |
1676 | #endif | 1677 | #endif |
1677 | nfs_cleanup_cb_ident_idr(); | ||
1678 | unregister_nfs_fs(); | 1678 | unregister_nfs_fs(); |
1679 | nfs_fs_proc_exit(); | 1679 | nfs_fs_proc_exit(); |
1680 | nfsiod_stop(); | 1680 | nfsiod_stop(); |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index a9ae8069fff9..958fff2927c0 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -148,9 +148,9 @@ extern void nfs_umount(const struct nfs_mount_request *info); | |||
148 | extern const struct rpc_program nfs_program; | 148 | extern const struct rpc_program nfs_program; |
149 | extern void nfs_clients_init(struct net *net); | 149 | extern void nfs_clients_init(struct net *net); |
150 | 150 | ||
151 | extern void nfs_cleanup_cb_ident_idr(void); | 151 | extern void nfs_cleanup_cb_ident_idr(struct net *); |
152 | extern void nfs_put_client(struct nfs_client *); | 152 | extern void nfs_put_client(struct nfs_client *); |
153 | extern struct nfs_client *nfs4_find_client_ident(int); | 153 | extern struct nfs_client *nfs4_find_client_ident(struct net *, int); |
154 | extern struct nfs_client * | 154 | extern struct nfs_client * |
155 | nfs4_find_client_sessionid(const struct sockaddr *, struct nfs4_sessionid *); | 155 | nfs4_find_client_sessionid(const struct sockaddr *, struct nfs4_sessionid *); |
156 | extern struct nfs_server *nfs_create_server( | 156 | extern struct nfs_server *nfs_create_server( |
diff --git a/fs/nfs/netns.h b/fs/nfs/netns.h index 0fbd4e017d27..547cc9525ba2 100644 --- a/fs/nfs/netns.h +++ b/fs/nfs/netns.h | |||
@@ -9,6 +9,9 @@ struct nfs_net { | |||
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 | struct list_head nfs_volume_list; |
12 | #ifdef CONFIG_NFS_V4 | ||
13 | struct idr cb_ident_idr; /* Protected by nfs_client_lock */ | ||
14 | #endif | ||
12 | }; | 15 | }; |
13 | 16 | ||
14 | extern int nfs_net_id; | 17 | extern int nfs_net_id; |