]>
Commit | Line | Data |
---|---|---|
b4d0d230 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
9cc6fc50 DH |
2 | /* Handle fileserver selection and rotation. |
3 | * | |
4 | * Copyright (C) 2017 Red Hat, Inc. All Rights Reserved. | |
5 | * Written by David Howells ([email protected]) | |
9cc6fc50 DH |
6 | */ |
7 | ||
8 | #include <linux/kernel.h> | |
9 | #include <linux/slab.h> | |
d2ddc776 DH |
10 | #include <linux/fs.h> |
11 | #include <linux/sched.h> | |
12 | #include <linux/delay.h> | |
13 | #include <linux/sched/signal.h> | |
9cc6fc50 | 14 | #include "internal.h" |
d2ddc776 | 15 | #include "afs_fs.h" |
9cc6fc50 | 16 | |
d2ddc776 DH |
17 | /* |
18 | * Begin iteration through a server list, starting with the vnode's last used | |
19 | * server if possible, or the last recorded good server if not. | |
20 | */ | |
a310082f | 21 | static bool afs_start_fs_iteration(struct afs_operation *op, |
d2ddc776 DH |
22 | struct afs_vnode *vnode) |
23 | { | |
20325960 DH |
24 | struct afs_server *server; |
25 | void *cb_server; | |
d2ddc776 DH |
26 | int i; |
27 | ||
e49c7b2f | 28 | read_lock(&op->volume->servers_lock); |
8a070a96 DH |
29 | op->server_list = afs_get_serverlist( |
30 | rcu_dereference_protected(op->volume->servers, | |
31 | lockdep_is_held(&op->volume->servers_lock))); | |
e49c7b2f | 32 | read_unlock(&op->volume->servers_lock); |
d2ddc776 | 33 | |
a310082f DH |
34 | op->untried = (1UL << op->server_list->nr_servers) - 1; |
35 | op->index = READ_ONCE(op->server_list->preferred); | |
3bf0fb6f | 36 | |
20325960 DH |
37 | cb_server = vnode->cb_server; |
38 | if (cb_server) { | |
d2ddc776 | 39 | /* See if the vnode's preferred record is still available */ |
a310082f | 40 | for (i = 0; i < op->server_list->nr_servers; i++) { |
20325960 DH |
41 | server = op->server_list->servers[i].server; |
42 | if (server == cb_server) { | |
a310082f | 43 | op->index = i; |
d2ddc776 DH |
44 | goto found_interest; |
45 | } | |
46 | } | |
47 | ||
48 | /* If we have a lock outstanding on a server that's no longer | |
49 | * serving this vnode, then we can't switch to another server | |
50 | * and have to return an error. | |
51 | */ | |
a310082f DH |
52 | if (op->flags & AFS_OPERATION_CUR_ONLY) { |
53 | op->error = -ESTALE; | |
d2ddc776 DH |
54 | return false; |
55 | } | |
56 | ||
57 | /* Note that the callback promise is effectively broken */ | |
58 | write_seqlock(&vnode->cb_lock); | |
20325960 DH |
59 | ASSERTCMP(cb_server, ==, vnode->cb_server); |
60 | vnode->cb_server = NULL; | |
d2ddc776 DH |
61 | if (test_and_clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) |
62 | vnode->cb_break++; | |
63 | write_sequnlock(&vnode->cb_lock); | |
d2ddc776 DH |
64 | } |
65 | ||
66 | found_interest: | |
d2ddc776 DH |
67 | return true; |
68 | } | |
69 | ||
70 | /* | |
71 | * Post volume busy note. | |
72 | */ | |
73 | static void afs_busy(struct afs_volume *volume, u32 abort_code) | |
74 | { | |
75 | const char *m; | |
76 | ||
77 | switch (abort_code) { | |
78 | case VOFFLINE: m = "offline"; break; | |
79 | case VRESTARTING: m = "restarting"; break; | |
80 | case VSALVAGING: m = "being salvaged"; break; | |
81 | default: m = "busy"; break; | |
82 | } | |
0fafdc9f | 83 | |
3b6492df | 84 | pr_notice("kAFS: Volume %llu '%s' is %s\n", volume->vid, volume->name, m); |
d2ddc776 DH |
85 | } |
86 | ||
87 | /* | |
88 | * Sleep and retry the operation to the same fileserver. | |
89 | */ | |
a310082f | 90 | static bool afs_sleep_and_retry(struct afs_operation *op) |
d2ddc776 | 91 | { |
e49c7b2f | 92 | if (!(op->flags & AFS_OPERATION_UNINTR)) { |
20b8391f DH |
93 | msleep_interruptible(1000); |
94 | if (signal_pending(current)) { | |
a310082f | 95 | op->error = -ERESTARTSYS; |
20b8391f DH |
96 | return false; |
97 | } | |
98 | } else { | |
99 | msleep(1000); | |
d2ddc776 DH |
100 | } |
101 | ||
102 | return true; | |
103 | } | |
104 | ||
105 | /* | |
106 | * Select the fileserver to use. May be called multiple times to rotate | |
107 | * through the fileservers. | |
108 | */ | |
a310082f | 109 | bool afs_select_fileserver(struct afs_operation *op) |
d2ddc776 DH |
110 | { |
111 | struct afs_addr_list *alist; | |
112 | struct afs_server *server; | |
e49c7b2f | 113 | struct afs_vnode *vnode = op->file[0].vnode; |
4584ae96 DH |
114 | struct afs_error e; |
115 | u32 rtt; | |
a310082f | 116 | int error = op->ac.error, i; |
d2ddc776 | 117 | |
3bf0fb6f | 118 | _enter("%lx[%d],%lx[%d],%d,%d", |
a310082f DH |
119 | op->untried, op->index, |
120 | op->ac.tried, op->ac.index, | |
121 | error, op->ac.abort_code); | |
d2ddc776 | 122 | |
a310082f | 123 | if (op->flags & AFS_OPERATION_STOP) { |
d2ddc776 DH |
124 | _leave(" = f [stopped]"); |
125 | return false; | |
126 | } | |
127 | ||
a310082f | 128 | op->nr_iterations++; |
744bcd71 | 129 | |
d2ddc776 | 130 | /* Evaluate the result of the previous operation, if there was one. */ |
e7f680f4 | 131 | switch (error) { |
d2ddc776 DH |
132 | case SHRT_MAX: |
133 | goto start; | |
134 | ||
135 | case 0: | |
136 | default: | |
137 | /* Success or local failure. Stop. */ | |
a310082f DH |
138 | op->error = error; |
139 | op->flags |= AFS_OPERATION_STOP; | |
e7f680f4 | 140 | _leave(" = f [okay/local %d]", error); |
d2ddc776 DH |
141 | return false; |
142 | ||
143 | case -ECONNABORTED: | |
144 | /* The far side rejected the operation on some grounds. This | |
145 | * might involve the server being busy or the volume having been moved. | |
146 | */ | |
a310082f | 147 | switch (op->ac.abort_code) { |
d2ddc776 DH |
148 | case VNOVOL: |
149 | /* This fileserver doesn't know about the volume. | |
150 | * - May indicate that the VL is wrong - retry once and compare | |
151 | * the results. | |
152 | * - May indicate that the fileserver couldn't attach to the vol. | |
153 | */ | |
a310082f DH |
154 | if (op->flags & AFS_OPERATION_VNOVOL) { |
155 | op->error = -EREMOTEIO; | |
3d9fa911 | 156 | goto next_server; |
d2ddc776 DH |
157 | } |
158 | ||
e49c7b2f | 159 | write_lock(&op->volume->servers_lock); |
a310082f | 160 | op->server_list->vnovol_mask |= 1 << op->index; |
e49c7b2f | 161 | write_unlock(&op->volume->servers_lock); |
d2ddc776 | 162 | |
e49c7b2f DH |
163 | set_bit(AFS_VOLUME_NEEDS_UPDATE, &op->volume->flags); |
164 | error = afs_check_volume_status(op->volume, op); | |
e7f680f4 DH |
165 | if (error < 0) |
166 | goto failed_set_error; | |
d2ddc776 | 167 | |
e49c7b2f | 168 | if (test_bit(AFS_VOLUME_DELETED, &op->volume->flags)) { |
a310082f | 169 | op->error = -ENOMEDIUM; |
d2ddc776 DH |
170 | goto failed; |
171 | } | |
172 | ||
173 | /* If the server list didn't change, then assume that | |
174 | * it's the fileserver having trouble. | |
175 | */ | |
8a070a96 | 176 | if (rcu_access_pointer(op->volume->servers) == op->server_list) { |
a310082f | 177 | op->error = -EREMOTEIO; |
3d9fa911 | 178 | goto next_server; |
d2ddc776 DH |
179 | } |
180 | ||
181 | /* Try again */ | |
a310082f | 182 | op->flags |= AFS_OPERATION_VNOVOL; |
d2ddc776 DH |
183 | _leave(" = t [vnovol]"); |
184 | return true; | |
185 | ||
186 | case VSALVAGE: /* TODO: Should this return an error or iterate? */ | |
187 | case VVOLEXISTS: | |
188 | case VNOSERVICE: | |
189 | case VONLINE: | |
190 | case VDISKFULL: | |
191 | case VOVERQUOTA: | |
a310082f | 192 | op->error = afs_abort_to_error(op->ac.abort_code); |
d2ddc776 DH |
193 | goto next_server; |
194 | ||
195 | case VOFFLINE: | |
e49c7b2f DH |
196 | if (!test_and_set_bit(AFS_VOLUME_OFFLINE, &op->volume->flags)) { |
197 | afs_busy(op->volume, op->ac.abort_code); | |
198 | clear_bit(AFS_VOLUME_BUSY, &op->volume->flags); | |
d2ddc776 | 199 | } |
a310082f DH |
200 | if (op->flags & AFS_OPERATION_NO_VSLEEP) { |
201 | op->error = -EADV; | |
d2ddc776 DH |
202 | goto failed; |
203 | } | |
a310082f DH |
204 | if (op->flags & AFS_OPERATION_CUR_ONLY) { |
205 | op->error = -ESTALE; | |
d2ddc776 DH |
206 | goto failed; |
207 | } | |
208 | goto busy; | |
209 | ||
210 | case VSALVAGING: | |
211 | case VRESTARTING: | |
212 | case VBUSY: | |
213 | /* Retry after going round all the servers unless we | |
214 | * have a file lock we need to maintain. | |
215 | */ | |
a310082f DH |
216 | if (op->flags & AFS_OPERATION_NO_VSLEEP) { |
217 | op->error = -EBUSY; | |
d2ddc776 DH |
218 | goto failed; |
219 | } | |
e49c7b2f DH |
220 | if (!test_and_set_bit(AFS_VOLUME_BUSY, &op->volume->flags)) { |
221 | afs_busy(op->volume, op->ac.abort_code); | |
222 | clear_bit(AFS_VOLUME_OFFLINE, &op->volume->flags); | |
d2ddc776 DH |
223 | } |
224 | busy: | |
a310082f DH |
225 | if (op->flags & AFS_OPERATION_CUR_ONLY) { |
226 | if (!afs_sleep_and_retry(op)) | |
d2ddc776 DH |
227 | goto failed; |
228 | ||
229 | /* Retry with same server & address */ | |
230 | _leave(" = t [vbusy]"); | |
231 | return true; | |
232 | } | |
233 | ||
a310082f | 234 | op->flags |= AFS_OPERATION_VBUSY; |
d2ddc776 DH |
235 | goto next_server; |
236 | ||
237 | case VMOVED: | |
238 | /* The volume migrated to another server. We consider | |
239 | * consider all locks and callbacks broken and request | |
240 | * an update from the VLDB. | |
241 | * | |
242 | * We also limit the number of VMOVED hops we will | |
243 | * honour, just in case someone sets up a loop. | |
244 | */ | |
a310082f DH |
245 | if (op->flags & AFS_OPERATION_VMOVED) { |
246 | op->error = -EREMOTEIO; | |
d2ddc776 DH |
247 | goto failed; |
248 | } | |
a310082f | 249 | op->flags |= AFS_OPERATION_VMOVED; |
d2ddc776 | 250 | |
e49c7b2f DH |
251 | set_bit(AFS_VOLUME_WAIT, &op->volume->flags); |
252 | set_bit(AFS_VOLUME_NEEDS_UPDATE, &op->volume->flags); | |
253 | error = afs_check_volume_status(op->volume, op); | |
e7f680f4 DH |
254 | if (error < 0) |
255 | goto failed_set_error; | |
d2ddc776 DH |
256 | |
257 | /* If the server list didn't change, then the VLDB is | |
258 | * out of sync with the fileservers. This is hopefully | |
259 | * a temporary condition, however, so we don't want to | |
260 | * permanently block access to the file. | |
261 | * | |
262 | * TODO: Try other fileservers if we can. | |
263 | * | |
264 | * TODO: Retry a few times with sleeps. | |
265 | */ | |
8a070a96 | 266 | if (rcu_access_pointer(op->volume->servers) == op->server_list) { |
a310082f | 267 | op->error = -ENOMEDIUM; |
d2ddc776 DH |
268 | goto failed; |
269 | } | |
270 | ||
271 | goto restart_from_beginning; | |
272 | ||
273 | default: | |
e49c7b2f DH |
274 | clear_bit(AFS_VOLUME_OFFLINE, &op->volume->flags); |
275 | clear_bit(AFS_VOLUME_BUSY, &op->volume->flags); | |
a310082f | 276 | op->error = afs_abort_to_error(op->ac.abort_code); |
d2ddc776 DH |
277 | goto failed; |
278 | } | |
279 | ||
e7f680f4 DH |
280 | case -ETIMEDOUT: |
281 | case -ETIME: | |
a310082f | 282 | if (op->error != -EDESTADDRREQ) |
e7f680f4 | 283 | goto iterate_address; |
df561f66 | 284 | fallthrough; |
4584ae96 DH |
285 | case -ERFKILL: |
286 | case -EADDRNOTAVAIL: | |
d2ddc776 DH |
287 | case -ENETUNREACH: |
288 | case -EHOSTUNREACH: | |
4584ae96 | 289 | case -EHOSTDOWN: |
d2ddc776 | 290 | case -ECONNREFUSED: |
d2ddc776 | 291 | _debug("no conn"); |
a310082f | 292 | op->error = error; |
d2ddc776 | 293 | goto iterate_address; |
1a025028 DH |
294 | |
295 | case -ECONNRESET: | |
296 | _debug("call reset"); | |
a310082f | 297 | op->error = error; |
1a025028 | 298 | goto failed; |
d2ddc776 DH |
299 | } |
300 | ||
301 | restart_from_beginning: | |
302 | _debug("restart"); | |
a310082f | 303 | afs_end_cursor(&op->ac); |
20325960 | 304 | op->server = NULL; |
e49c7b2f | 305 | afs_put_serverlist(op->net, op->server_list); |
a310082f | 306 | op->server_list = NULL; |
d2ddc776 DH |
307 | start: |
308 | _debug("start"); | |
309 | /* See if we need to do an update of the volume record. Note that the | |
310 | * volume may have moved or even have been deleted. | |
311 | */ | |
e49c7b2f | 312 | error = afs_check_volume_status(op->volume, op); |
e7f680f4 DH |
313 | if (error < 0) |
314 | goto failed_set_error; | |
d2ddc776 | 315 | |
a310082f | 316 | if (!afs_start_fs_iteration(op, vnode)) |
d2ddc776 | 317 | goto failed; |
d2ddc776 | 318 | |
e49c7b2f | 319 | _debug("__ VOL %llx __", op->volume->vid); |
3bf0fb6f DH |
320 | |
321 | pick_server: | |
a310082f | 322 | _debug("pick [%lx]", op->untried); |
3bf0fb6f | 323 | |
a310082f | 324 | error = afs_wait_for_fs_probes(op->server_list, op->untried); |
3bf0fb6f DH |
325 | if (error < 0) |
326 | goto failed_set_error; | |
327 | ||
328 | /* Pick the untried server with the lowest RTT. If we have outstanding | |
329 | * callbacks, we stick with the server we're already using if we can. | |
330 | */ | |
20325960 DH |
331 | if (op->server) { |
332 | _debug("server %u", op->index); | |
a310082f | 333 | if (test_bit(op->index, &op->untried)) |
3bf0fb6f | 334 | goto selected_server; |
20325960 DH |
335 | op->server = NULL; |
336 | _debug("no server"); | |
3bf0fb6f DH |
337 | } |
338 | ||
a310082f | 339 | op->index = -1; |
3bf0fb6f | 340 | rtt = U32_MAX; |
a310082f DH |
341 | for (i = 0; i < op->server_list->nr_servers; i++) { |
342 | struct afs_server *s = op->server_list->servers[i].server; | |
3bf0fb6f | 343 | |
f3c130e6 DH |
344 | if (!test_bit(i, &op->untried) || |
345 | !test_bit(AFS_SERVER_FL_RESPONDING, &s->flags)) | |
3bf0fb6f DH |
346 | continue; |
347 | if (s->probe.rtt < rtt) { | |
a310082f | 348 | op->index = i; |
3bf0fb6f DH |
349 | rtt = s->probe.rtt; |
350 | } | |
351 | } | |
352 | ||
a310082f | 353 | if (op->index == -1) |
3bf0fb6f DH |
354 | goto no_more_servers; |
355 | ||
356 | selected_server: | |
a310082f DH |
357 | _debug("use %d", op->index); |
358 | __clear_bit(op->index, &op->untried); | |
3bf0fb6f | 359 | |
d2ddc776 DH |
360 | /* We're starting on a different fileserver from the list. We need to |
361 | * check it, create a callback intercept, find its address list and | |
362 | * probe its capabilities before we use it. | |
363 | */ | |
a310082f DH |
364 | ASSERTCMP(op->ac.alist, ==, NULL); |
365 | server = op->server_list->servers[op->index].server; | |
d2ddc776 | 366 | |
a310082f | 367 | if (!afs_check_server_record(op, server)) |
d2ddc776 DH |
368 | goto failed; |
369 | ||
370 | _debug("USING SERVER: %pU", &server->uuid); | |
371 | ||
8409f67b | 372 | op->flags |= AFS_OPERATION_RETRY_SERVER; |
20325960 DH |
373 | op->server = server; |
374 | if (vnode->cb_server != server) { | |
375 | vnode->cb_server = server; | |
376 | vnode->cb_s_break = server->cb_s_break; | |
377 | vnode->cb_v_break = vnode->volume->cb_v_break; | |
378 | clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags); | |
379 | } | |
d2ddc776 DH |
380 | |
381 | read_lock(&server->fs_lock); | |
382 | alist = rcu_dereference_protected(server->addresses, | |
383 | lockdep_is_held(&server->fs_lock)); | |
384 | afs_get_addrlist(alist); | |
385 | read_unlock(&server->fs_lock); | |
386 | ||
8409f67b | 387 | retry_server: |
a310082f | 388 | memset(&op->ac, 0, sizeof(op->ac)); |
d2ddc776 | 389 | |
a310082f DH |
390 | if (!op->ac.alist) |
391 | op->ac.alist = alist; | |
d2ddc776 DH |
392 | else |
393 | afs_put_addrlist(alist); | |
394 | ||
a310082f | 395 | op->ac.index = -1; |
d2ddc776 DH |
396 | |
397 | iterate_address: | |
a310082f | 398 | ASSERT(op->ac.alist); |
d2ddc776 DH |
399 | /* Iterate over the current server's address list to try and find an |
400 | * address on which it will respond to us. | |
401 | */ | |
a310082f | 402 | if (!afs_iterate_addresses(&op->ac)) |
8409f67b | 403 | goto out_of_addresses; |
d2ddc776 | 404 | |
8409f67b DH |
405 | _debug("address [%u] %u/%u %pISp", |
406 | op->index, op->ac.index, op->ac.alist->nr_addrs, | |
407 | &op->ac.alist->addrs[op->ac.index].transport); | |
3bf0fb6f | 408 | |
fe4d774c DH |
409 | _leave(" = t"); |
410 | return true; | |
d2ddc776 | 411 | |
8409f67b DH |
412 | out_of_addresses: |
413 | /* We've now had a failure to respond on all of a server's addresses - | |
414 | * immediately probe them again and consider retrying the server. | |
415 | */ | |
416 | afs_probe_fileserver(op->net, op->server); | |
417 | if (op->flags & AFS_OPERATION_RETRY_SERVER) { | |
418 | alist = op->ac.alist; | |
419 | error = afs_wait_for_one_fs_probe( | |
420 | op->server, !(op->flags & AFS_OPERATION_UNINTR)); | |
421 | switch (error) { | |
422 | case 0: | |
423 | op->flags &= ~AFS_OPERATION_RETRY_SERVER; | |
424 | goto retry_server; | |
425 | case -ERESTARTSYS: | |
426 | goto failed_set_error; | |
427 | case -ETIME: | |
428 | case -EDESTADDRREQ: | |
429 | goto next_server; | |
430 | } | |
431 | } | |
432 | ||
16280a15 DH |
433 | next_server: |
434 | _debug("next"); | |
a310082f | 435 | afs_end_cursor(&op->ac); |
3bf0fb6f | 436 | goto pick_server; |
16280a15 | 437 | |
3bf0fb6f | 438 | no_more_servers: |
16280a15 DH |
439 | /* That's all the servers poked to no good effect. Try again if some |
440 | * of them were busy. | |
441 | */ | |
a310082f | 442 | if (op->flags & AFS_OPERATION_VBUSY) |
16280a15 DH |
443 | goto restart_from_beginning; |
444 | ||
4584ae96 DH |
445 | e.error = -EDESTADDRREQ; |
446 | e.responded = false; | |
a310082f DH |
447 | for (i = 0; i < op->server_list->nr_servers; i++) { |
448 | struct afs_server *s = op->server_list->servers[i].server; | |
3bf0fb6f | 449 | |
4584ae96 DH |
450 | afs_prioritise_error(&e, READ_ONCE(s->probe.error), |
451 | s->probe.abort_code); | |
3bf0fb6f DH |
452 | } |
453 | ||
51eba999 DH |
454 | error = e.error; |
455 | ||
e7f680f4 | 456 | failed_set_error: |
a310082f | 457 | op->error = error; |
d2ddc776 | 458 | failed: |
a310082f DH |
459 | op->flags |= AFS_OPERATION_STOP; |
460 | afs_end_cursor(&op->ac); | |
461 | _leave(" = f [failed %d]", op->error); | |
d2ddc776 DH |
462 | return false; |
463 | } | |
464 | ||
744bcd71 DH |
465 | /* |
466 | * Dump cursor state in the case of the error being EDESTADDRREQ. | |
467 | */ | |
e49c7b2f | 468 | void afs_dump_edestaddrreq(const struct afs_operation *op) |
744bcd71 DH |
469 | { |
470 | static int count; | |
471 | int i; | |
472 | ||
473 | if (!IS_ENABLED(CONFIG_AFS_DEBUG_CURSOR) || count > 3) | |
474 | return; | |
475 | count++; | |
476 | ||
477 | rcu_read_lock(); | |
478 | ||
479 | pr_notice("EDESTADDR occurred\n"); | |
e49c7b2f DH |
480 | pr_notice("FC: cbb=%x cbb2=%x fl=%x err=%hd\n", |
481 | op->file[0].cb_break_before, | |
482 | op->file[1].cb_break_before, op->flags, op->error); | |
3bf0fb6f | 483 | pr_notice("FC: ut=%lx ix=%d ni=%u\n", |
a310082f | 484 | op->untried, op->index, op->nr_iterations); |
744bcd71 | 485 | |
a310082f DH |
486 | if (op->server_list) { |
487 | const struct afs_server_list *sl = op->server_list; | |
3bf0fb6f DH |
488 | pr_notice("FC: SL nr=%u pr=%u vnov=%hx\n", |
489 | sl->nr_servers, sl->preferred, sl->vnovol_mask); | |
744bcd71 DH |
490 | for (i = 0; i < sl->nr_servers; i++) { |
491 | const struct afs_server *s = sl->servers[i].server; | |
492 | pr_notice("FC: server fl=%lx av=%u %pU\n", | |
493 | s->flags, s->addr_version, &s->uuid); | |
494 | if (s->addresses) { | |
495 | const struct afs_addr_list *a = | |
496 | rcu_dereference(s->addresses); | |
3bf0fb6f | 497 | pr_notice("FC: - av=%u nr=%u/%u/%u pr=%u\n", |
744bcd71 DH |
498 | a->version, |
499 | a->nr_ipv4, a->nr_addrs, a->max_addrs, | |
3bf0fb6f | 500 | a->preferred); |
f6cbb368 DH |
501 | pr_notice("FC: - R=%lx F=%lx\n", |
502 | a->responded, a->failed); | |
a310082f | 503 | if (a == op->ac.alist) |
744bcd71 DH |
504 | pr_notice("FC: - current\n"); |
505 | } | |
506 | } | |
507 | } | |
508 | ||
3bf0fb6f | 509 | pr_notice("AC: t=%lx ax=%u ac=%d er=%d r=%u ni=%u\n", |
a310082f DH |
510 | op->ac.tried, op->ac.index, op->ac.abort_code, op->ac.error, |
511 | op->ac.responded, op->ac.nr_iterations); | |
744bcd71 DH |
512 | rcu_read_unlock(); |
513 | } |