]> git.ipfire.org Git - people/arne_f/kernel.git/blame - fs/afs/cache.c
cifs/smb3: Fix data inconsistent when zero file range
[people/arne_f/kernel.git] / fs / afs / cache.c
CommitLineData
08e0e7c8
DH
1/* AFS caching stuff
2 *
9b3f26c9 3 * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved.
08e0e7c8
DH
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
9b3f26c9
DH
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);
9b3f26c9
DH
42
43struct fscache_netfs afs_cache_netfs = {
44 .name = "afs",
45 .version = 0,
46};
47
48struct fscache_cookie_def afs_cell_cache_index_def = {
49 .name = "AFS.cell",
50 .type = FSCACHE_COOKIE_TYPE_INDEX,
51 .get_key = afs_cell_cache_get_key,
52 .get_aux = afs_cell_cache_get_aux,
53 .check_aux = afs_cell_cache_check_aux,
54};
55
56struct fscache_cookie_def afs_vlocation_cache_index_def = {
57 .name = "AFS.vldb",
58 .type = FSCACHE_COOKIE_TYPE_INDEX,
59 .get_key = afs_vlocation_cache_get_key,
60 .get_aux = afs_vlocation_cache_get_aux,
61 .check_aux = afs_vlocation_cache_check_aux,
62};
63
64struct fscache_cookie_def afs_volume_cache_index_def = {
65 .name = "AFS.volume",
66 .type = FSCACHE_COOKIE_TYPE_INDEX,
67 .get_key = afs_volume_cache_get_key,
68};
69
70struct fscache_cookie_def afs_vnode_cache_index_def = {
71 .name = "AFS.vnode",
72 .type = FSCACHE_COOKIE_TYPE_DATAFILE,
73 .get_key = afs_vnode_cache_get_key,
74 .get_attr = afs_vnode_cache_get_attr,
75 .get_aux = afs_vnode_cache_get_aux,
76 .check_aux = afs_vnode_cache_check_aux,
08e0e7c8 77};
08e0e7c8
DH
78
79/*
9b3f26c9 80 * set the key for the index entry
08e0e7c8 81 */
9b3f26c9
DH
82static uint16_t afs_cell_cache_get_key(const void *cookie_netfs_data,
83 void *buffer, uint16_t bufmax)
08e0e7c8 84{
9b3f26c9
DH
85 const struct afs_cell *cell = cookie_netfs_data;
86 uint16_t klen;
08e0e7c8 87
9b3f26c9 88 _enter("%p,%p,%u", cell, buffer, bufmax);
08e0e7c8 89
9b3f26c9
DH
90 klen = strlen(cell->name);
91 if (klen > bufmax)
92 return 0;
08e0e7c8 93
9b3f26c9
DH
94 memcpy(buffer, cell->name, klen);
95 return klen;
08e0e7c8 96}
08e0e7c8
DH
97
98/*
25985edc 99 * provide new auxiliary cache data
08e0e7c8 100 */
9b3f26c9
DH
101static uint16_t afs_cell_cache_get_aux(const void *cookie_netfs_data,
102 void *buffer, uint16_t bufmax)
08e0e7c8 103{
9b3f26c9
DH
104 const struct afs_cell *cell = cookie_netfs_data;
105 uint16_t dlen;
08e0e7c8 106
9b3f26c9 107 _enter("%p,%p,%u", cell, buffer, bufmax);
08e0e7c8 108
9b3f26c9
DH
109 dlen = cell->vl_naddrs * sizeof(cell->vl_addrs[0]);
110 dlen = min(dlen, bufmax);
111 dlen &= ~(sizeof(cell->vl_addrs[0]) - 1);
08e0e7c8 112
9b3f26c9
DH
113 memcpy(buffer, cell->vl_addrs, dlen);
114 return dlen;
115}
08e0e7c8 116
9b3f26c9 117/*
25985edc 118 * check that the auxiliary data indicates that the entry is still valid
9b3f26c9
DH
119 */
120static enum fscache_checkaux afs_cell_cache_check_aux(void *cookie_netfs_data,
121 const void *buffer,
122 uint16_t buflen)
123{
124 _leave(" = OKAY");
125 return FSCACHE_CHECKAUX_OKAY;
08e0e7c8 126}
08e0e7c8 127
9b3f26c9 128/*****************************************************************************/
08e0e7c8 129/*
9b3f26c9 130 * set the key for the index entry
08e0e7c8 131 */
9b3f26c9
DH
132static uint16_t afs_vlocation_cache_get_key(const void *cookie_netfs_data,
133 void *buffer, uint16_t bufmax)
08e0e7c8 134{
9b3f26c9
DH
135 const struct afs_vlocation *vlocation = cookie_netfs_data;
136 uint16_t klen;
137
138 _enter("{%s},%p,%u", vlocation->vldb.name, buffer, bufmax);
139
140 klen = strnlen(vlocation->vldb.name, sizeof(vlocation->vldb.name));
141 if (klen > bufmax)
142 return 0;
08e0e7c8 143
9b3f26c9 144 memcpy(buffer, vlocation->vldb.name, klen);
08e0e7c8 145
9b3f26c9
DH
146 _leave(" = %u", klen);
147 return klen;
148}
149
150/*
25985edc 151 * provide new auxiliary cache data
9b3f26c9
DH
152 */
153static uint16_t afs_vlocation_cache_get_aux(const void *cookie_netfs_data,
154 void *buffer, uint16_t bufmax)
155{
156 const struct afs_vlocation *vlocation = cookie_netfs_data;
157 uint16_t dlen;
158
159 _enter("{%s},%p,%u", vlocation->vldb.name, buffer, bufmax);
160
161 dlen = sizeof(struct afs_cache_vlocation);
162 dlen -= offsetof(struct afs_cache_vlocation, nservers);
163 if (dlen > bufmax)
164 return 0;
165
166 memcpy(buffer, (uint8_t *)&vlocation->vldb.nservers, dlen);
167
168 _leave(" = %u", dlen);
169 return dlen;
170}
171
172/*
25985edc 173 * check that the auxiliary data indicates that the entry is still valid
9b3f26c9
DH
174 */
175static
176enum fscache_checkaux afs_vlocation_cache_check_aux(void *cookie_netfs_data,
177 const void *buffer,
178 uint16_t buflen)
179{
180 const struct afs_cache_vlocation *cvldb;
181 struct afs_vlocation *vlocation = cookie_netfs_data;
182 uint16_t dlen;
183
184 _enter("{%s},%p,%u", vlocation->vldb.name, buffer, buflen);
185
186 /* check the size of the data is what we're expecting */
187 dlen = sizeof(struct afs_cache_vlocation);
188 dlen -= offsetof(struct afs_cache_vlocation, nservers);
189 if (dlen != buflen)
190 return FSCACHE_CHECKAUX_OBSOLETE;
191
192 cvldb = container_of(buffer, struct afs_cache_vlocation, nservers);
193
194 /* if what's on disk is more valid than what's in memory, then use the
195 * VL record from the cache */
196 if (!vlocation->valid || vlocation->vldb.rtime == cvldb->rtime) {
197 memcpy((uint8_t *)&vlocation->vldb.nservers, buffer, dlen);
198 vlocation->valid = 1;
199 _leave(" = SUCCESS [c->m]");
200 return FSCACHE_CHECKAUX_OKAY;
201 }
202
203 /* need to update the cache if the cached info differs */
204 if (memcmp(&vlocation->vldb, buffer, dlen) != 0) {
205 /* delete if the volume IDs for this name differ */
206 if (memcmp(&vlocation->vldb.vid, &cvldb->vid,
207 sizeof(cvldb->vid)) != 0
08e0e7c8 208 ) {
9b3f26c9
DH
209 _leave(" = OBSOLETE");
210 return FSCACHE_CHECKAUX_OBSOLETE;
08e0e7c8 211 }
9b3f26c9
DH
212
213 _leave(" = UPDATE");
214 return FSCACHE_CHECKAUX_NEEDS_UPDATE;
08e0e7c8
DH
215 }
216
9b3f26c9
DH
217 _leave(" = OKAY");
218 return FSCACHE_CHECKAUX_OKAY;
08e0e7c8 219}
08e0e7c8 220
9b3f26c9 221/*****************************************************************************/
08e0e7c8 222/*
9b3f26c9 223 * set the key for the volume index entry
08e0e7c8 224 */
9b3f26c9
DH
225static uint16_t afs_volume_cache_get_key(const void *cookie_netfs_data,
226 void *buffer, uint16_t bufmax)
08e0e7c8 227{
9b3f26c9
DH
228 const struct afs_volume *volume = cookie_netfs_data;
229 uint16_t klen;
230
231 _enter("{%u},%p,%u", volume->type, buffer, bufmax);
232
233 klen = sizeof(volume->type);
234 if (klen > bufmax)
235 return 0;
08e0e7c8 236
9b3f26c9
DH
237 memcpy(buffer, &volume->type, sizeof(volume->type));
238
239 _leave(" = %u", klen);
240 return klen;
08e0e7c8 241
08e0e7c8 242}
08e0e7c8 243
9b3f26c9 244/*****************************************************************************/
08e0e7c8 245/*
9b3f26c9 246 * set the key for the index entry
08e0e7c8 247 */
9b3f26c9
DH
248static uint16_t afs_vnode_cache_get_key(const void *cookie_netfs_data,
249 void *buffer, uint16_t bufmax)
08e0e7c8 250{
9b3f26c9
DH
251 const struct afs_vnode *vnode = cookie_netfs_data;
252 uint16_t klen;
08e0e7c8 253
9b3f26c9
DH
254 _enter("{%x,%x,%llx},%p,%u",
255 vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version,
256 buffer, bufmax);
08e0e7c8 257
9b3f26c9
DH
258 klen = sizeof(vnode->fid.vnode);
259 if (klen > bufmax)
260 return 0;
261
262 memcpy(buffer, &vnode->fid.vnode, sizeof(vnode->fid.vnode));
08e0e7c8 263
9b3f26c9
DH
264 _leave(" = %u", klen);
265 return klen;
08e0e7c8 266}
08e0e7c8
DH
267
268/*
9b3f26c9 269 * provide updated file attributes
08e0e7c8 270 */
9b3f26c9
DH
271static void afs_vnode_cache_get_attr(const void *cookie_netfs_data,
272 uint64_t *size)
08e0e7c8 273{
9b3f26c9 274 const struct afs_vnode *vnode = cookie_netfs_data;
08e0e7c8 275
9b3f26c9
DH
276 _enter("{%x,%x,%llx},",
277 vnode->fid.vnode, vnode->fid.unique,
278 vnode->status.data_version);
08e0e7c8 279
9b3f26c9 280 *size = vnode->status.size;
08e0e7c8 281}
08e0e7c8
DH
282
283/*
25985edc 284 * provide new auxiliary cache data
9b3f26c9
DH
285 */
286static uint16_t afs_vnode_cache_get_aux(const void *cookie_netfs_data,
287 void *buffer, uint16_t bufmax)
288{
289 const struct afs_vnode *vnode = cookie_netfs_data;
290 uint16_t dlen;
291
292 _enter("{%x,%x,%Lx},%p,%u",
293 vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version,
294 buffer, bufmax);
295
296 dlen = sizeof(vnode->fid.unique) + sizeof(vnode->status.data_version);
297 if (dlen > bufmax)
298 return 0;
299
300 memcpy(buffer, &vnode->fid.unique, sizeof(vnode->fid.unique));
301 buffer += sizeof(vnode->fid.unique);
302 memcpy(buffer, &vnode->status.data_version,
303 sizeof(vnode->status.data_version));
304
305 _leave(" = %u", dlen);
306 return dlen;
307}
308
309/*
25985edc 310 * check that the auxiliary data indicates that the entry is still valid
08e0e7c8 311 */
9b3f26c9
DH
312static enum fscache_checkaux afs_vnode_cache_check_aux(void *cookie_netfs_data,
313 const void *buffer,
314 uint16_t buflen)
08e0e7c8 315{
9b3f26c9
DH
316 struct afs_vnode *vnode = cookie_netfs_data;
317 uint16_t dlen;
318
319 _enter("{%x,%x,%llx},%p,%u",
320 vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version,
321 buffer, buflen);
322
323 /* check the size of the data is what we're expecting */
324 dlen = sizeof(vnode->fid.unique) + sizeof(vnode->status.data_version);
325 if (dlen != buflen) {
326 _leave(" = OBSOLETE [len %hx != %hx]", dlen, buflen);
327 return FSCACHE_CHECKAUX_OBSOLETE;
08e0e7c8
DH
328 }
329
9b3f26c9
DH
330 if (memcmp(buffer,
331 &vnode->fid.unique,
332 sizeof(vnode->fid.unique)
333 ) != 0) {
334 unsigned unique;
335
336 memcpy(&unique, buffer, sizeof(unique));
337
338 _leave(" = OBSOLETE [uniq %x != %x]",
339 unique, vnode->fid.unique);
340 return FSCACHE_CHECKAUX_OBSOLETE;
341 }
342
343 if (memcmp(buffer + sizeof(vnode->fid.unique),
344 &vnode->status.data_version,
345 sizeof(vnode->status.data_version)
346 ) != 0) {
347 afs_dataversion_t version;
348
349 memcpy(&version, buffer + sizeof(vnode->fid.unique),
350 sizeof(version));
351
352 _leave(" = OBSOLETE [vers %llx != %llx]",
353 version, vnode->status.data_version);
354 return FSCACHE_CHECKAUX_OBSOLETE;
08e0e7c8
DH
355 }
356
357 _leave(" = SUCCESS");
9b3f26c9 358 return FSCACHE_CHECKAUX_OKAY;
08e0e7c8 359}