NFSv4.1 Use MDS auth flavor for data server connection
Commit 4edaa308
"NFS: Use "krb5i" to establish NFSv4 state whenever possible"
uses the nfs_client cl_rpcclient for all state management operations, and
will use krb5i or auth_sys with no regard to the mount command authflavor
choice.
The MDS, as any NFSv4.1 mount point, uses the nfs_server rpc client for all
non-state management operations with a different nfs_server for each fsid
encountered traversing the mount point, each with a potentially different
auth flavor.
pNFS data servers are not mounted in the normal sense as there is no associated
nfs_server structure. Data servers can also export multiple fsids, each with
a potentially different auth flavor.
Data servers need to use the same authflavor as the MDS server rpc client for
non-state management operations. Populate a list of rpc clients with the MDS
server rpc client auth flavor for the DS to use.
Signed-off-by: Andy Adamson <andros@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
parent
4109bb7496
commit
0e20162ed1
4 changed files with 146 additions and 8 deletions
|
@ -41,9 +41,124 @@ static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_NFS_V4_1
|
||||
/**
|
||||
* Per auth flavor data server rpc clients
|
||||
*/
|
||||
struct nfs4_ds_server {
|
||||
struct list_head list; /* ds_clp->cl_ds_clients */
|
||||
struct rpc_clnt *rpc_clnt;
|
||||
};
|
||||
|
||||
/**
|
||||
* Common lookup case for DS I/O
|
||||
*/
|
||||
static struct nfs4_ds_server *
|
||||
nfs4_find_ds_client(struct nfs_client *ds_clp, rpc_authflavor_t flavor)
|
||||
{
|
||||
struct nfs4_ds_server *dss;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(dss, &ds_clp->cl_ds_clients, list) {
|
||||
if (dss->rpc_clnt->cl_auth->au_flavor != flavor)
|
||||
continue;
|
||||
goto out;
|
||||
}
|
||||
dss = NULL;
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
return dss;
|
||||
}
|
||||
|
||||
static struct nfs4_ds_server *
|
||||
nfs4_add_ds_client(struct nfs_client *ds_clp, rpc_authflavor_t flavor,
|
||||
struct nfs4_ds_server *new)
|
||||
{
|
||||
struct nfs4_ds_server *dss;
|
||||
|
||||
spin_lock(&ds_clp->cl_lock);
|
||||
list_for_each_entry(dss, &ds_clp->cl_ds_clients, list) {
|
||||
if (dss->rpc_clnt->cl_auth->au_flavor != flavor)
|
||||
continue;
|
||||
goto out;
|
||||
}
|
||||
if (new)
|
||||
list_add_rcu(&new->list, &ds_clp->cl_ds_clients);
|
||||
dss = new;
|
||||
out:
|
||||
spin_unlock(&ds_clp->cl_lock); /* need some lock to protect list */
|
||||
return dss;
|
||||
}
|
||||
|
||||
static struct nfs4_ds_server *
|
||||
nfs4_alloc_ds_server(struct nfs_client *ds_clp, rpc_authflavor_t flavor)
|
||||
{
|
||||
struct nfs4_ds_server *dss;
|
||||
|
||||
dss = kmalloc(sizeof(*dss), GFP_NOFS);
|
||||
if (dss == NULL)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
dss->rpc_clnt = rpc_clone_client_set_auth(ds_clp->cl_rpcclient, flavor);
|
||||
if (IS_ERR(dss->rpc_clnt)) {
|
||||
int err = PTR_ERR(dss->rpc_clnt);
|
||||
kfree (dss);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
INIT_LIST_HEAD(&dss->list);
|
||||
|
||||
return dss;
|
||||
}
|
||||
|
||||
static void
|
||||
nfs4_free_ds_server(struct nfs4_ds_server *dss)
|
||||
{
|
||||
rpc_release_client(dss->rpc_clnt);
|
||||
kfree(dss);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find or create a DS rpc client with th MDS server rpc client auth flavor
|
||||
* in the nfs_client cl_ds_clients list.
|
||||
*/
|
||||
struct rpc_clnt *
|
||||
nfs4_find_or_create_ds_client(struct nfs_client *ds_clp, struct inode *inode)
|
||||
{
|
||||
struct nfs4_ds_server *dss, *new;
|
||||
rpc_authflavor_t flavor = NFS_SERVER(inode)->client->cl_auth->au_flavor;
|
||||
|
||||
dss = nfs4_find_ds_client(ds_clp, flavor);
|
||||
if (dss != NULL)
|
||||
goto out;
|
||||
new = nfs4_alloc_ds_server(ds_clp, flavor);
|
||||
if (IS_ERR(new))
|
||||
return ERR_CAST(new);
|
||||
dss = nfs4_add_ds_client(ds_clp, flavor, new);
|
||||
if (dss != new)
|
||||
nfs4_free_ds_server(new);
|
||||
out:
|
||||
return dss->rpc_clnt;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs4_find_or_create_ds_client);
|
||||
|
||||
static void
|
||||
nfs4_shutdown_ds_clients(struct nfs_client *clp)
|
||||
{
|
||||
struct nfs4_ds_server *dss;
|
||||
LIST_HEAD(shutdown_list);
|
||||
|
||||
while (!list_empty(&clp->cl_ds_clients)) {
|
||||
dss = list_entry(clp->cl_ds_clients.next,
|
||||
struct nfs4_ds_server, list);
|
||||
list_del(&dss->list);
|
||||
rpc_shutdown_client(dss->rpc_clnt);
|
||||
kfree (dss);
|
||||
}
|
||||
}
|
||||
|
||||
void nfs41_shutdown_client(struct nfs_client *clp)
|
||||
{
|
||||
if (nfs4_has_session(clp)) {
|
||||
nfs4_shutdown_ds_clients(clp);
|
||||
nfs4_destroy_session(clp->cl_session);
|
||||
nfs4_destroy_clientid(clp);
|
||||
}
|
||||
|
@ -77,6 +192,7 @@ struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init)
|
|||
|
||||
spin_lock_init(&clp->cl_lock);
|
||||
INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state);
|
||||
INIT_LIST_HEAD(&clp->cl_ds_clients);
|
||||
rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client");
|
||||
clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
|
||||
clp->cl_minorversion = cl_init->minorversion;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue