vlocation.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  1. /* AFS volume location management
  2. *
  3. * Copyright (C) 2002, 2007 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 "internal.h"
  15. unsigned afs_vlocation_timeout = 10; /* volume location timeout in seconds */
  16. unsigned afs_vlocation_update_timeout = 10 * 60;
  17. static void afs_vlocation_reaper(struct work_struct *);
  18. static void afs_vlocation_updater(struct work_struct *);
  19. static LIST_HEAD(afs_vlocation_updates);
  20. static LIST_HEAD(afs_vlocation_graveyard);
  21. static DEFINE_SPINLOCK(afs_vlocation_updates_lock);
  22. static DEFINE_SPINLOCK(afs_vlocation_graveyard_lock);
  23. static DECLARE_DELAYED_WORK(afs_vlocation_reap, afs_vlocation_reaper);
  24. static DECLARE_DELAYED_WORK(afs_vlocation_update, afs_vlocation_updater);
  25. static struct workqueue_struct *afs_vlocation_update_worker;
  26. /*
  27. * iterate through the VL servers in a cell until one of them admits knowing
  28. * about the volume in question
  29. */
  30. static int afs_vlocation_access_vl_by_name(struct afs_vlocation *vl,
  31. struct afs_cache_vlocation *vldb)
  32. {
  33. struct afs_cell *cell = vl->cell;
  34. struct in_addr addr;
  35. int count, ret;
  36. _enter("%s,%s", cell->name, vl->vldb.name);
  37. down_write(&vl->cell->vl_sem);
  38. ret = -ENOMEDIUM;
  39. for (count = cell->vl_naddrs; count > 0; count--) {
  40. addr = cell->vl_addrs[cell->vl_curr_svix];
  41. _debug("CellServ[%hu]: %08x", cell->vl_curr_svix, addr.s_addr);
  42. /* attempt to access the VL server */
  43. ret = afs_vl_get_entry_by_name(&addr, vl->vldb.name, vldb,
  44. &afs_sync_call);
  45. switch (ret) {
  46. case 0:
  47. goto out;
  48. case -ENOMEM:
  49. case -ENONET:
  50. case -ENETUNREACH:
  51. case -EHOSTUNREACH:
  52. case -ECONNREFUSED:
  53. if (ret == -ENOMEM || ret == -ENONET)
  54. goto out;
  55. goto rotate;
  56. case -ENOMEDIUM:
  57. goto out;
  58. default:
  59. ret = -EIO;
  60. goto rotate;
  61. }
  62. /* rotate the server records upon lookup failure */
  63. rotate:
  64. cell->vl_curr_svix++;
  65. cell->vl_curr_svix %= cell->vl_naddrs;
  66. }
  67. out:
  68. up_write(&vl->cell->vl_sem);
  69. _leave(" = %d", ret);
  70. return ret;
  71. }
  72. /*
  73. * iterate through the VL servers in a cell until one of them admits knowing
  74. * about the volume in question
  75. */
  76. static int afs_vlocation_access_vl_by_id(struct afs_vlocation *vl,
  77. afs_volid_t volid,
  78. afs_voltype_t voltype,
  79. struct afs_cache_vlocation *vldb)
  80. {
  81. struct afs_cell *cell = vl->cell;
  82. struct in_addr addr;
  83. int count, ret;
  84. _enter("%s,%x,%d,", cell->name, volid, voltype);
  85. down_write(&vl->cell->vl_sem);
  86. ret = -ENOMEDIUM;
  87. for (count = cell->vl_naddrs; count > 0; count--) {
  88. addr = cell->vl_addrs[cell->vl_curr_svix];
  89. _debug("CellServ[%hu]: %08x", cell->vl_curr_svix, addr.s_addr);
  90. /* attempt to access the VL server */
  91. ret = afs_vl_get_entry_by_id(&addr, volid, voltype, vldb,
  92. &afs_sync_call);
  93. switch (ret) {
  94. case 0:
  95. goto out;
  96. case -ENOMEM:
  97. case -ENONET:
  98. case -ENETUNREACH:
  99. case -EHOSTUNREACH:
  100. case -ECONNREFUSED:
  101. if (ret == -ENOMEM || ret == -ENONET)
  102. goto out;
  103. goto rotate;
  104. case -EBUSY:
  105. vl->upd_busy_cnt++;
  106. if (vl->upd_busy_cnt <= 3) {
  107. if (vl->upd_busy_cnt > 1) {
  108. /* second+ BUSY - sleep a little bit */
  109. set_current_state(TASK_UNINTERRUPTIBLE);
  110. schedule_timeout(1);
  111. __set_current_state(TASK_RUNNING);
  112. }
  113. continue;
  114. }
  115. break;
  116. case -ENOMEDIUM:
  117. vl->upd_rej_cnt++;
  118. goto rotate;
  119. default:
  120. ret = -EIO;
  121. goto rotate;
  122. }
  123. /* rotate the server records upon lookup failure */
  124. rotate:
  125. cell->vl_curr_svix++;
  126. cell->vl_curr_svix %= cell->vl_naddrs;
  127. vl->upd_busy_cnt = 0;
  128. }
  129. out:
  130. if (ret < 0 && vl->upd_rej_cnt > 0) {
  131. printk(KERN_NOTICE "kAFS:"
  132. " Active volume no longer valid '%s'\n",
  133. vl->vldb.name);
  134. vl->valid = 0;
  135. ret = -ENOMEDIUM;
  136. }
  137. up_write(&vl->cell->vl_sem);
  138. _leave(" = %d", ret);
  139. return ret;
  140. }
  141. /*
  142. * allocate a volume location record
  143. */
  144. static struct afs_vlocation *afs_vlocation_alloc(struct afs_cell *cell,
  145. const char *name,
  146. size_t namesz)
  147. {
  148. struct afs_vlocation *vl;
  149. vl = kzalloc(sizeof(struct afs_vlocation), GFP_KERNEL);
  150. if (vl) {
  151. vl->cell = cell;
  152. vl->state = AFS_VL_NEW;
  153. atomic_set(&vl->usage, 1);
  154. INIT_LIST_HEAD(&vl->link);
  155. INIT_LIST_HEAD(&vl->grave);
  156. INIT_LIST_HEAD(&vl->update);
  157. init_waitqueue_head(&vl->waitq);
  158. rwlock_init(&vl->lock);
  159. memcpy(vl->vldb.name, name, namesz);
  160. }
  161. _leave(" = %p", vl);
  162. return vl;
  163. }
  164. /*
  165. * update record if we found it in the cache
  166. */
  167. static int afs_vlocation_update_record(struct afs_vlocation *vl,
  168. struct afs_cache_vlocation *vldb)
  169. {
  170. afs_voltype_t voltype;
  171. afs_volid_t vid;
  172. int ret;
  173. /* try to look up a cached volume in the cell VL databases by ID */
  174. _debug("Locally Cached: %s %02x { %08x(%x) %08x(%x) %08x(%x) }",
  175. vl->vldb.name,
  176. vl->vldb.vidmask,
  177. ntohl(vl->vldb.servers[0].s_addr),
  178. vl->vldb.srvtmask[0],
  179. ntohl(vl->vldb.servers[1].s_addr),
  180. vl->vldb.srvtmask[1],
  181. ntohl(vl->vldb.servers[2].s_addr),
  182. vl->vldb.srvtmask[2]);
  183. _debug("Vids: %08x %08x %08x",
  184. vl->vldb.vid[0],
  185. vl->vldb.vid[1],
  186. vl->vldb.vid[2]);
  187. if (vl->vldb.vidmask & AFS_VOL_VTM_RW) {
  188. vid = vl->vldb.vid[0];
  189. voltype = AFSVL_RWVOL;
  190. } else if (vl->vldb.vidmask & AFS_VOL_VTM_RO) {
  191. vid = vl->vldb.vid[1];
  192. voltype = AFSVL_ROVOL;
  193. } else if (vl->vldb.vidmask & AFS_VOL_VTM_BAK) {
  194. vid = vl->vldb.vid[2];
  195. voltype = AFSVL_BACKVOL;
  196. } else {
  197. BUG();
  198. vid = 0;
  199. voltype = 0;
  200. }
  201. /* contact the server to make sure the volume is still available
  202. * - TODO: need to handle disconnected operation here
  203. */
  204. ret = afs_vlocation_access_vl_by_id(vl, vid, voltype, vldb);
  205. switch (ret) {
  206. /* net error */
  207. default:
  208. printk(KERN_WARNING "kAFS:"
  209. " failed to update volume '%s' (%x) up in '%s': %d\n",
  210. vl->vldb.name, vid, vl->cell->name, ret);
  211. _leave(" = %d", ret);
  212. return ret;
  213. /* pulled from local cache into memory */
  214. case 0:
  215. _leave(" = 0");
  216. return 0;
  217. /* uh oh... looks like the volume got deleted */
  218. case -ENOMEDIUM:
  219. printk(KERN_ERR "kAFS:"
  220. " volume '%s' (%x) does not exist '%s'\n",
  221. vl->vldb.name, vid, vl->cell->name);
  222. /* TODO: make existing record unavailable */
  223. _leave(" = %d", ret);
  224. return ret;
  225. }
  226. }
  227. /*
  228. * apply the update to a VL record
  229. */
  230. static void afs_vlocation_apply_update(struct afs_vlocation *vl,
  231. struct afs_cache_vlocation *vldb)
  232. {
  233. _debug("Done VL Lookup: %s %02x { %08x(%x) %08x(%x) %08x(%x) }",
  234. vldb->name, vldb->vidmask,
  235. ntohl(vldb->servers[0].s_addr), vldb->srvtmask[0],
  236. ntohl(vldb->servers[1].s_addr), vldb->srvtmask[1],
  237. ntohl(vldb->servers[2].s_addr), vldb->srvtmask[2]);
  238. _debug("Vids: %08x %08x %08x",
  239. vldb->vid[0], vldb->vid[1], vldb->vid[2]);
  240. if (strcmp(vldb->name, vl->vldb.name) != 0)
  241. printk(KERN_NOTICE "kAFS:"
  242. " name of volume '%s' changed to '%s' on server\n",
  243. vl->vldb.name, vldb->name);
  244. vl->vldb = *vldb;
  245. #ifdef AFS_CACHING_SUPPORT
  246. /* update volume entry in local cache */
  247. cachefs_update_cookie(vl->cache);
  248. #endif
  249. }
  250. /*
  251. * fill in a volume location record, consulting the cache and the VL server
  252. * both
  253. */
  254. static int afs_vlocation_fill_in_record(struct afs_vlocation *vl)
  255. {
  256. struct afs_cache_vlocation vldb;
  257. int ret;
  258. _enter("");
  259. ASSERTCMP(vl->valid, ==, 0);
  260. memset(&vldb, 0, sizeof(vldb));
  261. /* see if we have an in-cache copy (will set vl->valid if there is) */
  262. #ifdef AFS_CACHING_SUPPORT
  263. cachefs_acquire_cookie(cell->cache,
  264. &afs_volume_cache_index_def,
  265. vlocation,
  266. &vl->cache);
  267. #endif
  268. if (vl->valid) {
  269. /* try to update a known volume in the cell VL databases by
  270. * ID as the name may have changed */
  271. _debug("found in cache");
  272. ret = afs_vlocation_update_record(vl, &vldb);
  273. } else {
  274. /* try to look up an unknown volume in the cell VL databases by
  275. * name */
  276. ret = afs_vlocation_access_vl_by_name(vl, &vldb);
  277. if (ret < 0) {
  278. printk("kAFS: failed to locate '%s' in cell '%s'\n",
  279. vl->vldb.name, vl->cell->name);
  280. return ret;
  281. }
  282. }
  283. afs_vlocation_apply_update(vl, &vldb);
  284. _leave(" = 0");
  285. return 0;
  286. }
  287. /*
  288. * queue a vlocation record for updates
  289. */
  290. void afs_vlocation_queue_for_updates(struct afs_vlocation *vl)
  291. {
  292. struct afs_vlocation *xvl;
  293. /* wait at least 10 minutes before updating... */
  294. vl->update_at = get_seconds() + afs_vlocation_update_timeout;
  295. spin_lock(&afs_vlocation_updates_lock);
  296. if (!list_empty(&afs_vlocation_updates)) {
  297. /* ... but wait at least 1 second more than the newest record
  298. * already queued so that we don't spam the VL server suddenly
  299. * with lots of requests
  300. */
  301. xvl = list_entry(afs_vlocation_updates.prev,
  302. struct afs_vlocation, update);
  303. if (vl->update_at <= xvl->update_at)
  304. vl->update_at = xvl->update_at + 1;
  305. } else {
  306. queue_delayed_work(afs_vlocation_update_worker,
  307. &afs_vlocation_update,
  308. afs_vlocation_update_timeout * HZ);
  309. }
  310. list_add_tail(&vl->update, &afs_vlocation_updates);
  311. spin_unlock(&afs_vlocation_updates_lock);
  312. }
  313. /*
  314. * lookup volume location
  315. * - iterate through the VL servers in a cell until one of them admits knowing
  316. * about the volume in question
  317. * - lookup in the local cache if not able to find on the VL server
  318. * - insert/update in the local cache if did get a VL response
  319. */
  320. struct afs_vlocation *afs_vlocation_lookup(struct afs_cell *cell,
  321. const char *name,
  322. size_t namesz)
  323. {
  324. struct afs_vlocation *vl;
  325. int ret;
  326. _enter("{%s},%*.*s,%zu",
  327. cell->name, (int) namesz, (int) namesz, name, namesz);
  328. if (namesz > sizeof(vl->vldb.name)) {
  329. _leave(" = -ENAMETOOLONG");
  330. return ERR_PTR(-ENAMETOOLONG);
  331. }
  332. /* see if we have an in-memory copy first */
  333. down_write(&cell->vl_sem);
  334. spin_lock(&cell->vl_lock);
  335. list_for_each_entry(vl, &cell->vl_list, link) {
  336. if (vl->vldb.name[namesz] != '\0')
  337. continue;
  338. if (memcmp(vl->vldb.name, name, namesz) == 0)
  339. goto found_in_memory;
  340. }
  341. spin_unlock(&cell->vl_lock);
  342. /* not in the cell's in-memory lists - create a new record */
  343. vl = afs_vlocation_alloc(cell, name, namesz);
  344. if (!vl) {
  345. up_write(&cell->vl_sem);
  346. return ERR_PTR(-ENOMEM);
  347. }
  348. afs_get_cell(cell);
  349. list_add_tail(&vl->link, &cell->vl_list);
  350. vl->state = AFS_VL_CREATING;
  351. up_write(&cell->vl_sem);
  352. fill_in_record:
  353. ret = afs_vlocation_fill_in_record(vl);
  354. if (ret < 0)
  355. goto error_abandon;
  356. vl->state = AFS_VL_VALID;
  357. wake_up(&vl->waitq);
  358. /* schedule for regular updates */
  359. afs_vlocation_queue_for_updates(vl);
  360. goto success;
  361. found_in_memory:
  362. /* found in memory */
  363. _debug("found in memory");
  364. atomic_inc(&vl->usage);
  365. spin_unlock(&cell->vl_lock);
  366. if (!list_empty(&vl->grave)) {
  367. spin_lock(&afs_vlocation_graveyard_lock);
  368. list_del_init(&vl->grave);
  369. spin_unlock(&afs_vlocation_graveyard_lock);
  370. }
  371. up_write(&cell->vl_sem);
  372. /* see if it was an abandoned record that we might try filling in */
  373. while (vl->state != AFS_VL_VALID) {
  374. afs_vlocation_state_t state = vl->state;
  375. _debug("invalid [state %d]", state);
  376. if ((state == AFS_VL_NEW || state == AFS_VL_NO_VOLUME)) {
  377. if (cmpxchg(&vl->state, state, AFS_VL_CREATING) ==
  378. state)
  379. goto fill_in_record;
  380. continue;
  381. }
  382. /* must now wait for creation or update by someone else to
  383. * complete */
  384. _debug("wait");
  385. ret = wait_event_interruptible(
  386. vl->waitq,
  387. vl->state == AFS_VL_NEW ||
  388. vl->state == AFS_VL_VALID ||
  389. vl->state == AFS_VL_NO_VOLUME);
  390. if (ret < 0)
  391. goto error;
  392. }
  393. success:
  394. _leave(" = %p",vl);
  395. return vl;
  396. error_abandon:
  397. vl->state = AFS_VL_NEW;
  398. wake_up(&vl->waitq);
  399. error:
  400. ASSERT(vl != NULL);
  401. afs_put_vlocation(vl);
  402. _leave(" = %d", ret);
  403. return ERR_PTR(ret);
  404. }
  405. /*
  406. * finish using a volume location record
  407. */
  408. void afs_put_vlocation(struct afs_vlocation *vl)
  409. {
  410. if (!vl)
  411. return;
  412. _enter("%s", vl->vldb.name);
  413. ASSERTCMP(atomic_read(&vl->usage), >, 0);
  414. if (likely(!atomic_dec_and_test(&vl->usage))) {
  415. _leave("");
  416. return;
  417. }
  418. spin_lock(&afs_vlocation_graveyard_lock);
  419. if (atomic_read(&vl->usage) == 0) {
  420. _debug("buried");
  421. list_move_tail(&vl->grave, &afs_vlocation_graveyard);
  422. vl->time_of_death = get_seconds();
  423. schedule_delayed_work(&afs_vlocation_reap,
  424. afs_vlocation_timeout * HZ);
  425. /* suspend updates on this record */
  426. if (!list_empty(&vl->update)) {
  427. spin_lock(&afs_vlocation_updates_lock);
  428. list_del_init(&vl->update);
  429. spin_unlock(&afs_vlocation_updates_lock);
  430. }
  431. }
  432. spin_unlock(&afs_vlocation_graveyard_lock);
  433. _leave(" [killed?]");
  434. }
  435. /*
  436. * destroy a dead volume location record
  437. */
  438. static void afs_vlocation_destroy(struct afs_vlocation *vl)
  439. {
  440. _enter("%p", vl);
  441. #ifdef AFS_CACHING_SUPPORT
  442. cachefs_relinquish_cookie(vl->cache, 0);
  443. #endif
  444. afs_put_cell(vl->cell);
  445. kfree(vl);
  446. }
  447. /*
  448. * reap dead volume location records
  449. */
  450. static void afs_vlocation_reaper(struct work_struct *work)
  451. {
  452. LIST_HEAD(corpses);
  453. struct afs_vlocation *vl;
  454. unsigned long delay, expiry;
  455. time_t now;
  456. _enter("");
  457. now = get_seconds();
  458. spin_lock(&afs_vlocation_graveyard_lock);
  459. while (!list_empty(&afs_vlocation_graveyard)) {
  460. vl = list_entry(afs_vlocation_graveyard.next,
  461. struct afs_vlocation, grave);
  462. _debug("check %p", vl);
  463. /* the queue is ordered most dead first */
  464. expiry = vl->time_of_death + afs_vlocation_timeout;
  465. if (expiry > now) {
  466. delay = (expiry - now) * HZ;
  467. _debug("delay %lu", delay);
  468. if (!schedule_delayed_work(&afs_vlocation_reap,
  469. delay)) {
  470. cancel_delayed_work(&afs_vlocation_reap);
  471. schedule_delayed_work(&afs_vlocation_reap,
  472. delay);
  473. }
  474. break;
  475. }
  476. spin_lock(&vl->cell->vl_lock);
  477. if (atomic_read(&vl->usage) > 0) {
  478. _debug("no reap");
  479. list_del_init(&vl->grave);
  480. } else {
  481. _debug("reap");
  482. list_move_tail(&vl->grave, &corpses);
  483. list_del_init(&vl->link);
  484. }
  485. spin_unlock(&vl->cell->vl_lock);
  486. }
  487. spin_unlock(&afs_vlocation_graveyard_lock);
  488. /* now reap the corpses we've extracted */
  489. while (!list_empty(&corpses)) {
  490. vl = list_entry(corpses.next, struct afs_vlocation, grave);
  491. list_del(&vl->grave);
  492. afs_vlocation_destroy(vl);
  493. }
  494. _leave("");
  495. }
  496. /*
  497. * initialise the VL update process
  498. */
  499. int __init afs_vlocation_update_init(void)
  500. {
  501. afs_vlocation_update_worker =
  502. create_singlethread_workqueue("kafs_vlupdated");
  503. return afs_vlocation_update_worker ? 0 : -ENOMEM;
  504. }
  505. /*
  506. * discard all the volume location records for rmmod
  507. */
  508. void __exit afs_vlocation_purge(void)
  509. {
  510. afs_vlocation_timeout = 0;
  511. spin_lock(&afs_vlocation_updates_lock);
  512. list_del_init(&afs_vlocation_updates);
  513. spin_unlock(&afs_vlocation_updates_lock);
  514. cancel_delayed_work(&afs_vlocation_update);
  515. queue_delayed_work(afs_vlocation_update_worker,
  516. &afs_vlocation_update, 0);
  517. destroy_workqueue(afs_vlocation_update_worker);
  518. cancel_delayed_work(&afs_vlocation_reap);
  519. schedule_delayed_work(&afs_vlocation_reap, 0);
  520. }
  521. /*
  522. * update a volume location
  523. */
  524. static void afs_vlocation_updater(struct work_struct *work)
  525. {
  526. struct afs_cache_vlocation vldb;
  527. struct afs_vlocation *vl, *xvl;
  528. time_t now;
  529. long timeout;
  530. int ret;
  531. _enter("");
  532. now = get_seconds();
  533. /* find a record to update */
  534. spin_lock(&afs_vlocation_updates_lock);
  535. for (;;) {
  536. if (list_empty(&afs_vlocation_updates)) {
  537. spin_unlock(&afs_vlocation_updates_lock);
  538. _leave(" [nothing]");
  539. return;
  540. }
  541. vl = list_entry(afs_vlocation_updates.next,
  542. struct afs_vlocation, update);
  543. if (atomic_read(&vl->usage) > 0)
  544. break;
  545. list_del_init(&vl->update);
  546. }
  547. timeout = vl->update_at - now;
  548. if (timeout > 0) {
  549. queue_delayed_work(afs_vlocation_update_worker,
  550. &afs_vlocation_update, timeout * HZ);
  551. spin_unlock(&afs_vlocation_updates_lock);
  552. _leave(" [nothing]");
  553. return;
  554. }
  555. list_del_init(&vl->update);
  556. atomic_inc(&vl->usage);
  557. spin_unlock(&afs_vlocation_updates_lock);
  558. /* we can now perform the update */
  559. _debug("update %s", vl->vldb.name);
  560. vl->state = AFS_VL_UPDATING;
  561. vl->upd_rej_cnt = 0;
  562. vl->upd_busy_cnt = 0;
  563. ret = afs_vlocation_update_record(vl, &vldb);
  564. switch (ret) {
  565. case 0:
  566. afs_vlocation_apply_update(vl, &vldb);
  567. vl->state = AFS_VL_VALID;
  568. break;
  569. case -ENOMEDIUM:
  570. vl->state = AFS_VL_VOLUME_DELETED;
  571. break;
  572. default:
  573. vl->state = AFS_VL_UNCERTAIN;
  574. break;
  575. }
  576. /* and then reschedule */
  577. _debug("reschedule");
  578. vl->update_at = get_seconds() + afs_vlocation_update_timeout;
  579. spin_lock(&afs_vlocation_updates_lock);
  580. if (!list_empty(&afs_vlocation_updates)) {
  581. /* next update in 10 minutes, but wait at least 1 second more
  582. * than the newest record already queued so that we don't spam
  583. * the VL server suddenly with lots of requests
  584. */
  585. xvl = list_entry(afs_vlocation_updates.prev,
  586. struct afs_vlocation, update);
  587. if (vl->update_at <= xvl->update_at)
  588. vl->update_at = xvl->update_at + 1;
  589. xvl = list_entry(afs_vlocation_updates.next,
  590. struct afs_vlocation, update);
  591. timeout = xvl->update_at - now;
  592. if (timeout < 0)
  593. timeout = 0;
  594. } else {
  595. timeout = afs_vlocation_update_timeout;
  596. }
  597. ASSERT(list_empty(&vl->update));
  598. list_add_tail(&vl->update, &afs_vlocation_updates);
  599. _debug("timeout %ld", timeout);
  600. queue_delayed_work(afs_vlocation_update_worker,
  601. &afs_vlocation_update, timeout * HZ);
  602. spin_unlock(&afs_vlocation_updates_lock);
  603. afs_put_vlocation(vl);
  604. }