blob: cd857db9b112e2f5f4782ab20ad5e704b6d0fe01 [file] [log] [blame]
David Howells08e0e7c2007-04-26 15:55:03 -07001/* AFS caching stuff
2 *
David Howells9b3f26c2009-04-03 16:42:41 +01003 * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved.
David Howells08e0e7c2007-04-26 15:55:03 -07004 * 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
David Howells9b3f26c2009-04-03 16:42:41 +010012#include <linux/sched.h>
13#include "internal.h"
David Howells08e0e7c2007-04-26 15:55:03 -070014
David Howells9b3f26c2009-04-03 16:42:41 +010015static uint16_t afs_cell_cache_get_key(const void *cookie_netfs_data,
16 void *buffer, uint16_t buflen);
David Howells9b3f26c2009-04-03 16:42:41 +010017static uint16_t afs_volume_cache_get_key(const void *cookie_netfs_data,
18 void *buffer, uint16_t buflen);
19
20static uint16_t afs_vnode_cache_get_key(const void *cookie_netfs_data,
21 void *buffer, uint16_t buflen);
22static void afs_vnode_cache_get_attr(const void *cookie_netfs_data,
23 uint64_t *size);
24static uint16_t afs_vnode_cache_get_aux(const void *cookie_netfs_data,
25 void *buffer, uint16_t buflen);
26static enum fscache_checkaux afs_vnode_cache_check_aux(void *cookie_netfs_data,
27 const void *buffer,
28 uint16_t buflen);
David Howells9b3f26c2009-04-03 16:42:41 +010029
30struct fscache_netfs afs_cache_netfs = {
31 .name = "afs",
David Howells27a3ee32018-04-04 13:41:25 +010032 .version = 2,
David Howells08e0e7c2007-04-26 15:55:03 -070033};
David Howells9b3f26c2009-04-03 16:42:41 +010034
35struct fscache_cookie_def afs_cell_cache_index_def = {
36 .name = "AFS.cell",
37 .type = FSCACHE_COOKIE_TYPE_INDEX,
38 .get_key = afs_cell_cache_get_key,
David Howells9b3f26c2009-04-03 16:42:41 +010039};
40
41struct fscache_cookie_def afs_volume_cache_index_def = {
42 .name = "AFS.volume",
43 .type = FSCACHE_COOKIE_TYPE_INDEX,
44 .get_key = afs_volume_cache_get_key,
45};
46
47struct fscache_cookie_def afs_vnode_cache_index_def = {
48 .name = "AFS.vnode",
49 .type = FSCACHE_COOKIE_TYPE_DATAFILE,
50 .get_key = afs_vnode_cache_get_key,
51 .get_attr = afs_vnode_cache_get_attr,
52 .get_aux = afs_vnode_cache_get_aux,
53 .check_aux = afs_vnode_cache_check_aux,
David Howells9b3f26c2009-04-03 16:42:41 +010054};
David Howells08e0e7c2007-04-26 15:55:03 -070055
56/*
David Howells9b3f26c2009-04-03 16:42:41 +010057 * set the key for the index entry
David Howells08e0e7c2007-04-26 15:55:03 -070058 */
David Howells9b3f26c2009-04-03 16:42:41 +010059static uint16_t afs_cell_cache_get_key(const void *cookie_netfs_data,
60 void *buffer, uint16_t bufmax)
David Howells08e0e7c2007-04-26 15:55:03 -070061{
David Howells9b3f26c2009-04-03 16:42:41 +010062 const struct afs_cell *cell = cookie_netfs_data;
63 uint16_t klen;
David Howells08e0e7c2007-04-26 15:55:03 -070064
David Howells9b3f26c2009-04-03 16:42:41 +010065 _enter("%p,%p,%u", cell, buffer, bufmax);
David Howells08e0e7c2007-04-26 15:55:03 -070066
David Howells9b3f26c2009-04-03 16:42:41 +010067 klen = strlen(cell->name);
68 if (klen > bufmax)
69 return 0;
70
71 memcpy(buffer, cell->name, klen);
72 return klen;
73}
74
David Howells9b3f26c2009-04-03 16:42:41 +010075/*****************************************************************************/
76/*
77 * set the key for the volume index entry
78 */
79static uint16_t afs_volume_cache_get_key(const void *cookie_netfs_data,
David Howellsad6a9422017-11-02 15:27:47 +000080 void *buffer, uint16_t bufmax)
David Howells9b3f26c2009-04-03 16:42:41 +010081{
82 const struct afs_volume *volume = cookie_netfs_data;
David Howellsad6a9422017-11-02 15:27:47 +000083 struct {
84 u64 volid;
85 } __packed key;
David Howells9b3f26c2009-04-03 16:42:41 +010086
87 _enter("{%u},%p,%u", volume->type, buffer, bufmax);
88
David Howellsad6a9422017-11-02 15:27:47 +000089 if (bufmax < sizeof(key))
David Howells9b3f26c2009-04-03 16:42:41 +010090 return 0;
91
David Howellsad6a9422017-11-02 15:27:47 +000092 key.volid = volume->vid;
93 memcpy(buffer, &key, sizeof(key));
94 return sizeof(key);
David Howells9b3f26c2009-04-03 16:42:41 +010095}
96
97/*****************************************************************************/
98/*
99 * set the key for the index entry
100 */
101static uint16_t afs_vnode_cache_get_key(const void *cookie_netfs_data,
102 void *buffer, uint16_t bufmax)
103{
104 const struct afs_vnode *vnode = cookie_netfs_data;
David Howellsad6a9422017-11-02 15:27:47 +0000105 struct {
David Howells27a3ee32018-04-04 13:41:25 +0100106 u32 vnode_id;
107 u32 unique;
108 u32 vnode_id_ext[2]; /* Allow for a 96-bit key */
David Howellsad6a9422017-11-02 15:27:47 +0000109 } __packed key;
David Howells9b3f26c2009-04-03 16:42:41 +0100110
111 _enter("{%x,%x,%llx},%p,%u",
112 vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version,
113 buffer, bufmax);
114
David Howellsad6a9422017-11-02 15:27:47 +0000115 /* Allow for a 96-bit key */
116 memset(&key, 0, sizeof(key));
David Howells27a3ee32018-04-04 13:41:25 +0100117 key.vnode_id = vnode->fid.vnode;
118 key.unique = vnode->fid.unique;
119 key.vnode_id_ext[0] = 0;
120 key.vnode_id_ext[1] = 0;
David Howellsad6a9422017-11-02 15:27:47 +0000121
122 if (sizeof(key) > bufmax)
David Howells9b3f26c2009-04-03 16:42:41 +0100123 return 0;
124
David Howellsad6a9422017-11-02 15:27:47 +0000125 memcpy(buffer, &key, sizeof(key));
126 return sizeof(key);
David Howells9b3f26c2009-04-03 16:42:41 +0100127}
David Howells08e0e7c2007-04-26 15:55:03 -0700128
129/*
David Howells9b3f26c2009-04-03 16:42:41 +0100130 * provide updated file attributes
David Howells08e0e7c2007-04-26 15:55:03 -0700131 */
David Howells9b3f26c2009-04-03 16:42:41 +0100132static void afs_vnode_cache_get_attr(const void *cookie_netfs_data,
133 uint64_t *size)
David Howells08e0e7c2007-04-26 15:55:03 -0700134{
David Howells9b3f26c2009-04-03 16:42:41 +0100135 const struct afs_vnode *vnode = cookie_netfs_data;
David Howells08e0e7c2007-04-26 15:55:03 -0700136
David Howells9b3f26c2009-04-03 16:42:41 +0100137 _enter("{%x,%x,%llx},",
138 vnode->fid.vnode, vnode->fid.unique,
139 vnode->status.data_version);
David Howells08e0e7c2007-04-26 15:55:03 -0700140
David Howells9b3f26c2009-04-03 16:42:41 +0100141 *size = vnode->status.size;
David Howells08e0e7c2007-04-26 15:55:03 -0700142}
David Howells08e0e7c2007-04-26 15:55:03 -0700143
David Howellsad6a9422017-11-02 15:27:47 +0000144struct afs_vnode_cache_aux {
145 u64 data_version;
David Howellsad6a9422017-11-02 15:27:47 +0000146} __packed;
147
David Howells08e0e7c2007-04-26 15:55:03 -0700148/*
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300149 * provide new auxiliary cache data
David Howells08e0e7c2007-04-26 15:55:03 -0700150 */
David Howells9b3f26c2009-04-03 16:42:41 +0100151static uint16_t afs_vnode_cache_get_aux(const void *cookie_netfs_data,
152 void *buffer, uint16_t bufmax)
David Howells08e0e7c2007-04-26 15:55:03 -0700153{
David Howells9b3f26c2009-04-03 16:42:41 +0100154 const struct afs_vnode *vnode = cookie_netfs_data;
David Howellsad6a9422017-11-02 15:27:47 +0000155 struct afs_vnode_cache_aux aux;
David Howells08e0e7c2007-04-26 15:55:03 -0700156
David Howells9b3f26c2009-04-03 16:42:41 +0100157 _enter("{%x,%x,%Lx},%p,%u",
158 vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version,
159 buffer, bufmax);
David Howells08e0e7c2007-04-26 15:55:03 -0700160
David Howellsad6a9422017-11-02 15:27:47 +0000161 aux.data_version = vnode->status.data_version;
David Howellsad6a9422017-11-02 15:27:47 +0000162
163 if (bufmax < sizeof(aux))
David Howells9b3f26c2009-04-03 16:42:41 +0100164 return 0;
165
David Howellsad6a9422017-11-02 15:27:47 +0000166 memcpy(buffer, &aux, sizeof(aux));
167 return sizeof(aux);
David Howells9b3f26c2009-04-03 16:42:41 +0100168}
169
170/*
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300171 * check that the auxiliary data indicates that the entry is still valid
David Howells9b3f26c2009-04-03 16:42:41 +0100172 */
173static enum fscache_checkaux afs_vnode_cache_check_aux(void *cookie_netfs_data,
174 const void *buffer,
175 uint16_t buflen)
176{
177 struct afs_vnode *vnode = cookie_netfs_data;
David Howellsad6a9422017-11-02 15:27:47 +0000178 struct afs_vnode_cache_aux aux;
David Howells9b3f26c2009-04-03 16:42:41 +0100179
180 _enter("{%x,%x,%llx},%p,%u",
181 vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version,
182 buffer, buflen);
183
David Howellsad6a9422017-11-02 15:27:47 +0000184 memcpy(&aux, buffer, sizeof(aux));
185
David Howells9b3f26c2009-04-03 16:42:41 +0100186 /* check the size of the data is what we're expecting */
David Howellsad6a9422017-11-02 15:27:47 +0000187 if (buflen != sizeof(aux)) {
188 _leave(" = OBSOLETE [len %hx != %zx]", buflen, sizeof(aux));
David Howells9b3f26c2009-04-03 16:42:41 +0100189 return FSCACHE_CHECKAUX_OBSOLETE;
David Howells08e0e7c2007-04-26 15:55:03 -0700190 }
191
David Howellsad6a9422017-11-02 15:27:47 +0000192 if (vnode->status.data_version != aux.data_version) {
David Howells9b3f26c2009-04-03 16:42:41 +0100193 _leave(" = OBSOLETE [vers %llx != %llx]",
David Howellsad6a9422017-11-02 15:27:47 +0000194 aux.data_version, vnode->status.data_version);
David Howells9b3f26c2009-04-03 16:42:41 +0100195 return FSCACHE_CHECKAUX_OBSOLETE;
David Howells08e0e7c2007-04-26 15:55:03 -0700196 }
197
198 _leave(" = SUCCESS");
David Howells9b3f26c2009-04-03 16:42:41 +0100199 return FSCACHE_CHECKAUX_OKAY;
David Howells08e0e7c2007-04-26 15:55:03 -0700200}