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