Blame view

fs/afs/cache.c 10.8 KB
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
1
2
  /* AFS caching stuff
   *
9b3f26c91   David Howells   FS-Cache: Make kA...
3
   * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved.
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
4
5
6
7
8
9
10
   * 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.
   */
9b3f26c91   David Howells   FS-Cache: Make kA...
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
  #include <linux/sched.h>
  #include "internal.h"
  
  static uint16_t afs_cell_cache_get_key(const void *cookie_netfs_data,
  				       void *buffer, uint16_t buflen);
  static uint16_t afs_cell_cache_get_aux(const void *cookie_netfs_data,
  				       void *buffer, uint16_t buflen);
  static enum fscache_checkaux afs_cell_cache_check_aux(void *cookie_netfs_data,
  						      const void *buffer,
  						      uint16_t buflen);
  
  static uint16_t afs_vlocation_cache_get_key(const void *cookie_netfs_data,
  					    void *buffer, uint16_t buflen);
  static uint16_t afs_vlocation_cache_get_aux(const void *cookie_netfs_data,
  					    void *buffer, uint16_t buflen);
  static enum fscache_checkaux afs_vlocation_cache_check_aux(
  	void *cookie_netfs_data, const void *buffer, uint16_t buflen);
  
  static uint16_t afs_volume_cache_get_key(const void *cookie_netfs_data,
  					 void *buffer, uint16_t buflen);
  
  static uint16_t afs_vnode_cache_get_key(const void *cookie_netfs_data,
  					void *buffer, uint16_t buflen);
  static void afs_vnode_cache_get_attr(const void *cookie_netfs_data,
  				     uint64_t *size);
  static uint16_t afs_vnode_cache_get_aux(const void *cookie_netfs_data,
  					void *buffer, uint16_t buflen);
  static enum fscache_checkaux afs_vnode_cache_check_aux(void *cookie_netfs_data,
  						       const void *buffer,
  						       uint16_t buflen);
  static void afs_vnode_cache_now_uncached(void *cookie_netfs_data);
  
  struct fscache_netfs afs_cache_netfs = {
  	.name			= "afs",
  	.version		= 0,
  };
  
  struct fscache_cookie_def afs_cell_cache_index_def = {
  	.name		= "AFS.cell",
  	.type		= FSCACHE_COOKIE_TYPE_INDEX,
  	.get_key	= afs_cell_cache_get_key,
  	.get_aux	= afs_cell_cache_get_aux,
  	.check_aux	= afs_cell_cache_check_aux,
  };
  
  struct fscache_cookie_def afs_vlocation_cache_index_def = {
  	.name			= "AFS.vldb",
  	.type			= FSCACHE_COOKIE_TYPE_INDEX,
  	.get_key		= afs_vlocation_cache_get_key,
  	.get_aux		= afs_vlocation_cache_get_aux,
  	.check_aux		= afs_vlocation_cache_check_aux,
  };
  
  struct fscache_cookie_def afs_volume_cache_index_def = {
  	.name		= "AFS.volume",
  	.type		= FSCACHE_COOKIE_TYPE_INDEX,
  	.get_key	= afs_volume_cache_get_key,
  };
  
  struct fscache_cookie_def afs_vnode_cache_index_def = {
  	.name			= "AFS.vnode",
  	.type			= FSCACHE_COOKIE_TYPE_DATAFILE,
  	.get_key		= afs_vnode_cache_get_key,
  	.get_attr		= afs_vnode_cache_get_attr,
  	.get_aux		= afs_vnode_cache_get_aux,
  	.check_aux		= afs_vnode_cache_check_aux,
  	.now_uncached		= afs_vnode_cache_now_uncached,
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
78
  };
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
79
80
  
  /*
9b3f26c91   David Howells   FS-Cache: Make kA...
81
   * set the key for the index entry
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
82
   */
