Linux Audio

Check our new training course

Loading...
v4.17
 1/* AFS caching stuff
 2 *
 3 * Copyright (C) 2008 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#include <linux/sched.h>
13#include "internal.h"
14
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15static enum fscache_checkaux afs_vnode_cache_check_aux(void *cookie_netfs_data,
16						       const void *buffer,
17						       uint16_t buflen,
18						       loff_t object_size);
19
20struct fscache_netfs afs_cache_netfs = {
21	.name			= "afs",
22	.version		= 2,
23};
24
25struct fscache_cookie_def afs_cell_cache_index_def = {
26	.name		= "AFS.cell",
27	.type		= FSCACHE_COOKIE_TYPE_INDEX,
 
 
 
 
 
 
 
 
 
 
 
28};
29
30struct fscache_cookie_def afs_volume_cache_index_def = {
31	.name		= "AFS.volume",
32	.type		= FSCACHE_COOKIE_TYPE_INDEX,
 
33};
34
35struct fscache_cookie_def afs_vnode_cache_index_def = {
36	.name		= "AFS.vnode",
37	.type		= FSCACHE_COOKIE_TYPE_DATAFILE,
38	.check_aux	= afs_vnode_cache_check_aux,
 
 
 
 
39};
40
41/*
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42 * check that the auxiliary data indicates that the entry is still valid
43 */
44static enum fscache_checkaux afs_vnode_cache_check_aux(void *cookie_netfs_data,
45						       const void *buffer,
46						       uint16_t buflen,
47						       loff_t object_size)
48{
49	struct afs_vnode *vnode = cookie_netfs_data;
50	struct afs_vnode_cache_aux aux;
51
52	_enter("{%x,%x,%llx},%p,%u",
53	       vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version,
54	       buffer, buflen);
55
56	memcpy(&aux, buffer, sizeof(aux));
57
58	/* check the size of the data is what we're expecting */
59	if (buflen != sizeof(aux)) {
60		_leave(" = OBSOLETE [len %hx != %zx]", buflen, sizeof(aux));
 
61		return FSCACHE_CHECKAUX_OBSOLETE;
62	}
63
64	if (vnode->status.data_version != aux.data_version) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65		_leave(" = OBSOLETE [vers %llx != %llx]",
66		       aux.data_version, vnode->status.data_version);
67		return FSCACHE_CHECKAUX_OBSOLETE;
68	}
69
70	_leave(" = SUCCESS");
71	return FSCACHE_CHECKAUX_OKAY;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72}
v3.1
  1/* AFS caching stuff
  2 *
  3 * Copyright (C) 2008 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#include <linux/sched.h>
 13#include "internal.h"
 14
 15static uint16_t afs_cell_cache_get_key(const void *cookie_netfs_data,
 16				       void *buffer, uint16_t buflen);
 17static uint16_t afs_cell_cache_get_aux(const void *cookie_netfs_data,
 18				       void *buffer, uint16_t buflen);
 19static enum fscache_checkaux afs_cell_cache_check_aux(void *cookie_netfs_data,
 20						      const void *buffer,
 21						      uint16_t buflen);
 22
 23static uint16_t afs_vlocation_cache_get_key(const void *cookie_netfs_data,
 24					    void *buffer, uint16_t buflen);
 25static uint16_t afs_vlocation_cache_get_aux(const void *cookie_netfs_data,
 26					    void *buffer, uint16_t buflen);
 27static enum fscache_checkaux afs_vlocation_cache_check_aux(
 28	void *cookie_netfs_data, const void *buffer, uint16_t buflen);
 29
 30static uint16_t afs_volume_cache_get_key(const void *cookie_netfs_data,
 31					 void *buffer, uint16_t buflen);
 32
 33static uint16_t afs_vnode_cache_get_key(const void *cookie_netfs_data,
 34					void *buffer, uint16_t buflen);
 35static void afs_vnode_cache_get_attr(const void *cookie_netfs_data,
 36				     uint64_t *size);
 37static uint16_t afs_vnode_cache_get_aux(const void *cookie_netfs_data,
 38					void *buffer, uint16_t buflen);
 39static enum fscache_checkaux afs_vnode_cache_check_aux(void *cookie_netfs_data,
 40						       const void *buffer,
 41						       uint16_t buflen);
 42static void afs_vnode_cache_now_uncached(void *cookie_netfs_data);
 43
 44struct fscache_netfs afs_cache_netfs = {
 45	.name			= "afs",
 46	.version		= 0,
 47};
 48
 49struct fscache_cookie_def afs_cell_cache_index_def = {
 50	.name		= "AFS.cell",
 51	.type		= FSCACHE_COOKIE_TYPE_INDEX,
 52	.get_key	= afs_cell_cache_get_key,
 53	.get_aux	= afs_cell_cache_get_aux,
 54	.check_aux	= afs_cell_cache_check_aux,
 55};
 56
 57struct fscache_cookie_def afs_vlocation_cache_index_def = {
 58	.name			= "AFS.vldb",
 59	.type			= FSCACHE_COOKIE_TYPE_INDEX,
 60	.get_key		= afs_vlocation_cache_get_key,
 61	.get_aux		= afs_vlocation_cache_get_aux,
 62	.check_aux		= afs_vlocation_cache_check_aux,
 63};
 64
 65struct fscache_cookie_def afs_volume_cache_index_def = {
 66	.name		= "AFS.volume",
 67	.type		= FSCACHE_COOKIE_TYPE_INDEX,
 68	.get_key	= afs_volume_cache_get_key,
 69};
 70
 71struct fscache_cookie_def afs_vnode_cache_index_def = {
 72	.name			= "AFS.vnode",
 73	.type			= FSCACHE_COOKIE_TYPE_DATAFILE,
 74	.get_key		= afs_vnode_cache_get_key,
 75	.get_attr		= afs_vnode_cache_get_attr,
 76	.get_aux		= afs_vnode_cache_get_aux,
 77	.check_aux		= afs_vnode_cache_check_aux,
 78	.now_uncached		= afs_vnode_cache_now_uncached,
 79};
 80
 81/*
 82 * set the key for the index entry
 83 */
 84static uint16_t afs_cell_cache_get_key(const void *cookie_netfs_data,
 85				       void *buffer, uint16_t bufmax)
 86{
 87	const struct afs_cell *cell = cookie_netfs_data;
 88	uint16_t klen;
 89
 90	_enter("%p,%p,%u", cell, buffer, bufmax);
 91
 92	klen = strlen(cell->name);
 93	if (klen > bufmax)
 94		return 0;
 95
 96	memcpy(buffer, cell->name, klen);
 97	return klen;
 98}
 99
