]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
NFS implement v4.0 callback_ident
authorAndy Adamson <andros@netapp.com>
Thu, 6 Jan 2011 02:04:30 +0000 (02:04 +0000)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Thu, 6 Jan 2011 19:46:24 +0000 (14:46 -0500)
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>
fs/nfs/client.c
fs/nfs/inode.c
fs/nfs/internal.h
fs/nfs/nfs4proc.c
include/linux/nfs_fs_sb.h

index 855add62abc159645696129507c45dae4f763100..bc3a8620e8c34285c310e082abb4a5205251d875 100644 (file)
@@ -56,6 +56,30 @@ static DEFINE_SPINLOCK(nfs_client_lock);
 static LIST_HEAD(nfs_client_list);
 static LIST_HEAD(nfs_volume_list);
 static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq);
+#ifdef CONFIG_NFS_V4
+static DEFINE_IDR(cb_ident_idr); /* Protected by nfs_client_lock */
+
+/*
+ * Get a unique NFSv4.0 callback identifier which will be used
+ * by the V4.0 callback service to lookup the nfs_client struct
+ */
+static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion)
+{
+       int ret = 0;
+
+       if (clp->rpc_ops->version != 4 || minorversion != 0)
+               return ret;
+retry:
+       if (!idr_pre_get(&cb_ident_idr, GFP_KERNEL))
+               return -ENOMEM;
+       spin_lock(&nfs_client_lock);
+       ret = idr_get_new(&cb_ident_idr, clp, &clp->cl_cb_ident);
+       spin_unlock(&nfs_client_lock);
+       if (ret == -EAGAIN)
+               goto retry;
+       return ret;
+}
+#endif /* CONFIG_NFS_V4 */
 
 /*
  * RPC cruft for NFS
@@ -144,6 +168,10 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
        clp->cl_proto = cl_init->proto;
 
 #ifdef CONFIG_NFS_V4
+       err = nfs_get_cb_ident_idr(clp, cl_init->minorversion);
+       if (err)
+               goto error_cleanup;
+
        INIT_LIST_HEAD(&clp->cl_delegations);
        spin_lock_init(&clp->cl_lock);
        INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state);
@@ -202,10 +230,32 @@ static void nfs4_shutdown_client(struct nfs_client *clp)
 
        rpc_destroy_wait_queue(&clp->cl_rpcwaitq);
 }
+
+/* idr_remove_all is not needed as all id's are removed by nfs_put_client */
+void nfs_cleanup_cb_ident_idr(void)
+{
+       idr_destroy(&cb_ident_idr);
+}
+
+/* nfs_client_lock held */
+static void nfs_cb_idr_remove_locked(struct nfs_client *clp)
+{
+       if (clp->cl_cb_ident)
+               idr_remove(&cb_ident_idr, clp->cl_cb_ident);
+}
+
 #else
 static void nfs4_shutdown_client(struct nfs_client *clp)
 {
 }
+
+void nfs_cleanup_cb_ident_idr(void)
+{
+}
+
+static void nfs_cb_idr_remove_locked(struct nfs_client *clp)
+{
+}
 #endif /* CONFIG_NFS_V4 */
 
 /*
@@ -244,6 +294,7 @@ void nfs_put_client(struct nfs_client *clp)
 
        if (atomic_dec_and_lock(&clp->cl_count, &nfs_client_lock)) {
                list_del(&clp->cl_share_link);
+               nfs_cb_idr_remove_locked(clp);
                spin_unlock(&nfs_client_lock);
 
                BUG_ON(!list_empty(&clp->cl_superblocks));
index e67e31c734163c6fe6c0eef0d338a2b87ae55763..c7782b278e8bdd1219815f447398c129a6f9d19c 100644 (file)
@@ -1612,6 +1612,7 @@ static void __exit exit_nfs_fs(void)
 #ifdef CONFIG_PROC_FS
        rpc_proc_unregister("nfs");
 #endif
+       nfs_cleanup_cb_ident_idr();
        unregister_nfs_fs();
        nfs_fs_proc_exit();
        nfsiod_stop();
index 435eae3666bd5fe263c4825cb015f658284bd610..7c803c916574c71b40446ca565745823154c8d93 100644 (file)
@@ -128,6 +128,7 @@ extern void nfs_umount(const struct nfs_mount_request *info);
 /* client.c */
 extern struct rpc_program nfs_program;
 
+extern void nfs_cleanup_cb_ident_idr(void);
 extern void nfs_put_client(struct nfs_client *);
 extern struct nfs_client *nfs_find_client(const struct sockaddr *, u32);
 extern struct nfs_client *nfs_find_client_next(struct nfs_client *);
index 82f3a82b7115b438d02924dd6023bca97dce218b..e165c53db08fbcb9287ea3b4f6592d1c2a3cc4a6 100644 (file)
@@ -3484,6 +3484,7 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program,
        struct nfs4_setclientid setclientid = {
                .sc_verifier = &sc_verifier,
                .sc_prog = program,
+               .sc_cb_ident = clp->cl_cb_ident,
        };
        struct rpc_message msg = {
                .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID],
index 452d96436d266d6ea6cef73f2e3e1dd74a1f76b2..1eaa054a2c7d4c78b7d969d77765102cbc051b16 100644 (file)
@@ -71,6 +71,7 @@ struct nfs_client {
         */
        char                    cl_ipaddr[48];
        unsigned char           cl_id_uniquifier;
+       u32                     cl_cb_ident;    /* v4.0 callback identifier */
        const struct nfs4_minor_version_ops *cl_mvops;
 #endif /* CONFIG_NFS_V4 */