9b3f26c91   David Howells   FS-Cache: Make kA...
83
84
  static uint16_t afs_cell_cache_get_key(const void *cookie_netfs_data,
  				       void *buffer, uint16_t bufmax)
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
85
  {
9b3f26c91   David Howells   FS-Cache: Make kA...
86
87
  	const struct afs_cell *cell = cookie_netfs_data;
  	uint16_t klen;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
88

9b3f26c91   David Howells   FS-Cache: Make kA...
89
  	_enter("%p,%p,%u", cell, buffer, bufmax);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
90

9b3f26c91   David Howells   FS-Cache: Make kA...
91
92
93
  	klen = strlen(cell->name);
  	if (klen > bufmax)
  		return 0;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
94

9b3f26c91   David Howells   FS-Cache: Make kA...
95
96
  	memcpy(buffer, cell->name, klen);
  	return klen;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
97
  }
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
98
99
  
  /*
25985edce   Lucas De Marchi   Fix common misspe...
100
   * provide new auxiliary cache data
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
101
   */
9b3f26c91   David Howells   FS-Cache: Make kA...
102
103
  static uint16_t afs_cell_cache_get_aux(const void *cookie_netfs_data,
  				       void *buffer, uint16_t bufmax)
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
104
  {
9b3f26c91   David Howells   FS-Cache: Make kA...
105
106
  	const struct afs_cell *cell = cookie_netfs_data;
  	uint16_t dlen;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
107

9b3f26c91   David Howells   FS-Cache: Make kA...
108
  	_enter("%p,%p,%u", cell, buffer, bufmax);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
109

9b3f26c91   David Howells   FS-Cache: Make kA...
110
111
112
  	dlen = cell->vl_naddrs * sizeof(cell->vl_addrs[0]);
  	dlen = min(dlen, bufmax);
  	dlen &= ~(sizeof(cell->vl_addrs[0]) - 1);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
113

9b3f26c91   David Howells   FS-Cache: Make kA...
114
115
116
  	memcpy(buffer, cell->vl_addrs, dlen);
  	return dlen;
  }
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
117

9b3f26c91   David Howells   FS-Cache: Make kA...
118
  /*
25985edce   Lucas De Marchi   Fix common misspe...
119
   * check that the auxiliary data indicates that the entry is still valid
9b3f26c91   David Howells   FS-Cache: Make kA...
120
121
122
123
124
125
126
   */
  static enum fscache_checkaux afs_cell_cache_check_aux(void *cookie_netfs_data,
  						      const void *buffer,
  						      uint16_t buflen)
  {
  	_leave(" = OKAY");
  	return FSCACHE_CHECKAUX_OKAY;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
127
  }
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
128

9b3f26c91   David Howells   FS-Cache: Make kA...
129
  /*****************************************************************************/
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
130
  /*
9b3f26c91   David Howells   FS-Cache: Make kA...
131
   * set the key for the index entry
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
132
   */
