From patchwork Wed Jan 5 20:51:25 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Adamson X-Patchwork-Id: 454941 X-Patchwork-Delegate: Trond.Myklebust@netapp.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p05Kps3t001282 for ; Wed, 5 Jan 2011 20:51:57 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753053Ab1AEUvz (ORCPT ); Wed, 5 Jan 2011 15:51:55 -0500 Received: from mx2.netapp.com ([216.240.18.37]:19703 "EHLO mx2.netapp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753021Ab1AEUvy (ORCPT ); Wed, 5 Jan 2011 15:51:54 -0500 X-IronPort-AV: E=Sophos;i="4.60,279,1291622400"; d="scan'208";a="502095659" Received: from smtp1.corp.netapp.com ([10.57.156.124]) by mx2-out.netapp.com with ESMTP; 05 Jan 2011 12:51:43 -0800 Received: from localhost.localdomain (isabel3-lxp.hq.netapp.com [10.58.58.218] (may be forged)) by smtp1.corp.netapp.com (8.13.1/8.13.1/NTAP-1.6) with ESMTP id p05KpZtK013531; Wed, 5 Jan 2011 12:51:42 -0800 (PST) From: andros@netapp.com To: trond.myklebust@netapp.com Cc: bfields@redhat.com, linux-nfs@vger.kernel.org, Andy Adamson Subject: [PATCH_V8 07/13] NFS implement v4.0 callback_ident Date: Wed, 5 Jan 2011 15:51:25 -0500 Message-Id: <1294260690-3095-8-git-send-email-andros@netapp.com> X-Mailer: git-send-email 1.6.6 In-Reply-To: <1294260690-3095-7-git-send-email-andros@netapp.com> References: <1294260690-3095-1-git-send-email-andros@netapp.com> <1294260690-3095-2-git-send-email-andros@netapp.com> <1294260690-3095-3-git-send-email-andros@netapp.com> <1294260690-3095-4-git-send-email-andros@netapp.com> <1294260690-3095-5-git-send-email-andros@netapp.com> <1294260690-3095-6-git-send-email-andros@netapp.com> <1294260690-3095-7-git-send-email-andros@netapp.com> Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Wed, 05 Jan 2011 20:51:57 +0000 (UTC) diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 855add6..251c78f 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -56,6 +56,8 @@ 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); +/* NFSv4.0 callback identifier */ +static DEFINE_IDR(cb_ident_idr); /* * RPC cruft for NFS @@ -359,6 +361,30 @@ static int nfs_sockaddr_cmp(const struct sockaddr *sa1, return 0; } +/* 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); +} + +/* + * Get a unique NFSv4.0 callback identifier which will be used + * by the V4.0 callback service to lookup the nfs_client struct + */ +int nfs_get_cb_ident(struct nfs_client *clp, int *cb_ident) +{ + int 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, cb_ident); + spin_unlock(&nfs_client_lock); + if (ret == -EAGAIN) + goto retry; + return ret; +} + /* * Find a client by IP address and protocol version * - returns NULL if no such client diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index e67e31c..c7782b2 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -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(); diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 435eae3..7a6c05f 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -128,6 +128,8 @@ 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 int nfs_get_cb_ident(struct nfs_client *, int *); 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 *); diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 78b0899..1cbc99d 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -3489,6 +3489,11 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, int loop = 0; int status; + /* get a unique callback identifier */ + status = nfs_get_cb_ident(clp, &setclientid.sc_cb_ident); + if (status) + return status; + p = (__be32*)sc_verifier.data; *p++ = htonl((u32)clp->cl_boot_time.tv_sec); *p = htonl((u32)clp->cl_boot_time.tv_nsec); @@ -3522,6 +3527,8 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, if (++clp->cl_id_uniquifier == 0) break; } + if (status == NFS_OK) + res->cb_ident = setclientid.sc_cb_ident; return status; } diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index f575a31..fe61422 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -79,6 +79,7 @@ int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) if (status != 0) goto out; clp->cl_clientid = clid.clientid; + clp->cl_cb_ident = clid.cb_ident; nfs4_schedule_state_renewal(clp); out: return status; diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index 452d964..1eaa054 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h @@ -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 */ diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 236e7e4..d325def 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -869,6 +869,7 @@ struct nfs4_setclientid { struct nfs4_setclientid_res { u64 clientid; nfs4_verifier confirm; + u32 cb_ident; }; struct nfs4_statfs_arg {