aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/afs/Makefile4
-rw-r--r--fs/afs/addr_list.c40
-rw-r--r--fs/afs/cmservice.c129
-rw-r--r--fs/afs/fs_probe.c270
-rw-r--r--fs/afs/fsclient.c27
-rw-r--r--fs/afs/internal.h98
-rw-r--r--fs/afs/proc.c6
-rw-r--r--fs/afs/rotate.c174
-rw-r--r--fs/afs/rxrpc.c44
-rw-r--r--fs/afs/server.c109
-rw-r--r--fs/afs/server_list.c6
-rw-r--r--fs/afs/vl_list.c6
-rw-r--r--fs/afs/vl_probe.c273
-rw-r--r--fs/afs/vl_rotate.c159
-rw-r--r--fs/afs/vlclient.c35
-rw-r--r--fs/afs/volume.c16
-rw-r--r--include/trace/events/afs.h4
17 files changed, 1050 insertions, 350 deletions
diff --git a/fs/afs/Makefile b/fs/afs/Makefile
index cc942b790cff..0738e2bf5193 100644
--- a/fs/afs/Makefile
+++ b/fs/afs/Makefile
@@ -17,6 +17,7 @@ kafs-y := \
17 file.o \ 17 file.o \
18 flock.o \ 18 flock.o \
19 fsclient.o \ 19 fsclient.o \
20 fs_probe.o \
20 inode.o \ 21 inode.o \
21 main.o \ 22 main.o \
22 misc.o \ 23 misc.o \
@@ -29,8 +30,9 @@ kafs-y := \
29 super.o \ 30 super.o \
30 netdevices.o \ 31 netdevices.o \
31 vlclient.o \ 32 vlclient.o \
32 vl_rotate.o \
33 vl_list.o \ 33 vl_list.o \
34 vl_probe.o \
35 vl_rotate.o \
34 volume.o \ 36 volume.o \
35 write.o \ 37 write.o \
36 xattr.o \ 38 xattr.o \
diff --git a/fs/afs/addr_list.c b/fs/afs/addr_list.c
index 1536d1d21c33..967db336d11a 100644
--- a/fs/afs/addr_list.c
+++ b/fs/afs/addr_list.c
@@ -303,6 +303,8 @@ void afs_merge_fs_addr4(struct afs_addr_list *alist, __be32 xdr, u16 port)
303 sizeof(alist->addrs[0]) * (alist->nr_addrs - i)); 303 sizeof(alist->addrs[0]) * (alist->nr_addrs - i));
304 304
305 srx = &alist->addrs[i]; 305 srx = &alist->addrs[i];
306 srx->srx_family = AF_RXRPC;
307 srx->transport_type = SOCK_DGRAM;
306 srx->transport_len = sizeof(srx->transport.sin); 308 srx->transport_len = sizeof(srx->transport.sin);
307 srx->transport.sin.sin_family = AF_INET; 309 srx->transport.sin.sin_family = AF_INET;
308 srx->transport.sin.sin_port = htons(port); 310 srx->transport.sin.sin_port = htons(port);
@@ -341,6 +343,8 @@ void afs_merge_fs_addr6(struct afs_addr_list *alist, __be32 *xdr, u16 port)
341 sizeof(alist->addrs[0]) * (alist->nr_addrs - i)); 343 sizeof(alist->addrs[0]) * (alist->nr_addrs - i));
342 344
343 srx = &alist->addrs[i]; 345 srx = &alist->addrs[i];
346 srx->srx_family = AF_RXRPC;
347 srx->transport_type = SOCK_DGRAM;
344 srx->transport_len = sizeof(srx->transport.sin6); 348 srx->transport_len = sizeof(srx->transport.sin6);
345 srx->transport.sin6.sin6_family = AF_INET6; 349 srx->transport.sin6.sin6_family = AF_INET6;
346 srx->transport.sin6.sin6_port = htons(port); 350 srx->transport.sin6.sin6_port = htons(port);
@@ -353,23 +357,32 @@ void afs_merge_fs_addr6(struct afs_addr_list *alist, __be32 *xdr, u16 port)
353 */ 357 */
354bool afs_iterate_addresses(struct afs_addr_cursor *ac) 358bool afs_iterate_addresses(struct afs_addr_cursor *ac)
355{ 359{
356 _enter("%hu+%hd", ac->start, (short)ac->index); 360 unsigned long set, failed;
361 int index;
357 362
358 if (!ac->alist) 363 if (!ac->alist)
359 return false; 364 return false;
360 365
366 set = ac->alist->responded;
367 failed = ac->alist->failed;
368 _enter("%lx-%lx-%lx,%d", set, failed, ac->tried, ac->index);
369
361 ac->nr_iterations++; 370 ac->nr_iterations++;
362 371
363 if (ac->begun) { 372 set &= ~(failed | ac->tried);
364 ac->index++;
365 if (ac->index == ac->alist->nr_addrs)
366 ac->index = 0;
367 373
368 if (ac->index == ac->start) 374 if (!set)
369 return false; 375 return false;
370 } 376
377 index = READ_ONCE(ac->alist->preferred);
378 if (test_bit(index, &set))
379 goto selected;
380
381 index = __ffs(set);
371 382
372 ac->begun = true; 383selected:
384 ac->index = index;
385 set_bit(index, &ac->tried);
373 ac->responded = false; 386 ac->responded = false;
374 return true; 387 return true;
375} 388}
@@ -383,12 +396,13 @@ int afs_end_cursor(struct afs_addr_cursor *ac)
383 396
384 alist = ac->alist; 397 alist = ac->alist;
385 if (alist) { 398 if (alist) {
386 if (ac->responded && ac->index != ac->start) 399 if (ac->responded &&
387 WRITE_ONCE(alist->index, ac->index); 400 ac->index != alist->preferred &&
401 test_bit(ac->alist->preferred, &ac->tried))
402 WRITE_ONCE(alist->preferred, ac->index);
388 afs_put_addrlist(alist); 403 afs_put_addrlist(alist);
404 ac->alist = NULL;
389 } 405 }
390 406
391 ac->alist = NULL;
392 ac->begun = false;
393 return ac->error; 407 return ac->error;
394} 408}
diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c
index 8cf8d10daa6c..8ee5972893ed 100644
--- a/fs/afs/cmservice.c
+++ b/fs/afs/cmservice.c
@@ -122,6 +122,8 @@ bool afs_cm_incoming_call(struct afs_call *call)
122{ 122{
123 _enter("{%u, CB.OP %u}", call->service_id, call->operation_ID); 123 _enter("{%u, CB.OP %u}", call->service_id, call->operation_ID);
124 124
125 call->epoch = rxrpc_kernel_get_epoch(call->net->socket, call->rxcall);
126
125 switch (call->operation_ID) { 127 switch (call->operation_ID) {
126 case CBCallBack: 128 case CBCallBack:
127 call->type = &afs_SRXCBCallBack; 129 call->type = &afs_SRXCBCallBack;
@@ -152,6 +154,91 @@ bool afs_cm_incoming_call(struct afs_call *call)
152} 154}
153 155
154/* 156/*
157 * Record a probe to the cache manager from a server.
158 */
159static int afs_record_cm_probe(struct afs_call *call, struct afs_server *server)
160{
161 _enter("");
162
163 if (test_bit(AFS_SERVER_FL_HAVE_EPOCH, &server->flags) &&
164 !test_bit(AFS_SERVER_FL_PROBING, &server->flags)) {
165 if (server->cm_epoch == call->epoch)
166 return 0;
167
168 if (!server->probe.said_rebooted) {
169 pr_notice("kAFS: FS rebooted %pU\n", &server->uuid);
170 server->probe.said_rebooted = true;
171 }
172 }
173
174 spin_lock(&server->probe_lock);
175
176 if (!test_bit(AFS_SERVER_FL_HAVE_EPOCH, &server->flags)) {
177 server->cm_epoch = call->epoch;
178 server->probe.cm_epoch = call->epoch;
179 goto out;
180 }
181
182 if (server->probe.cm_probed &&
183 call->epoch != server->probe.cm_epoch &&
184 !server->probe.said_inconsistent) {
185 pr_notice("kAFS: FS endpoints inconsistent %pU\n",
186 &server->uuid);
187 server->probe.said_inconsistent = true;
188 }
189
190 if (!server->probe.cm_probed || call->epoch == server->cm_epoch)
191 server->probe.cm_epoch = server->cm_epoch;
192
193out:
194 server->probe.cm_probed = true;
195 spin_unlock(&server->probe_lock);
196 return 0;
197}
198
199/*
200 * Find the server record by peer address and record a probe to the cache
201 * manager from a server.
202 */
203static int afs_find_cm_server_by_peer(struct afs_call *call)
204{
205 struct sockaddr_rxrpc srx;
206 struct afs_server *server;
207
208 rxrpc_kernel_get_peer(call->net->socket, call->rxcall, &srx);
209
210 server = afs_find_server(call->net, &srx);
211 if (!server) {
212 trace_afs_cm_no_server(call, &srx);
213 return 0;
214 }
215
216 call->cm_server = server;
217 return afs_record_cm_probe(call, server);
218}
219