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
13static cachefs_match_val_t afs_cell_cache_match(void *target,
14						const void *entry);
15static void afs_cell_cache_update(void *source, void *entry);
16
17struct 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
30static 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
52static 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
69static cachefs_match_val_t afs_vlocation_cache_match(void *target,
70						     const void *entry);
71static void afs_vlocation_cache_update(void *source, void *entry);
72
73struct 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
87static 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
130static 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
142static cachefs_match_val_t afs_volume_cache_match(void *target,
143						  const void *entry);
144static void afs_volume_cache_update(void *source, void *entry);
145
146struct 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
160static 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
182static 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
194static cachefs_match_val_t afs_vnode_cache_match(void *target,
195						 const void *entry);
196static void afs_vnode_cache_update(void *source, void *entry);
197
198struct 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
211static 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
245static 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
257