Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f4eecd5d authored by Andy Adamson's avatar Andy Adamson Committed by Trond Myklebust
Browse files

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: default avatarAndy Adamson <andros@netapp.com>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent ea005281
Loading
Loading
Loading
Loading
+51 −0
Original line number Diff line number Diff line
@@ -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));
+1 −0
Original line number Diff line number Diff line
@@ -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();
+1 −0
Original line number Diff line number Diff line
@@ -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 *);
+1 −0
Original line number Diff line number Diff line
@@ -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],
+1 −0
Original line number Diff line number Diff line
@@ -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 */