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