100/*
101 * provide new auxiliary cache data
102 */
103static uint16_t afs_cell_cache_get_aux(const void *cookie_netfs_data,
104				       void *buffer, uint16_t bufmax)
105{
106	const struct afs_cell *cell = cookie_netfs_data;
107	uint16_t dlen;
108
109	_enter("%p,%p,%u", cell, buffer, bufmax);
110
111	dlen = cell->vl_naddrs * sizeof(cell->vl_addrs[0]);
112	dlen = min(dlen, bufmax);
113	dlen &= ~(sizeof(cell->vl_addrs[0]) - 1);
114
115	memcpy(buffer, cell->vl_addrs, dlen);
116	return dlen;
117}
118
119/*
120 * check that the auxiliary data indicates that the entry is still valid
121 */
122static enum fscache_checkaux afs_cell_cache_check_aux(void *cookie_netfs_data,
123						      const void *buffer,
124						      uint16_t buflen)
125{
126	_leave(" = OKAY");
127	return FSCACHE_CHECKAUX_OKAY;
128}
129
130/*****************************************************************************/
131/*
132 * set the key for the index entry
133 */
134static uint16_t afs_vlocation_cache_get_key(const void *cookie_netfs_data,
135					    void *buffer, uint16_t bufmax)
136{
137	const struct afs_vlocation *vlocation = cookie_netfs_data;
138	uint16_t klen;
139
140	_enter("{%s},%p,%u", vlocation->vldb.name, buffer, bufmax);
141
142	klen = strnlen(vlocation->vldb.name, sizeof(vlocation->vldb.name));
143	if (klen > bufmax)
144		return 0;
145
146	memcpy(buffer, vlocation->vldb.name, klen);
147
148	_leave(" = %u", klen);
149	return klen;
150}
151
152/*
153 * provide new auxiliary cache data
154 */
155static uint16_t afs_vlocation_cache_get_aux(const void *cookie_netfs_data,
156					    void *buffer, uint16_t bufmax)
157{
158	const struct afs_vlocation *vlocation = cookie_netfs_data;
159	uint16_t dlen;
160
161	_enter("{%s},%p,%u", vlocation->vldb.name, buffer, bufmax);
162
163	dlen = sizeof(struct afs_cache_vlocation);
164	dlen -= offsetof(struct afs_cache_vlocation, nservers);
165	if (dlen > bufmax)
166		return 0;
167
168	memcpy(buffer, (uint8_t *)&vlocation->vldb.nservers, dlen);
169
170	_leave(" = %u", dlen);
171	return dlen;
172}
173
174/*
175 * check that the auxiliary data indicates that the entry is still valid
176 */
177static
178enum fscache_checkaux afs_vlocation_cache_check_aux(void *cookie_netfs_data,
179						    const void *buffer,
180						    uint16_t buflen)
181{
182	const struct afs_cache_vlocation *cvldb;
183	struct afs_vlocation *vlocation = cookie_netfs_data;
184	uint16_t dlen;
185
186	_enter("{%s},%p,%u", vlocation->vldb.name, buffer, buflen);
187
188	/* check the size of the data is what we're expecting */
189	dlen = sizeof(struct afs_cache_vlocation);
190	dlen -= offsetof(struct afs_cache_vlocation, nservers);
191	if (dlen != buflen)
192		return FSCACHE_CHECKAUX_OBSOLETE;
193
194	cvldb = container_of(buffer, struct afs_cache_vlocation, nservers);
195
196	/* if what's on disk is more valid than what's in memory, then use the
197	 * VL record from the cache */
198	if (!vlocation->valid || vlocation->vldb.rtime == cvldb->rtime) {
199		memcpy((uint8_t *)&vlocation->vldb.nservers, buffer, dlen);
200		vlocation->valid = 1;
201		_leave(" = SUCCESS [c->m]");
202		return FSCACHE_CHECKAUX_OKAY;
203	}
204
205	/* need to update the cache if the cached info differs */
206	if (memcmp(&vlocation->vldb, buffer, dlen) != 0) {
207		/* delete if the volume IDs for this name differ */
208		if (memcmp(&vlocation->vldb.vid, &cvldb->vid,
209			   sizeof(cvldb->vid)) != 0
210		    ) {
211			_leave(" = OBSOLETE");
212			return FSCACHE_CHECKAUX_OBSOLETE;
213		}
214
215		_leave(" = UPDATE");
216		return FSCACHE_CHECKAUX_NEEDS_UPDATE;
217	}
218
219	_leave(" = OKAY");
220	return FSCACHE_CHECKAUX_OKAY;
221}
222
223/*****************************************************************************/
224/*
225 * set the key for the volume index entry
226 */
227static uint16_t afs_volume_cache_get_key(const void *cookie_netfs_data,
228					void *buffer, uint16_t bufmax)
229{
230	const struct afs_volume *volume = cookie_netfs_data;
231	uint16_t klen;
232
233	_enter("{%u},%p,%u", volume->type, buffer, bufmax);
234
235	klen = sizeof(volume->type);
236	if (klen > bufmax)
237		return 0;
238
239	memcpy(buffer, &volume->type, sizeof(volume->type));
240
241	_leave(" = %u", klen);
242	return klen;
243
244}
245
246/*****************************************************************************/
247/*
248 * set the key for the index entry
249 */
250static uint16_t afs_vnode_cache_get_key(const void *cookie_netfs_data,
251					void *buffer, uint16_t bufmax)
252{
253	const struct afs_vnode *vnode = cookie_netfs_data;
254	uint16_t klen;
255
256	_enter("{%x,%x,%llx},%p,%u",
257	       vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version,
258	       buffer, bufmax);
259
260	klen = sizeof(vnode->fid.vnode);
261	if (klen > bufmax)
262		return 0;
263
264	memcpy(buffer, &vnode->fid.vnode, sizeof(vnode->fid.vnode));
265
266	_leave(" = %u", klen);
267	return klen;
268}
269
270/*
271 * provide updated file attributes
272 */
273static void afs_vnode_cache_get_attr(const void *cookie_netfs_data,
274				     uint64_t *size)
275{
276	const struct afs_vnode *vnode = cookie_netfs_data;
277
278	_enter("{%x,%x,%llx},",
279	       vnode->fid.vnode, vnode->fid.unique,
280	       vnode->status.data_version);
281
282	*size = vnode->status.size;
283}
284
285/*
286 * provide new auxiliary cache data
287 */
288static uint16_t afs_vnode_cache_get_aux(const void *cookie_netfs_data,
289					void *buffer, uint16_t bufmax)
290{
291	const struct afs_vnode *vnode = cookie_netfs_data;
292	uint16_t dlen;
293
294	_enter("{%x,%x,%Lx},%p,%u",
295	       vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version,
296	       buffer, bufmax);
297
298	dlen = sizeof(vnode->fid.unique) + sizeof(vnode->status.data_version);
299	if (dlen > bufmax)
300		return 0;
301
302	memcpy(buffer, &vnode->fid.unique, sizeof(vnode->fid.unique));
303	buffer += sizeof(vnode->fid.unique);
304	memcpy(buffer, &vnode->status.data_version,
305	       sizeof(vnode->status.data_version));
306
307	_leave(" = %u", dlen);
308	return dlen;
309}
310
311/*
312 * check that the auxiliary data indicates that the entry is still valid
313 */
314static enum fscache_checkaux afs_vnode_cache_check_aux(void *cookie_netfs_data,
315						       const void *buffer,
316						       uint16_t buflen)
 
