fs_probe.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. /* AFS fileserver probing
  2. *
  3. * Copyright (C) 2018 Red Hat, Inc. All Rights Reserved.
  4. * Written by David Howells (dhowells@redhat.com)
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public Licence
  8. * as published by the Free Software Foundation; either version
  9. * 2 of the Licence, or (at your option) any later version.
  10. */
  11. #include <linux/sched.h>
  12. #include <linux/slab.h>
  13. #include "afs_fs.h"
  14. #include "internal.h"
  15. #include "protocol_yfs.h"
  16. static bool afs_fs_probe_done(struct afs_server *server)
  17. {
  18. if (!atomic_dec_and_test(&server->probe_outstanding))
  19. return false;
  20. wake_up_var(&server->probe_outstanding);
  21. clear_bit_unlock(AFS_SERVER_FL_PROBING, &server->flags);
  22. wake_up_bit(&server->flags, AFS_SERVER_FL_PROBING);
  23. return true;
  24. }
  25. /*
  26. * Process the result of probing a fileserver. This is called after successful
  27. * or failed delivery of an FS.GetCapabilities operation.
  28. */
  29. void afs_fileserver_probe_result(struct afs_call *call)
  30. {
  31. struct afs_addr_list *alist = call->alist;
  32. struct afs_server *server = call->reply[0];
  33. unsigned int server_index = (long)call->reply[1];
  34. unsigned int index = call->addr_ix;
  35. unsigned int rtt = UINT_MAX;
  36. bool have_result = false;
  37. u64 _rtt;
  38. int ret = call->error;
  39. _enter("%pU,%u", &server->uuid, index);
  40. spin_lock(&server->probe_lock);
  41. switch (ret) {
  42. case 0:
  43. server->probe.error = 0;
  44. goto responded;
  45. case -ECONNABORTED:
  46. if (!server->probe.responded) {
  47. server->probe.abort_code = call->abort_code;
  48. server->probe.error = ret;
  49. }
  50. goto responded;
  51. case -ENOMEM:
  52. case -ENONET:
  53. server->probe.local_failure = true;
  54. afs_io_error(call, afs_io_error_fs_probe_fail);
  55. goto out;
  56. case -ECONNRESET: /* Responded, but call expired. */
  57. case -ERFKILL:
  58. case -EADDRNOTAVAIL:
  59. case -ENETUNREACH:
  60. case -EHOSTUNREACH:
  61. case -EHOSTDOWN:
  62. case -ECONNREFUSED:
  63. case -ETIMEDOUT:
  64. case -ETIME:
  65. default:
  66. clear_bit(index, &alist->responded);
  67. set_bit(index, &alist->failed);
  68. if (!server->probe.responded &&
  69. (server->probe.error == 0 ||
  70. server->probe.error == -ETIMEDOUT ||
  71. server->probe.error == -ETIME))
  72. server->probe.error = ret;
  73. afs_io_error(call, afs_io_error_fs_probe_fail);
  74. goto out;
  75. }
  76. responded:
  77. set_bit(index, &alist->responded);
  78. clear_bit(index, &alist->failed);
  79. if (call->service_id == YFS_FS_SERVICE) {
  80. server->probe.is_yfs = true;
  81. set_bit(AFS_SERVER_FL_IS_YFS, &server->flags);
  82. alist->addrs[index].srx_service = call->service_id;
  83. } else {
  84. server->probe.not_yfs = true;
  85. if (!server->probe.is_yfs) {
  86. clear_bit(AFS_SERVER_FL_IS_YFS, &server->flags);
  87. alist->addrs[index].srx_service = call->service_id;
  88. }
  89. }
  90. /* Get the RTT and scale it to fit into a 32-bit value that represents
  91. * over a minute of time so that we can access it with one instruction
  92. * on a 32-bit system.
  93. */
  94. _rtt = rxrpc_kernel_get_rtt(call->net->socket, call->rxcall);
  95. _rtt /= 64;
  96. rtt = (_rtt > UINT_MAX) ? UINT_MAX : _rtt;
  97. if (rtt < server->probe.rtt) {
  98. server->probe.rtt = rtt;
  99. alist->preferred = index;
  100. have_result = true;
  101. }
  102. smp_wmb(); /* Set rtt before responded. */
  103. server->probe.responded = true;
  104. set_bit(AFS_SERVER_FL_PROBED, &server->flags);
  105. out:
  106. spin_unlock(&server->probe_lock);
  107. _debug("probe [%u][%u] %pISpc rtt=%u ret=%d",
  108. server_index, index, &alist->addrs[index].transport,
  109. (unsigned int)rtt, ret);
  110. have_result |= afs_fs_probe_done(server);
  111. if (have_result) {
  112. server->probe.have_result = true;
  113. wake_up_var(&server->probe.have_result);
  114. wake_up_all(&server->probe_wq);
  115. }
  116. }
  117. /*
  118. * Probe all of a fileserver's addresses to find out the best route and to
  119. * query its capabilities.
  120. */
  121. static int afs_do_probe_fileserver(struct afs_net *net,
  122. struct afs_server *server,
  123. struct key *key,
  124. unsigned int server_index,
  125. struct afs_error *_e)
  126. {
  127. struct afs_addr_cursor ac = {
  128. .index = 0,
  129. };
  130. bool in_progress = false;
  131. int err;
  132. _enter("%pU", &server->uuid);
  133. read_lock(&server->fs_lock);
  134. ac.alist = rcu_dereference_protected(server->addresses,
  135. lockdep_is_held(&server->fs_lock));
  136. read_unlock(&server->fs_lock);
  137. atomic_set(&server->probe_outstanding, ac.alist->nr_addrs);
  138. memset(&server->probe, 0, sizeof(server->probe));
  139. server->probe.rtt = UINT_MAX;
  140. for (ac.index = 0; ac.index < ac.alist->nr_addrs; ac.index++) {
  141. err = afs_fs_get_capabilities(net, server, &ac, key, server_index,
  142. true);
  143. if (err == -EINPROGRESS)
  144. in_progress = true;
  145. else
  146. afs_prioritise_error(_e, err, ac.abort_code);
  147. }
  148. if (!in_progress)
  149. afs_fs_probe_done(server);
  150. return in_progress;
  151. }
  152. /*
  153. * Send off probes to all unprobed servers.
  154. */
  155. int afs_probe_fileservers(struct afs_net *net, struct key *key,
  156. struct afs_server_list *list)
  157. {
  158. struct afs_server *server;
  159. struct afs_error e;
  160. bool in_progress = false;
  161. int i;
  162. e.error = 0;
  163. e.responded = false;
  164. for (i = 0; i < list->nr_servers; i++) {
  165. server = list->servers[i].server;
  166. if (test_bit(AFS_SERVER_FL_PROBED, &server->flags))
  167. continue;
  168. if (!test_and_set_bit_lock(AFS_SERVER_FL_PROBING, &server->flags) &&
  169. afs_do_probe_fileserver(net, server, key, i, &e))
  170. in_progress = true;
  171. }
  172. return in_progress ? 0 : e.error;
  173. }
  174. /*
  175. * Wait for the first as-yet untried fileserver to respond.
  176. */
  177. int afs_wait_for_fs_probes(struct afs_server_list *slist, unsigned long untried)
  178. {
  179. struct wait_queue_entry *waits;
  180. struct afs_server *server;
  181. unsigned int rtt = UINT_MAX;
  182. bool have_responders = false;
  183. int pref = -1, i;
  184. _enter("%u,%lx", slist->nr_servers, untried);
  185. /* Only wait for servers that have a probe outstanding. */
  186. for (i = 0; i < slist->nr_servers; i++) {
  187. if (test_bit(i, &untried)) {
  188. server = slist->servers[i].server;
  189. if (!test_bit(AFS_SERVER_FL_PROBING, &server->flags))
  190. __clear_bit(i, &untried);
  191. if (server->probe.responded)
  192. have_responders = true;
  193. }
  194. }
  195. if (have_responders || !untried)
  196. return 0;
  197. waits = kmalloc(array_size(slist->nr_servers, sizeof(*waits)), GFP_KERNEL);
  198. if (!waits)
  199. return -ENOMEM;
  200. for (i = 0; i < slist->nr_servers; i++) {
  201. if (test_bit(i, &untried)) {
  202. server = slist->servers[i].server;
  203. init_waitqueue_entry(&waits[i], current);
  204. add_wait_queue(&server->probe_wq, &waits[i]);
  205. }
  206. }
  207. for (;;) {
  208. bool still_probing = false;
  209. set_current_state(TASK_INTERRUPTIBLE);
  210. for (i = 0; i < slist->nr_servers; i++) {
  211. if (test_bit(i, &untried)) {
  212. server = slist->servers[i].server;
  213. if (server->probe.responded)
  214. goto stop;
  215. if (test_bit(AFS_SERVER_FL_PROBING, &server->flags))
  216. still_probing = true;
  217. }
  218. }
  219. if (!still_probing || unlikely(signal_pending(current)))
  220. goto stop;
  221. schedule();
  222. }
  223. stop:
  224. set_current_state(TASK_RUNNING);
  225. for (i = 0; i < slist->nr_servers; i++) {
  226. if (test_bit(i, &untried)) {
  227. server = slist->servers[i].server;
  228. if (server->probe.responded &&
  229. server->probe.rtt < rtt) {
  230. pref = i;
  231. rtt = server->probe.rtt;
  232. }
  233. remove_wait_queue(&server->probe_wq, &waits[i]);
  234. }
  235. }
  236. kfree(waits);
  237. if (pref == -1 && signal_pending(current))
  238. return -ERESTARTSYS;
  239. if (pref >= 0)
  240. slist->preferred = pref;
  241. return 0;
  242. }