vlocation.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954
  1. /* vlocation.c: volume location management
  2. *
  3. * Copyright (C) 2002 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 License
  8. * as published by the Free Software Foundation; either version
  9. * 2 of the License, or (at your option) any later version.
  10. */
  11. #include <linux/kernel.h>
  12. #include <linux/module.h>
  13. #include <linux/init.h>
  14. #include <linux/slab.h>
  15. #include <linux/fs.h>
  16. #include <linux/pagemap.h>
  17. #include "volume.h"
  18. #include "cell.h"
  19. #include "cmservice.h"
  20. #include "fsclient.h"
  21. #include "vlclient.h"
  22. #include "kafstimod.h"
  23. #include <rxrpc/connection.h>
  24. #include "internal.h"
  25. #define AFS_VLDB_TIMEOUT HZ*1000
  26. static void afs_vlocation_update_timer(struct afs_timer *timer);
  27. static void afs_vlocation_update_attend(struct afs_async_op *op);
  28. static void afs_vlocation_update_discard(struct afs_async_op *op);
  29. static void __afs_put_vlocation(struct afs_vlocation *vlocation);
  30. static void __afs_vlocation_timeout(struct afs_timer *timer)
  31. {
  32. struct afs_vlocation *vlocation =
  33. list_entry(timer, struct afs_vlocation, timeout);
  34. _debug("VL TIMEOUT [%s{u=%d}]",
  35. vlocation->vldb.name, atomic_read(&vlocation->usage));
  36. afs_vlocation_do_timeout(vlocation);
  37. }
  38. static const struct afs_timer_ops afs_vlocation_timer_ops = {
  39. .timed_out = __afs_vlocation_timeout,
  40. };
  41. static const struct afs_timer_ops afs_vlocation_update_timer_ops = {
  42. .timed_out = afs_vlocation_update_timer,
  43. };
  44. static const struct afs_async_op_ops afs_vlocation_update_op_ops = {
  45. .attend = afs_vlocation_update_attend,
  46. .discard = afs_vlocation_update_discard,
  47. };
  48. static LIST_HEAD(afs_vlocation_update_pendq); /* queue of VLs awaiting update */
  49. static struct afs_vlocation *afs_vlocation_update; /* VL currently being updated */
  50. static DEFINE_SPINLOCK(afs_vlocation_update_lock); /* lock guarding update queue */
  51. #ifdef AFS_CACHING_SUPPORT
  52. static cachefs_match_val_t afs_vlocation_cache_match(void *target,
  53. const void *entry);
  54. static void afs_vlocation_cache_update(void *source, void *entry);
  55. struct cachefs_index_def afs_vlocation_cache_index_def = {
  56. .name = "vldb",
  57. .data_size = sizeof(struct afs_cache_vlocation),
  58. .keys[0] = { CACHEFS_INDEX_KEYS_ASCIIZ, 64 },
  59. .match = afs_vlocation_cache_match,
  60. .update = afs_vlocation_cache_update,
  61. };
  62. #endif
  63. /*****************************************************************************/
  64. /*
  65. * iterate through the VL servers in a cell until one of them admits knowing
  66. * about the volume in question
  67. * - caller must have cell->vl_sem write-locked
  68. */
  69. static int afs_vlocation_access_vl_by_name(struct afs_vlocation *vlocation,
  70. const char *name,
  71. unsigned namesz,
  72. struct afs_cache_vlocation *vldb)
  73. {
  74. struct afs_server *server = NULL;
  75. struct afs_cell *cell = vlocation->cell;
  76. int count, ret;
  77. _enter("%s,%*.*s,%u", cell->name, namesz, namesz, name, namesz);
  78. ret = -ENOMEDIUM;
  79. for (count = cell->vl_naddrs; count > 0; count--) {
  80. _debug("CellServ[%hu]: %08x",
  81. cell->vl_curr_svix,
  82. cell->vl_addrs[cell->vl_curr_svix].s_addr);
  83. /* try and create a server */
  84. ret = afs_server_lookup(cell,
  85. &cell->vl_addrs[cell->vl_curr_svix],
  86. &server);
  87. switch (ret) {
  88. case 0:
  89. break;
  90. case -ENOMEM:
  91. case -ENONET:
  92. goto out;
  93. default:
  94. goto rotate;
  95. }
  96. /* attempt to access the VL server */
  97. ret = afs_rxvl_get_entry_by_name(server, name, namesz, vldb);
  98. switch (ret) {
  99. case 0:
  100. afs_put_server(server);
  101. goto out;
  102. case -ENOMEM:
  103. case -ENONET:
  104. case -ENETUNREACH:
  105. case -EHOSTUNREACH:
  106. case -ECONNREFUSED:
  107. down_write(&server->sem);
  108. if (server->vlserver) {
  109. rxrpc_put_connection(server->vlserver);
  110. server->vlserver = NULL;
  111. }
  112. up_write(&server->sem);
  113. afs_put_server(server);
  114. if (ret == -ENOMEM || ret == -ENONET)
  115. goto out;
  116. goto rotate;
  117. case -ENOMEDIUM:
  118. afs_put_server(server);
  119. goto out;
  120. default:
  121. afs_put_server(server);
  122. ret = -ENOMEDIUM;
  123. goto rotate;
  124. }
  125. /* rotate the server records upon lookup failure */
  126. rotate:
  127. cell->vl_curr_svix++;
  128. cell->vl_curr_svix %= cell->vl_naddrs;
  129. }
  130. out:
  131. _leave(" = %d", ret);
  132. return ret;
  133. } /* end afs_vlocation_access_vl_by_name() */
  134. /*****************************************************************************/
  135. /*
  136. * iterate through the VL servers in a cell until one of them admits knowing
  137. * about the volume in question
  138. * - caller must have cell->vl_sem write-locked
  139. */
  140. static int afs_vlocation_access_vl_by_id(struct afs_vlocation *vlocation,
  141. afs_volid_t volid,
  142. afs_voltype_t voltype,
  143. struct afs_cache_vlocation *vldb)
  144. {
  145. struct afs_server *server = NULL;
  146. struct afs_cell *cell = vlocation->cell;
  147. int count, ret;
  148. _enter("%s,%x,%d,", cell->name, volid, voltype);
  149. ret = -ENOMEDIUM;
  150. for (count = cell->vl_naddrs; count > 0; count--) {
  151. _debug("CellServ[%hu]: %08x",
  152. cell->vl_curr_svix,
  153. cell->vl_addrs[cell->vl_curr_svix].s_addr);
  154. /* try and create a server */
  155. ret = afs_server_lookup(cell,
  156. &cell->vl_addrs[cell->vl_curr_svix],
  157. &server);
  158. switch (ret) {
  159. case 0:
  160. break;
  161. case -ENOMEM:
  162. case -ENONET:
  163. goto out;
  164. default:
  165. goto rotate;
  166. }
  167. /* attempt to access the VL server */
  168. ret = afs_rxvl_get_entry_by_id(server, volid, voltype, vldb);
  169. switch (ret) {
  170. case 0:
  171. afs_put_server(server);
  172. goto out;
  173. case -ENOMEM:
  174. case -ENONET:
  175. case -ENETUNREACH:
  176. case -EHOSTUNREACH:
  177. case -ECONNREFUSED:
  178. down_write(&server->sem);
  179. if (server->vlserver) {
  180. rxrpc_put_connection(server->vlserver);
  181. server->vlserver = NULL;
  182. }
  183. up_write(&server->sem);
  184. afs_put_server(server);
  185. if (ret == -ENOMEM || ret == -ENONET)
  186. goto out;
  187. goto rotate;
  188. case -ENOMEDIUM:
  189. afs_put_server(server);
  190. goto out;
  191. default:
  192. afs_put_server(server);
  193. ret = -ENOMEDIUM;
  194. goto rotate;
  195. }
  196. /* rotate the server records upon lookup failure */
  197. rotate:
  198. cell->vl_curr_svix++;
  199. cell->vl_curr_svix %= cell->vl_naddrs;
  200. }
  201. out:
  202. _leave(" = %d", ret);
  203. return ret;
  204. } /* end afs_vlocation_access_vl_by_id() */
  205. /*****************************************************************************/
  206. /*
  207. * lookup volume location
  208. * - caller must have cell->vol_sem write-locked
  209. * - iterate through the VL servers in a cell until one of them admits knowing
  210. * about the volume in question
  211. * - lookup in the local cache if not able to find on the VL server
  212. * - insert/update in the local cache if did get a VL response
  213. */
  214. int afs_vlocation_lookup(struct afs_cell *cell,
  215. const char *name,
  216. unsigned namesz,
  217. struct afs_vlocation **_vlocation)
  218. {
  219. struct afs_cache_vlocation vldb;
  220. struct afs_vlocation *vlocation;
  221. afs_voltype_t voltype;
  222. afs_volid_t vid;
  223. int active = 0, ret;
  224. _enter("{%s},%*.*s,%u,", cell->name, namesz, namesz, name, namesz);
  225. if (namesz > sizeof(vlocation->vldb.name)) {
  226. _leave(" = -ENAMETOOLONG");
  227. return -ENAMETOOLONG;
  228. }
  229. /* search the cell's active list first */
  230. list_for_each_entry(vlocation, &cell->vl_list, link) {
  231. if (namesz < sizeof(vlocation->vldb.name) &&
  232. vlocation->vldb.name[namesz] != '\0')
  233. continue;
  234. if (memcmp(vlocation->vldb.name, name, namesz) == 0)
  235. goto found_in_memory;
  236. }
  237. /* search the cell's graveyard list second */
  238. spin_lock(&cell->vl_gylock);
  239. list_for_each_entry(vlocation, &cell->vl_graveyard, link) {
  240. if (namesz < sizeof(vlocation->vldb.name) &&
  241. vlocation->vldb.name[namesz] != '\0')
  242. continue;
  243. if (memcmp(vlocation->vldb.name, name, namesz) == 0)
  244. goto found_in_graveyard;
  245. }
  246. spin_unlock(&cell->vl_gylock);
  247. /* not in the cell's in-memory lists - create a new record */
  248. vlocation = kmalloc(sizeof(struct afs_vlocation), GFP_KERNEL);
  249. if (!vlocation)
  250. return -ENOMEM;
  251. memset(vlocation, 0, sizeof(struct afs_vlocation));
  252. atomic_set(&vlocation->usage, 1);
  253. INIT_LIST_HEAD(&vlocation->link);
  254. rwlock_init(&vlocation->lock);
  255. memcpy(vlocation->vldb.name, name, namesz);
  256. afs_timer_init(&vlocation->timeout, &afs_vlocation_timer_ops);
  257. afs_timer_init(&vlocation->upd_timer, &afs_vlocation_update_timer_ops);
  258. afs_async_op_init(&vlocation->upd_op, &afs_vlocation_update_op_ops);
  259. afs_get_cell(cell);
  260. vlocation->cell = cell;
  261. list_add_tail(&vlocation->link, &cell->vl_list);
  262. #ifdef AFS_CACHING_SUPPORT
  263. /* we want to store it in the cache, plus it might already be
  264. * encached */
  265. cachefs_acquire_cookie(cell->cache,
  266. &afs_volume_cache_index_def,
  267. vlocation,
  268. &vlocation->cache);
  269. if (vlocation->valid)
  270. goto found_in_cache;
  271. #endif
  272. /* try to look up an unknown volume in the cell VL databases by name */
  273. ret = afs_vlocation_access_vl_by_name(vlocation, name, namesz, &vldb);
  274. if (ret < 0) {
  275. printk("kAFS: failed to locate '%*.*s' in cell '%s'\n",
  276. namesz, namesz, name, cell->name);
  277. goto error;
  278. }
  279. goto found_on_vlserver;
  280. found_in_graveyard:
  281. /* found in the graveyard - resurrect */
  282. _debug("found in graveyard");
  283. atomic_inc(&vlocation->usage);
  284. list_del(&vlocation->link);
  285. list_add_tail(&vlocation->link, &cell->vl_list);
  286. spin_unlock(&cell->vl_gylock);
  287. afs_kafstimod_del_timer(&vlocation->timeout);
  288. goto active;
  289. found_in_memory:
  290. /* found in memory - check to see if it's active */
  291. _debug("found in memory");
  292. atomic_inc(&vlocation->usage);
  293. active:
  294. active = 1;
  295. #ifdef AFS_CACHING_SUPPORT
  296. found_in_cache:
  297. #endif
  298. /* try to look up a cached volume in the cell VL databases by ID */
  299. _debug("found in cache");
  300. _debug("Locally Cached: %s %02x { %08x(%x) %08x(%x) %08x(%x) }",
  301. vlocation->vldb.name,
  302. vlocation->vldb.vidmask,
  303. ntohl(vlocation->vldb.servers[0].s_addr),
  304. vlocation->vldb.srvtmask[0],
  305. ntohl(vlocation->vldb.servers[1].s_addr),
  306. vlocation->vldb.srvtmask[1],
  307. ntohl(vlocation->vldb.servers[2].s_addr),
  308. vlocation->vldb.srvtmask[2]
  309. );
  310. _debug("Vids: %08x %08x %08x",
  311. vlocation->vldb.vid[0],
  312. vlocation->vldb.vid[1],
  313. vlocation->vldb.vid[2]);
  314. if (vlocation->vldb.vidmask & AFS_VOL_VTM_RW) {
  315. vid = vlocation->vldb.vid[0];
  316. voltype = AFSVL_RWVOL;
  317. }
  318. else if (vlocation->vldb.vidmask & AFS_VOL_VTM_RO) {
  319. vid = vlocation->vldb.vid[1];
  320. voltype = AFSVL_ROVOL;
  321. }
  322. else if (vlocation->vldb.vidmask & AFS_VOL_VTM_BAK) {
  323. vid = vlocation->vldb.vid[2];
  324. voltype = AFSVL_BACKVOL;
  325. }
  326. else {
  327. BUG();
  328. vid = 0;
  329. voltype = 0;
  330. }
  331. ret = afs_vlocation_access_vl_by_id(vlocation, vid, voltype, &vldb);
  332. switch (ret) {
  333. /* net error */
  334. default:
  335. printk("kAFS: failed to volume '%*.*s' (%x) up in '%s': %d\n",
  336. namesz, namesz, name, vid, cell->name, ret);
  337. goto error;
  338. /* pulled from local cache into memory */
  339. case 0:
  340. goto found_on_vlserver;
  341. /* uh oh... looks like the volume got deleted */
  342. case -ENOMEDIUM:
  343. printk("kAFS: volume '%*.*s' (%x) does not exist '%s'\n",
  344. namesz, namesz, name, vid, cell->name);
  345. /* TODO: make existing record unavailable */
  346. goto error;
  347. }
  348. found_on_vlserver:
  349. _debug("Done VL Lookup: %*.*s %02x { %08x(%x) %08x(%x) %08x(%x) }",
  350. namesz, namesz, name,
  351. vldb.vidmask,
  352. ntohl(vldb.servers[0].s_addr), vldb.srvtmask[0],
  353. ntohl(vldb.servers[1].s_addr), vldb.srvtmask[1],
  354. ntohl(vldb.servers[2].s_addr), vldb.srvtmask[2]
  355. );
  356. _debug("Vids: %08x %08x %08x", vldb.vid[0], vldb.vid[1], vldb.vid[2]);
  357. if ((namesz < sizeof(vlocation->vldb.name) &&
  358. vlocation->vldb.name[namesz] != '\0') ||
  359. memcmp(vldb.name, name, namesz) != 0)
  360. printk("kAFS: name of volume '%*.*s' changed to '%s' on server\n",
  361. namesz, namesz, name, vldb.name);
  362. memcpy(&vlocation->vldb, &vldb, sizeof(vlocation->vldb));
  363. afs_kafstimod_add_timer(&vlocation->upd_timer, 10 * HZ);
  364. #ifdef AFS_CACHING_SUPPORT
  365. /* update volume entry in local cache */
  366. cachefs_update_cookie(vlocation->cache);
  367. #endif
  368. *_vlocation = vlocation;
  369. _leave(" = 0 (%p)",vlocation);
  370. return 0;
  371. error:
  372. if (vlocation) {
  373. if (active) {
  374. __afs_put_vlocation(vlocation);
  375. }
  376. else {
  377. list_del(&vlocation->link);
  378. #ifdef AFS_CACHING_SUPPORT
  379. cachefs_relinquish_cookie(vlocation->cache, 0);
  380. #endif
  381. afs_put_cell(vlocation->cell);
  382. kfree(vlocation);
  383. }
  384. }
  385. _leave(" = %d", ret);
  386. return ret;
  387. } /* end afs_vlocation_lookup() */
  388. /*****************************************************************************/
  389. /*
  390. * finish using a volume location record
  391. * - caller must have cell->vol_sem write-locked
  392. */
  393. static void __afs_put_vlocation(struct afs_vlocation *vlocation)
  394. {
  395. struct afs_cell *cell;
  396. if (!vlocation)
  397. return;
  398. _enter("%s", vlocation->vldb.name);
  399. cell = vlocation->cell;
  400. /* sanity check */
  401. BUG_ON(atomic_read(&vlocation->usage) <= 0);
  402. spin_lock(&cell->vl_gylock);
  403. if (likely(!atomic_dec_and_test(&vlocation->usage))) {
  404. spin_unlock(&cell->vl_gylock);
  405. _leave("");
  406. return;
  407. }
  408. /* move to graveyard queue */
  409. list_del(&vlocation->link);
  410. list_add_tail(&vlocation->link,&cell->vl_graveyard);
  411. /* remove from pending timeout queue (refcounted if actually being
  412. * updated) */
  413. list_del_init(&vlocation->upd_op.link);
  414. /* time out in 10 secs */
  415. afs_kafstimod_del_timer(&vlocation->upd_timer);
  416. afs_kafstimod_add_timer(&vlocation->timeout, 10 * HZ);
  417. spin_unlock(&cell->vl_gylock);
  418. _leave(" [killed]");
  419. } /* end __afs_put_vlocation() */
  420. /*****************************************************************************/
  421. /*
  422. * finish using a volume location record
  423. */
  424. void afs_put_vlocation(struct afs_vlocation *vlocation)
  425. {
  426. if (vlocation) {
  427. struct afs_cell *cell = vlocation->cell;
  428. down_write(&cell->vl_sem);
  429. __afs_put_vlocation(vlocation);
  430. up_write(&cell->vl_sem);
  431. }
  432. } /* end afs_put_vlocation() */
  433. /*****************************************************************************/
  434. /*
  435. * timeout vlocation record
  436. * - removes from the cell's graveyard if the usage count is zero
  437. */
  438. void afs_vlocation_do_timeout(struct afs_vlocation *vlocation)
  439. {
  440. struct afs_cell *cell;
  441. _enter("%s", vlocation->vldb.name);
  442. cell = vlocation->cell;
  443. BUG_ON(atomic_read(&vlocation->usage) < 0);
  444. /* remove from graveyard if still dead */
  445. spin_lock(&cell->vl_gylock);
  446. if (atomic_read(&vlocation->usage) == 0)
  447. list_del_init(&vlocation->link);
  448. else
  449. vlocation = NULL;
  450. spin_unlock(&cell->vl_gylock);
  451. if (!vlocation) {
  452. _leave("");
  453. return; /* resurrected */
  454. }
  455. /* we can now destroy it properly */
  456. #ifdef AFS_CACHING_SUPPORT
  457. cachefs_relinquish_cookie(vlocation->cache, 0);
  458. #endif
  459. afs_put_cell(cell);
  460. kfree(vlocation);
  461. _leave(" [destroyed]");
  462. } /* end afs_vlocation_do_timeout() */
  463. /*****************************************************************************/
  464. /*
  465. * send an update operation to the currently selected server
  466. */
  467. static int afs_vlocation_update_begin(struct afs_vlocation *vlocation)
  468. {
  469. afs_voltype_t voltype;
  470. afs_volid_t vid;
  471. int ret;
  472. _enter("%s{ufs=%u ucs=%u}",
  473. vlocation->vldb.name,
  474. vlocation->upd_first_svix,
  475. vlocation->upd_curr_svix);
  476. /* try to look up a cached volume in the cell VL databases by ID */
  477. if (vlocation->vldb.vidmask & AFS_VOL_VTM_RW) {
  478. vid = vlocation->vldb.vid[0];
  479. voltype = AFSVL_RWVOL;
  480. }
  481. else if (vlocation->vldb.vidmask & AFS_VOL_VTM_RO) {
  482. vid = vlocation->vldb.vid[1];
  483. voltype = AFSVL_ROVOL;
  484. }
  485. else if (vlocation->vldb.vidmask & AFS_VOL_VTM_BAK) {
  486. vid = vlocation->vldb.vid[2];
  487. voltype = AFSVL_BACKVOL;
  488. }
  489. else {
  490. BUG();
  491. vid = 0;
  492. voltype = 0;
  493. }
  494. /* contact the chosen server */
  495. ret = afs_server_lookup(
  496. vlocation->cell,
  497. &vlocation->cell->vl_addrs[vlocation->upd_curr_svix],
  498. &vlocation->upd_op.server);
  499. switch (ret) {
  500. case 0:
  501. break;
  502. case -ENOMEM:
  503. case -ENONET:
  504. default:
  505. _leave(" = %d", ret);
  506. return ret;
  507. }
  508. /* initiate the update operation */
  509. ret = afs_rxvl_get_entry_by_id_async(&vlocation->upd_op, vid, voltype);
  510. if (ret < 0) {
  511. _leave(" = %d", ret);
  512. return ret;
  513. }
  514. _leave(" = %d", ret);
  515. return ret;
  516. } /* end afs_vlocation_update_begin() */
  517. /*****************************************************************************/
  518. /*
  519. * abandon updating a VL record
  520. * - does not restart the update timer
  521. */
  522. static void afs_vlocation_update_abandon(struct afs_vlocation *vlocation,
  523. afs_vlocation_upd_t state,
  524. int ret)
  525. {
  526. _enter("%s,%u", vlocation->vldb.name, state);
  527. if (ret < 0)
  528. printk("kAFS: Abandoning VL update '%s': %d\n",
  529. vlocation->vldb.name, ret);
  530. /* discard the server record */
  531. afs_put_server(vlocation->upd_op.server);
  532. vlocation->upd_op.server = NULL;
  533. spin_lock(&afs_vlocation_update_lock);
  534. afs_vlocation_update = NULL;
  535. vlocation->upd_state = state;
  536. /* TODO: start updating next VL record on pending list */
  537. spin_unlock(&afs_vlocation_update_lock);
  538. _leave("");
  539. } /* end afs_vlocation_update_abandon() */
  540. /*****************************************************************************/
  541. /*
  542. * handle periodic update timeouts and busy retry timeouts
  543. * - called from kafstimod
  544. */
  545. static void afs_vlocation_update_timer(struct afs_timer *timer)
  546. {
  547. struct afs_vlocation *vlocation =
  548. list_entry(timer, struct afs_vlocation, upd_timer);
  549. int ret;
  550. _enter("%s", vlocation->vldb.name);
  551. /* only update if not in the graveyard (defend against putting too) */
  552. spin_lock(&vlocation->cell->vl_gylock);
  553. if (!atomic_read(&vlocation->usage))
  554. goto out_unlock1;
  555. spin_lock(&afs_vlocation_update_lock);
  556. /* if we were woken up due to EBUSY sleep then restart immediately if
  557. * possible or else jump to front of pending queue */
  558. if (vlocation->upd_state == AFS_VLUPD_BUSYSLEEP) {
  559. if (afs_vlocation_update) {
  560. list_add(&vlocation->upd_op.link,
  561. &afs_vlocation_update_pendq);
  562. }
  563. else {
  564. afs_get_vlocation(vlocation);
  565. afs_vlocation_update = vlocation;
  566. vlocation->upd_state = AFS_VLUPD_INPROGRESS;
  567. }
  568. goto out_unlock2;
  569. }
  570. /* put on pending queue if there's already another update in progress */
  571. if (afs_vlocation_update) {
  572. vlocation->upd_state = AFS_VLUPD_PENDING;
  573. list_add_tail(&vlocation->upd_op.link,
  574. &afs_vlocation_update_pendq);
  575. goto out_unlock2;
  576. }
  577. /* hold a ref on it while actually updating */
  578. afs_get_vlocation(vlocation);
  579. afs_vlocation_update = vlocation;
  580. vlocation->upd_state = AFS_VLUPD_INPROGRESS;
  581. spin_unlock(&afs_vlocation_update_lock);
  582. spin_unlock(&vlocation->cell->vl_gylock);
  583. /* okay... we can start the update */
  584. _debug("BEGIN VL UPDATE [%s]", vlocation->vldb.name);
  585. vlocation->upd_first_svix = vlocation->cell->vl_curr_svix;
  586. vlocation->upd_curr_svix = vlocation->upd_first_svix;
  587. vlocation->upd_rej_cnt = 0;
  588. vlocation->upd_busy_cnt = 0;
  589. ret = afs_vlocation_update_begin(vlocation);
  590. if (ret < 0) {
  591. afs_vlocation_update_abandon(vlocation, AFS_VLUPD_SLEEP, ret);
  592. afs_kafstimod_add_timer(&vlocation->upd_timer,
  593. AFS_VLDB_TIMEOUT);
  594. afs_put_vlocation(vlocation);
  595. }
  596. _leave("");
  597. return;
  598. out_unlock2:
  599. spin_unlock(&afs_vlocation_update_lock);
  600. out_unlock1:
  601. spin_unlock(&vlocation->cell->vl_gylock);
  602. _leave("");
  603. return;
  604. } /* end afs_vlocation_update_timer() */
  605. /*****************************************************************************/
  606. /*
  607. * attend to an update operation upon which an event happened
  608. * - called in kafsasyncd context
  609. */
  610. static void afs_vlocation_update_attend(struct afs_async_op *op)
  611. {
  612. struct afs_cache_vlocation vldb;
  613. struct afs_vlocation *vlocation =
  614. list_entry(op, struct afs_vlocation, upd_op);
  615. unsigned tmp;
  616. int ret;
  617. _enter("%s", vlocation->vldb.name);
  618. ret = afs_rxvl_get_entry_by_id_async2(op, &vldb);
  619. switch (ret) {
  620. case -EAGAIN:
  621. _leave(" [unfinished]");
  622. return;
  623. case 0:
  624. _debug("END VL UPDATE: %d\n", ret);
  625. vlocation->valid = 1;
  626. _debug("Done VL Lookup: %02x { %08x(%x) %08x(%x) %08x(%x) }",
  627. vldb.vidmask,
  628. ntohl(vldb.servers[0].s_addr), vldb.srvtmask[0],
  629. ntohl(vldb.servers[1].s_addr), vldb.srvtmask[1],
  630. ntohl(vldb.servers[2].s_addr), vldb.srvtmask[2]
  631. );
  632. _debug("Vids: %08x %08x %08x",
  633. vldb.vid[0], vldb.vid[1], vldb.vid[2]);
  634. afs_vlocation_update_abandon(vlocation, AFS_VLUPD_SLEEP, 0);
  635. down_write(&vlocation->cell->vl_sem);
  636. /* actually update the cache */
  637. if (strncmp(vldb.name, vlocation->vldb.name,
  638. sizeof(vlocation->vldb.name)) != 0)
  639. printk("kAFS: name of volume '%s'"
  640. " changed to '%s' on server\n",
  641. vlocation->vldb.name, vldb.name);
  642. memcpy(&vlocation->vldb, &vldb, sizeof(vlocation->vldb));
  643. #if 0
  644. /* TODO update volume entry in local cache */
  645. #endif
  646. up_write(&vlocation->cell->vl_sem);
  647. if (ret < 0)
  648. printk("kAFS: failed to update local cache: %d\n", ret);
  649. afs_kafstimod_add_timer(&vlocation->upd_timer,
  650. AFS_VLDB_TIMEOUT);
  651. afs_put_vlocation(vlocation);
  652. _leave(" [found]");
  653. return;
  654. case -ENOMEDIUM:
  655. vlocation->upd_rej_cnt++;
  656. goto try_next;
  657. /* the server is locked - retry in a very short while */
  658. case -EBUSY:
  659. vlocation->upd_busy_cnt++;
  660. if (vlocation->upd_busy_cnt > 3)
  661. goto try_next; /* too many retries */
  662. afs_vlocation_update_abandon(vlocation,
  663. AFS_VLUPD_BUSYSLEEP, 0);
  664. afs_kafstimod_add_timer(&vlocation->upd_timer, HZ / 2);
  665. afs_put_vlocation(vlocation);
  666. _leave(" [busy]");
  667. return;
  668. case -ENETUNREACH:
  669. case -EHOSTUNREACH:
  670. case -ECONNREFUSED:
  671. case -EREMOTEIO:
  672. /* record bad vlserver info in the cell too
  673. * - TODO: use down_write_trylock() if available
  674. */
  675. if (vlocation->upd_curr_svix == vlocation->cell->vl_curr_svix)
  676. vlocation->cell->vl_curr_svix =
  677. vlocation->cell->vl_curr_svix %
  678. vlocation->cell->vl_naddrs;
  679. case -EBADRQC:
  680. case -EINVAL:
  681. case -EACCES:
  682. case -EBADMSG:
  683. goto try_next;
  684. default:
  685. goto abandon;
  686. }
  687. /* try contacting the next server */
  688. try_next:
  689. vlocation->upd_busy_cnt = 0;
  690. /* discard the server record */
  691. afs_put_server(vlocation->upd_op.server);
  692. vlocation->upd_op.server = NULL;
  693. tmp = vlocation->cell->vl_naddrs;
  694. if (tmp == 0)
  695. goto abandon;
  696. vlocation->upd_curr_svix++;
  697. if (vlocation->upd_curr_svix >= tmp)
  698. vlocation->upd_curr_svix = 0;
  699. if (vlocation->upd_first_svix >= tmp)
  700. vlocation->upd_first_svix = tmp - 1;
  701. /* move to the next server */
  702. if (vlocation->upd_curr_svix != vlocation->upd_first_svix) {
  703. afs_vlocation_update_begin(vlocation);
  704. _leave(" [next]");
  705. return;
  706. }
  707. /* run out of servers to try - was the volume rejected? */
  708. if (vlocation->upd_rej_cnt > 0) {
  709. printk("kAFS: Active volume no longer valid '%s'\n",
  710. vlocation->vldb.name);
  711. vlocation->valid = 0;
  712. afs_vlocation_update_abandon(vlocation, AFS_VLUPD_SLEEP, 0);
  713. afs_kafstimod_add_timer(&vlocation->upd_timer,
  714. AFS_VLDB_TIMEOUT);
  715. afs_put_vlocation(vlocation);
  716. _leave(" [invalidated]");
  717. return;
  718. }
  719. /* abandon the update */
  720. abandon:
  721. afs_vlocation_update_abandon(vlocation, AFS_VLUPD_SLEEP, ret);
  722. afs_kafstimod_add_timer(&vlocation->upd_timer, HZ * 10);
  723. afs_put_vlocation(vlocation);
  724. _leave(" [abandoned]");
  725. } /* end afs_vlocation_update_attend() */
  726. /*****************************************************************************/
  727. /*
  728. * deal with an update operation being discarded
  729. * - called in kafsasyncd context when it's dying due to rmmod
  730. * - the call has already been aborted and put()'d
  731. */
  732. static void afs_vlocation_update_discard(struct afs_async_op *op)
  733. {
  734. struct afs_vlocation *vlocation =
  735. list_entry(op, struct afs_vlocation, upd_op);
  736. _enter("%s", vlocation->vldb.name);
  737. afs_put_server(op->server);
  738. op->server = NULL;
  739. afs_put_vlocation(vlocation);
  740. _leave("");
  741. } /* end afs_vlocation_update_discard() */
  742. /*****************************************************************************/
  743. /*
  744. * match a VLDB record stored in the cache
  745. * - may also load target from entry
  746. */
  747. #ifdef AFS_CACHING_SUPPORT
  748. static cachefs_match_val_t afs_vlocation_cache_match(void *target,
  749. const void *entry)
  750. {
  751. const struct afs_cache_vlocation *vldb = entry;
  752. struct afs_vlocation *vlocation = target;
  753. _enter("{%s},{%s}", vlocation->vldb.name, vldb->name);
  754. if (strncmp(vlocation->vldb.name, vldb->name, sizeof(vldb->name)) == 0
  755. ) {
  756. if (!vlocation->valid ||
  757. vlocation->vldb.rtime == vldb->rtime
  758. ) {
  759. vlocation->vldb = *vldb;
  760. vlocation->valid = 1;
  761. _leave(" = SUCCESS [c->m]");
  762. return CACHEFS_MATCH_SUCCESS;
  763. }
  764. /* need to update cache if cached info differs */
  765. else if (memcmp(&vlocation->vldb, vldb, sizeof(*vldb)) != 0) {
  766. /* delete if VIDs for this name differ */
  767. if (memcmp(&vlocation->vldb.vid,
  768. &vldb->vid,
  769. sizeof(vldb->vid)) != 0) {
  770. _leave(" = DELETE");
  771. return CACHEFS_MATCH_SUCCESS_DELETE;
  772. }
  773. _leave(" = UPDATE");
  774. return CACHEFS_MATCH_SUCCESS_UPDATE;
  775. }
  776. else {
  777. _leave(" = SUCCESS");
  778. return CACHEFS_MATCH_SUCCESS;
  779. }
  780. }
  781. _leave(" = FAILED");
  782. return CACHEFS_MATCH_FAILED;
  783. } /* end afs_vlocation_cache_match() */
  784. #endif
  785. /*****************************************************************************/
  786. /*
  787. * update a VLDB record stored in the cache
  788. */
  789. #ifdef AFS_CACHING_SUPPORT
  790. static void afs_vlocation_cache_update(void *source, void *entry)
  791. {
  792. struct afs_cache_vlocation *vldb = entry;
  793. struct afs_vlocation *vlocation = source;
  794. _enter("");
  795. *vldb = vlocation->vldb;
  796. } /* end afs_vlocation_cache_update() */
  797. #endif