9b3f26c91   David Howells   FS-Cache: Make kA...
133
134
  static uint16_t afs_vlocation_cache_get_key(const void *cookie_netfs_data,
  					    void *buffer, uint16_t bufmax)
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
135
  {
9b3f26c91   David Howells   FS-Cache: Make kA...
136
137
138
139
140
141
142
143
  	const struct afs_vlocation *vlocation = cookie_netfs_data;
  	uint16_t klen;
  
  	_enter("{%s},%p,%u", vlocation->vldb.name, buffer, bufmax);
  
  	klen = strnlen(vlocation->vldb.name, sizeof(vlocation->vldb.name));
  	if (klen > bufmax)
  		return 0;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
144

9b3f26c91   David Howells   FS-Cache: Make kA...
145
  	memcpy(buffer, vlocation->vldb.name, klen);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
146

9b3f26c91   David Howells   FS-Cache: Make kA...
147
148
149
150
151
  	_leave(" = %u", klen);
  	return klen;
  }
  
  /*
25985edce   Lucas De Marchi   Fix common misspe...
152
   * provide new auxiliary cache data
9b3f26c91   David Howells   FS-Cache: Make kA...
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
   */
  static uint16_t afs_vlocation_cache_get_aux(const void *cookie_netfs_data,
  					    void *buffer, uint16_t bufmax)
  {
  	const struct afs_vlocation *vlocation = cookie_netfs_data;
  	uint16_t dlen;
  
  	_enter("{%s},%p,%u", vlocation->vldb.name, buffer, bufmax);
  
  	dlen = sizeof(struct afs_cache_vlocation);
  	dlen -= offsetof(struct afs_cache_vlocation, nservers);
  	if (dlen > bufmax)
  		return 0;
  
  	memcpy(buffer, (uint8_t *)&vlocation->vldb.nservers, dlen);
  
  	_leave(" = %u", dlen);
  	return dlen;
  }
  
  /*
25985edce   Lucas De Marchi   Fix common misspe...
174
   * check that the auxiliary data indicates that the entry is still valid
9b3f26c91   David Howells   FS-Cache: Make kA...
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
   */
  static
  enum fscache_checkaux afs_vlocation_cache_check_aux(void *cookie_netfs_data,
  						    const void *buffer,
  						    uint16_t buflen)
  {
  	const struct afs_cache_vlocation *cvldb;
  	struct afs_vlocation *vlocation = cookie_netfs_data;
  	uint16_t dlen;
  
  	_enter("{%s},%p,%u", vlocation->vldb.name, buffer, buflen);
  
  	/* check the size of the data is what we're expecting */
  	dlen = sizeof(struct afs_cache_vlocation);
  	dlen -= offsetof(struct afs_cache_vlocation, nservers);
  	if (dlen != buflen)
  		return FSCACHE_CHECKAUX_OBSOLETE;
  
  	cvldb = container_of(buffer, struct afs_cache_vlocation, nservers);
  
  	/* if what's on disk is more valid than what's in memory, then use the
  	 * VL record from the cache */
  	if (!vlocation->valid || vlocation->vldb.rtime == cvldb->rtime) {
  		memcpy((uint8_t *)&vlocation->vldb.nservers, buffer, dlen);
  		vlocation->valid = 1;
  		_leave(" = SUCCESS [c->m]");
  		return FSCACHE_CHECKAUX_OKAY;
  	}
  
  	/* need to update the cache if the cached info differs */
  	if (memcmp(&vlocation->vldb, buffer, dlen) != 0) {
  		/* delete if the volume IDs for this name differ */
  		if (memcmp(&vlocation->vldb.vid, &cvldb->vid,
  			   sizeof(cvldb->vid)) != 0
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
209
  		    ) {
9b3f26c91   David Howells   FS-Cache: Make kA...
210
211
  			_leave(" = OBSOLETE");
  			return FSCACHE_CHECKAUX_OBSOLETE;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
212
  		}
9b3f26c91   David Howells   FS-Cache: Make kA...
213
214
215
  
  		_leave(" = UPDATE");
  		return FSCACHE_CHECKAUX_NEEDS_UPDATE;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
216
  	}
9b3f26c91   David Howells   FS-Cache: Make kA...
217
218
  	_leave(" = OKAY");
  	return FSCACHE_CHECKAUX_OKAY;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
219
  }
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
220

9b3f26c91   David Howells   FS-Cache: Make kA...
221
  /*****************************************************************************/
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
222
  /*
9b3f26c91   David Howells   FS-Cache: Make kA...
223
   * set the key for the volume index entry
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
224
   */
