3 * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
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.
12 #include <linux/sched.h>
15 static uint16_t afs_cell_cache_get_key(const void *cookie_netfs_data
,
16 void *buffer
, uint16_t buflen
);
17 static uint16_t afs_cell_cache_get_aux(const void *cookie_netfs_data
,
18 void *buffer
, uint16_t buflen
);
19 static enum fscache_checkaux
afs_cell_cache_check_aux(void *cookie_netfs_data
,
23 static uint16_t afs_vlocation_cache_get_key(const void *cookie_netfs_data
,
24 void *buffer
, uint16_t buflen
);
25 static uint16_t afs_vlocation_cache_get_aux(const void *cookie_netfs_data
,
26 void *buffer
, uint16_t buflen
);
27 static enum fscache_checkaux
afs_vlocation_cache_check_aux(
28 void *cookie_netfs_data
, const void *buffer
, uint16_t buflen
);
30 static uint16_t afs_volume_cache_get_key(const void *cookie_netfs_data
,
31 void *buffer
, uint16_t buflen
);
33 static uint16_t afs_vnode_cache_get_key(const void *cookie_netfs_data
,
34 void *buffer
, uint16_t buflen
);
35 static void afs_vnode_cache_get_attr(const void *cookie_netfs_data
,
37 static uint16_t afs_vnode_cache_get_aux(const void *cookie_netfs_data
,
38 void *buffer
, uint16_t buflen
);
39 static enum fscache_checkaux
afs_vnode_cache_check_aux(void *cookie_netfs_data
,
42 static void afs_vnode_cache_now_uncached(void *cookie_netfs_data
);
44 struct fscache_netfs afs_cache_netfs
= {
49 struct fscache_cookie_def afs_cell_cache_index_def
= {
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
,
57 struct fscache_cookie_def afs_vlocation_cache_index_def
= {
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
,
65 struct fscache_cookie_def afs_volume_cache_index_def
= {
67 .type
= FSCACHE_COOKIE_TYPE_INDEX
,
68 .get_key
= afs_volume_cache_get_key
,
71 struct fscache_cookie_def afs_vnode_cache_index_def
= {
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
,
82 * set the key for the index entry
84 static uint16_t afs_cell_cache_get_key(const void *cookie_netfs_data
,
85 void *buffer
, uint16_t bufmax
)
87 const struct afs_cell
*cell
= cookie_netfs_data
;
90 _enter("%p,%p,%u", cell
, buffer
, bufmax
);
92 klen
= strlen(cell
->name
);
96 memcpy(buffer
, cell
->name
, klen
);
101 * provide new auxilliary cache data
103 static uint16_t afs_cell_cache_get_aux(const void *cookie_netfs_data
,
104 void *buffer
, uint16_t bufmax
)
106 const struct afs_cell
*cell
= cookie_netfs_data
;
109 _enter("%p,%p,%u", cell
, buffer
, bufmax
);
111 dlen
= cell
->vl_naddrs
* sizeof(cell
->vl_addrs
[0]);
112 dlen
= min(dlen
, bufmax
);
113 dlen
&= ~(sizeof(cell
->vl_addrs
[0]) - 1);
115 memcpy(buffer
, cell
->vl_addrs
, dlen
);
120 * check that the auxilliary data indicates that the entry is still valid
122 static enum fscache_checkaux
afs_cell_cache_check_aux(void *cookie_netfs_data
,
127 return FSCACHE_CHECKAUX_OKAY
;
130 /*****************************************************************************/
132 * set the key for the index entry
134 static uint16_t afs_vlocation_cache_get_key(const void *cookie_netfs_data
,
135 void *buffer
, uint16_t bufmax
)
137 const struct afs_vlocation
*vlocation
= cookie_netfs_data
;
140 _enter("{%s},%p,%u", vlocation
->vldb
.name
, buffer
, bufmax
);
142 klen
= strnlen(vlocation
->vldb
.name
, sizeof(vlocation
->vldb
.name
));
146 memcpy(buffer
, vlocation
->vldb
.name
, klen
);
148 _leave(" = %u", klen
);
153 * provide new auxilliary cache data
155 static uint16_t afs_vlocation_cache_get_aux(const void *cookie_netfs_data
,
156 void *buffer
, uint16_t bufmax
)
158 const struct afs_vlocation
*vlocation
= cookie_netfs_data
;
161 _enter("{%s},%p,%u", vlocation
->vldb
.name
, buffer
, bufmax
);
163 dlen
= sizeof(struct afs_cache_vlocation
);
164 dlen
-= offsetof(struct afs_cache_vlocation
, nservers
);
168 memcpy(buffer
, (uint8_t *)&vlocation
->vldb
.nservers
, dlen
);
170 _leave(" = %u", dlen
);
175 * check that the auxilliary data indicates that the entry is still valid
178 enum fscache_checkaux
afs_vlocation_cache_check_aux(void *cookie_netfs_data
,
182 const struct afs_cache_vlocation
*cvldb
;
183 struct afs_vlocation
*vlocation
= cookie_netfs_data
;
186 _enter("{%s},%p,%u", vlocation
->vldb
.name
, buffer
, buflen
);
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
);
192 return FSCACHE_CHECKAUX_OBSOLETE
;
194 cvldb
= container_of(buffer
, struct afs_cache_vlocation
, nservers
);
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
;
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
211 _leave(" = OBSOLETE");
212 return FSCACHE_CHECKAUX_OBSOLETE
;
216 return FSCACHE_CHECKAUX_NEEDS_UPDATE
;
220 return FSCACHE_CHECKAUX_OKAY
;
223 /*****************************************************************************/
225 * set the key for the volume index entry
227 static uint16_t afs_volume_cache_get_key(const void *cookie_netfs_data
,
228 void *buffer
, uint16_t bufmax
)
230 const struct afs_volume
*volume
= cookie_netfs_data
;
233 _enter("{%u},%p,%u", volume
->type
, buffer
, bufmax
);
235 klen
= sizeof(volume
->type
);
239 memcpy(buffer
, &volume
->type
, sizeof(volume
->type
));
241 _leave(" = %u", klen
);
246 /*****************************************************************************/
248 * set the key for the index entry
250 static uint16_t afs_vnode_cache_get_key(const void *cookie_netfs_data
,
251 void *buffer
, uint16_t bufmax
)
253 const struct afs_vnode
*vnode
= cookie_netfs_data
;
256 _enter("{%x,%x,%llx},%p,%u",
257 vnode
->fid
.vnode
, vnode
->fid
.unique
, vnode
->status
.data_version
,
260 klen
= sizeof(vnode
->fid
.vnode
);
264 memcpy(buffer
, &vnode
->fid
.vnode
, sizeof(vnode
->fid
.vnode
));
266 _leave(" = %u", klen
);
271 * provide updated file attributes
273 static void afs_vnode_cache_get_attr(const void *cookie_netfs_data
,
276 const struct afs_vnode
*vnode
= cookie_netfs_data
;
278 _enter("{%x,%x,%llx},",
279 vnode
->fid
.vnode
, vnode
->fid
.unique
,
280 vnode
->status
.data_version
);
282 *size
= vnode
->status
.size
;
286 * provide new auxilliary cache data
288 static uint16_t afs_vnode_cache_get_aux(const void *cookie_netfs_data
,
289 void *buffer
, uint16_t bufmax
)
291 const struct afs_vnode
*vnode
= cookie_netfs_data
;
294 _enter("{%x,%x,%Lx},%p,%u",
295 vnode
->fid
.vnode
, vnode
->fid
.unique
, vnode
->status
.data_version
,
298 dlen
= sizeof(vnode
->fid
.unique
) + sizeof(vnode
->status
.data_version
);
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
));
307 _leave(" = %u", dlen
);
312 * check that the auxilliary data indicates that the entry is still valid
314 static enum fscache_checkaux
afs_vnode_cache_check_aux(void *cookie_netfs_data
,
318 struct afs_vnode
*vnode
= cookie_netfs_data
;
321 _enter("{%x,%x,%llx},%p,%u",
322 vnode
->fid
.vnode
, vnode
->fid
.unique
, vnode
->status
.data_version
,
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
;
334 sizeof(vnode
->fid
.unique
)
338 memcpy(&unique
, buffer
, sizeof(unique
));
340 _leave(" = OBSOLETE [uniq %x != %x]",
341 unique
, vnode
->fid
.unique
);
342 return FSCACHE_CHECKAUX_OBSOLETE
;
345 if (memcmp(buffer
+ sizeof(vnode
->fid
.unique
),
346 &vnode
->status
.data_version
,
347 sizeof(vnode
->status
.data_version
)
349 afs_dataversion_t version
;
351 memcpy(&version
, buffer
+ sizeof(vnode
->fid
.unique
),
354 _leave(" = OBSOLETE [vers %llx != %llx]",
355 version
, vnode
->status
.data_version
);
356 return FSCACHE_CHECKAUX_OBSOLETE
;
359 _leave(" = SUCCESS");
360 return FSCACHE_CHECKAUX_OKAY
;
364 * indication the cookie is no longer uncached
365 * - this function is called when the backing store currently caching a cookie
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
370 static void afs_vnode_cache_now_uncached(void *cookie_netfs_data
)
372 struct afs_vnode
*vnode
= cookie_netfs_data
;
377 _enter("{%x,%x,%Lx}",
378 vnode
->fid
.vnode
, vnode
->fid
.unique
, vnode
->status
.data_version
);
380 pagevec_init(&pvec
, 0);
384 /* grab a bunch of pages to clean */
385 nr_pages
= pagevec_lookup(&pvec
, vnode
->vfs_inode
.i_mapping
,
387 PAGEVEC_SIZE
- pagevec_count(&pvec
));
391 for (loop
= 0; loop
< nr_pages
; loop
++)
392 ClearPageFsCache(pvec
.pages
[loop
]);
394 first
= pvec
.pages
[nr_pages
- 1]->index
+ 1;
397 pagevec_release(&pvec
);