317{
318	struct afs_vnode *vnode = cookie_netfs_data;
319	uint16_t dlen;
320
321	_enter("{%x,%x,%llx},%p,%u",
322	       vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version,
323	       buffer, buflen);
324
 
 
325	/* check the size of the data is what we're expecting */
326	dlen = sizeof(vnode->fid.unique) + sizeof(vnode->status.data_version);
327	if (dlen != buflen) {
328		_leave(" = OBSOLETE [len %hx != %hx]", dlen, buflen);
329		return FSCACHE_CHECKAUX_OBSOLETE;
330	}
331
332	if (memcmp(buffer,
333		   &vnode->fid.unique,
334		   sizeof(vnode->fid.unique)
335		   ) != 0) {
336		unsigned unique;
337
338		memcpy(&unique, buffer, sizeof(unique));
339
340		_leave(" = OBSOLETE [uniq %x != %x]",
341		       unique, vnode->fid.unique);
342		return FSCACHE_CHECKAUX_OBSOLETE;
343	}
344
345	if (memcmp(buffer + sizeof(vnode->fid.unique),
346		   &vnode->status.data_version,
347		   sizeof(vnode->status.data_version)
348		   ) != 0) {
349		afs_dataversion_t version;
350
351		memcpy(&version, buffer + sizeof(vnode->fid.unique),
352		       sizeof(version));
353
354		_leave(" = OBSOLETE [vers %llx != %llx]",
355		       version, vnode->status.data_version);
356		return FSCACHE_CHECKAUX_OBSOLETE;
357	}
358
359	_leave(" = SUCCESS");
360	return FSCACHE_CHECKAUX_OKAY;
361}
362
363/*
364 * indication the cookie is no longer uncached
365 * - this function is called when the backing store currently caching a cookie
366 *   is removed
367 * - the netfs should use this to clean up any markers indicating cached pages
368 * - this is mandatory for any object that may have data
369 */
370static void afs_vnode_cache_now_uncached(void *cookie_netfs_data)
371{
372	struct afs_vnode *vnode = cookie_netfs_data;
373	struct pagevec pvec;
374	pgoff_t first;
375	int loop, nr_pages;
376
377	_enter("{%x,%x,%Lx}",
378	       vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version);
379
380	pagevec_init(&pvec, 0);
381	first = 0;
382
383	for (;;) {
384		/* grab a bunch of pages to clean */
385		nr_pages = pagevec_lookup(&pvec, vnode->vfs_inode.i_mapping,
386					  first,
387					  PAGEVEC_SIZE - pagevec_count(&pvec));
388		if (!nr_pages)
389			break;
390
391		for (loop = 0; loop < nr_pages; loop++)
392			ClearPageFsCache(pvec.pages[loop]);
393
394		first = pvec.pages[nr_pages - 1]->index + 1;
395
396		pvec.nr = nr_pages;
397		pagevec_release(&pvec);
398		cond_resched();
399	}
400
401	_leave("");
402}