9b3f26c91   David Howells   FS-Cache: Make kA...
225
226
  static uint16_t afs_volume_cache_get_key(const void *cookie_netfs_data,
  					void *buffer, uint16_t bufmax)
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
227
  {
9b3f26c91   David Howells   FS-Cache: Make kA...
228
229
230
231
232
233
234
235
  	const struct afs_volume *volume = cookie_netfs_data;
  	uint16_t klen;
  
  	_enter("{%u},%p,%u", volume->type, buffer, bufmax);
  
  	klen = sizeof(volume->type);
  	if (klen > bufmax)
  		return 0;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
236

9b3f26c91   David Howells   FS-Cache: Make kA...
237
238
239
240
  	memcpy(buffer, &volume->type, sizeof(volume->type));
  
  	_leave(" = %u", klen);
  	return klen;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
241

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
242
  }
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
243

9b3f26c91   David Howells   FS-Cache: Make kA...
244
  /*****************************************************************************/
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
245
  /*
9b3f26c91   David Howells   FS-Cache: Make kA...
246
   * set the key for the index entry
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
247
   */
9b3f26c91   David Howells   FS-Cache: Make kA...
248
249
  static uint16_t afs_vnode_cache_get_key(const void *cookie_netfs_data,
  					void *buffer, uint16_t bufmax)
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
250
  {
9b3f26c91   David Howells   FS-Cache: Make kA...
251
252
  	const struct afs_vnode *vnode = cookie_netfs_data;
  	uint16_t klen;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
253

9b3f26c91   David Howells   FS-Cache: Make kA...
254
255
256
  	_enter("{%x,%x,%llx},%p,%u",
  	       vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version,
  	       buffer, bufmax);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
257

9b3f26c91   David Howells   FS-Cache: Make kA...
258
259
260
261
262
  	klen = sizeof(vnode->fid.vnode);
  	if (klen > bufmax)
  		return 0;
  
  	memcpy(buffer, &vnode->fid.vnode, sizeof(vnode->fid.vnode));
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
263

9b3f26c91   David Howells   FS-Cache: Make kA...
264
265
  	_leave(" = %u", klen);
  	return klen;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
266
  }
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
267
268
  
  /*
9b3f26c91   David Howells   FS-Cache: Make kA...
269
   * provide updated file attributes
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
270
   */
9b3f26c91   David Howells   FS-Cache: Make kA...
271
272
  static void afs_vnode_cache_get_attr(const void *cookie_netfs_data,
  				     uint64_t *size)
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
273
  {
9b3f26c91   David Howells   FS-Cache: Make kA...
274
  	const struct afs_vnode *vnode = cookie_netfs_data;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
275

9b3f26c91   David Howells   FS-Cache: Make kA...
276
277
278
  	_enter("{%x,%x,%llx},",
  	       vnode->fid.vnode, vnode->fid.unique,
  	       vnode->status.data_version);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
279

9b3f26c91   David Howells   FS-Cache: Make kA...
280
  	*size = vnode->status.size;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
281
  }
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
282
283
  
  /*
25985edce   Lucas De Marchi   Fix common misspe...
284
   * provide new auxiliary cache data
9b3f26c91   David Howells   FS-Cache: Make kA...
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
   */
  static uint16_t afs_vnode_cache_get_aux(const void *cookie_netfs_data,
  					void *buffer, uint16_t bufmax)
  {
  	const struct afs_vnode *vnode = cookie_netfs_data;
  	uint16_t dlen;
  
  	_enter("{%x,%x,%Lx},%p,%u",
  	       vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version,
  	       buffer, bufmax);
  
  	dlen = sizeof(vnode->fid.unique) + sizeof(vnode->status.data_version);
  	if (dlen > bufmax)
  		return 0;
  
  	memcpy(buffer, &vnode->fid.unique, sizeof(vnode->fid.unique));
  	buffer += sizeof(vnode->fid.unique);
  	memcpy(buffer, &vnode->status.data_version,
  	       sizeof(vnode->status.data_version));
  
  	_leave(" = %u", dlen);
  	return dlen;
  }
  
  /*
25985edce   Lucas De Marchi   Fix common misspe...
310
   * check that the auxiliary data indicates that the entry is still valid
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
311
   */
