diff options
author | Andy Adamson <andros@netapp.com> | 2011-01-05 21:04:30 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-01-06 14:46:24 -0500 |
commit | f4eecd5da3422e82e88e36c33cbd2595eebcacb1 (patch) | |
tree | 8e49bbe401ed4233e1652843489a4360a94dc69b /fs/nfs | |
parent | ea00528126a701845d7c445e725b271940381e3d (diff) |
NFS implement v4.0 callback_ident
Use the small id to pointer translator service to provide a unique callback
identifier per SETCLIENTID call used to identify the v4.0 callback service
associated with the clientid.
Signed-off-by: Andy Adamson <andros@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/client.c | 51 | ||||
-rw-r--r-- | fs/nfs/inode.c | 1 | ||||
-rw-r--r-- | fs/nfs/internal.h | 1 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 1 |
4 files changed, 54 insertions, 0 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 855add62abc1..bc3a8620e8c3 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -56,6 +56,30 @@ static DEFINE_SPINLOCK(nfs_client_lock); | |||
56 | static LIST_HEAD(nfs_client_list); | 56 | static LIST_HEAD(nfs_client_list); |
57 | static LIST_HEAD(nfs_volume_list); | 57 | static LIST_HEAD(nfs_volume_list); |
58 | static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq); | 58 | static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq); |
59 | #ifdef CONFIG_NFS_V4 | ||
60 | static DEFINE_IDR(cb_ident_idr); /* Protected by nfs_client_lock */ | ||
61 | |||
62 | /* | ||
63 | * Get a unique NFSv4.0 callback identifier which will be used | ||
64 | * by the V4.0 callback service to lookup the nfs_client struct | ||
65 | */ | ||
66 | static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion) | ||
67 | { | ||
68 | int ret = 0; | ||
69 | |||
70 | if (clp->rpc_ops->version != 4 || minorversion != 0) | ||
71 | return ret; | ||
72 | retry: | ||
73 | if (!idr_pre_get(&cb_ident_idr, GFP_KERNEL)) | ||
74 | return -ENOMEM; | ||
75 | spin_lock(&nfs_client_lock); | ||
76 | ret = idr_get_new(&cb_ident_idr, clp, &clp->cl_cb_ident); | ||
77 | spin_unlock(&nfs_client_lock); | ||
78 | if (ret == -EAGAIN) | ||
79 | goto retry; | ||
80 | return ret; | ||
81 | } | ||
82 | #endif /* CONFIG_NFS_V4 */ | ||
59 | 83 | ||
60 | /* | 84 | /* |
61 | * RPC cruft for NFS | 85 | * RPC cruft for NFS |
@@ -144,6 +168,10 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_ | |||
144 | clp->cl_proto = cl_init->proto; | 168 | clp->cl_proto = cl_init->proto; |
145 | 169 | ||
146 | #ifdef CONFIG_NFS_V4 | 170 | #ifdef CONFIG_NFS_V4 |
171 | err = nfs_get_cb_ident_idr(clp, cl_init->minorversion); | ||
172 | if (err) | ||
173 | goto error_cleanup; | ||
174 | |||
147 | INIT_LIST_HEAD(&clp->cl_delegations); | 175 | INIT_LIST_HEAD(&clp->cl_delegations); |
148 | spin_lock_init(&clp->cl_lock); | 176 | spin_lock_init(&clp->cl_lock); |
149 | INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state); | 177 | INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state); |
@@ -202,10 +230,32 @@ static void nfs4_shutdown_client(struct nfs_client *clp) | |||
202 | 230 | ||
203 | rpc_destroy_wait_queue(&clp->cl_rpcwaitq); | 231 | rpc_destroy_wait_queue(&clp->cl_rpcwaitq); |
204 | } | 232 | } |
233 | |||
234 | /* idr_remove_all is not needed as all id's are removed by nfs_put_client */ | ||
235 | void nfs_cleanup_cb_ident_idr(void) | ||
236 | { | ||
237 | idr_destroy(&cb_ident_idr); | ||
238 | } | ||
239 | |||
240 | /* nfs_client_lock held */ | ||
241 | static void nfs_cb_idr_remove_locked(struct nfs_client *clp) | ||
242 | { | ||
243 | if (clp->cl_cb_ident) | ||
244 | idr_remove(&cb_ident_idr, clp->cl_cb_ident); | ||
245 | } | ||
246 | |||
205 | #else | 247 | #else |
206 | static void nfs4_shutdown_client(struct nfs_client *clp) | 248 | static void nfs4_shutdown_client(struct nfs_client *clp) |
207 | { | 249 | { |
208 | } | 250 | } |
251 | |||
252 | void nfs_cleanup_cb_ident_idr(void) | ||
253 | { | ||
254 | } | ||
255 | |||
256 | static void nfs_cb_idr_remove_locked(struct nfs_client *clp) | ||
257 | { | ||
258 | } | ||
209 | #endif /* CONFIG_NFS_V4 */ | 259 | #endif /* CONFIG_NFS_V4 */ |
210 | 260 | ||
211 | /* | 261 | /* |
@@ -244,6 +294,7 @@ void nfs_put_client(struct nfs_client *clp) | |||
244 | 294 | ||
245 | if (atomic_dec_and_lock(&clp->cl_count, &nfs_client_lock)) { | 295 | if (atomic_dec_and_lock(&clp->cl_count, &nfs_client_lock)) { |
246 | list_del(&clp->cl_share_link); | 296 | list_del(&clp->cl_share_link); |
297 | nfs_cb_idr_remove_locked(clp); | ||
247 | spin_unlock(&nfs_client_lock); | 298 | spin_unlock(&nfs_client_lock); |
248 | 299 | ||
249 | BUG_ON(!list_empty(&clp->cl_superblocks)); | 300 | BUG_ON(!list_empty(&clp->cl_superblocks)); |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index e67e31c73416..c7782b278e8b 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -1612,6 +1612,7 @@ static void __exit exit_nfs_fs(void) | |||
1612 | #ifdef CONFIG_PROC_FS | 1612 | #ifdef CONFIG_PROC_FS |
1613 | rpc_proc_unregister("nfs"); | 1613 | rpc_proc_unregister("nfs"); |
1614 | #endif | 1614 | #endif |
1615 | nfs_cleanup_cb_ident_idr(); | ||
1615 | unregister_nfs_fs(); | 1616 | unregister_nfs_fs(); |
1616 | nfs_fs_proc_exit(); | 1617 | nfs_fs_proc_exit(); |
1617 | nfsiod_stop(); | 1618 | nfsiod_stop(); |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 435eae3666bd..7c803c916574 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -128,6 +128,7 @@ extern void nfs_umount(const struct nfs_mount_request *info); | |||
128 | /* client.c */ | 128 | /* client.c */ |
129 | extern struct rpc_program nfs_program; | 129 | extern struct rpc_program nfs_program; |
130 | 130 | ||
131 | extern void nfs_cleanup_cb_ident_idr(void); | ||
131 | extern void nfs_put_client(struct nfs_client *); | 132 | extern void nfs_put_client(struct nfs_client *); |
132 | extern struct nfs_client *nfs_find_client(const struct sockaddr *, u32); | 133 | extern struct nfs_client *nfs_find_client(const struct sockaddr *, u32); |
133 | extern struct nfs_client *nfs_find_client_next(struct nfs_client *); | 134 | extern struct nfs_client *nfs_find_client_next(struct nfs_client *); |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 82f3a82b7115..e165c53db08f 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -3484,6 +3484,7 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, | |||
3484 | struct nfs4_setclientid setclientid = { | 3484 | struct nfs4_setclientid setclientid = { |
3485 | .sc_verifier = &sc_verifier, | 3485 | .sc_verifier = &sc_verifier, |
3486 | .sc_prog = program, | 3486 | .sc_prog = program, |
3487 | .sc_cb_ident = clp->cl_cb_ident, | ||
3487 | }; | 3488 | }; |
3488 | struct rpc_message msg = { | 3489 | struct rpc_message msg = { |
3489 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID], | 3490 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID], |