Pull one more egcs 1.1.2 workaround.
[linux-2.6/linux-mips.git] / fs / afs / vlocation.c
blob8d9f4d7e8f2935a4a6c0a697631a51d0efdd39d0
1 /* vlocation.c: volume location management
3 * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
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.
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/slab.h>
16 #include <linux/fs.h>
17 #include <linux/pagemap.h>
18 #include "volume.h"
19 #include "cell.h"
20 #include "cmservice.h"
21 #include "fsclient.h"
22 #include "vlclient.h"
23 #include "kafstimod.h"
24 #include <rxrpc/connection.h>
25 #include "internal.h"
27 #define AFS_VLDB_TIMEOUT HZ*1000
29 static void afs_vlocation_update_timer(afs_timer_t *timer);
30 static void afs_vlocation_update_attend(afs_async_op_t *op);
31 static void afs_vlocation_update_discard(afs_async_op_t *op);
33 static void __afs_vlocation_timeout(afs_timer_t *timer)
35 afs_vlocation_t *vlocation = list_entry(timer,afs_vlocation_t,timeout);
37 _debug("VL TIMEOUT [%s{u=%d}]",vlocation->vldb.name,atomic_read(&vlocation->usage));
39 afs_vlocation_do_timeout(vlocation);
42 static const struct afs_timer_ops afs_vlocation_timer_ops = {
43 .timed_out = __afs_vlocation_timeout,
46 static const struct afs_timer_ops afs_vlocation_update_timer_ops = {
47 .timed_out = afs_vlocation_update_timer,
50 static const struct afs_async_op_ops afs_vlocation_update_op_ops = {
51 .attend = afs_vlocation_update_attend,
52 .discard = afs_vlocation_update_discard,
55 static LIST_HEAD(afs_vlocation_update_pendq); /* queue of VLs awaiting update */
56 static afs_vlocation_t *afs_vlocation_update; /* VL currently being updated */
57 static spinlock_t afs_vlocation_update_lock = SPIN_LOCK_UNLOCKED; /* lock guarding update queue */
59 /*****************************************************************************/
61 * iterate through the VL servers in a cell until one of them admits knowing about the volume in
62 * question
63 * - caller must have cell->vl_sem write-locked
65 static int afs_vlocation_access_vl_by_name(afs_vlocation_t *vlocation,
66 const char *name,
67 afsc_vldb_record_t *vldb)
69 afs_server_t *server = NULL;
70 afs_cell_t *cell = vlocation->cell;
71 int count, ret;
73 _enter("%s,%s,",cell->name,name);
75 ret = -ENOMEDIUM;
76 for (count=cell->vl_naddrs; count>0; count--) {
77 _debug("CellServ[%hu]: %08x",
78 cell->vl_curr_svix,cell->vl_addrs[cell->vl_curr_svix].s_addr);
80 /* try and create a server */
81 ret = afs_server_lookup(cell,&cell->vl_addrs[cell->vl_curr_svix],&server);
82 switch (ret) {
83 case 0:
84 break;
85 case -ENOMEM:
86 case -ENONET:
87 goto out;
88 default:
89 goto rotate;
92 /* attempt to access the VL server */
93 ret = afs_rxvl_get_entry_by_name(server,name,vldb);
94 switch (ret) {
95 case 0:
96 afs_put_server(server);
97 goto out;
98 case -ENOMEM:
99 case -ENONET:
100 case -ENETUNREACH:
101 case -EHOSTUNREACH:
102 case -ECONNREFUSED:
103 down_write(&server->sem);
104 if (server->vlserver) {
105 rxrpc_put_connection(server->vlserver);
106 server->vlserver = NULL;
108 up_write(&server->sem);
109 afs_put_server(server);
110 if (ret==-ENOMEM || ret==-ENONET)
111 goto out;
112 goto rotate;
113 case -ENOMEDIUM:
114 afs_put_server(server);
115 goto out;
116 default:
117 afs_put_server(server);
118 ret = -ENOMEDIUM;
119 goto rotate;
122 /* rotate the server records upon lookup failure */
123 rotate:
124 cell->vl_curr_svix++;
125 cell->vl_curr_svix %= cell->vl_naddrs;
128 out:
129 _leave(" = %d",ret);
130 return ret;
132 } /* end afs_vlocation_access_vl_by_name() */
134 /*****************************************************************************/
136 * iterate through the VL servers in a cell until one of them admits knowing about the volume in
137 * question
138 * - caller must have cell->vl_sem write-locked
140 static int afs_vlocation_access_vl_by_id(afs_vlocation_t *vlocation,
141 afs_volid_t volid,
142 afs_voltype_t voltype,
143 afsc_vldb_record_t *vldb)
145 afs_server_t *server = NULL;
146 afs_cell_t *cell = vlocation->cell;
147 int count, ret;
149 _enter("%s,%x,%d,",cell->name,volid,voltype);
151 ret = -ENOMEDIUM;
152 for (count=cell->vl_naddrs; count>0; count--) {
153 _debug("CellServ[%hu]: %08x",
154 cell->vl_curr_svix,cell->vl_addrs[cell->vl_curr_svix].s_addr);
156 /* try and create a server */
157 ret = afs_server_lookup(cell,&cell->vl_addrs[cell->vl_curr_svix],&server);
158 switch (ret) {
159 case 0:
160 break;
161 case -ENOMEM:
162 case -ENONET:
163 goto out;
164 default:
165 goto rotate;
168 /* attempt to access the VL server */
169 ret = afs_rxvl_get_entry_by_id(server,volid,voltype,vldb);
170 switch (ret) {
171 case 0:
172 afs_put_server(server);
173 goto out;
174 case -ENOMEM:
175 case -ENONET:
176 case -ENETUNREACH:
177 case -EHOSTUNREACH:
178 case -ECONNREFUSED:
179 down_write(&server->sem);
180 if (server->vlserver) {
181 rxrpc_put_connection(server->vlserver);
182 server->vlserver = NULL;
184 up_write(&server->sem);
185 afs_put_server(server);
186 if (ret==-ENOMEM || ret==-ENONET)
187 goto out;
188 goto rotate;
189 case -ENOMEDIUM:
190 afs_put_server(server);
191 goto out;
192 default:
193 afs_put_server(server);
194 ret = -ENOMEDIUM;
195 goto rotate;
198 /* rotate the server records upon lookup failure */
199 rotate:
200 cell->vl_curr_svix++;
201 cell->vl_curr_svix %= cell->vl_naddrs;
204 out:
205 _leave(" = %d",ret);
206 return ret;
208 } /* end afs_vlocation_access_vl_by_id() */
210 /*****************************************************************************/
212 * lookup volume location
213 * - caller must have cell->vol_sem write-locked
214 * - iterate through the VL servers in a cell until one of them admits knowing about the volume in
215 * question
216 * - lookup in the local cache if not able to find on the VL server
217 * - insert/update in the local cache if did get a VL response
219 int afs_vlocation_lookup(afs_cell_t *cell, const char *name, afs_vlocation_t **_vlocation)
221 afsc_vldb_record_t vldb;
222 struct list_head *_p;
223 afs_vlocation_t *vlocation;
224 afs_voltype_t voltype;
225 afs_volid_t vid;
226 int active = 0, ret;
228 _enter(",%s,%s,",cell->name,name);
230 if (strlen(name)>sizeof(vlocation->vldb.name)) {
231 _leave(" = -ENAMETOOLONG");
232 return -ENAMETOOLONG;
235 /* search the cell's active list first */
236 list_for_each(_p,&cell->vl_list) {
237 vlocation = list_entry(_p,afs_vlocation_t,link);
238 if (strncmp(vlocation->vldb.name,name,sizeof(vlocation->vldb.name))==0)
239 goto found_in_memory;
242 /* search the cell's graveyard list second */
243 spin_lock(&cell->vl_gylock);
244 list_for_each(_p,&cell->vl_graveyard) {
245 vlocation = list_entry(_p,afs_vlocation_t,link);
246 if (strncmp(vlocation->vldb.name,name,sizeof(vlocation->vldb.name))==0)
247 goto found_in_graveyard;
249 spin_unlock(&cell->vl_gylock);
251 /* not in the cell's in-memory lists - create a new record */
252 vlocation = kmalloc(sizeof(afs_vlocation_t),GFP_KERNEL);
253 if (!vlocation)
254 return -ENOMEM;
256 memset(vlocation,0,sizeof(afs_vlocation_t));
257 atomic_set(&vlocation->usage,1);
258 INIT_LIST_HEAD(&vlocation->link);
259 rwlock_init(&vlocation->lock);
260 strncpy(vlocation->vldb.name,name,sizeof(vlocation->vldb.name));
262 afs_timer_init(&vlocation->timeout,&afs_vlocation_timer_ops);
263 afs_timer_init(&vlocation->upd_timer,&afs_vlocation_update_timer_ops);
264 afs_async_op_init(&vlocation->upd_op,&afs_vlocation_update_op_ops);
266 INIT_LIST_HEAD(&vlocation->caches);
268 afs_get_cell(cell);
269 vlocation->cell = cell;
271 list_add_tail(&vlocation->link,&cell->vl_list);
273 #if 0
274 /* search local cache if wasn't in memory */
275 ret = afsc_lookup_vlocation(vlocation);
276 switch (ret) {
277 default: goto error; /* disk error */
278 case 0: goto found_in_cache; /* pulled from local cache into memory */
279 case -ENOENT: break; /* not in local cache */
281 #endif
283 /* try to look up an unknown volume in the cell VL databases by name */
284 ret = afs_vlocation_access_vl_by_name(vlocation,name,&vldb);
285 if (ret<0) {
286 printk("kAFS: failed to locate '%s' in cell '%s'\n",name,cell->name);
287 goto error;
290 goto found_on_vlserver;
292 found_in_graveyard:
293 /* found in the graveyard - resurrect */
294 _debug("found in graveyard");
295 atomic_inc(&vlocation->usage);
296 list_del(&vlocation->link);
297 list_add_tail(&vlocation->link,&cell->vl_list);
298 spin_unlock(&cell->vl_gylock);
300 afs_kafstimod_del_timer(&vlocation->timeout);
301 goto active;
303 found_in_memory:
304 /* found in memory - check to see if it's active */
305 _debug("found in memory");
306 atomic_inc(&vlocation->usage);
308 active:
309 active = 1;
311 /* found_in_cache: */
312 /* try to look up a cached volume in the cell VL databases by ID */
313 _debug("found in cache");
315 _debug("Locally Cached: %s %02x { %08x(%x) %08x(%x) %08x(%x) }",
316 vlocation->vldb.name,
317 vlocation->vldb.vidmask,
318 ntohl(vlocation->vldb.servers[0].s_addr),vlocation->vldb.srvtmask[0],
319 ntohl(vlocation->vldb.servers[1].s_addr),vlocation->vldb.srvtmask[1],
320 ntohl(vlocation->vldb.servers[2].s_addr),vlocation->vldb.srvtmask[2]
323 _debug("Vids: %08x %08x %08x",
324 vlocation->vldb.vid[0],vlocation->vldb.vid[1],vlocation->vldb.vid[2]);
326 if (vlocation->vldb.vidmask & AFSC_VOL_STM_RW) {
327 vid = vlocation->vldb.vid[0];
328 voltype = AFSVL_RWVOL;
330 else if (vlocation->vldb.vidmask & AFSC_VOL_STM_RO) {
331 vid = vlocation->vldb.vid[1];
332 voltype = AFSVL_ROVOL;
334 else if (vlocation->vldb.vidmask & AFSC_VOL_STM_BAK) {
335 vid = vlocation->vldb.vid[2];
336 voltype = AFSVL_BACKVOL;
338 else {
339 BUG();
340 vid = 0;
341 voltype = 0;
344 ret = afs_vlocation_access_vl_by_id(vlocation,vid,voltype,&vldb);
345 switch (ret) {
346 /* net error */
347 default:
348 printk("kAFS: failed to volume '%s' (%x) up in '%s': %d\n",
349 name,vid,cell->name,ret);
350 goto error;
352 /* pulled from local cache into memory */
353 case 0:
354 goto found_on_vlserver;
356 /* uh oh... looks like the volume got deleted */
357 case -ENOMEDIUM:
358 printk("kAFS: volume '%s' (%x) does not exist '%s'\n",name,vid,cell->name);
360 /* TODO: make existing record unavailable */
361 goto error;
364 found_on_vlserver:
365 _debug("Done VL Lookup: %s %02x { %08x(%x) %08x(%x) %08x(%x) }",
366 name,
367 vldb.vidmask,
368 ntohl(vldb.servers[0].s_addr),vldb.srvtmask[0],
369 ntohl(vldb.servers[1].s_addr),vldb.srvtmask[1],
370 ntohl(vldb.servers[2].s_addr),vldb.srvtmask[2]
373 _debug("Vids: %08x %08x %08x",vldb.vid[0],vldb.vid[1],vldb.vid[2]);
375 if (strncmp(vldb.name,name,sizeof(vlocation->vldb.name))!=0)
376 printk("kAFS: name of volume '%s' changed to '%s' on server\n",name,vldb.name);
378 memcpy(&vlocation->vldb,&vldb,sizeof(vlocation->vldb));
380 #if 0
381 /* add volume entry to local cache */
382 ret = afsc_update_vlocation(vlocation);
383 if (ret<0)
384 goto error;
385 #endif
387 afs_kafstimod_add_timer(&vlocation->upd_timer,10*HZ);
389 *_vlocation = vlocation;
390 _leave(" = 0 (%p)",vlocation);
391 return 0;
393 error:
394 if (vlocation) {
395 if (active) {
396 __afs_put_vlocation(vlocation);
398 else {
399 list_del(&vlocation->link);
400 afs_put_cell(vlocation->cell);
401 #if 0
402 afs_put_cache(vlocation->cache);
403 #endif
404 kfree(vlocation);
408 _leave(" = %d",ret);
409 return ret;
410 } /* end afs_vlocation_lookup() */
412 /*****************************************************************************/
414 * finish using a volume location record
415 * - caller must have cell->vol_sem write-locked
417 void __afs_put_vlocation(afs_vlocation_t *vlocation)
419 afs_cell_t *cell = vlocation->cell;
421 _enter("%s",vlocation->vldb.name);
423 /* sanity check */
424 if (atomic_read(&vlocation->usage)<=0)
425 BUG();
427 spin_lock(&cell->vl_gylock);
428 if (likely(!atomic_dec_and_test(&vlocation->usage))) {
429 spin_unlock(&cell->vl_gylock);
430 _leave("");
431 return;
434 /* move to graveyard queue */
435 list_del(&vlocation->link);
436 list_add_tail(&vlocation->link,&cell->vl_graveyard);
438 /* remove from pending timeout queue (refcounted if actually being updated) */
439 list_del_init(&vlocation->upd_op.link);
441 /* time out in 10 secs */
442 afs_kafstimod_del_timer(&vlocation->upd_timer);
443 afs_kafstimod_add_timer(&vlocation->timeout,10*HZ);
445 spin_unlock(&cell->vl_gylock);
447 _leave(" [killed]");
448 } /* end __afs_put_vlocation() */
450 /*****************************************************************************/
452 * finish using a volume location record
454 void afs_put_vlocation(afs_vlocation_t *vlocation)
456 afs_cell_t *cell = vlocation->cell;
458 down_write(&cell->vl_sem);
459 __afs_put_vlocation(vlocation);
460 up_write(&cell->vl_sem);
461 } /* end afs_put_vlocation() */
463 /*****************************************************************************/
465 * timeout vlocation record
466 * - removes from the cell's graveyard if the usage count is zero
468 void afs_vlocation_do_timeout(afs_vlocation_t *vlocation)
470 afs_cell_t *cell;
472 _enter("%s",vlocation->vldb.name);
474 cell = vlocation->cell;
476 if (atomic_read(&vlocation->usage)<0) BUG();
478 /* remove from graveyard if still dead */
479 spin_lock(&cell->vl_gylock);
480 if (atomic_read(&vlocation->usage)==0)
481 list_del_init(&vlocation->link);
482 else
483 vlocation = NULL;
484 spin_unlock(&cell->vl_gylock);
486 if (!vlocation) {
487 _leave("");
488 return; /* resurrected */
491 /* we can now destroy it properly */
492 afs_put_cell(cell);
493 #if 0
494 afs_put_cache(vlocation->cache);
495 #endif
497 kfree(vlocation);
499 _leave(" [destroyed]");
500 } /* end afs_vlocation_do_timeout() */
502 /*****************************************************************************/
504 * send an update operation to the currently selected server
506 static int afs_vlocation_update_begin(afs_vlocation_t *vlocation)
508 afs_voltype_t voltype;
509 afs_volid_t vid;
510 int ret;
512 _enter("%s{ufs=%u ucs=%u}",
513 vlocation->vldb.name,vlocation->upd_first_svix,vlocation->upd_curr_svix);
515 /* try to look up a cached volume in the cell VL databases by ID */
516 if (vlocation->vldb.vidmask & AFSC_VOL_STM_RW) {
517 vid = vlocation->vldb.vid[0];
518 voltype = AFSVL_RWVOL;
520 else if (vlocation->vldb.vidmask & AFSC_VOL_STM_RO) {
521 vid = vlocation->vldb.vid[1];
522 voltype = AFSVL_ROVOL;
524 else if (vlocation->vldb.vidmask & AFSC_VOL_STM_BAK) {
525 vid = vlocation->vldb.vid[2];
526 voltype = AFSVL_BACKVOL;
528 else {
529 BUG();
530 vid = 0;
531 voltype = 0;
534 /* contact the chosen server */
535 ret = afs_server_lookup(vlocation->cell,
536 &vlocation->cell->vl_addrs[vlocation->upd_curr_svix],
537 &vlocation->upd_op.server);
538 switch (ret) {
539 case 0:
540 break;
541 case -ENOMEM:
542 case -ENONET:
543 default:
544 _leave(" = %d",ret);
545 return ret;
548 /* initiate the update operation */
549 ret = afs_rxvl_get_entry_by_id_async(&vlocation->upd_op,vid,voltype);
550 if (ret<0) {
551 _leave(" = %d",ret);
552 return ret;
555 _leave(" = %d",ret);
556 return ret;
557 } /* end afs_vlocation_update_begin() */
559 /*****************************************************************************/
561 * abandon updating a VL record
562 * - does not restart the update timer
564 static void afs_vlocation_update_abandon(afs_vlocation_t *vlocation,
565 afs_vlocation_upd_t state,
566 int ret)
568 _enter("%s,%u",vlocation->vldb.name,state);
570 if (ret<0)
571 printk("kAFS: Abandoning VL update '%s': %d\n",vlocation->vldb.name,ret);
573 /* discard the server record */
574 if (vlocation->upd_op.server) {
575 afs_put_server(vlocation->upd_op.server);
576 vlocation->upd_op.server = NULL;
579 spin_lock(&afs_vlocation_update_lock);
580 afs_vlocation_update = NULL;
581 vlocation->upd_state = state;
583 /* TODO: start updating next VL record on pending list */
585 spin_unlock(&afs_vlocation_update_lock);
587 _leave("");
588 } /* end afs_vlocation_update_abandon() */
590 /*****************************************************************************/
592 * handle periodic update timeouts and busy retry timeouts
593 * - called from kafstimod
595 static void afs_vlocation_update_timer(afs_timer_t *timer)
597 afs_vlocation_t *vlocation = list_entry(timer,afs_vlocation_t,upd_timer);
598 int ret;
600 _enter("%s",vlocation->vldb.name);
602 /* only update if not in the graveyard (defend against putting too) */
603 spin_lock(&vlocation->cell->vl_gylock);
605 if (!atomic_read(&vlocation->usage))
606 goto out_unlock1;
608 spin_lock(&afs_vlocation_update_lock);
610 /* if we were woken up due to EBUSY sleep then restart immediately if possible or else jump
611 * to front of pending queue */
612 if (vlocation->upd_state==AFS_VLUPD_BUSYSLEEP) {
613 if (afs_vlocation_update) {
614 list_add(&vlocation->upd_op.link,&afs_vlocation_update_pendq);
616 else {
617 afs_get_vlocation(vlocation);
618 afs_vlocation_update = vlocation;
619 vlocation->upd_state = AFS_VLUPD_INPROGRESS;
621 goto out_unlock2;
624 /* put on pending queue if there's already another update in progress */
625 if (afs_vlocation_update) {
626 vlocation->upd_state = AFS_VLUPD_PENDING;
627 list_add_tail(&vlocation->upd_op.link,&afs_vlocation_update_pendq);
628 goto out_unlock2;
631 /* hold a ref on it while actually updating */
632 afs_get_vlocation(vlocation);
633 afs_vlocation_update = vlocation;
634 vlocation->upd_state = AFS_VLUPD_INPROGRESS;
636 spin_unlock(&afs_vlocation_update_lock);
637 spin_unlock(&vlocation->cell->vl_gylock);
639 /* okay... we can start the update */
640 _debug("BEGIN VL UPDATE [%s]",vlocation->vldb.name);
641 vlocation->upd_first_svix = vlocation->cell->vl_curr_svix;
642 vlocation->upd_curr_svix = vlocation->upd_first_svix;
643 vlocation->upd_rej_cnt = 0;
644 vlocation->upd_busy_cnt = 0;
646 ret = afs_vlocation_update_begin(vlocation);
647 if (ret<0) {
648 afs_vlocation_update_abandon(vlocation,AFS_VLUPD_SLEEP,ret);
649 afs_kafstimod_add_timer(&vlocation->upd_timer,AFS_VLDB_TIMEOUT);
650 afs_put_vlocation(vlocation);
653 _leave("");
654 return;
656 out_unlock2:
657 spin_unlock(&afs_vlocation_update_lock);
658 out_unlock1:
659 spin_unlock(&vlocation->cell->vl_gylock);
660 _leave("");
661 return;
663 } /* end afs_vlocation_update_timer() */
665 /*****************************************************************************/
667 * attend to an update operation upon which an event happened
668 * - called in kafsasyncd context
670 static void afs_vlocation_update_attend(afs_async_op_t *op)
672 afsc_vldb_record_t vldb;
673 afs_vlocation_t *vlocation = list_entry(op,afs_vlocation_t,upd_op);
674 unsigned tmp;
675 int ret;
677 _enter("%s",vlocation->vldb.name);
679 ret = afs_rxvl_get_entry_by_id_async2(op,&vldb);
680 switch (ret) {
681 case -EAGAIN:
682 _leave(" [unfinished]");
683 return;
685 case 0:
686 _debug("END VL UPDATE: %d\n",ret);
687 vlocation->valid = 1;
689 _debug("Done VL Lookup: %02x { %08x(%x) %08x(%x) %08x(%x) }",
690 vldb.vidmask,
691 ntohl(vldb.servers[0].s_addr),vldb.srvtmask[0],
692 ntohl(vldb.servers[1].s_addr),vldb.srvtmask[1],
693 ntohl(vldb.servers[2].s_addr),vldb.srvtmask[2]
696 _debug("Vids: %08x %08x %08x",vldb.vid[0],vldb.vid[1],vldb.vid[2]);
698 afs_vlocation_update_abandon(vlocation,AFS_VLUPD_SLEEP,0);
700 down_write(&vlocation->cell->vl_sem);
702 /* actually update the cache */
703 if (strncmp(vldb.name,vlocation->vldb.name,sizeof(vlocation->vldb.name))!=0)
704 printk("kAFS: name of volume '%s' changed to '%s' on server\n",
705 vlocation->vldb.name,vldb.name);
707 memcpy(&vlocation->vldb,&vldb,sizeof(vlocation->vldb));
709 #if 0
710 /* add volume entry to local cache */
711 ret = afsc_update_vlocation(vlocation);
712 #endif
714 up_write(&vlocation->cell->vl_sem);
716 if (ret<0)
717 printk("kAFS: failed to update local cache: %d\n",ret);
719 afs_kafstimod_add_timer(&vlocation->upd_timer,AFS_VLDB_TIMEOUT);
720 afs_put_vlocation(vlocation);
721 _leave(" [found]");
722 return;
724 case -ENOMEDIUM:
725 vlocation->upd_rej_cnt++;
726 goto try_next;
728 /* the server is locked - retry in a very short while */
729 case -EBUSY:
730 vlocation->upd_busy_cnt++;
731 if (vlocation->upd_busy_cnt>3)
732 goto try_next; /* too many retries */
734 afs_vlocation_update_abandon(vlocation,AFS_VLUPD_BUSYSLEEP,0);
735 afs_kafstimod_add_timer(&vlocation->upd_timer,HZ/2);
736 afs_put_vlocation(vlocation);
737 _leave(" [busy]");
738 return;
740 case -ENETUNREACH:
741 case -EHOSTUNREACH:
742 case -ECONNREFUSED:
743 case -EREMOTEIO:
744 /* record bad vlserver info in the cell too
745 * - TODO: use down_write_trylock() if available
747 if (vlocation->upd_curr_svix == vlocation->cell->vl_curr_svix)
748 vlocation->cell->vl_curr_svix =
749 vlocation->cell->vl_curr_svix % vlocation->cell->vl_naddrs;
751 case -EBADRQC:
752 case -EINVAL:
753 case -EACCES:
754 case -EBADMSG:
755 goto try_next;
757 default:
758 goto abandon;
761 /* try contacting the next server */
762 try_next:
763 vlocation->upd_busy_cnt = 0;
765 if (vlocation->upd_op.server) {
766 /* discard the server record */
767 afs_put_server(vlocation->upd_op.server);
768 vlocation->upd_op.server = NULL;
771 tmp = vlocation->cell->vl_naddrs;
772 if (tmp==0)
773 goto abandon;
775 vlocation->upd_curr_svix++;
776 if (vlocation->upd_curr_svix >= tmp) vlocation->upd_curr_svix = 0;
777 if (vlocation->upd_first_svix >= tmp) vlocation->upd_first_svix = tmp - 1;
779 /* move to the next server */
780 if (vlocation->upd_curr_svix!=vlocation->upd_first_svix) {
781 afs_vlocation_update_begin(vlocation);
782 _leave(" [next]");
783 return;
786 /* run out of servers to try - was the volume rejected? */
787 if (vlocation->upd_rej_cnt>0) {
788 printk("kAFS: Active volume no longer valid '%s'\n",vlocation->vldb.name);
789 vlocation->valid = 0;
790 afs_vlocation_update_abandon(vlocation,AFS_VLUPD_SLEEP,0);
791 afs_kafstimod_add_timer(&vlocation->upd_timer,AFS_VLDB_TIMEOUT);
792 afs_put_vlocation(vlocation);
793 _leave(" [invalidated]");
794 return;
797 /* abandon the update */
798 abandon:
799 afs_vlocation_update_abandon(vlocation,AFS_VLUPD_SLEEP,ret);
800 afs_kafstimod_add_timer(&vlocation->upd_timer,HZ*10);
801 afs_put_vlocation(vlocation);
802 _leave(" [abandoned]");
804 } /* end afs_vlocation_update_attend() */
806 /*****************************************************************************/
808 * deal with an update operation being discarded
809 * - called in kafsasyncd context when it's dying due to rmmod
810 * - the call has already been aborted and put()'d
812 static void afs_vlocation_update_discard(afs_async_op_t *op)
814 afs_vlocation_t *vlocation = list_entry(op,afs_vlocation_t,upd_op);
816 _enter("%s",vlocation->vldb.name);
818 afs_put_server(op->server);
819 op->server = NULL;
821 afs_put_vlocation(vlocation);
823 _leave("");
824 } /* end afs_vlocation_update_discard() */