9b3f26c91   David Howells   FS-Cache: Make kA...
312
313
314
  static enum fscache_checkaux afs_vnode_cache_check_aux(void *cookie_netfs_data,
  						       const void *buffer,
  						       uint16_t buflen)
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
315
  {
9b3f26c91   David Howells   FS-Cache: Make kA...
316
317
318
319
320
321
322
323
324
325
326
327
  	struct afs_vnode *vnode = cookie_netfs_data;
  	uint16_t dlen;
  
  	_enter("{%x,%x,%llx},%p,%u",
  	       vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version,
  	       buffer, buflen);
  
  	/* check the size of the data is what we're expecting */
  	dlen = sizeof(vnode->fid.unique) + sizeof(vnode->status.data_version);
  	if (dlen != buflen) {
  		_leave(" = OBSOLETE [len %hx != %hx]", dlen, buflen);
  		return FSCACHE_CHECKAUX_OBSOLETE;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
328
  	}
9b3f26c91   David Howells   FS-Cache: Make kA...
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
  	if (memcmp(buffer,
  		   &vnode->fid.unique,
  		   sizeof(vnode->fid.unique)
  		   ) != 0) {
  		unsigned unique;
  
  		memcpy(&unique, buffer, sizeof(unique));
  
  		_leave(" = OBSOLETE [uniq %x != %x]",
  		       unique, vnode->fid.unique);
  		return FSCACHE_CHECKAUX_OBSOLETE;
  	}
  
  	if (memcmp(buffer + sizeof(vnode->fid.unique),
  		   &vnode->status.data_version,
  		   sizeof(vnode->status.data_version)
  		   ) != 0) {
  		afs_dataversion_t version;
  
  		memcpy(&version, buffer + sizeof(vnode->fid.unique),
  		       sizeof(version));
  
  		_leave(" = OBSOLETE [vers %llx != %llx]",
  		       version, vnode->status.data_version);
  		return FSCACHE_CHECKAUX_OBSOLETE;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
354
355
356
  	}
  
  	_leave(" = SUCCESS");
9b3f26c91   David Howells   FS-Cache: Make kA...
357
  	return FSCACHE_CHECKAUX_OKAY;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
358
  }
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
359
360
  
  /*
9b3f26c91   David Howells   FS-Cache: Make kA...
361
362
363
364
365
   * indication the cookie is no longer uncached
   * - this function is called when the backing store currently caching a cookie
   *   is removed
   * - the netfs should use this to clean up any markers indicating cached pages
   * - this is mandatory for any object that may have data
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
366
   */
9b3f26c91   David Howells   FS-Cache: Make kA...
367
  static void afs_vnode_cache_now_uncached(void *cookie_netfs_data)
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
368
  {
9b3f26c91   David Howells   FS-Cache: Make kA...
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
  	struct afs_vnode *vnode = cookie_netfs_data;
  	struct pagevec pvec;
  	pgoff_t first;
  	int loop, nr_pages;
  
  	_enter("{%x,%x,%Lx}",
  	       vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version);
  
  	pagevec_init(&pvec, 0);
  	first = 0;
  
  	for (;;) {
  		/* grab a bunch of pages to clean */
  		nr_pages = pagevec_lookup(&pvec, vnode->vfs_inode.i_mapping,
  					  first,
  					  PAGEVEC_SIZE - pagevec_count(&pvec));
  		if (!nr_pages)
  			break;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
387

9b3f26c91   David Howells   FS-Cache: Make kA...
388
389
390
391
392
393
394
395
396
  		for (loop = 0; loop < nr_pages; loop++)
  			ClearPageFsCache(pvec.pages[loop]);
  
  		first = pvec.pages[nr_pages - 1]->index + 1;
  
  		pvec.nr = nr_pages;
  		pagevec_release(&pvec);
  		cond_resched();
  	}
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
397

9b3f26c91   David Howells   FS-Cache: Make kA...
398
  	_leave("");
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
399
  }