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>
This commit is contained in:
Родитель
ea00528126
Коммит
f4eecd5da3
|
@ -56,6 +56,30 @@ static DEFINE_SPINLOCK(nfs_client_lock);
|
||||||
static LIST_HEAD(nfs_client_list);
|
static LIST_HEAD(nfs_client_list);
|
||||||
static LIST_HEAD(nfs_volume_list);
|
static LIST_HEAD(nfs_volume_list);
|
||||||
static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq);
|
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
|
* 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;
|
clp->cl_proto = cl_init->proto;
|
||||||
|
|
||||||
#ifdef CONFIG_NFS_V4
|
#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);
|
INIT_LIST_HEAD(&clp->cl_delegations);
|
||||||
spin_lock_init(&clp->cl_lock);
|
spin_lock_init(&clp->cl_lock);
|
||||||
INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state);
|
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);
|
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
|
#else
|
||||||
static void nfs4_shutdown_client(struct nfs_client *clp)
|
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 */
|
#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)) {
|
if (atomic_dec_and_lock(&clp->cl_count, &nfs_client_lock)) {
|
||||||
list_del(&clp->cl_share_link);
|
list_del(&clp->cl_share_link);
|
||||||
|
nfs_cb_idr_remove_locked(clp);
|
||||||
spin_unlock(&nfs_client_lock);
|
spin_unlock(&nfs_client_lock);
|
||||||
|
|
||||||
BUG_ON(!list_empty(&clp->cl_superblocks));
|
BUG_ON(!list_empty(&clp->cl_superblocks));
|
||||||
|
|
|
@ -1612,6 +1612,7 @@ static void __exit exit_nfs_fs(void)
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
rpc_proc_unregister("nfs");
|
rpc_proc_unregister("nfs");
|
||||||
#endif
|
#endif
|
||||||
|
nfs_cleanup_cb_ident_idr();
|
||||||
unregister_nfs_fs();
|
unregister_nfs_fs();
|
||||||
nfs_fs_proc_exit();
|
nfs_fs_proc_exit();
|
||||||
nfsiod_stop();
|
nfsiod_stop();
|
||||||
|
|
|
@ -128,6 +128,7 @@ extern void nfs_umount(const struct nfs_mount_request *info);
|
||||||
/* client.c */
|
/* client.c */
|
||||||
extern struct rpc_program nfs_program;
|
extern struct rpc_program nfs_program;
|
||||||
|
|
||||||
|
extern void nfs_cleanup_cb_ident_idr(void);
|
||||||
extern void nfs_put_client(struct nfs_client *);
|
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(const struct sockaddr *, u32);
|
||||||
extern struct nfs_client *nfs_find_client_next(struct nfs_client *);
|
extern struct nfs_client *nfs_find_client_next(struct nfs_client *);
|
||||||
|
|
|
@ -3484,6 +3484,7 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program,
|
||||||
struct nfs4_setclientid setclientid = {
|
struct nfs4_setclientid setclientid = {
|
||||||
.sc_verifier = &sc_verifier,
|
.sc_verifier = &sc_verifier,
|
||||||
.sc_prog = program,
|
.sc_prog = program,
|
||||||
|
.sc_cb_ident = clp->cl_cb_ident,
|
||||||
};
|
};
|
||||||
struct rpc_message msg = {
|
struct rpc_message msg = {
|
||||||
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID],
|
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID],
|
||||||
|
|
|
@ -71,6 +71,7 @@ struct nfs_client {
|
||||||
*/
|
*/
|
||||||
char cl_ipaddr[48];
|
char cl_ipaddr[48];
|
||||||
unsigned char cl_id_uniquifier;
|
unsigned char cl_id_uniquifier;
|
||||||
|
u32 cl_cb_ident; /* v4.0 callback identifier */
|
||||||
const struct nfs4_minor_version_ops *cl_mvops;
|
const struct nfs4_minor_version_ops *cl_mvops;
|
||||||
#endif /* CONFIG_NFS_V4 */
|
#endif /* CONFIG_NFS_V4 */
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче