aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorAndy Adamson <andros@netapp.com>2013-09-06 14:14:00 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2013-09-06 14:49:16 -0400
commit0e20162ed1e9a639fc61d62c71327169fb1a1970 (patch)
tree299ac444cffc3087c5221c30bce9fbbf4ba9d133 /fs/nfs
parent4109bb7496640aa97a12904527ba8e3a19b7ce7a (diff)
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>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/internal.h2
-rw-r--r--fs/nfs/nfs4client.c116
-rw-r--r--fs/nfs/nfs4filelayout.c35
3 files changed, 145 insertions, 8 deletions
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 2415198d29ad..23ec6e8e8a4d 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -186,6 +186,8 @@ extern struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp,
186 int ds_addrlen, int ds_proto, 186 int ds_addrlen, int ds_proto,
187 unsigned int ds_timeo, 187 unsigned int ds_timeo,
188 unsigned int ds_retrans); 188 unsigned int ds_retrans);
189extern struct rpc_clnt *nfs4_find_or_create_ds_client(struct nfs_client *,
190 struct inode *);
189#ifdef CONFIG_PROC_FS 191#ifdef CONFIG_PROC_FS
190extern int __init nfs_fs_proc_init(void); 192extern int __init nfs_fs_proc_init(void);
191extern void nfs_fs_proc_exit(void); 193extern void nfs_fs_proc_exit(void);
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
index 98c0104bb0c4..f798925d8291 100644
--- a/fs/nfs/nfs4client.c
+++ b/fs/nfs/nfs4client.c
@@ -41,9 +41,124 @@ static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion)
41} 41}
42 42
43#ifdef CONFIG_NFS_V4_1 43#ifdef CONFIG_NFS_V4_1
44/**
45 * Per auth flavor data server rpc clients
46 */
47struct nfs4_ds_server {
48 struct list_head list; /* ds_clp->cl_ds_clients */
49 struct rpc_clnt *rpc_clnt;
50};
51
52/**
53 * Common lookup case for DS I/O
54 */
55static struct nfs4_ds_server *
56nfs4_find_ds_client(struct nfs_client *ds_clp, rpc_authflavor_t flavor)
57{
58 struct nfs4_ds_server *dss;
59
60 rcu_read_lock();
61 list_for_each_entry_rcu(dss, &ds_clp->cl_ds_clients, list) {
62 if (dss->rpc_clnt->cl_auth->au_flavor != flavor)
63 continue;
64 goto out;
65 }
66 dss = NULL;
67out:
68 rcu_read_unlock();
69 return dss;
70}
71
72static struct nfs4_ds_server *
73nfs4_add_ds_client(struct nfs_client *ds_clp, rpc_authflavor_t flavor,
74 struct nfs4_ds_server *new)
75{
76 struct nfs4_ds_server *dss;
77
78 spin_lock(&ds_clp->cl_lock);
79 list_for_each_entry(dss, &ds_clp->cl_ds_clients, list) {
80 if (dss->rpc_clnt->cl_auth->au_flavor != flavor)
81 continue;
82 goto out;
83 }
84 if (new)
85 list_add_rcu(&new->list, &ds_clp->cl_ds_clients);
86 dss = new;
87out:
88 spin_unlock(&ds_clp->cl_lock); /* need some lock to protect list */
89 return dss;
90}
91
92static struct nfs4_ds_server *
93nfs4_alloc_ds_server(struct nfs_client *ds_clp, rpc_authflavor_t flavor)
94{
95 struct nfs4_ds_server *dss;
96
97 dss = kmalloc(sizeof(*dss), GFP_NOFS);
98 if (dss == NULL)
99 return ERR_PTR(-ENOMEM);
100
101 dss->rpc_clnt = rpc_clone_client_set_auth(ds_clp->cl_rpcclient, flavor);
102 if (IS_ERR(dss->rpc_clnt)) {
103 int err = PTR_ERR(dss->rpc_clnt);
104 kfree (dss);
105 return ERR_PTR(err);
106 }
107 INIT_LIST_HEAD(&dss->list);
108
109 return dss;
110}
111
112static void
113nfs4_free_ds_server(struct nfs4_ds_server *dss)
114{
115 rpc_release_client(dss->rpc_clnt);
116 kfree(dss);
117}
118
119/**
120* Find or create a DS rpc client with th MDS server rpc client auth flavor
121* in the nfs_client cl_ds_clients list.
122*/
123struct rpc_clnt *
124nfs4_find_or_create_ds_client(struct nfs_client *ds_clp, struct inode *inode)
125{
126 struct nfs4_ds_server *dss, *new;
127 rpc_authflavor_t flavor = NFS_SERVER(inode)->client->cl_auth->au_flavor;
128
129 dss = nfs4_find_ds_client(ds_clp, flavor);
130 if (dss != NULL)
131 goto out;
132 new = nfs4_alloc_ds_server(ds_clp, flavor);
133 if (IS_ERR(new))
134 return ERR_CAST(new);
135 dss = nfs4_add_ds_client(ds_clp, flavor, new);
136 if (dss != new)
137 nfs4_free_ds_server(new);
138out:
139 return dss->rpc_clnt;
140}
141EXPORT_SYMBOL_GPL(nfs4_find_or_create_ds_client);
142
143static void
144nfs4_shutdown_ds_clients(struct nfs_client *clp)
145{
146 struct nfs4_ds_server *dss;
147 LIST_HEAD(shutdown_list);
148
149 while (!list_empty(&clp->cl_ds_clients)) {
150 dss = list_entry(clp->cl_ds_clients.next,
151 struct nfs4_ds_server, list);
152 list_del(&dss->list);
153 rpc_shutdown_client(dss->rpc_clnt);
154 kfree (dss);
155 }
156}
157
44void nfs41_shutdown_client(struct nfs_client *clp) 158void nfs41_shutdown_client(struct nfs_client *clp)
45{ 159{
46 if (nfs4_has_session(clp)) { 160 if (nfs4_has_session(clp)) {
161 nfs4_shutdown_ds_clients(clp);
47 nfs4_destroy_session(clp->cl_session); 162 nfs4_destroy_session(clp->cl_session);
48 nfs4_destroy_clientid(clp); 163 nfs4_destroy_clientid(clp);
49 } 164 }
@@ -77,6 +192,7 @@ struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init)
77 192
78 spin_lock_init(&clp->cl_lock); 193 spin_lock_init(&clp->cl_lock);
79 INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state); 194 INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state);
195 INIT_LIST_HEAD(&clp->cl_ds_clients);
80 rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client"); 196 rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client");
81 clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; 197 clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
82 clp->cl_minorversion = cl_init->minorversion; 198 clp->cl_minorversion = cl_init->minorversion;
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
index a70cb3a0b96e..b86464ba25e1 100644
--- a/fs/nfs/nfs4filelayout.c
+++ b/fs/nfs/nfs4filelayout.c
@@ -528,6 +528,7 @@ filelayout_read_pagelist(struct nfs_read_data *data)
528 struct nfs_pgio_header *hdr = data->header; 528 struct nfs_pgio_header *hdr = data->header;
529 struct pnfs_layout_segment *lseg = hdr->lseg; 529 struct pnfs_layout_segment *lseg = hdr->lseg;
530 struct nfs4_pnfs_ds *ds; 530 struct nfs4_pnfs_ds *ds;
531 struct rpc_clnt *ds_clnt;
531 loff_t offset = data->args.offset; 532 loff_t offset = data->args.offset;
532 u32 j, idx; 533 u32 j, idx;
533 struct nfs_fh *fh; 534 struct nfs_fh *fh;
@@ -542,6 +543,11 @@ filelayout_read_pagelist(struct nfs_read_data *data)
542 ds = nfs4_fl_prepare_ds(lseg, idx); 543 ds = nfs4_fl_prepare_ds(lseg, idx);
543 if (!ds) 544 if (!ds)
544 return PNFS_NOT_ATTEMPTED; 545 return PNFS_NOT_ATTEMPTED;
546
547 ds_clnt = nfs4_find_or_create_ds_client(ds->ds_clp, hdr->inode);
548 if (IS_ERR(ds_clnt))
549 return PNFS_NOT_ATTEMPTED;
550
545 dprintk("%s USE DS: %s cl_count %d\n", __func__, 551 dprintk("%s USE DS: %s cl_count %d\n", __func__,
546 ds->ds_remotestr, atomic_read(&ds->ds_clp->cl_count)); 552 ds->ds_remotestr, atomic_read(&ds->ds_clp->cl_count));
547 553
@@ -556,7 +562,7 @@ filelayout_read_pagelist(struct nfs_read_data *data)
556 data->mds_offset = offset; 562 data->mds_offset = offset;
557 563
558 /* Perform an asynchronous read to ds */ 564 /* Perform an asynchronous read to ds */
559 nfs_initiate_read(ds->ds_clp->cl_rpcclient, data, 565 nfs_initiate_read(ds_clnt, data,
560 &filelayout_read_call_ops, RPC_TASK_SOFTCONN); 566 &filelayout_read_call_ops, RPC_TASK_SOFTCONN);
561 return PNFS_ATTEMPTED; 567 return PNFS_ATTEMPTED;
562} 568}
@@ -568,6 +574,7 @@ filelayout_write_pagelist(struct nfs_write_data *data, int sync)
568 struct nfs_pgio_header *hdr = data->header; 574 struct nfs_pgio_header *hdr = data->header;
569 struct pnfs_layout_segment *lseg = hdr->lseg; 575 struct pnfs_layout_segment *lseg = hdr->lseg;
570 struct nfs4_pnfs_ds *ds; 576 struct nfs4_pnfs_ds *ds;
577 struct rpc_clnt *ds_clnt;
571 loff_t offset = data->args.offset; 578 loff_t offset = data->args.offset;
572 u32 j, idx; 579 u32 j, idx;
573 struct nfs_fh *fh; 580 struct nfs_fh *fh;
@@ -578,6 +585,11 @@ filelayout_write_pagelist(struct nfs_write_data *data, int sync)
578 ds = nfs4_fl_prepare_ds(lseg, idx); 585 ds = nfs4_fl_prepare_ds(lseg, idx);
579 if (!ds) 586 if (!ds)
580 return PNFS_NOT_ATTEMPTED; 587 return PNFS_NOT_ATTEMPTED;
588
589 ds_clnt = nfs4_find_or_create_ds_client(ds->ds_clp, hdr->inode);
590 if (IS_ERR(ds_clnt))
591 return PNFS_NOT_ATTEMPTED;
592
581 dprintk("%s ino %lu sync %d req %Zu@%llu DS: %s cl_count %d\n", 593 dprintk("%s ino %lu sync %d req %Zu@%llu DS: %s cl_count %d\n",
582 __func__, hdr->inode->i_ino, sync, (size_t) data->args.count, 594 __func__, hdr->inode->i_ino, sync, (size_t) data->args.count,
583 offset, ds->ds_remotestr, atomic_read(&ds->ds_clp->cl_count)); 595 offset, ds->ds_remotestr, atomic_read(&ds->ds_clp->cl_count));
@@ -595,7 +607,7 @@ filelayout_write_pagelist(struct nfs_write_data *data, int sync)
595 data->args.offset = filelayout_get_dserver_offset(lseg, offset); 607 data->args.offset = filelayout_get_dserver_offset(lseg, offset);
596 608
597 /* Perform an asynchronous write */ 609 /* Perform an asynchronous write */
598 nfs_initiate_write(ds->ds_clp->cl_rpcclient, data, 610 nfs_initiate_write(ds_clnt, data,
599 &filelayout_write_call_ops, sync, 611 &filelayout_write_call_ops, sync,
600 RPC_TASK_SOFTCONN); 612 RPC_TASK_SOFTCONN);
601 return PNFS_ATTEMPTED; 613 return PNFS_ATTEMPTED;
@@ -1105,16 +1117,19 @@ static int filelayout_initiate_commit(struct nfs_commit_data *data, int how)
1105{ 1117{
1106 struct pnfs_layout_segment *lseg = data->lseg; 1118 struct pnfs_layout_segment *lseg = data->lseg;
1107 struct nfs4_pnfs_ds *ds; 1119 struct nfs4_pnfs_ds *ds;
1120 struct rpc_clnt *ds_clnt;
1108 u32 idx; 1121 u32 idx;
1109 struct nfs_fh *fh; 1122 struct nfs_fh *fh;
1110 1123
1111 idx = calc_ds_index_from_commit(lseg, data->ds_commit_index); 1124 idx = calc_ds_index_from_commit(lseg, data->ds_commit_index);
1112 ds = nfs4_fl_prepare_ds(lseg, idx); 1125 ds = nfs4_fl_prepare_ds(lseg, idx);
1113 if (!ds) { 1126 if (!ds)
1114 prepare_to_resend_writes(data); 1127 goto out_err;
1115 filelayout_commit_release(data); 1128
1116 return -EAGAIN; 1129 ds_clnt = nfs4_find_or_create_ds_client(ds->ds_clp, data->inode);
1117 } 1130 if (IS_ERR(ds_clnt))
1131 goto out_err;
1132
1118 dprintk("%s ino %lu, how %d cl_count %d\n", __func__, 1133 dprintk("%s ino %lu, how %d cl_count %d\n", __func__,
1119 data->inode->i_ino, how, atomic_read(&ds->ds_clp->cl_count)); 1134 data->inode->i_ino, how, atomic_read(&ds->ds_clp->cl_count));
1120 data->commit_done_cb = filelayout_commit_done_cb; 1135 data->commit_done_cb = filelayout_commit_done_cb;
@@ -1123,9 +1138,13 @@ static int filelayout_initiate_commit(struct nfs_commit_data *data, int how)
1123 fh = select_ds_fh_from_commit(lseg, data->ds_commit_index); 1138 fh = select_ds_fh_from_commit(lseg, data->ds_commit_index);
1124 if (fh) 1139 if (fh)
1125 data->args.fh = fh; 1140 data->args.fh = fh;
1126 return nfs_initiate_commit(ds->ds_clp->cl_rpcclient, data, 1141 return nfs_initiate_commit(ds_clnt, data,
1127 &filelayout_commit_call_ops, how, 1142 &filelayout_commit_call_ops, how,
1128 RPC_TASK_SOFTCONN); 1143 RPC_TASK_SOFTCONN);
1144out_err:
1145 prepare_to_resend_writes(data);
1146 filelayout_commit_release(data);
1147 return -EAGAIN;
1129} 1148}
1130 1149
1131static int 1150static int