server_list.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /* AFS fileserver list management.
  3. *
  4. * Copyright (C) 2017 Red Hat, Inc. All Rights Reserved.
  5. * Written by David Howells (dhowells@redhat.com)
  6. */
  7. #include <linux/kernel.h>
  8. #include <linux/slab.h>
  9. #include "internal.h"
  10. void afs_put_serverlist(struct afs_net *net, struct afs_server_list *slist)
  11. {
  12. int i;
  13. if (slist && refcount_dec_and_test(&slist->usage)) {
  14. for (i = 0; i < slist->nr_servers; i++)
  15. afs_unuse_server(net, slist->servers[i].server,
  16. afs_server_trace_put_slist);
  17. kfree_rcu(slist, rcu);
  18. }
  19. }
  20. /*
  21. * Build a server list from a VLDB record.
  22. */
  23. struct afs_server_list *afs_alloc_server_list(struct afs_volume *volume,
  24. struct key *key,
  25. struct afs_vldb_entry *vldb)
  26. {
  27. struct afs_server_list *slist;
  28. struct afs_server *server;
  29. unsigned int type_mask = 1 << volume->type;
  30. bool use_newrepsites = false;
  31. int ret = -ENOMEM, nr_servers = 0, newrep = 0, i, j, usable = 0;
  32. /* Work out if we're going to restrict to NEWREPSITE-marked servers or
  33. * not. If at least one site is marked as NEWREPSITE, then it's likely
  34. * that "vos release" is busy updating RO sites. We cut over from one
  35. * to the other when >=50% of the sites have been updated. Sites that
  36. * are in the process of being updated are marked DONTUSE.
  37. */
  38. for (i = 0; i < vldb->nr_servers; i++) {
  39. if (!(vldb->fs_mask[i] & type_mask))
  40. continue;
  41. nr_servers++;
  42. if (vldb->vlsf_flags[i] & AFS_VLSF_DONTUSE)
  43. continue;
  44. usable++;
  45. if (vldb->vlsf_flags[i] & AFS_VLSF_NEWREPSITE)
  46. newrep++;
  47. }
  48. slist = kzalloc(struct_size(slist, servers, nr_servers), GFP_KERNEL);
  49. if (!slist)
  50. goto error;
  51. if (newrep) {
  52. if (newrep < usable / 2) {
  53. slist->ro_replicating = AFS_RO_REPLICATING_USE_OLD;
  54. } else {
  55. slist->ro_replicating = AFS_RO_REPLICATING_USE_NEW;
  56. use_newrepsites = true;
  57. }
  58. }
  59. refcount_set(&slist->usage, 1);
  60. rwlock_init(&slist->lock);
  61. /* Make sure a records exists for each server in the list. */
  62. for (i = 0; i < vldb->nr_servers; i++) {
  63. unsigned long se_flags = 0;
  64. bool newrepsite = vldb->vlsf_flags[i] & AFS_VLSF_NEWREPSITE;
  65. if (!(vldb->fs_mask[i] & type_mask))
  66. continue;
  67. if (vldb->vlsf_flags[i] & AFS_VLSF_DONTUSE)
  68. __set_bit(AFS_SE_EXCLUDED, &se_flags);
  69. if (newrep && (newrepsite ^ use_newrepsites))
  70. __set_bit(AFS_SE_EXCLUDED, &se_flags);
  71. server = afs_lookup_server(volume->cell, key, &vldb->fs_server[i],
  72. vldb->addr_version[i]);
  73. if (IS_ERR(server)) {
  74. ret = PTR_ERR(server);
  75. if (ret == -ENOENT ||
  76. ret == -ENOMEDIUM)
  77. continue;
  78. goto error_2;
  79. }
  80. /* Insertion-sort by UUID */
  81. for (j = 0; j < slist->nr_servers; j++)
  82. if (memcmp(&slist->servers[j].server->uuid,
  83. &server->uuid,
  84. sizeof(server->uuid)) >= 0)
  85. break;
  86. if (j < slist->nr_servers) {
  87. if (slist->servers[j].server == server) {
  88. afs_unuse_server(volume->cell->net, server,
  89. afs_server_trace_put_slist_isort);
  90. continue;
  91. }
  92. memmove(slist->servers + j + 1,
  93. slist->servers + j,
  94. (slist->nr_servers - j) * sizeof(struct afs_server_entry));
  95. }
  96. slist->servers[j].server = server;
  97. slist->servers[j].volume = volume;
  98. slist->servers[j].flags = se_flags;
  99. slist->servers[j].cb_expires_at = AFS_NO_CB_PROMISE;
  100. slist->nr_servers++;
  101. }
  102. if (slist->nr_servers == 0) {
  103. ret = -EDESTADDRREQ;
  104. goto error_2;
  105. }
  106. return slist;
  107. error_2:
  108. afs_put_serverlist(volume->cell->net, slist);
  109. error:
  110. return ERR_PTR(ret);
  111. }
  112. /*
  113. * Copy the annotations from an old server list to its potential replacement.
  114. */
  115. bool afs_annotate_server_list(struct afs_server_list *new,
  116. struct afs_server_list *old)
  117. {
  118. unsigned long mask = 1UL << AFS_SE_EXCLUDED;
  119. int i;
  120. if (old->nr_servers != new->nr_servers ||
  121. old->ro_replicating != new->ro_replicating)
  122. goto changed;
  123. for (i = 0; i < old->nr_servers; i++) {
  124. if (old->servers[i].server != new->servers[i].server)
  125. goto changed;
  126. if ((old->servers[i].flags & mask) != (new->servers[i].flags & mask))
  127. goto changed;
  128. }
  129. return false;
  130. changed:
  131. return true;
  132. }
  133. /*
  134. * Attach a volume to the servers it is going to use.
  135. */
  136. void afs_attach_volume_to_servers(struct afs_volume *volume, struct afs_server_list *slist)
  137. {
  138. struct afs_server_entry *se, *pe;
  139. struct afs_server *server;
  140. struct list_head *p;
  141. unsigned int i;
  142. down_write(&volume->cell->vs_lock);
  143. for (i = 0; i < slist->nr_servers; i++) {
  144. se = &slist->servers[i];
  145. server = se->server;
  146. list_for_each(p, &server->volumes) {
  147. pe = list_entry(p, struct afs_server_entry, slink);
  148. if (volume->vid <= pe->volume->vid)
  149. break;
  150. }
  151. list_add_tail(&se->slink, p);
  152. }
  153. slist->attached = true;
  154. up_write(&volume->cell->vs_lock);
  155. }
  156. /*
  157. * Reattach a volume to the servers it is going to use when server list is
  158. * replaced. We try to switch the attachment points to avoid rewalking the
  159. * lists.
  160. */
  161. void afs_reattach_volume_to_servers(struct afs_volume *volume, struct afs_server_list *new,
  162. struct afs_server_list *old)
  163. {
  164. unsigned int n = 0, o = 0;
  165. down_write(&volume->cell->vs_lock);
  166. while (n < new->nr_servers || o < old->nr_servers) {
  167. struct afs_server_entry *pn = n < new->nr_servers ? &new->servers[n] : NULL;
  168. struct afs_server_entry *po = o < old->nr_servers ? &old->servers[o] : NULL;
  169. struct afs_server_entry *s;
  170. struct list_head *p;
  171. int diff;
  172. if (pn && po && pn->server == po->server) {
  173. pn->cb_expires_at = po->cb_expires_at;
  174. list_replace(&po->slink, &pn->slink);
  175. n++;
  176. o++;
  177. continue;
  178. }
  179. if (pn && po)
  180. diff = memcmp(&pn->server->uuid, &po->server->uuid,
  181. sizeof(pn->server->uuid));
  182. else
  183. diff = pn ? -1 : 1;
  184. if (diff < 0) {
  185. list_for_each(p, &pn->server->volumes) {
  186. s = list_entry(p, struct afs_server_entry, slink);
  187. if (volume->vid <= s->volume->vid)
  188. break;
  189. }
  190. list_add_tail(&pn->slink, p);
  191. n++;
  192. } else {
  193. list_del(&po->slink);
  194. o++;
  195. }
  196. }
  197. up_write(&volume->cell->vs_lock);
  198. }
  199. /*
  200. * Detach a volume from the servers it has been using.
  201. */
  202. void afs_detach_volume_from_servers(struct afs_volume *volume, struct afs_server_list *slist)
  203. {
  204. unsigned int i;
  205. if (!slist->attached)
  206. return;
  207. down_write(&volume->cell->vs_lock);
  208. for (i = 0; i < slist->nr_servers; i++)
  209. list_del(&slist->servers[i].slink);
  210. slist->attached = false;
  211. up_write(&volume->cell->vs_lock);
  212. }