Commit 0e20162ed1e9a639fc61d62c71327169fb1a1970
Committed by
Trond Myklebust
1 parent
4109bb7496
Exists in
smarc-imx_3.14.28_1.0.0_ga
and in
1 other branch
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>
Showing 4 changed files with 146 additions and 8 deletions Side-by-side Diff
fs/nfs/internal.h
... | ... | @@ -186,6 +186,8 @@ |
186 | 186 | int ds_addrlen, int ds_proto, |
187 | 187 | unsigned int ds_timeo, |
188 | 188 | unsigned int ds_retrans); |
189 | +extern struct rpc_clnt *nfs4_find_or_create_ds_client(struct nfs_client *, | |
190 | + struct inode *); | |
189 | 191 | #ifdef CONFIG_PROC_FS |
190 | 192 | extern int __init nfs_fs_proc_init(void); |
191 | 193 | extern void nfs_fs_proc_exit(void); |
fs/nfs/nfs4client.c
... | ... | @@ -41,9 +41,124 @@ |
41 | 41 | } |
42 | 42 | |
43 | 43 | #ifdef CONFIG_NFS_V4_1 |
44 | +/** | |
45 | + * Per auth flavor data server rpc clients | |
46 | + */ | |
47 | +struct 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 | + */ | |
55 | +static struct nfs4_ds_server * | |
56 | +nfs4_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; | |
67 | +out: | |
68 | + rcu_read_unlock(); | |
69 | + return dss; | |
70 | +} | |
71 | + | |
72 | +static struct nfs4_ds_server * | |
73 | +nfs4_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; | |
87 | +out: | |
88 | + spin_unlock(&ds_clp->cl_lock); /* need some lock to protect list */ | |
89 | + return dss; | |
90 | +} | |
91 | + | |
92 | +static struct nfs4_ds_server * | |
93 | +nfs4_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 | + | |
112 | +static void | |
113 | +nfs4_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 | +*/ | |
123 | +struct rpc_clnt * | |
124 | +nfs4_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); | |
138 | +out: | |
139 | + return dss->rpc_clnt; | |
140 | +} | |
141 | +EXPORT_SYMBOL_GPL(nfs4_find_or_create_ds_client); | |
142 | + | |
143 | +static void | |
144 | +nfs4_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 | + | |
44 | 158 | void nfs41_shutdown_client(struct nfs_client *clp) |
45 | 159 | { |
46 | 160 | if (nfs4_has_session(clp)) { |
161 | + nfs4_shutdown_ds_clients(clp); | |
47 | 162 | nfs4_destroy_session(clp->cl_session); |
48 | 163 | nfs4_destroy_clientid(clp); |
49 | 164 | } |
... | ... | @@ -77,6 +192,7 @@ |
77 | 192 | |
78 | 193 | spin_lock_init(&clp->cl_lock); |
79 | 194 | INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state); |
195 | + INIT_LIST_HEAD(&clp->cl_ds_clients); | |
80 | 196 | rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client"); |
81 | 197 | clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; |
82 | 198 | clp->cl_minorversion = cl_init->minorversion; |
fs/nfs/nfs4filelayout.c
... | ... | @@ -528,6 +528,7 @@ |
528 | 528 | struct nfs_pgio_header *hdr = data->header; |
529 | 529 | struct pnfs_layout_segment *lseg = hdr->lseg; |
530 | 530 | struct nfs4_pnfs_ds *ds; |
531 | + struct rpc_clnt *ds_clnt; | |
531 | 532 | loff_t offset = data->args.offset; |
532 | 533 | u32 j, idx; |
533 | 534 | struct nfs_fh *fh; |
... | ... | @@ -542,6 +543,11 @@ |
542 | 543 | ds = nfs4_fl_prepare_ds(lseg, idx); |
543 | 544 | if (!ds) |
544 | 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 | 551 | dprintk("%s USE DS: %s cl_count %d\n", __func__, |
546 | 552 | ds->ds_remotestr, atomic_read(&ds->ds_clp->cl_count)); |
547 | 553 | |
... | ... | @@ -556,7 +562,7 @@ |
556 | 562 | data->mds_offset = offset; |
557 | 563 | |
558 | 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 | 566 | &filelayout_read_call_ops, RPC_TASK_SOFTCONN); |
561 | 567 | return PNFS_ATTEMPTED; |
562 | 568 | } |
... | ... | @@ -568,6 +574,7 @@ |
568 | 574 | struct nfs_pgio_header *hdr = data->header; |
569 | 575 | struct pnfs_layout_segment *lseg = hdr->lseg; |
570 | 576 | struct nfs4_pnfs_ds *ds; |
577 | + struct rpc_clnt *ds_clnt; | |
571 | 578 | loff_t offset = data->args.offset; |
572 | 579 | u32 j, idx; |
573 | 580 | struct nfs_fh *fh; |
... | ... | @@ -578,6 +585,11 @@ |
578 | 585 | ds = nfs4_fl_prepare_ds(lseg, idx); |
579 | 586 | if (!ds) |
580 | 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 | 593 | dprintk("%s ino %lu sync %d req %Zu@%llu DS: %s cl_count %d\n", |
582 | 594 | __func__, hdr->inode->i_ino, sync, (size_t) data->args.count, |
583 | 595 | offset, ds->ds_remotestr, atomic_read(&ds->ds_clp->cl_count)); |
... | ... | @@ -595,7 +607,7 @@ |
595 | 607 | data->args.offset = filelayout_get_dserver_offset(lseg, offset); |
596 | 608 | |
597 | 609 | /* Perform an asynchronous write */ |
598 | - nfs_initiate_write(ds->ds_clp->cl_rpcclient, data, | |
610 | + nfs_initiate_write(ds_clnt, data, | |
599 | 611 | &filelayout_write_call_ops, sync, |
600 | 612 | RPC_TASK_SOFTCONN); |
601 | 613 | return PNFS_ATTEMPTED; |
602 | 614 | |
... | ... | @@ -1105,16 +1117,19 @@ |
1105 | 1117 | { |
1106 | 1118 | struct pnfs_layout_segment *lseg = data->lseg; |
1107 | 1119 | struct nfs4_pnfs_ds *ds; |
1120 | + struct rpc_clnt *ds_clnt; | |
1108 | 1121 | u32 idx; |
1109 | 1122 | struct nfs_fh *fh; |
1110 | 1123 | |
1111 | 1124 | idx = calc_ds_index_from_commit(lseg, data->ds_commit_index); |
1112 | 1125 | ds = nfs4_fl_prepare_ds(lseg, idx); |
1113 | - if (!ds) { | |
1114 | - prepare_to_resend_writes(data); | |
1115 | - filelayout_commit_release(data); | |
1116 | - return -EAGAIN; | |
1117 | - } | |
1126 | + if (!ds) | |
1127 | + goto out_err; | |
1128 | + | |
1129 | + ds_clnt = nfs4_find_or_create_ds_client(ds->ds_clp, data->inode); | |
1130 | + if (IS_ERR(ds_clnt)) | |
1131 | + goto out_err; | |
1132 | + | |
1118 | 1133 | dprintk("%s ino %lu, how %d cl_count %d\n", __func__, |
1119 | 1134 | data->inode->i_ino, how, atomic_read(&ds->ds_clp->cl_count)); |
1120 | 1135 | data->commit_done_cb = filelayout_commit_done_cb; |
1121 | 1136 | |
... | ... | @@ -1123,9 +1138,13 @@ |
1123 | 1138 | fh = select_ds_fh_from_commit(lseg, data->ds_commit_index); |
1124 | 1139 | if (fh) |
1125 | 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 | 1142 | &filelayout_commit_call_ops, how, |
1128 | 1143 | RPC_TASK_SOFTCONN); |
1144 | +out_err: | |
1145 | + prepare_to_resend_writes(data); | |
1146 | + filelayout_commit_release(data); | |
1147 | + return -EAGAIN; | |
1129 | 1148 | } |
1130 | 1149 | |
1131 | 1150 | static int |
include/linux/nfs_fs_sb.h