at v4.14 359 lines 9.9 kB view raw
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 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); 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, 77}; 78 79/* 80 * set the key for the index entry 81 */ 82static 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 */ 101static 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 */ 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; 126} 127 128/*****************************************************************************/ 129/* 130 * set the key for the index entry 131 */ 132static 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 */ 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/* 173 * check that the auxiliary data indicates that the entry is still valid 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 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 */ 225static 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 */ 248static 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 */ 271static 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 */ 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/* 310 * check that the auxiliary data indicates that the entry is still valid 311 */ 312static 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}