vlocation.c 18 KB

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