1fe855191261fce57a85be27f59690743957ecd6
[GitHub/LineageOS/android_kernel_motorola_exynos9610.git] / fs / afs / cache.c
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
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,
20 const void *buffer,
21 uint16_t buflen);
22
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);
29
30 static uint16_t afs_volume_cache_get_key(const void *cookie_netfs_data,
31 void *buffer, uint16_t buflen);
32
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,
36 uint64_t *size);
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,
40 const void *buffer,
41 uint16_t buflen);
42
43 struct fscache_netfs afs_cache_netfs = {
44 .name = "afs",
45 .version = 0,
46 };
47
48 struct 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
56 struct 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
64 struct 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
70 struct 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,
77 };
78
79 /*
80 * set the key for the index entry
81 */
82 static uint16_t afs_cell_cache_get_key(const void *cookie_netfs_data,
83 void *buffer, uint16_t bufmax)
84 {
85 const struct afs_cell *cell = cookie_netfs_data;
86 uint16_t klen;
87
88 _enter("%p,%p,%u", cell, buffer, bufmax);
89
90 klen = strlen(cell->name);
91 if (klen > bufmax)
92 return 0;
93
94 memcpy(buffer, cell->name, klen);
95 return klen;
96 }
97
98 /*
99 * provide new auxiliary cache data
100 */
101 static uint16_t afs_cell_cache_get_aux(const void *cookie_netfs_data,
102 void *buffer, uint16_t bufmax)
103 {
104 const struct afs_cell *cell = cookie_netfs_data;
105 uint16_t dlen;
106
107 _enter("%p,%p,%u", cell, buffer, bufmax);
108
109 dlen = cell->vl_naddrs * sizeof(cell->vl_addrs[0]);
110 dlen = min(dlen, bufmax);
111 dlen &= ~(sizeof(cell->vl_addrs[0]) - 1);
112
113 memcpy(buffer, cell->vl_addrs, dlen);
114 return dlen;
115 }
116
117 /*
118 * check that the auxiliary data indicates that the entry is still valid
119 */
120 static 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;
126 }
127
128 /*****************************************************************************/
129 /*
130 * set the key for the index entry
131 */
132 static uint16_t afs_vlocation_cache_get_key(const void *cookie_netfs_data,
133 void *buffer, uint16_t bufmax)
134 {
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;
143
144 memcpy(buffer, vlocation->vldb.name, klen);
145
146 _leave(" = %u", klen);
147 return klen;
148 }
149
150 /*
151 * provide new auxiliary cache data
152 */
153 static 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 /*
173 * check that the auxiliary data indicates that the entry is still valid
174 */
175 static
176 enum 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
208 ) {
209 _leave(" = OBSOLETE");
210 return FSCACHE_CHECKAUX_OBSOLETE;
211 }
212
213 _leave(" = UPDATE");
214 return FSCACHE_CHECKAUX_NEEDS_UPDATE;
215 }
216
217 _leave(" = OKAY");
218 return FSCACHE_CHECKAUX_OKAY;
219 }
220
221 /*****************************************************************************/
222 /*
223 * set the key for the volume index entry
224 */
225 static uint16_t afs_volume_cache_get_key(const void *cookie_netfs_data,
226 void *buffer, uint16_t bufmax)
227 {
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;
236
237 memcpy(buffer, &volume->type, sizeof(volume->type));
238
239 _leave(" = %u", klen);
240 return klen;
241
242 }
243
244 /*****************************************************************************/
245 /*
246 * set the key for the index entry
247 */
248 static uint16_t afs_vnode_cache_get_key(const void *cookie_netfs_data,
249 void *buffer, uint16_t bufmax)
250 {
251 const struct afs_vnode *vnode = cookie_netfs_data;
252 uint16_t klen;
253
254 _enter("{%x,%x,%llx},%p,%u",
255 vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version,
256 buffer, bufmax);
257
258 klen = sizeof(vnode->fid.vnode);
259 if (klen > bufmax)
260 return 0;
261
262 memcpy(buffer, &vnode->fid.vnode, sizeof(vnode->fid.vnode));
263
264 _leave(" = %u", klen);
265 return klen;
266 }
267
268 /*
269 * provide updated file attributes
270 */
271 static void afs_vnode_cache_get_attr(const void *cookie_netfs_data,
272 uint64_t *size)
273 {
274 const struct afs_vnode *vnode = cookie_netfs_data;
275
276 _enter("{%x,%x,%llx},",
277 vnode->fid.vnode, vnode->fid.unique,
278 vnode->status.data_version);
279
280 *size = vnode->status.size;
281 }
282
283 /*
284 * provide new auxiliary cache data
285 */
286 static 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 /*
310 * check that the auxiliary data indicates that the entry is still valid
311 */
312 static enum fscache_checkaux afs_vnode_cache_check_aux(void *cookie_netfs_data,
313 const void *buffer,
314 uint16_t buflen)
315 {
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;
328 }
329
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;
355 }
356
357 _leave(" = SUCCESS");
358 return FSCACHE_CHECKAUX_OKAY;
359 }