|  | /* AFS caching stuff | 
|  | * | 
|  | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | 
|  | * Written by David Howells (dhowells@redhat.com) | 
|  | * | 
|  | * This program is free software; you can redistribute it and/or | 
|  | * modify it under the terms of the GNU General Public License | 
|  | * as published by the Free Software Foundation; either version | 
|  | * 2 of the License, or (at your option) any later version. | 
|  | */ | 
|  |  | 
|  | #ifdef AFS_CACHING_SUPPORT | 
|  | static cachefs_match_val_t afs_cell_cache_match(void *target, | 
|  | const void *entry); | 
|  | static void afs_cell_cache_update(void *source, void *entry); | 
|  |  | 
|  | struct cachefs_index_def afs_cache_cell_index_def = { | 
|  | .name			= "cell_ix", | 
|  | .data_size		= sizeof(struct afs_cache_cell), | 
|  | .keys[0]		= { CACHEFS_INDEX_KEYS_ASCIIZ, 64 }, | 
|  | .match			= afs_cell_cache_match, | 
|  | .update			= afs_cell_cache_update, | 
|  | }; | 
|  | #endif | 
|  |  | 
|  | /* | 
|  | * match a cell record obtained from the cache | 
|  | */ | 
|  | #ifdef AFS_CACHING_SUPPORT | 
|  | static cachefs_match_val_t afs_cell_cache_match(void *target, | 
|  | const void *entry) | 
|  | { | 
|  | const struct afs_cache_cell *ccell = entry; | 
|  | struct afs_cell *cell = target; | 
|  |  | 
|  | _enter("{%s},{%s}", ccell->name, cell->name); | 
|  |  | 
|  | if (strncmp(ccell->name, cell->name, sizeof(ccell->name)) == 0) { | 
|  | _leave(" = SUCCESS"); | 
|  | return CACHEFS_MATCH_SUCCESS; | 
|  | } | 
|  |  | 
|  | _leave(" = FAILED"); | 
|  | return CACHEFS_MATCH_FAILED; | 
|  | } | 
|  | #endif | 
|  |  | 
|  | /* | 
|  | * update a cell record in the cache | 
|  | */ | 
|  | #ifdef AFS_CACHING_SUPPORT | 
|  | static void afs_cell_cache_update(void *source, void *entry) | 
|  | { | 
|  | struct afs_cache_cell *ccell = entry; | 
|  | struct afs_cell *cell = source; | 
|  |  | 
|  | _enter("%p,%p", source, entry); | 
|  |  | 
|  | strncpy(ccell->name, cell->name, sizeof(ccell->name)); | 
|  |  | 
|  | memcpy(ccell->vl_servers, | 
|  | cell->vl_addrs, | 
|  | min(sizeof(ccell->vl_servers), sizeof(cell->vl_addrs))); | 
|  |  | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #ifdef AFS_CACHING_SUPPORT | 
|  | static cachefs_match_val_t afs_vlocation_cache_match(void *target, | 
|  | const void *entry); | 
|  | static void afs_vlocation_cache_update(void *source, void *entry); | 
|  |  | 
|  | struct cachefs_index_def afs_vlocation_cache_index_def = { | 
|  | .name		= "vldb", | 
|  | .data_size	= sizeof(struct afs_cache_vlocation), | 
|  | .keys[0]	= { CACHEFS_INDEX_KEYS_ASCIIZ, 64 }, | 
|  | .match		= afs_vlocation_cache_match, | 
|  | .update		= afs_vlocation_cache_update, | 
|  | }; | 
|  | #endif | 
|  |  | 
|  | /* | 
|  | * match a VLDB record stored in the cache | 
|  | * - may also load target from entry | 
|  | */ | 
|  | #ifdef AFS_CACHING_SUPPORT | 
|  | static cachefs_match_val_t afs_vlocation_cache_match(void *target, | 
|  | const void *entry) | 
|  | { | 
|  | const struct afs_cache_vlocation *vldb = entry; | 
|  | struct afs_vlocation *vlocation = target; | 
|  |  | 
|  | _enter("{%s},{%s}", vlocation->vldb.name, vldb->name); | 
|  |  | 
|  | if (strncmp(vlocation->vldb.name, vldb->name, sizeof(vldb->name)) == 0 | 
|  | ) { | 
|  | if (!vlocation->valid || | 
|  | vlocation->vldb.rtime == vldb->rtime | 
|  | ) { | 
|  | vlocation->vldb = *vldb; | 
|  | vlocation->valid = 1; | 
|  | _leave(" = SUCCESS [c->m]"); | 
|  | return CACHEFS_MATCH_SUCCESS; | 
|  | } else if (memcmp(&vlocation->vldb, vldb, sizeof(*vldb)) != 0) { | 
|  | /* delete if VIDs for this name differ */ | 
|  | if (memcmp(&vlocation->vldb.vid, | 
|  | &vldb->vid, | 
|  | sizeof(vldb->vid)) != 0) { | 
|  | _leave(" = DELETE"); | 
|  | return CACHEFS_MATCH_SUCCESS_DELETE; | 
|  | } | 
|  |  | 
|  | _leave(" = UPDATE"); | 
|  | return CACHEFS_MATCH_SUCCESS_UPDATE; | 
|  | } else { | 
|  | _leave(" = SUCCESS"); | 
|  | return CACHEFS_MATCH_SUCCESS; | 
|  | } | 
|  | } | 
|  |  | 
|  | _leave(" = FAILED"); | 
|  | return CACHEFS_MATCH_FAILED; | 
|  | } | 
|  | #endif | 
|  |  | 
|  | /* | 
|  | * update a VLDB record stored in the cache | 
|  | */ | 
|  | #ifdef AFS_CACHING_SUPPORT | 
|  | static void afs_vlocation_cache_update(void *source, void *entry) | 
|  | { | 
|  | struct afs_cache_vlocation *vldb = entry; | 
|  | struct afs_vlocation *vlocation = source; | 
|  |  | 
|  | _enter(""); | 
|  |  | 
|  | *vldb = vlocation->vldb; | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #ifdef AFS_CACHING_SUPPORT | 
|  | static cachefs_match_val_t afs_volume_cache_match(void *target, | 
|  | const void *entry); | 
|  | static void afs_volume_cache_update(void *source, void *entry); | 
|  |  | 
|  | struct cachefs_index_def afs_volume_cache_index_def = { | 
|  | .name		= "volume", | 
|  | .data_size	= sizeof(struct afs_cache_vhash), | 
|  | .keys[0]	= { CACHEFS_INDEX_KEYS_BIN, 1 }, | 
|  | .keys[1]	= { CACHEFS_INDEX_KEYS_BIN, 1 }, | 
|  | .match		= afs_volume_cache_match, | 
|  | .update		= afs_volume_cache_update, | 
|  | }; | 
|  | #endif | 
|  |  | 
|  | /* | 
|  | * match a volume hash record stored in the cache | 
|  | */ | 
|  | #ifdef AFS_CACHING_SUPPORT | 
|  | static cachefs_match_val_t afs_volume_cache_match(void *target, | 
|  | const void *entry) | 
|  | { | 
|  | const struct afs_cache_vhash *vhash = entry; | 
|  | struct afs_volume *volume = target; | 
|  |  | 
|  | _enter("{%u},{%u}", volume->type, vhash->vtype); | 
|  |  | 
|  | if (volume->type == vhash->vtype) { | 
|  | _leave(" = SUCCESS"); | 
|  | return CACHEFS_MATCH_SUCCESS; | 
|  | } | 
|  |  | 
|  | _leave(" = FAILED"); | 
|  | return CACHEFS_MATCH_FAILED; | 
|  | } | 
|  | #endif | 
|  |  | 
|  | /* | 
|  | * update a volume hash record stored in the cache | 
|  | */ | 
|  | #ifdef AFS_CACHING_SUPPORT | 
|  | static void afs_volume_cache_update(void *source, void *entry) | 
|  | { | 
|  | struct afs_cache_vhash *vhash = entry; | 
|  | struct afs_volume *volume = source; | 
|  |  | 
|  | _enter(""); | 
|  |  | 
|  | vhash->vtype = volume->type; | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #ifdef AFS_CACHING_SUPPORT | 
|  | static cachefs_match_val_t afs_vnode_cache_match(void *target, | 
|  | const void *entry); | 
|  | static void afs_vnode_cache_update(void *source, void *entry); | 
|  |  | 
|  | struct cachefs_index_def afs_vnode_cache_index_def = { | 
|  | .name		= "vnode", | 
|  | .data_size	= sizeof(struct afs_cache_vnode), | 
|  | .keys[0]	= { CACHEFS_INDEX_KEYS_BIN, 4 }, | 
|  | .match		= afs_vnode_cache_match, | 
|  | .update		= afs_vnode_cache_update, | 
|  | }; | 
|  | #endif | 
|  |  | 
|  | /* | 
|  | * match a vnode record stored in the cache | 
|  | */ | 
|  | #ifdef AFS_CACHING_SUPPORT | 
|  | static cachefs_match_val_t afs_vnode_cache_match(void *target, | 
|  | const void *entry) | 
|  | { | 
|  | const struct afs_cache_vnode *cvnode = entry; | 
|  | struct afs_vnode *vnode = target; | 
|  |  | 
|  | _enter("{%x,%x,%Lx},{%x,%x,%Lx}", | 
|  | vnode->fid.vnode, | 
|  | vnode->fid.unique, | 
|  | vnode->status.version, | 
|  | cvnode->vnode_id, | 
|  | cvnode->vnode_unique, | 
|  | cvnode->data_version); | 
|  |  | 
|  | if (vnode->fid.vnode != cvnode->vnode_id) { | 
|  | _leave(" = FAILED"); | 
|  | return CACHEFS_MATCH_FAILED; | 
|  | } | 
|  |  | 
|  | if (vnode->fid.unique != cvnode->vnode_unique || | 
|  | vnode->status.version != cvnode->data_version) { | 
|  | _leave(" = DELETE"); | 
|  | return CACHEFS_MATCH_SUCCESS_DELETE; | 
|  | } | 
|  |  | 
|  | _leave(" = SUCCESS"); | 
|  | return CACHEFS_MATCH_SUCCESS; | 
|  | } | 
|  | #endif | 
|  |  | 
|  | /* | 
|  | * update a vnode record stored in the cache | 
|  | */ | 
|  | #ifdef AFS_CACHING_SUPPORT | 
|  | static void afs_vnode_cache_update(void *source, void *entry) | 
|  | { | 
|  | struct afs_cache_vnode *cvnode = entry; | 
|  | struct afs_vnode *vnode = source; | 
|  |  | 
|  | _enter(""); | 
|  |  | 
|  | cvnode->vnode_id	= vnode->fid.vnode; | 
|  | cvnode->vnode_unique	= vnode->fid.unique; | 
|  | cvnode->data_version	= vnode->status.version; | 
|  | } | 
|  | #endif |