| David Howells | 08e0e7c | 2007-04-26 15:55:03 -0700 | [diff] [blame] | 1 | /* AFS caching stuff | 
 | 2 |  * | 
 | 3 |  * Copyright (C) 2007 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 | #ifdef AFS_CACHING_SUPPORT | 
 | 13 | static cachefs_match_val_t afs_cell_cache_match(void *target, | 
 | 14 | 						const void *entry); | 
 | 15 | static void afs_cell_cache_update(void *source, void *entry); | 
 | 16 |  | 
 | 17 | struct cachefs_index_def afs_cache_cell_index_def = { | 
 | 18 | 	.name			= "cell_ix", | 
 | 19 | 	.data_size		= sizeof(struct afs_cache_cell), | 
 | 20 | 	.keys[0]		= { CACHEFS_INDEX_KEYS_ASCIIZ, 64 }, | 
 | 21 | 	.match			= afs_cell_cache_match, | 
 | 22 | 	.update			= afs_cell_cache_update, | 
 | 23 | }; | 
 | 24 | #endif | 
 | 25 |  | 
 | 26 | /* | 
 | 27 |  * match a cell record obtained from the cache | 
 | 28 |  */ | 
 | 29 | #ifdef AFS_CACHING_SUPPORT | 
 | 30 | static cachefs_match_val_t afs_cell_cache_match(void *target, | 
 | 31 | 						const void *entry) | 
 | 32 | { | 
 | 33 | 	const struct afs_cache_cell *ccell = entry; | 
 | 34 | 	struct afs_cell *cell = target; | 
 | 35 |  | 
 | 36 | 	_enter("{%s},{%s}", ccell->name, cell->name); | 
 | 37 |  | 
 | 38 | 	if (strncmp(ccell->name, cell->name, sizeof(ccell->name)) == 0) { | 
 | 39 | 		_leave(" = SUCCESS"); | 
 | 40 | 		return CACHEFS_MATCH_SUCCESS; | 
 | 41 | 	} | 
 | 42 |  | 
 | 43 | 	_leave(" = FAILED"); | 
 | 44 | 	return CACHEFS_MATCH_FAILED; | 
 | 45 | } | 
 | 46 | #endif | 
 | 47 |  | 
 | 48 | /* | 
 | 49 |  * update a cell record in the cache | 
 | 50 |  */ | 
 | 51 | #ifdef AFS_CACHING_SUPPORT | 
 | 52 | static void afs_cell_cache_update(void *source, void *entry) | 
 | 53 | { | 
 | 54 | 	struct afs_cache_cell *ccell = entry; | 
 | 55 | 	struct afs_cell *cell = source; | 
 | 56 |  | 
 | 57 | 	_enter("%p,%p", source, entry); | 
 | 58 |  | 
 | 59 | 	strncpy(ccell->name, cell->name, sizeof(ccell->name)); | 
 | 60 |  | 
 | 61 | 	memcpy(ccell->vl_servers, | 
 | 62 | 	       cell->vl_addrs, | 
 | 63 | 	       min(sizeof(ccell->vl_servers), sizeof(cell->vl_addrs))); | 
 | 64 |  | 
 | 65 | } | 
 | 66 | #endif | 
 | 67 |  | 
 | 68 | #ifdef AFS_CACHING_SUPPORT | 
 | 69 | static cachefs_match_val_t afs_vlocation_cache_match(void *target, | 
 | 70 | 						     const void *entry); | 
 | 71 | static void afs_vlocation_cache_update(void *source, void *entry); | 
 | 72 |  | 
 | 73 | struct cachefs_index_def afs_vlocation_cache_index_def = { | 
 | 74 | 	.name		= "vldb", | 
 | 75 | 	.data_size	= sizeof(struct afs_cache_vlocation), | 
 | 76 | 	.keys[0]	= { CACHEFS_INDEX_KEYS_ASCIIZ, 64 }, | 
 | 77 | 	.match		= afs_vlocation_cache_match, | 
 | 78 | 	.update		= afs_vlocation_cache_update, | 
 | 79 | }; | 
 | 80 | #endif | 
 | 81 |  | 
 | 82 | /* | 
 | 83 |  * match a VLDB record stored in the cache | 
 | 84 |  * - may also load target from entry | 
 | 85 |  */ | 
 | 86 | #ifdef AFS_CACHING_SUPPORT | 
 | 87 | static cachefs_match_val_t afs_vlocation_cache_match(void *target, | 
 | 88 | 						     const void *entry) | 
 | 89 | { | 
 | 90 | 	const struct afs_cache_vlocation *vldb = entry; | 
 | 91 | 	struct afs_vlocation *vlocation = target; | 
 | 92 |  | 
 | 93 | 	_enter("{%s},{%s}", vlocation->vldb.name, vldb->name); | 
 | 94 |  | 
 | 95 | 	if (strncmp(vlocation->vldb.name, vldb->name, sizeof(vldb->name)) == 0 | 
 | 96 | 	    ) { | 
 | 97 | 		if (!vlocation->valid || | 
 | 98 | 		    vlocation->vldb.rtime == vldb->rtime | 
 | 99 | 		    ) { | 
 | 100 | 			vlocation->vldb = *vldb; | 
 | 101 | 			vlocation->valid = 1; | 
 | 102 | 			_leave(" = SUCCESS [c->m]"); | 
 | 103 | 			return CACHEFS_MATCH_SUCCESS; | 
 | 104 | 		} else if (memcmp(&vlocation->vldb, vldb, sizeof(*vldb)) != 0) { | 
 | 105 | 			/* delete if VIDs for this name differ */ | 
 | 106 | 			if (memcmp(&vlocation->vldb.vid, | 
 | 107 | 				   &vldb->vid, | 
 | 108 | 				   sizeof(vldb->vid)) != 0) { | 
 | 109 | 				_leave(" = DELETE"); | 
 | 110 | 				return CACHEFS_MATCH_SUCCESS_DELETE; | 
 | 111 | 			} | 
 | 112 |  | 
 | 113 | 			_leave(" = UPDATE"); | 
 | 114 | 			return CACHEFS_MATCH_SUCCESS_UPDATE; | 
 | 115 | 		} else { | 
 | 116 | 			_leave(" = SUCCESS"); | 
 | 117 | 			return CACHEFS_MATCH_SUCCESS; | 
 | 118 | 		} | 
 | 119 | 	} | 
 | 120 |  | 
 | 121 | 	_leave(" = FAILED"); | 
 | 122 | 	return CACHEFS_MATCH_FAILED; | 
 | 123 | } | 
 | 124 | #endif | 
 | 125 |  | 
 | 126 | /* | 
 | 127 |  * update a VLDB record stored in the cache | 
 | 128 |  */ | 
 | 129 | #ifdef AFS_CACHING_SUPPORT | 
 | 130 | static void afs_vlocation_cache_update(void *source, void *entry) | 
 | 131 | { | 
 | 132 | 	struct afs_cache_vlocation *vldb = entry; | 
 | 133 | 	struct afs_vlocation *vlocation = source; | 
 | 134 |  | 
 | 135 | 	_enter(""); | 
 | 136 |  | 
 | 137 | 	*vldb = vlocation->vldb; | 
 | 138 | } | 
 | 139 | #endif | 
 | 140 |  | 
 | 141 | #ifdef AFS_CACHING_SUPPORT | 
 | 142 | static cachefs_match_val_t afs_volume_cache_match(void *target, | 
 | 143 | 						  const void *entry); | 
 | 144 | static void afs_volume_cache_update(void *source, void *entry); | 
 | 145 |  | 
 | 146 | struct cachefs_index_def afs_volume_cache_index_def = { | 
 | 147 | 	.name		= "volume", | 
 | 148 | 	.data_size	= sizeof(struct afs_cache_vhash), | 
 | 149 | 	.keys[0]	= { CACHEFS_INDEX_KEYS_BIN, 1 }, | 
 | 150 | 	.keys[1]	= { CACHEFS_INDEX_KEYS_BIN, 1 }, | 
 | 151 | 	.match		= afs_volume_cache_match, | 
 | 152 | 	.update		= afs_volume_cache_update, | 
 | 153 | }; | 
 | 154 | #endif | 
 | 155 |  | 
 | 156 | /* | 
 | 157 |  * match a volume hash record stored in the cache | 
 | 158 |  */ | 
 | 159 | #ifdef AFS_CACHING_SUPPORT | 
 | 160 | static cachefs_match_val_t afs_volume_cache_match(void *target, | 
 | 161 | 						  const void *entry) | 
 | 162 | { | 
 | 163 | 	const struct afs_cache_vhash *vhash = entry; | 
 | 164 | 	struct afs_volume *volume = target; | 
 | 165 |  | 
 | 166 | 	_enter("{%u},{%u}", volume->type, vhash->vtype); | 
 | 167 |  | 
 | 168 | 	if (volume->type == vhash->vtype) { | 
 | 169 | 		_leave(" = SUCCESS"); | 
 | 170 | 		return CACHEFS_MATCH_SUCCESS; | 
 | 171 | 	} | 
 | 172 |  | 
 | 173 | 	_leave(" = FAILED"); | 
 | 174 | 	return CACHEFS_MATCH_FAILED; | 
 | 175 | } | 
 | 176 | #endif | 
 | 177 |  | 
 | 178 | /* | 
 | 179 |  * update a volume hash record stored in the cache | 
 | 180 |  */ | 
 | 181 | #ifdef AFS_CACHING_SUPPORT | 
 | 182 | static void afs_volume_cache_update(void *source, void *entry) | 
 | 183 | { | 
 | 184 | 	struct afs_cache_vhash *vhash = entry; | 
 | 185 | 	struct afs_volume *volume = source; | 
 | 186 |  | 
 | 187 | 	_enter(""); | 
 | 188 |  | 
 | 189 | 	vhash->vtype = volume->type; | 
 | 190 | } | 
 | 191 | #endif | 
 | 192 |  | 
 | 193 | #ifdef AFS_CACHING_SUPPORT | 
 | 194 | static cachefs_match_val_t afs_vnode_cache_match(void *target, | 
 | 195 | 						 const void *entry); | 
 | 196 | static void afs_vnode_cache_update(void *source, void *entry); | 
 | 197 |  | 
 | 198 | struct cachefs_index_def afs_vnode_cache_index_def = { | 
 | 199 | 	.name		= "vnode", | 
 | 200 | 	.data_size	= sizeof(struct afs_cache_vnode), | 
 | 201 | 	.keys[0]	= { CACHEFS_INDEX_KEYS_BIN, 4 }, | 
 | 202 | 	.match		= afs_vnode_cache_match, | 
 | 203 | 	.update		= afs_vnode_cache_update, | 
 | 204 | }; | 
 | 205 | #endif | 
 | 206 |  | 
 | 207 | /* | 
 | 208 |  * match a vnode record stored in the cache | 
 | 209 |  */ | 
 | 210 | #ifdef AFS_CACHING_SUPPORT | 
 | 211 | static cachefs_match_val_t afs_vnode_cache_match(void *target, | 
 | 212 | 						 const void *entry) | 
 | 213 | { | 
 | 214 | 	const struct afs_cache_vnode *cvnode = entry; | 
 | 215 | 	struct afs_vnode *vnode = target; | 
 | 216 |  | 
 | 217 | 	_enter("{%x,%x,%Lx},{%x,%x,%Lx}", | 
 | 218 | 	       vnode->fid.vnode, | 
 | 219 | 	       vnode->fid.unique, | 
 | 220 | 	       vnode->status.version, | 
 | 221 | 	       cvnode->vnode_id, | 
 | 222 | 	       cvnode->vnode_unique, | 
 | 223 | 	       cvnode->data_version); | 
 | 224 |  | 
 | 225 | 	if (vnode->fid.vnode != cvnode->vnode_id) { | 
 | 226 | 		_leave(" = FAILED"); | 
 | 227 | 		return CACHEFS_MATCH_FAILED; | 
 | 228 | 	} | 
 | 229 |  | 
 | 230 | 	if (vnode->fid.unique != cvnode->vnode_unique || | 
 | 231 | 	    vnode->status.version != cvnode->data_version) { | 
 | 232 | 		_leave(" = DELETE"); | 
 | 233 | 		return CACHEFS_MATCH_SUCCESS_DELETE; | 
 | 234 | 	} | 
 | 235 |  | 
 | 236 | 	_leave(" = SUCCESS"); | 
 | 237 | 	return CACHEFS_MATCH_SUCCESS; | 
 | 238 | } | 
 | 239 | #endif | 
 | 240 |  | 
 | 241 | /* | 
 | 242 |  * update a vnode record stored in the cache | 
 | 243 |  */ | 
 | 244 | #ifdef AFS_CACHING_SUPPORT | 
 | 245 | static void afs_vnode_cache_update(void *source, void *entry) | 
 | 246 | { | 
 | 247 | 	struct afs_cache_vnode *cvnode = entry; | 
 | 248 | 	struct afs_vnode *vnode = source; | 
 | 249 |  | 
 | 250 | 	_enter(""); | 
 | 251 |  | 
 | 252 | 	cvnode->vnode_id	= vnode->fid.vnode; | 
 | 253 | 	cvnode->vnode_unique	= vnode->fid.unique; | 
 | 254 | 	cvnode->data_version	= vnode->status.version; | 
 | 255 | } | 
 | 256 | #endif |