diff options
author | David Howells <dhowells@redhat.com> | 2009-04-03 11:42:41 -0400 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2009-04-03 11:42:41 -0400 |
commit | 9b3f26c9110dcea62716aca9b8c68ceb482227ef (patch) | |
tree | f11fc0b125d6bc2149e99cb269073320ff50dba9 /fs/afs/cache.c | |
parent | 9ae326a69004dea8af2dae4fde58de27db700a8d (diff) |
FS-Cache: Make kAFS use FS-Cache
The attached patch makes the kAFS filesystem in fs/afs/ use FS-Cache, and
through it any attached caches. The kAFS filesystem will use caching
automatically if it's available.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Steve Dickson <steved@redhat.com>
Acked-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Acked-by: Al Viro <viro@zeniv.linux.org.uk>
Tested-by: Daire Byrne <Daire.Byrne@framestore.com>
Diffstat (limited to 'fs/afs/cache.c')
-rw-r--r-- | fs/afs/cache.c | 503 |
1 files changed, 325 insertions, 178 deletions
diff --git a/fs/afs/cache.c b/fs/afs/cache.c index de0d7de69edc..e2b1d3f16519 100644 --- a/fs/afs/cache.c +++ b/fs/afs/cache.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* AFS caching stuff | 1 | /* AFS caching stuff |
2 | * | 2 | * |
3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved. |
4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
@@ -9,248 +9,395 @@ | |||
9 | * 2 of the License, or (at your option) any later version. | 9 | * 2 of the License, or (at your option) any later version. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #ifdef AFS_CACHING_SUPPORT | 12 | #include <linux/slab.h> |
13 | static cachefs_match_val_t afs_cell_cache_match(void *target, | 13 | #include <linux/sched.h> |
14 | const void *entry); | 14 | #include "internal.h" |
15 | static void afs_cell_cache_update(void *source, void *entry); | 15 | |
16 | 16 | static uint16_t afs_cell_cache_get_key(const void *cookie_netfs_data, | |
17 | struct cachefs_index_def afs_cache_cell_index_def = { | 17 | void *buffer, uint16_t buflen); |
18 | .name = "cell_ix", | 18 | static uint16_t afs_cell_cache_get_aux(const void *cookie_netfs_data, |
19 | .data_size = sizeof(struct afs_cache_cell), | 19 | void *buffer, uint16_t buflen); |
20 | .keys[0] = { CACHEFS_INDEX_KEYS_ASCIIZ, 64 }, | 20 | static enum fscache_checkaux afs_cell_cache_check_aux(void *cookie_netfs_data, |
21 | .match = afs_cell_cache_match, | 21 | const void *buffer, |
22 | .update = afs_cell_cache_update, | 22 | uint16_t buflen); |
23 | |||
24 | static uint16_t afs_vlocation_cache_get_key(const void *cookie_netfs_data, | ||
25 | void *buffer, uint16_t buflen); | ||
26 | static uint16_t afs_vlocation_cache_get_aux(const void *cookie_netfs_data, | ||
27 | void *buffer, uint16_t buflen); | ||
28 | static enum fscache_checkaux afs_vlocation_cache_check_aux( | ||
29 | void *cookie_netfs_data, const void *buffer, uint16_t buflen); | ||
30 | |||
31 | static uint16_t afs_volume_cache_get_key(const void *cookie_netfs_data, | ||
32 | void *buffer, uint16_t buflen); | ||
33 | |||
34 | static uint16_t afs_vnode_cache_get_key(const void *cookie_netfs_data, | ||
35 | void *buffer, uint16_t buflen); | ||
36 | static void afs_vnode_cache_get_attr(const void *cookie_netfs_data, | ||
37 | uint64_t *size); | ||
38 | static uint16_t afs_vnode_cache_get_aux(const void *cookie_netfs_data, | ||
39 | void *buffer, uint16_t buflen); | ||
40 | static enum fscache_checkaux afs_vnode_cache_check_aux(void *cookie_netfs_data, | ||
41 | const void *buffer, | ||
42 | uint16_t buflen); | ||
43 | static void afs_vnode_cache_now_uncached(void *cookie_netfs_data); | ||
44 | |||
45 | struct fscache_netfs afs_cache_netfs = { | ||
46 | .name = "afs", | ||
47 | .version = 0, | ||
48 | }; | ||
49 | |||
50 | struct fscache_cookie_def afs_cell_cache_index_def = { | ||
51 | .name = "AFS.cell", | ||
52 | .type = FSCACHE_COOKIE_TYPE_INDEX, | ||
53 | .get_key = afs_cell_cache_get_key, | ||
54 | .get_aux = afs_cell_cache_get_aux, | ||
55 | .check_aux = afs_cell_cache_check_aux, | ||
56 | }; | ||
57 | |||
58 | struct fscache_cookie_def afs_vlocation_cache_index_def = { | ||
59 | .name = "AFS.vldb", | ||
60 | .type = FSCACHE_COOKIE_TYPE_INDEX, | ||
61 | .get_key = afs_vlocation_cache_get_key, | ||
62 | .get_aux = afs_vlocation_cache_get_aux, | ||
63 | .check_aux = afs_vlocation_cache_check_aux, | ||
64 | }; | ||
65 | |||
66 | struct fscache_cookie_def afs_volume_cache_index_def = { | ||
67 | .name = "AFS.volume", | ||
68 | .type = FSCACHE_COOKIE_TYPE_INDEX, | ||
69 | .get_key = afs_volume_cache_get_key, | ||
70 | }; | ||
71 | |||
72 | struct fscache_cookie_def afs_vnode_cache_index_def = { | ||
73 | .name = "AFS.vnode", | ||
74 | .type = FSCACHE_COOKIE_TYPE_DATAFILE, | ||
75 | .get_key = afs_vnode_cache_get_key, | ||
76 | .get_attr = afs_vnode_cache_get_attr, | ||
77 | .get_aux = afs_vnode_cache_get_aux, | ||
78 | .check_aux = afs_vnode_cache_check_aux, | ||
79 | .now_uncached = afs_vnode_cache_now_uncached, | ||
23 | }; | 80 | }; |
24 | #endif | ||
25 | 81 | ||
26 | /* | 82 | /* |
27 | * match a cell record obtained from the cache | 83 | * set the key for the index entry |
28 | */ | 84 | */ |
29 | #ifdef AFS_CACHING_SUPPORT | 85 | static uint16_t afs_cell_cache_get_key(const void *cookie_netfs_data, |
30 | static cachefs_match_val_t afs_cell_cache_match(void *target, | 86 | void *buffer, uint16_t bufmax) |
31 | const void *entry) | ||
32 | { | 87 | { |
33 | const struct afs_cache_cell *ccell = entry; | 88 | const struct afs_cell *cell = cookie_netfs_data; |
34 | struct afs_cell *cell = target; | 89 | uint16_t klen; |
35 | 90 | ||
36 | _enter("{%s},{%s}", ccell->name, cell->name); | 91 | _enter("%p,%p,%u", cell, buffer, bufmax); |
37 | 92 | ||
38 | if (strncmp(ccell->name, cell->name, sizeof(ccell->name)) == 0) { | 93 | klen = strlen(cell->name); |
39 | _leave(" = SUCCESS"); | 94 | if (klen > bufmax) |
40 | return CACHEFS_MATCH_SUCCESS; | 95 | return 0; |
41 | } | ||
42 | 96 | ||
43 | _leave(" = FAILED"); | 97 | memcpy(buffer, cell->name, klen); |
44 | return CACHEFS_MATCH_FAILED; | 98 | return klen; |
45 | } | 99 | } |
46 | #endif | ||
47 | 100 | ||
48 | /* | 101 | /* |
49 | * update a cell record in the cache | 102 | * provide new auxilliary cache data |
50 | */ | 103 | */ |
51 | #ifdef AFS_CACHING_SUPPORT | 104 | static uint16_t afs_cell_cache_get_aux(const void *cookie_netfs_data, |
52 | static void afs_cell_cache_update(void *source, void *entry) | 105 | void *buffer, uint16_t bufmax) |
53 | { | 106 | { |
54 | struct afs_cache_cell *ccell = entry; | 107 | const struct afs_cell *cell = cookie_netfs_data; |
55 | struct afs_cell *cell = source; | 108 | uint16_t dlen; |
56 | 109 | ||
57 | _enter("%p,%p", source, entry); | 110 | _enter("%p,%p,%u", cell, buffer, bufmax); |
58 | 111 | ||
59 | strncpy(ccell->name, cell->name, sizeof(ccell->name)); | 112 | dlen = cell->vl_naddrs * sizeof(cell->vl_addrs[0]); |
113 | dlen = min(dlen, bufmax); | ||
114 | dlen &= ~(sizeof(cell->vl_addrs[0]) - 1); | ||
60 | 115 | ||
61 | memcpy(ccell->vl_servers, | 116 | memcpy(buffer, cell->vl_addrs, dlen); |
62 | cell->vl_addrs, | 117 | return dlen; |
63 | min(sizeof(ccell->vl_servers), sizeof(cell->vl_addrs))); | 118 | } |
64 | 119 | ||
120 | /* | ||
121 | * check that the auxilliary data indicates that the entry is still valid | ||
122 | */ | ||
123 | static enum fscache_checkaux afs_cell_cache_check_aux(void *cookie_netfs_data, | ||
124 | const void *buffer, | ||
125 | uint16_t buflen) | ||
126 | { | ||
127 | _leave(" = OKAY"); | ||
128 | return FSCACHE_CHECKAUX_OKAY; | ||
65 | } | 129 | } |
66 | #endif | ||
67 | |||
68 | #ifdef AFS_CACHING_SUPPORT | ||
69 | static cachefs_match_val_t afs_vlocation_cache_match(void *target, | ||
70 | const void *entry); | ||
71 | static void afs_vlocation_cache_update(void *source, void *entry); | ||
72 | |||
73 | struct 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 | 130 | ||
131 | /*****************************************************************************/ | ||
82 | /* | 132 | /* |
83 | * match a VLDB record stored in the cache | 133 | * set the key for the index entry |
84 | * - may also load target from entry | ||
85 | */ | 134 | */ |
86 | #ifdef AFS_CACHING_SUPPORT | 135 | static uint16_t afs_vlocation_cache_get_key(const void *cookie_netfs_data, |
87 | static cachefs_match_val_t afs_vlocation_cache_match(void *target, | 136 | void *buffer, uint16_t bufmax) |
88 | const void *entry) | ||
89 | { | 137 | { |
90 | const struct afs_cache_vlocation *vldb = entry; | 138 | const struct afs_vlocation *vlocation = cookie_netfs_data; |
91 | struct afs_vlocation *vlocation = target; | 139 | uint16_t klen; |
140 | |||
141 | _enter("{%s},%p,%u", vlocation->vldb.name, buffer, bufmax); | ||
142 | |||
143 | klen = strnlen(vlocation->vldb.name, sizeof(vlocation->vldb.name)); | ||
144 | if (klen > bufmax) | ||
145 | return 0; | ||
92 | 146 | ||
93 | _enter("{%s},{%s}", vlocation->vldb.name, vldb->name); | 147 | memcpy(buffer, vlocation->vldb.name, klen); |
94 | 148 | ||
95 | if (strncmp(vlocation->vldb.name, vldb->name, sizeof(vldb->name)) == 0 | 149 | _leave(" = %u", klen); |
96 | ) { | 150 | return klen; |
97 | if (!vlocation->valid || | 151 | } |
98 | vlocation->vldb.rtime == vldb->rtime | 152 | |
153 | /* | ||
154 | * provide new auxilliary cache data | ||
155 | */ | ||
156 | static uint16_t afs_vlocation_cache_get_aux(const void *cookie_netfs_data, | ||
157 | void *buffer, uint16_t bufmax) | ||
158 | { | ||
159 | const struct afs_vlocation *vlocation = cookie_netfs_data; | ||
160 | uint16_t dlen; | ||
161 | |||
162 | _enter("{%s},%p,%u", vlocation->vldb.name, buffer, bufmax); | ||
163 | |||
164 | dlen = sizeof(struct afs_cache_vlocation); | ||
165 | dlen -= offsetof(struct afs_cache_vlocation, nservers); | ||
166 | if (dlen > bufmax) | ||
167 | return 0; | ||
168 | |||
169 | memcpy(buffer, (uint8_t *)&vlocation->vldb.nservers, dlen); | ||
170 | |||
171 | _leave(" = %u", dlen); | ||
172 | return dlen; | ||
173 | } | ||
174 | |||
175 | /* | ||
176 | * check that the auxilliary data indicates that the entry is still valid | ||
177 | */ | ||
178 | static | ||
179 | enum fscache_checkaux afs_vlocation_cache_check_aux(void *cookie_netfs_data, | ||
180 | const void *buffer, | ||
181 | uint16_t buflen) | ||
182 | { | ||
183 | const struct afs_cache_vlocation *cvldb; | ||
184 | struct afs_vlocation *vlocation = cookie_netfs_data; | ||
185 | uint16_t dlen; | ||
186 | |||
187 | _enter("{%s},%p,%u", vlocation->vldb.name, buffer, buflen); | ||
188 | |||
189 | /* check the size of the data is what we're expecting */ | ||
190 | dlen = sizeof(struct afs_cache_vlocation); | ||
191 | dlen -= offsetof(struct afs_cache_vlocation, nservers); | ||
192 | if (dlen != buflen) | ||
193 | return FSCACHE_CHECKAUX_OBSOLETE; | ||
194 | |||
195 | cvldb = container_of(buffer, struct afs_cache_vlocation, nservers); | ||
196 | |||
197 | /* if what's on disk is more valid than what's in memory, then use the | ||
198 | * VL record from the cache */ | ||
199 | if (!vlocation->valid || vlocation->vldb.rtime == cvldb->rtime) { | ||
200 | memcpy((uint8_t *)&vlocation->vldb.nservers, buffer, dlen); | ||
201 | vlocation->valid = 1; | ||
202 | _leave(" = SUCCESS [c->m]"); | ||
203 | return FSCACHE_CHECKAUX_OKAY; | ||
204 | } | ||
205 | |||
206 | /* need to update the cache if the cached info differs */ | ||
207 | if (memcmp(&vlocation->vldb, buffer, dlen) != 0) { | ||
208 | /* delete if the volume IDs for this name differ */ | ||
209 | if (memcmp(&vlocation->vldb.vid, &cvldb->vid, | ||
210 | sizeof(cvldb->vid)) != 0 | ||
99 | ) { | 211 | ) { |
100 | vlocation->vldb = *vldb; | 212 | _leave(" = OBSOLETE"); |
101 | vlocation->valid = 1; | 213 | return FSCACHE_CHECKAUX_OBSOLETE; |
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 | } | 214 | } |
215 | |||
216 | _leave(" = UPDATE"); | ||
217 | return FSCACHE_CHECKAUX_NEEDS_UPDATE; | ||
119 | } | 218 | } |
120 | 219 | ||
121 | _leave(" = FAILED"); | 220 | _leave(" = OKAY"); |
122 | return CACHEFS_MATCH_FAILED; | 221 | return FSCACHE_CHECKAUX_OKAY; |
123 | } | 222 | } |
124 | #endif | ||
125 | 223 | ||
224 | /*****************************************************************************/ | ||
126 | /* | 225 | /* |
127 | * update a VLDB record stored in the cache | 226 | * set the key for the volume index entry |
128 | */ | 227 | */ |
129 | #ifdef AFS_CACHING_SUPPORT | 228 | static uint16_t afs_volume_cache_get_key(const void *cookie_netfs_data, |
130 | static void afs_vlocation_cache_update(void *source, void *entry) | 229 | void *buffer, uint16_t bufmax) |
131 | { | 230 | { |
132 | struct afs_cache_vlocation *vldb = entry; | 231 | const struct afs_volume *volume = cookie_netfs_data; |
133 | struct afs_vlocation *vlocation = source; | 232 | uint16_t klen; |
233 | |||
234 | _enter("{%u},%p,%u", volume->type, buffer, bufmax); | ||
235 | |||
236 | klen = sizeof(volume->type); | ||
237 | if (klen > bufmax) | ||
238 | return 0; | ||
134 | 239 | ||
135 | _enter(""); | 240 | memcpy(buffer, &volume->type, sizeof(volume->type)); |
241 | |||
242 | _leave(" = %u", klen); | ||
243 | return klen; | ||
136 | 244 | ||
137 | *vldb = vlocation->vldb; | ||
138 | } | 245 | } |
139 | #endif | ||
140 | |||
141 | #ifdef AFS_CACHING_SUPPORT | ||
142 | static cachefs_match_val_t afs_volume_cache_match(void *target, | ||
143 | const void *entry); | ||
144 | static void afs_volume_cache_update(void *source, void *entry); | ||
145 | |||
146 | struct 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 | 246 | ||
247 | /*****************************************************************************/ | ||
156 | /* | 248 | /* |
157 | * match a volume hash record stored in the cache | 249 | * set the key for the index entry |
158 | */ | 250 | */ |
159 | #ifdef AFS_CACHING_SUPPORT | 251 | static uint16_t afs_vnode_cache_get_key(const void *cookie_netfs_data, |
160 | static cachefs_match_val_t afs_volume_cache_match(void *target, | 252 | void *buffer, uint16_t bufmax) |
161 | const void *entry) | ||
162 | { | 253 | { |
163 | const struct afs_cache_vhash *vhash = entry; | 254 | const struct afs_vnode *vnode = cookie_netfs_data; |
164 | struct afs_volume *volume = target; | 255 | uint16_t klen; |
165 | 256 | ||
166 | _enter("{%u},{%u}", volume->type, vhash->vtype); | 257 | _enter("{%x,%x,%llx},%p,%u", |
258 | vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version, | ||
259 | buffer, bufmax); | ||
167 | 260 | ||
168 | if (volume->type == vhash->vtype) { | 261 | klen = sizeof(vnode->fid.vnode); |
169 | _leave(" = SUCCESS"); | 262 | if (klen > bufmax) |
170 | return CACHEFS_MATCH_SUCCESS; | 263 | return 0; |
171 | } | 264 | |
265 | memcpy(buffer, &vnode->fid.vnode, sizeof(vnode->fid.vnode)); | ||
172 | 266 | ||
173 | _leave(" = FAILED"); | 267 | _leave(" = %u", klen); |
174 | return CACHEFS_MATCH_FAILED; | 268 | return klen; |
175 | } | 269 | } |
176 | #endif | ||
177 | 270 | ||
178 | /* | 271 | /* |
179 | * update a volume hash record stored in the cache | 272 | * provide updated file attributes |
180 | */ | 273 | */ |
181 | #ifdef AFS_CACHING_SUPPORT | 274 | static void afs_vnode_cache_get_attr(const void *cookie_netfs_data, |
182 | static void afs_volume_cache_update(void *source, void *entry) | 275 | uint64_t *size) |
183 | { | 276 | { |
184 | struct afs_cache_vhash *vhash = entry; | 277 | const struct afs_vnode *vnode = cookie_netfs_data; |
185 | struct afs_volume *volume = source; | ||
186 | 278 | ||
187 | _enter(""); | 279 | _enter("{%x,%x,%llx},", |
280 | vnode->fid.vnode, vnode->fid.unique, | ||
281 | vnode->status.data_version); | ||
188 | 282 | ||
189 | vhash->vtype = volume->type; | 283 | *size = vnode->status.size; |
190 | } | 284 | } |
191 | #endif | ||
192 | |||
193 | #ifdef AFS_CACHING_SUPPORT | ||
194 | static cachefs_match_val_t afs_vnode_cache_match(void *target, | ||
195 | const void *entry); | ||
196 | static void afs_vnode_cache_update(void *source, void *entry); | ||
197 | |||
198 | struct 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 | 285 | ||
207 | /* | 286 | /* |
208 | * match a vnode record stored in the cache | 287 | * provide new auxilliary cache data |
288 | */ | ||
289 | static uint16_t afs_vnode_cache_get_aux(const void *cookie_netfs_data, | ||
290 | void *buffer, uint16_t bufmax) | ||
291 | { | ||
292 | const struct afs_vnode *vnode = cookie_netfs_data; | ||
293 | uint16_t dlen; | ||
294 | |||
295 | _enter("{%x,%x,%Lx},%p,%u", | ||
296 | vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version, | ||
297 | buffer, bufmax); | ||
298 | |||
299 | dlen = sizeof(vnode->fid.unique) + sizeof(vnode->status.data_version); | ||
300 | if (dlen > bufmax) | ||
301 | return 0; | ||
302 | |||
303 | memcpy(buffer, &vnode->fid.unique, sizeof(vnode->fid.unique)); | ||
304 | buffer += sizeof(vnode->fid.unique); | ||
305 | memcpy(buffer, &vnode->status.data_version, | ||
306 | sizeof(vnode->status.data_version)); | ||
307 | |||
308 | _leave(" = %u", dlen); | ||
309 | return dlen; | ||
310 | } | ||
311 | |||
312 | /* | ||
313 | * check that the auxilliary data indicates that the entry is still valid | ||
209 | */ | 314 | */ |
210 | #ifdef AFS_CACHING_SUPPORT | 315 | static enum fscache_checkaux afs_vnode_cache_check_aux(void *cookie_netfs_data, |
211 | static cachefs_match_val_t afs_vnode_cache_match(void *target, | 316 | const void *buffer, |
212 | const void *entry) | 317 | uint16_t buflen) |
213 | { | 318 | { |
214 | const struct afs_cache_vnode *cvnode = entry; | 319 | struct afs_vnode *vnode = cookie_netfs_data; |
215 | struct afs_vnode *vnode = target; | 320 | uint16_t dlen; |
216 | 321 | ||
217 | _enter("{%x,%x,%Lx},{%x,%x,%Lx}", | 322 | _enter("{%x,%x,%llx},%p,%u", |
218 | vnode->fid.vnode, | 323 | vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version, |
219 | vnode->fid.unique, | 324 | buffer, buflen); |
220 | vnode->status.version, | 325 | |
221 | cvnode->vnode_id, | 326 | /* check the size of the data is what we're expecting */ |
222 | cvnode->vnode_unique, | 327 | dlen = sizeof(vnode->fid.unique) + sizeof(vnode->status.data_version); |
223 | cvnode->data_version); | 328 | if (dlen != buflen) { |
224 | 329 | _leave(" = OBSOLETE [len %hx != %hx]", dlen, buflen); | |
225 | if (vnode->fid.vnode != cvnode->vnode_id) { | 330 | return FSCACHE_CHECKAUX_OBSOLETE; |
226 | _leave(" = FAILED"); | ||
227 | return CACHEFS_MATCH_FAILED; | ||
228 | } | 331 | } |
229 | 332 | ||
230 | if (vnode->fid.unique != cvnode->vnode_unique || | 333 | if (memcmp(buffer, |
231 | vnode->status.version != cvnode->data_version) { | 334 | &vnode->fid.unique, |
232 | _leave(" = DELETE"); | 335 | sizeof(vnode->fid.unique) |
233 | return CACHEFS_MATCH_SUCCESS_DELETE; | 336 | ) != 0) { |
337 | unsigned unique; | ||
338 | |||
339 | memcpy(&unique, buffer, sizeof(unique)); | ||
340 | |||
341 | _leave(" = OBSOLETE [uniq %x != %x]", | ||
342 | unique, vnode->fid.unique); | ||
343 | return FSCACHE_CHECKAUX_OBSOLETE; | ||
344 | } | ||
345 | |||
346 | if (memcmp(buffer + sizeof(vnode->fid.unique), | ||
347 | &vnode->status.data_version, | ||
348 | sizeof(vnode->status.data_version) | ||
349 | ) != 0) { | ||
350 | afs_dataversion_t version; | ||
351 | |||
352 | memcpy(&version, buffer + sizeof(vnode->fid.unique), | ||
353 | sizeof(version)); | ||
354 | |||
355 | _leave(" = OBSOLETE [vers %llx != %llx]", | ||
356 | version, vnode->status.data_version); | ||
357 | return FSCACHE_CHECKAUX_OBSOLETE; | ||
234 | } | 358 | } |
235 | 359 | ||
236 | _leave(" = SUCCESS"); | 360 | _leave(" = SUCCESS"); |
237 | return CACHEFS_MATCH_SUCCESS; | 361 | return FSCACHE_CHECKAUX_OKAY; |
238 | } | 362 | } |
239 | #endif | ||
240 | 363 | ||
241 | /* | 364 | /* |
242 | * update a vnode record stored in the cache | 365 | * indication the cookie is no longer uncached |
366 | * - this function is called when the backing store currently caching a cookie | ||
367 | * is removed | ||
368 | * - the netfs should use this to clean up any markers indicating cached pages | ||
369 | * - this is mandatory for any object that may have data | ||
243 | */ | 370 | */ |
244 | #ifdef AFS_CACHING_SUPPORT | 371 | static void afs_vnode_cache_now_uncached(void *cookie_netfs_data) |
245 | static void afs_vnode_cache_update(void *source, void *entry) | ||
246 | { | 372 | { |
247 | struct afs_cache_vnode *cvnode = entry; | 373 | struct afs_vnode *vnode = cookie_netfs_data; |
248 | struct afs_vnode *vnode = source; | 374 | struct pagevec pvec; |
375 | pgoff_t first; | ||
376 | int loop, nr_pages; | ||
377 | |||
378 | _enter("{%x,%x,%Lx}", | ||
379 | vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version); | ||
380 | |||
381 | pagevec_init(&pvec, 0); | ||
382 | first = 0; | ||
383 | |||
384 | for (;;) { | ||
385 | /* grab a bunch of pages to clean */ | ||
386 | nr_pages = pagevec_lookup(&pvec, vnode->vfs_inode.i_mapping, | ||
387 | first, | ||
388 | PAGEVEC_SIZE - pagevec_count(&pvec)); | ||
389 | if (!nr_pages) | ||
390 | break; | ||
249 | 391 | ||
250 | _enter(""); | 392 | for (loop = 0; loop < nr_pages; loop++) |
393 | ClearPageFsCache(pvec.pages[loop]); | ||
394 | |||
395 | first = pvec.pages[nr_pages - 1]->index + 1; | ||
396 | |||
397 | pvec.nr = nr_pages; | ||
398 | pagevec_release(&pvec); | ||
399 | cond_resched(); | ||
400 | } | ||
251 | 401 | ||
252 | cvnode->vnode_id = vnode->fid.vnode; | 402 | _leave(""); |
253 | cvnode->vnode_unique = vnode->fid.unique; | ||
254 | cvnode->data_version = vnode->status.version; | ||
255 | } | 403 | } |
256 | #endif | ||