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>
17 #include <linux/pagemap.h>
20 #include "cmservice.h"
23 #include "kafstimod.h"
24 #include <rxrpc/connection.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
63 * - caller must have cell->vl_sem write-locked
65 static int afs_vlocation_access_vl_by_name(afs_vlocation_t
*vlocation
,
67 afsc_vldb_record_t
*vldb
)
69 afs_server_t
*server
= NULL
;
70 afs_cell_t
*cell
= vlocation
->cell
;
73 _enter("%s,%s,",cell
->name
,name
);
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
);
92 /* attempt to access the VL server */
93 ret
= afs_rxvl_get_entry_by_name(server
,name
,vldb
);
96 afs_put_server(server
);
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
)
114 afs_put_server(server
);
117 afs_put_server(server
);
122 /* rotate the server records upon lookup failure */
124 cell
->vl_curr_svix
++;
125 cell
->vl_curr_svix
%= cell
->vl_naddrs
;
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
138 * - caller must have cell->vl_sem write-locked
140 static int afs_vlocation_access_vl_by_id(afs_vlocation_t
*vlocation
,
142 afs_voltype_t voltype
,
143 afsc_vldb_record_t
*vldb
)
145 afs_server_t
*server
= NULL
;
146 afs_cell_t
*cell
= vlocation
->cell
;
149 _enter("%s,%x,%d,",cell
->name
,volid
,voltype
);
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
);
168 /* attempt to access the VL server */
169 ret
= afs_rxvl_get_entry_by_id(server
,volid
,voltype
,vldb
);
172 afs_put_server(server
);
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
)
190 afs_put_server(server
);
193 afs_put_server(server
);
198 /* rotate the server records upon lookup failure */
200 cell
->vl_curr_svix
++;
201 cell
->vl_curr_svix
%= cell
->vl_naddrs
;
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
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
;
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
);
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
);
269 vlocation
->cell
= cell
;
271 list_add_tail(&vlocation
->link
,&cell
->vl_list
);
274 /* search local cache if wasn't in memory */
275 ret
= afsc_lookup_vlocation(vlocation
);
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 */
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
);
286 printk("kAFS: failed to locate '%s' in cell '%s'\n",name
,cell
->name
);
290 goto found_on_vlserver
;
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
);
304 /* found in memory - check to see if it's active */
305 _debug("found in memory");
306 atomic_inc(&vlocation
->usage
);
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
;
344 ret
= afs_vlocation_access_vl_by_id(vlocation
,vid
,voltype
,&vldb
);
348 printk("kAFS: failed to volume '%s' (%x) up in '%s': %d\n",
349 name
,vid
,cell
->name
,ret
);
352 /* pulled from local cache into memory */
354 goto found_on_vlserver
;
356 /* uh oh... looks like the volume got deleted */
358 printk("kAFS: volume '%s' (%x) does not exist '%s'\n",name
,vid
,cell
->name
);
360 /* TODO: make existing record unavailable */
365 _debug("Done VL Lookup: %s %02x { %08x(%x) %08x(%x) %08x(%x) }",
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
));
381 /* add volume entry to local cache */
382 ret
= afsc_update_vlocation(vlocation
);
387 afs_kafstimod_add_timer(&vlocation
->upd_timer
,10*HZ
);
389 *_vlocation
= vlocation
;
390 _leave(" = 0 (%p)",vlocation
);
396 __afs_put_vlocation(vlocation
);
399 list_del(&vlocation
->link
);
400 afs_put_cell(vlocation
->cell
);
402 afs_put_cache(vlocation
->cache
);
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
);
424 if (atomic_read(&vlocation
->usage
)<=0)
427 spin_lock(&cell
->vl_gylock
);
428 if (likely(!atomic_dec_and_test(&vlocation
->usage
))) {
429 spin_unlock(&cell
->vl_gylock
);
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
);
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
)
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
);
484 spin_unlock(&cell
->vl_gylock
);
488 return; /* resurrected */
491 /* we can now destroy it properly */
494 afs_put_cache(vlocation
->cache
);
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
;
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
;
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
);
548 /* initiate the update operation */
549 ret
= afs_rxvl_get_entry_by_id_async(&vlocation
->upd_op
,vid
,voltype
);
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
,
568 _enter("%s,%u",vlocation
->vldb
.name
,state
);
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
);
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
);
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
))
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
);
617 afs_get_vlocation(vlocation
);
618 afs_vlocation_update
= vlocation
;
619 vlocation
->upd_state
= AFS_VLUPD_INPROGRESS
;
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
);
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
);
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
);
657 spin_unlock(&afs_vlocation_update_lock
);
659 spin_unlock(&vlocation
->cell
->vl_gylock
);
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
);
677 _enter("%s",vlocation
->vldb
.name
);
679 ret
= afs_rxvl_get_entry_by_id_async2(op
,&vldb
);
682 _leave(" [unfinished]");
686 _debug("END VL UPDATE: %d\n",ret
);
687 vlocation
->valid
= 1;
689 _debug("Done VL Lookup: %02x { %08x(%x) %08x(%x) %08x(%x) }",
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
));
710 /* add volume entry to local cache */
711 ret
= afsc_update_vlocation(vlocation
);
714 up_write(&vlocation
->cell
->vl_sem
);
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
);
725 vlocation
->upd_rej_cnt
++;
728 /* the server is locked - retry in a very short while */
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
);
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
;
761 /* try contacting the next server */
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
;
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
);
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]");
797 /* abandon the update */
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
);
821 afs_put_vlocation(vlocation
);
824 } /* end afs_vlocation_update_discard() */