257 lines
		
	
	
	
		
			6.3 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			257 lines
		
	
	
	
		
			6.3 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								/* 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
							 |