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(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);
34 static void __afs_vlocation_timeout(struct afs_timer *timer)
36 struct afs_vlocation *vlocation =
37 list_entry(timer, struct afs_vlocation, timeout);
39 _debug("VL TIMEOUT [%s{u=%d}]",
40 vlocation->vldb.name, atomic_read(&vlocation->usage));
42 afs_vlocation_do_timeout(vlocation);
45 static const struct afs_timer_ops afs_vlocation_timer_ops = {
46 .timed_out = __afs_vlocation_timeout,
49 static const struct afs_timer_ops afs_vlocation_update_timer_ops = {
50 .timed_out = afs_vlocation_update_timer,
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,
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 */
62 #ifdef CONFIG_AFS_FSCACHE
63 static uint16_t afs_vlocation_cache_get_key(const void *cookie_netfs_data,
64 void *buffer, uint16_t buflen);
65 static uint16_t afs_vlocation_cache_get_aux(const void *cookie_netfs_data,
66 void *buffer, uint16_t buflen);
67 static fscache_checkaux_t afs_vlocation_cache_check_aux(void *cookie_netfs_data,
71 static struct fscache_cookie_def afs_vlocation_cache_index_def = {
73 .type = FSCACHE_COOKIE_TYPE_INDEX,
74 .get_key = afs_vlocation_cache_get_key,
75 .get_aux = afs_vlocation_cache_get_aux,
76 .check_aux = afs_vlocation_cache_check_aux,
80 /*****************************************************************************/
82 * iterate through the VL servers in a cell until one of them admits knowing
83 * about the volume in question
84 * - caller must have cell->vl_sem write-locked
86 static int afs_vlocation_access_vl_by_name(struct afs_vlocation *vlocation,
89 struct afs_cache_vlocation *vldb)
91 struct afs_server *server = NULL;
92 struct afs_cell *cell = vlocation->cell;
95 _enter("%s,%*.*s,%u", cell->name, namesz, namesz, name, namesz);
98 for (count = cell->vl_naddrs; count > 0; count--) {
99 _debug("CellServ[%hu]: %08x",
101 cell->vl_addrs[cell->vl_curr_svix].s_addr);
103 /* try and create a server */
104 ret = afs_server_lookup(cell,
105 &cell->vl_addrs[cell->vl_curr_svix],
117 /* attempt to access the VL server */
118 ret = afs_rxvl_get_entry_by_name(server, name, namesz, vldb);
121 afs_put_server(server);
128 down_write(&server->sem);
129 if (server->vlserver) {
130 rxrpc_put_connection(server->vlserver);
131 server->vlserver = NULL;
133 up_write(&server->sem);
134 afs_put_server(server);
135 if (ret == -ENOMEM || ret == -ENONET)
139 afs_put_server(server);
142 afs_put_server(server);
147 /* rotate the server records upon lookup failure */
149 cell->vl_curr_svix++;
150 cell->vl_curr_svix %= cell->vl_naddrs;
154 _leave(" = %d", ret);
157 } /* end afs_vlocation_access_vl_by_name() */
159 /*****************************************************************************/
161 * iterate through the VL servers in a cell until one of them admits knowing
162 * about the volume in question
163 * - caller must have cell->vl_sem write-locked
165 static int afs_vlocation_access_vl_by_id(struct afs_vlocation *vlocation,
167 afs_voltype_t voltype,
168 struct afs_cache_vlocation *vldb)
170 struct afs_server *server = NULL;
171 struct afs_cell *cell = vlocation->cell;
174 _enter("%s,%x,%d,", cell->name, volid, voltype);
177 for (count = cell->vl_naddrs; count > 0; count--) {
178 _debug("CellServ[%hu]: %08x",
180 cell->vl_addrs[cell->vl_curr_svix].s_addr);
182 /* try and create a server */
183 ret = afs_server_lookup(cell,
184 &cell->vl_addrs[cell->vl_curr_svix],
196 /* attempt to access the VL server */
197 ret = afs_rxvl_get_entry_by_id(server, volid, voltype, vldb);
200 afs_put_server(server);
207 down_write(&server->sem);
208 if (server->vlserver) {
209 rxrpc_put_connection(server->vlserver);
210 server->vlserver = NULL;
212 up_write(&server->sem);
213 afs_put_server(server);
214 if (ret == -ENOMEM || ret == -ENONET)
218 afs_put_server(server);
221 afs_put_server(server);
226 /* rotate the server records upon lookup failure */
228 cell->vl_curr_svix++;
229 cell->vl_curr_svix %= cell->vl_naddrs;
233 _leave(" = %d", ret);
236 } /* end afs_vlocation_access_vl_by_id() */
238 /*****************************************************************************/
240 * lookup volume location
241 * - caller must have cell->vol_sem write-locked
242 * - iterate through the VL servers in a cell until one of them admits knowing
243 * about the volume in question
244 * - lookup in the local cache if not able to find on the VL server
245 * - insert/update in the local cache if did get a VL response
247 int afs_vlocation_lookup(struct afs_cell *cell,
250 struct afs_vlocation **_vlocation)
252 struct afs_cache_vlocation vldb;
253 struct afs_vlocation *vlocation;
254 afs_voltype_t voltype;
258 _enter("{%s},%*.*s,%u,", cell->name, namesz, namesz, name, namesz);
260 if (namesz > sizeof(vlocation->vldb.name)) {
261 _leave(" = -ENAMETOOLONG");
262 return -ENAMETOOLONG;
265 /* search the cell's active list first */
266 list_for_each_entry(vlocation, &cell->vl_list, link) {
267 if (namesz < sizeof(vlocation->vldb.name) &&
268 vlocation->vldb.name[namesz] != '\0')
271 if (memcmp(vlocation->vldb.name, name, namesz) == 0)
272 goto found_in_memory;
275 /* search the cell's graveyard list second */
276 spin_lock(&cell->vl_gylock);
277 list_for_each_entry(vlocation, &cell->vl_graveyard, link) {
278 if (namesz < sizeof(vlocation->vldb.name) &&
279 vlocation->vldb.name[namesz] != '\0')
282 if (memcmp(vlocation->vldb.name, name, namesz) == 0)
283 goto found_in_graveyard;
285 spin_unlock(&cell->vl_gylock);
287 /* not in the cell's in-memory lists - create a new record */
288 vlocation = kmalloc(sizeof(struct afs_vlocation), GFP_KERNEL);
292 memset(vlocation, 0, sizeof(struct afs_vlocation));
293 atomic_set(&vlocation->usage, 1);
294 INIT_LIST_HEAD(&vlocation->link);
295 rwlock_init(&vlocation->lock);
296 memcpy(vlocation->vldb.name, name, namesz);
298 afs_timer_init(&vlocation->timeout, &afs_vlocation_timer_ops);
299 afs_timer_init(&vlocation->upd_timer, &afs_vlocation_update_timer_ops);
300 afs_async_op_init(&vlocation->upd_op, &afs_vlocation_update_op_ops);
303 vlocation->cell = cell;
305 list_add_tail(&vlocation->link, &cell->vl_list);
307 #ifdef CONFIG_AFS_FSCACHE
308 /* we want to store it in the cache, plus it might already be
310 vlocation->cache = fscache_acquire_cookie(cell->cache,
311 &afs_vlocation_cache_index_def,
314 if (vlocation->valid)
318 /* try to look up an unknown volume in the cell VL databases by name */
319 ret = afs_vlocation_access_vl_by_name(vlocation, name, namesz, &vldb);
321 printk("kAFS: failed to locate '%*.*s' in cell '%s'\n",
322 namesz, namesz, name, cell->name);
326 goto found_on_vlserver;
329 /* found in the graveyard - resurrect */
330 _debug("found in graveyard");
331 atomic_inc(&vlocation->usage);
332 list_move_tail(&vlocation->link, &cell->vl_list);
333 spin_unlock(&cell->vl_gylock);
335 afs_kafstimod_del_timer(&vlocation->timeout);
339 /* found in memory - check to see if it's active */
340 _debug("found in memory");
341 atomic_inc(&vlocation->usage);
346 #ifdef CONFIG_AFS_FSCACHE
349 /* try to look up a cached volume in the cell VL databases by ID */
350 _debug("found in cache");
352 _debug("Locally Cached: %s %02x { %08x(%x) %08x(%x) %08x(%x) }",
353 vlocation->vldb.name,
354 vlocation->vldb.vidmask,
355 ntohl(vlocation->vldb.servers[0].s_addr),
356 vlocation->vldb.srvtmask[0],
357 ntohl(vlocation->vldb.servers[1].s_addr),
358 vlocation->vldb.srvtmask[1],
359 ntohl(vlocation->vldb.servers[2].s_addr),
360 vlocation->vldb.srvtmask[2]
363 _debug("Vids: %08x %08x %08x",
364 vlocation->vldb.vid[0],
365 vlocation->vldb.vid[1],
366 vlocation->vldb.vid[2]);
368 if (vlocation->vldb.vidmask & AFS_VOL_VTM_RW) {
369 vid = vlocation->vldb.vid[0];
370 voltype = AFSVL_RWVOL;
372 else if (vlocation->vldb.vidmask & AFS_VOL_VTM_RO) {
373 vid = vlocation->vldb.vid[1];
374 voltype = AFSVL_ROVOL;
376 else if (vlocation->vldb.vidmask & AFS_VOL_VTM_BAK) {
377 vid = vlocation->vldb.vid[2];
378 voltype = AFSVL_BACKVOL;
386 ret = afs_vlocation_access_vl_by_id(vlocation, vid, voltype, &vldb);
390 printk("kAFS: failed to volume '%*.*s' (%x) up in '%s': %d\n",
391 namesz, namesz, name, vid, cell->name, ret);
394 /* pulled from local cache into memory */
396 goto found_on_vlserver;
398 /* uh oh... looks like the volume got deleted */
400 printk("kAFS: volume '%*.*s' (%x) does not exist '%s'\n",
401 namesz, namesz, name, vid, cell->name);
403 /* TODO: make existing record unavailable */
408 _debug("Done VL Lookup: %*.*s %02x { %08x(%x) %08x(%x) %08x(%x) }",
409 namesz, namesz, name,
411 ntohl(vldb.servers[0].s_addr), vldb.srvtmask[0],
412 ntohl(vldb.servers[1].s_addr), vldb.srvtmask[1],
413 ntohl(vldb.servers[2].s_addr), vldb.srvtmask[2]
416 _debug("Vids: %08x %08x %08x", vldb.vid[0], vldb.vid[1], vldb.vid[2]);
418 if ((namesz < sizeof(vlocation->vldb.name) &&
419 vlocation->vldb.name[namesz] != '\0') ||
420 memcmp(vldb.name, name, namesz) != 0)
421 printk("kAFS: name of volume '%*.*s' changed to '%s' on server\n",
422 namesz, namesz, name, vldb.name);
424 memcpy(&vlocation->vldb, &vldb, sizeof(vlocation->vldb));
426 afs_kafstimod_add_timer(&vlocation->upd_timer, 10 * HZ);
428 #ifdef CONFIG_AFS_FSCACHE
429 /* update volume entry in local cache */
430 fscache_update_cookie(vlocation->cache);
433 *_vlocation = vlocation;
434 _leave(" = 0 (%p)",vlocation);
440 __afs_put_vlocation(vlocation);
443 list_del(&vlocation->link);
444 #ifdef CONFIG_AFS_FSCACHE
445 fscache_relinquish_cookie(vlocation->cache, 0);
447 afs_put_cell(vlocation->cell);
452 _leave(" = %d", ret);
454 } /* end afs_vlocation_lookup() */
456 /*****************************************************************************/
458 * finish using a volume location record
459 * - caller must have cell->vol_sem write-locked
461 static void __afs_put_vlocation(struct afs_vlocation *vlocation)
463 struct afs_cell *cell;
468 _enter("%s", vlocation->vldb.name);
470 cell = vlocation->cell;
473 BUG_ON(atomic_read(&vlocation->usage) <= 0);
475 spin_lock(&cell->vl_gylock);
476 if (likely(!atomic_dec_and_test(&vlocation->usage))) {
477 spin_unlock(&cell->vl_gylock);
482 /* move to graveyard queue */
483 list_move_tail(&vlocation->link,&cell->vl_graveyard);
485 /* remove from pending timeout queue (refcounted if actually being
487 list_del_init(&vlocation->upd_op.link);
489 /* time out in 10 secs */
490 afs_kafstimod_del_timer(&vlocation->upd_timer);
491 afs_kafstimod_add_timer(&vlocation->timeout, 10 * HZ);
493 spin_unlock(&cell->vl_gylock);
496 } /* end __afs_put_vlocation() */
498 /*****************************************************************************/
500 * finish using a volume location record
502 void afs_put_vlocation(struct afs_vlocation *vlocation)
505 struct afs_cell *cell = vlocation->cell;
507 down_write(&cell->vl_sem);
508 __afs_put_vlocation(vlocation);
509 up_write(&cell->vl_sem);
511 } /* end afs_put_vlocation() */
513 /*****************************************************************************/
515 * timeout vlocation record
516 * - removes from the cell's graveyard if the usage count is zero
518 void afs_vlocation_do_timeout(struct afs_vlocation *vlocation)
520 struct afs_cell *cell;
522 _enter("%s", vlocation->vldb.name);
524 cell = vlocation->cell;
526 BUG_ON(atomic_read(&vlocation->usage) < 0);
528 /* remove from graveyard if still dead */
529 spin_lock(&cell->vl_gylock);
530 if (atomic_read(&vlocation->usage) == 0)
531 list_del_init(&vlocation->link);
534 spin_unlock(&cell->vl_gylock);
538 return; /* resurrected */
541 /* we can now destroy it properly */
542 #ifdef CONFIG_AFS_FSCACHE
543 fscache_relinquish_cookie(vlocation->cache, 0);
549 _leave(" [destroyed]");
550 } /* end afs_vlocation_do_timeout() */
552 /*****************************************************************************/
554 * send an update operation to the currently selected server
556 static int afs_vlocation_update_begin(struct afs_vlocation *vlocation)
558 afs_voltype_t voltype;
562 _enter("%s{ufs=%u ucs=%u}",
563 vlocation->vldb.name,
564 vlocation->upd_first_svix,
565 vlocation->upd_curr_svix);
567 /* try to look up a cached volume in the cell VL databases by ID */
568 if (vlocation->vldb.vidmask & AFS_VOL_VTM_RW) {
569 vid = vlocation->vldb.vid[0];
570 voltype = AFSVL_RWVOL;
572 else if (vlocation->vldb.vidmask & AFS_VOL_VTM_RO) {
573 vid = vlocation->vldb.vid[1];
574 voltype = AFSVL_ROVOL;
576 else if (vlocation->vldb.vidmask & AFS_VOL_VTM_BAK) {
577 vid = vlocation->vldb.vid[2];
578 voltype = AFSVL_BACKVOL;
586 /* contact the chosen server */
587 ret = afs_server_lookup(
589 &vlocation->cell->vl_addrs[vlocation->upd_curr_svix],
590 &vlocation->upd_op.server);
598 _leave(" = %d", ret);
602 /* initiate the update operation */
603 ret = afs_rxvl_get_entry_by_id_async(&vlocation->upd_op, vid, voltype);
605 _leave(" = %d", ret);
609 _leave(" = %d", ret);
611 } /* end afs_vlocation_update_begin() */
613 /*****************************************************************************/
615 * abandon updating a VL record
616 * - does not restart the update timer
618 static void afs_vlocation_update_abandon(struct afs_vlocation *vlocation,
619 afs_vlocation_upd_t state,
622 _enter("%s,%u", vlocation->vldb.name, state);
625 printk("kAFS: Abandoning VL update '%s': %d\n",
626 vlocation->vldb.name, ret);
628 /* discard the server record */
629 afs_put_server(vlocation->upd_op.server);
630 vlocation->upd_op.server = NULL;
632 spin_lock(&afs_vlocation_update_lock);
633 afs_vlocation_update = NULL;
634 vlocation->upd_state = state;
636 /* TODO: start updating next VL record on pending list */
638 spin_unlock(&afs_vlocation_update_lock);
641 } /* end afs_vlocation_update_abandon() */
643 /*****************************************************************************/
645 * handle periodic update timeouts and busy retry timeouts
646 * - called from kafstimod
648 static void afs_vlocation_update_timer(struct afs_timer *timer)
650 struct afs_vlocation *vlocation =
651 list_entry(timer, struct afs_vlocation, upd_timer);
654 _enter("%s", vlocation->vldb.name);
656 /* only update if not in the graveyard (defend against putting too) */
657 spin_lock(&vlocation->cell->vl_gylock);
659 if (!atomic_read(&vlocation->usage))
662 spin_lock(&afs_vlocation_update_lock);
664 /* if we were woken up due to EBUSY sleep then restart immediately if
665 * possible or else jump to front of pending queue */
666 if (vlocation->upd_state == AFS_VLUPD_BUSYSLEEP) {
667 if (afs_vlocation_update) {
668 list_add(&vlocation->upd_op.link,
669 &afs_vlocation_update_pendq);
672 afs_get_vlocation(vlocation);
673 afs_vlocation_update = vlocation;
674 vlocation->upd_state = AFS_VLUPD_INPROGRESS;
679 /* put on pending queue if there's already another update in progress */
680 if (afs_vlocation_update) {
681 vlocation->upd_state = AFS_VLUPD_PENDING;
682 list_add_tail(&vlocation->upd_op.link,
683 &afs_vlocation_update_pendq);
687 /* hold a ref on it while actually updating */
688 afs_get_vlocation(vlocation);
689 afs_vlocation_update = vlocation;
690 vlocation->upd_state = AFS_VLUPD_INPROGRESS;
692 spin_unlock(&afs_vlocation_update_lock);
693 spin_unlock(&vlocation->cell->vl_gylock);
695 /* okay... we can start the update */
696 _debug("BEGIN VL UPDATE [%s]", vlocation->vldb.name);
697 vlocation->upd_first_svix = vlocation->cell->vl_curr_svix;
698 vlocation->upd_curr_svix = vlocation->upd_first_svix;
699 vlocation->upd_rej_cnt = 0;
700 vlocation->upd_busy_cnt = 0;
702 ret = afs_vlocation_update_begin(vlocation);
704 afs_vlocation_update_abandon(vlocation, AFS_VLUPD_SLEEP, ret);
705 afs_kafstimod_add_timer(&vlocation->upd_timer,
707 afs_put_vlocation(vlocation);
714 spin_unlock(&afs_vlocation_update_lock);
716 spin_unlock(&vlocation->cell->vl_gylock);
720 } /* end afs_vlocation_update_timer() */
722 /*****************************************************************************/
724 * attend to an update operation upon which an event happened
725 * - called in kafsasyncd context
727 static void afs_vlocation_update_attend(struct afs_async_op *op)
729 struct afs_cache_vlocation vldb;
730 struct afs_vlocation *vlocation =
731 list_entry(op, struct afs_vlocation, upd_op);
735 _enter("%s", vlocation->vldb.name);
737 ret = afs_rxvl_get_entry_by_id_async2(op, &vldb);
740 _leave(" [unfinished]");
744 _debug("END VL UPDATE: %d\n", ret);
745 vlocation->valid = 1;
747 _debug("Done VL Lookup: %02x { %08x(%x) %08x(%x) %08x(%x) }",
749 ntohl(vldb.servers[0].s_addr), vldb.srvtmask[0],
750 ntohl(vldb.servers[1].s_addr), vldb.srvtmask[1],
751 ntohl(vldb.servers[2].s_addr), vldb.srvtmask[2]
754 _debug("Vids: %08x %08x %08x",
755 vldb.vid[0], vldb.vid[1], vldb.vid[2]);
757 afs_vlocation_update_abandon(vlocation, AFS_VLUPD_SLEEP, 0);
759 down_write(&vlocation->cell->vl_sem);
761 /* actually update the cache */
762 if (strncmp(vldb.name, vlocation->vldb.name,
763 sizeof(vlocation->vldb.name)) != 0)
764 printk("kAFS: name of volume '%s'"
765 " changed to '%s' on server\n",
766 vlocation->vldb.name, vldb.name);
768 memcpy(&vlocation->vldb, &vldb, sizeof(vlocation->vldb));
771 /* TODO update volume entry in local cache */
774 up_write(&vlocation->cell->vl_sem);
777 printk("kAFS: failed to update local cache: %d\n", ret);
779 afs_kafstimod_add_timer(&vlocation->upd_timer,
781 afs_put_vlocation(vlocation);
786 vlocation->upd_rej_cnt++;
789 /* the server is locked - retry in a very short while */
791 vlocation->upd_busy_cnt++;
792 if (vlocation->upd_busy_cnt > 3)
793 goto try_next; /* too many retries */
795 afs_vlocation_update_abandon(vlocation,
796 AFS_VLUPD_BUSYSLEEP, 0);
797 afs_kafstimod_add_timer(&vlocation->upd_timer, HZ / 2);
798 afs_put_vlocation(vlocation);
806 /* record bad vlserver info in the cell too
807 * - TODO: use down_write_trylock() if available
809 if (vlocation->upd_curr_svix == vlocation->cell->vl_curr_svix)
810 vlocation->cell->vl_curr_svix =
811 vlocation->cell->vl_curr_svix %
812 vlocation->cell->vl_naddrs;
824 /* try contacting the next server */
826 vlocation->upd_busy_cnt = 0;
828 /* discard the server record */
829 afs_put_server(vlocation->upd_op.server);
830 vlocation->upd_op.server = NULL;
832 tmp = vlocation->cell->vl_naddrs;
836 vlocation->upd_curr_svix++;
837 if (vlocation->upd_curr_svix >= tmp)
838 vlocation->upd_curr_svix = 0;
839 if (vlocation->upd_first_svix >= tmp)
840 vlocation->upd_first_svix = tmp - 1;
842 /* move to the next server */
843 if (vlocation->upd_curr_svix != vlocation->upd_first_svix) {
844 afs_vlocation_update_begin(vlocation);
849 /* run out of servers to try - was the volume rejected? */
850 if (vlocation->upd_rej_cnt > 0) {
851 printk("kAFS: Active volume no longer valid '%s'\n",
852 vlocation->vldb.name);
853 vlocation->valid = 0;
854 afs_vlocation_update_abandon(vlocation, AFS_VLUPD_SLEEP, 0);
855 afs_kafstimod_add_timer(&vlocation->upd_timer,
857 afs_put_vlocation(vlocation);
858 _leave(" [invalidated]");
862 /* abandon the update */
864 afs_vlocation_update_abandon(vlocation, AFS_VLUPD_SLEEP, ret);
865 afs_kafstimod_add_timer(&vlocation->upd_timer, HZ * 10);
866 afs_put_vlocation(vlocation);
867 _leave(" [abandoned]");
869 } /* end afs_vlocation_update_attend() */
871 /*****************************************************************************/
873 * deal with an update operation being discarded
874 * - called in kafsasyncd context when it's dying due to rmmod
875 * - the call has already been aborted and put()'d
877 static void afs_vlocation_update_discard(struct afs_async_op *op)
879 struct afs_vlocation *vlocation =
880 list_entry(op, struct afs_vlocation, upd_op);
882 _enter("%s", vlocation->vldb.name);
884 afs_put_server(op->server);
887 afs_put_vlocation(vlocation);
890 } /* end afs_vlocation_update_discard() */
892 /*****************************************************************************/
894 * set the key for the index entry
896 #ifdef CONFIG_AFS_FSCACHE
897 static uint16_t afs_vlocation_cache_get_key(const void *cookie_netfs_data,
898 void *buffer, uint16_t bufmax)
900 const struct afs_vlocation *vlocation = cookie_netfs_data;
903 _enter("{%s},%p,%u", vlocation->vldb.name, buffer, bufmax);
905 klen = strnlen(vlocation->vldb.name, sizeof(vlocation->vldb.name));
909 memcpy(buffer, vlocation->vldb.name, klen);
911 _leave(" = %u", klen);
914 } /* end afs_vlocation_cache_get_key() */
917 /*****************************************************************************/
919 * provide new auxilliary cache data
921 #ifdef CONFIG_AFS_FSCACHE
922 static uint16_t afs_vlocation_cache_get_aux(const void *cookie_netfs_data,
923 void *buffer, uint16_t bufmax)
925 const struct afs_vlocation *vlocation = cookie_netfs_data;
928 _enter("{%s},%p,%u", vlocation->vldb.name, buffer, bufmax);
930 dlen = sizeof(struct afs_cache_vlocation);
931 dlen -= offsetof(struct afs_cache_vlocation, nservers);
935 memcpy(buffer, (uint8_t *)&vlocation->vldb.nservers, dlen);
937 _leave(" = %u", dlen);
940 } /* end afs_vlocation_cache_get_aux() */
943 /*****************************************************************************/
945 * check that the auxilliary data indicates that the entry is still valid
947 #ifdef CONFIG_AFS_FSCACHE
948 static fscache_checkaux_t afs_vlocation_cache_check_aux(void *cookie_netfs_data,
952 const struct afs_cache_vlocation *cvldb;
953 struct afs_vlocation *vlocation = cookie_netfs_data;
956 _enter("{%s},%p,%u", vlocation->vldb.name, buffer, buflen);
958 /* check the size of the data is what we're expecting */
959 dlen = sizeof(struct afs_cache_vlocation);
960 dlen -= offsetof(struct afs_cache_vlocation, nservers);
962 return FSCACHE_CHECKAUX_OBSOLETE;
964 cvldb = container_of(buffer, struct afs_cache_vlocation, nservers);
966 /* if what's on disk is more valid than what's in memory, then use the
967 * VL record from the cache */
968 if (!vlocation->valid || vlocation->vldb.rtime == cvldb->rtime) {
969 memcpy((uint8_t *)&vlocation->vldb.nservers, buffer, dlen);
970 vlocation->valid = 1;
971 _leave(" = SUCCESS [c->m]");
972 return FSCACHE_CHECKAUX_OKAY;
975 /* need to update the cache if the cached info differs */
976 if (memcmp(&vlocation->vldb, buffer, dlen) != 0) {
977 /* delete if the volume IDs for this name differ */
978 if (memcmp(&vlocation->vldb.vid, &cvldb->vid,
979 sizeof(cvldb->vid)) != 0
981 _leave(" = OBSOLETE");
982 return FSCACHE_CHECKAUX_OBSOLETE;
986 return FSCACHE_CHECKAUX_NEEDS_UPDATE;
990 return FSCACHE_CHECKAUX_OKAY;
992 } /* end afs_vlocation_cache_check_aux() */