Commit | Line | Data |
---|---|---|
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 | ||
15 | static uint16_t afs_cell_cache_get_key(const void *cookie_netfs_data, | |
16 | void *buffer, uint16_t buflen); | |
9b3f26c9 DH |
17 | static uint16_t afs_volume_cache_get_key(const void *cookie_netfs_data, |
18 | void *buffer, uint16_t buflen); | |
19 | ||
20 | static uint16_t afs_vnode_cache_get_key(const void *cookie_netfs_data, | |
21 | void *buffer, uint16_t buflen); | |
22 | static void afs_vnode_cache_get_attr(const void *cookie_netfs_data, | |
23 | uint64_t *size); | |
24 | static uint16_t afs_vnode_cache_get_aux(const void *cookie_netfs_data, | |
25 | void *buffer, uint16_t buflen); | |
26 | static enum fscache_checkaux afs_vnode_cache_check_aux(void *cookie_netfs_data, | |
27 | const void *buffer, | |
28 | uint16_t buflen); | |
9b3f26c9 DH |
29 | |
30 | struct fscache_netfs afs_cache_netfs = { | |
31 | .name = "afs", | |
ad6a942a | 32 | .version = 1, |
9b3f26c9 DH |
33 | }; |
34 | ||
35 | struct 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, | |
9b3f26c9 DH |
39 | }; |
40 | ||
41 | struct 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 | ||
47 | struct 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, | |
08e0e7c8 | 54 | }; |
08e0e7c8 DH |
55 | |
56 | /* | |
9b3f26c9 | 57 | * set the key for the index entry |
08e0e7c8 | 58 | */ |
9b3f26c9 DH |
59 | static uint16_t afs_cell_cache_get_key(const void *cookie_netfs_data, |
60 | void *buffer, uint16_t bufmax) | |
08e0e7c8 | 61 | { |
9b3f26c9 DH |
62 | const struct afs_cell *cell = cookie_netfs_data; |
63 | uint16_t klen; | |
08e0e7c8 | 64 | |
9b3f26c9 | 65 | _enter("%p,%p,%u", cell, buffer, bufmax); |
08e0e7c8 | 66 | |
9b3f26c9 DH |
67 | klen = strlen(cell->name); |
68 | if (klen > bufmax) | |
69 | return 0; | |
08e0e7c8 | 70 | |
9b3f26c9 DH |
71 | memcpy(buffer, cell->name, klen); |
72 | return klen; | |
08e0e7c8 | 73 | } |
08e0e7c8 | 74 | |
9b3f26c9 | 75 | /*****************************************************************************/ |
08e0e7c8 | 76 | /* |
9b3f26c9 | 77 | * set the key for the volume index entry |
08e0e7c8 | 78 | */ |
9b3f26c9 | 79 | static uint16_t afs_volume_cache_get_key(const void *cookie_netfs_data, |
ad6a942a | 80 | void *buffer, uint16_t bufmax) |
08e0e7c8 | 81 | { |
9b3f26c9 | 82 | const struct afs_volume *volume = cookie_netfs_data; |
ad6a942a DH |
83 | struct { |
84 | u64 volid; | |
85 | } __packed key; | |
9b3f26c9 DH |
86 | |
87 | _enter("{%u},%p,%u", volume->type, buffer, bufmax); | |
88 | ||
ad6a942a | 89 | if (bufmax < sizeof(key)) |
9b3f26c9 | 90 | return 0; |
08e0e7c8 | 91 | |
ad6a942a DH |
92 | key.volid = volume->vid; |
93 | memcpy(buffer, &key, sizeof(key)); | |
94 | return sizeof(key); | |
08e0e7c8 | 95 | } |
08e0e7c8 | 96 | |
9b3f26c9 | 97 | /*****************************************************************************/ |
08e0e7c8 | 98 | /* |
9b3f26c9 | 99 | * set the key for the index entry |
08e0e7c8 | 100 | */ |
9b3f26c9 DH |
101 | static uint16_t afs_vnode_cache_get_key(const void *cookie_netfs_data, |
102 | void *buffer, uint16_t bufmax) | |
08e0e7c8 | 103 | { |
9b3f26c9 | 104 | const struct afs_vnode *vnode = cookie_netfs_data; |
ad6a942a DH |
105 | struct { |
106 | u32 vnode_id[3]; | |
107 | } __packed key; | |
08e0e7c8 | 108 | |
9b3f26c9 DH |
109 | _enter("{%x,%x,%llx},%p,%u", |
110 | vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version, | |
111 | buffer, bufmax); | |
08e0e7c8 | 112 | |
ad6a942a DH |
113 | /* Allow for a 96-bit key */ |
114 | memset(&key, 0, sizeof(key)); | |
115 | key.vnode_id[0] = vnode->fid.vnode; | |
116 | key.vnode_id[1] = 0; | |
117 | key.vnode_id[2] = 0; | |
9b3f26c9 | 118 | |
ad6a942a DH |
119 | if (sizeof(key) > bufmax) |
120 | return 0; | |
08e0e7c8 | 121 | |
ad6a942a DH |
122 | memcpy(buffer, &key, sizeof(key)); |
123 | return sizeof(key); | |
08e0e7c8 | 124 | } |
08e0e7c8 DH |
125 | |
126 | /* | |
9b3f26c9 | 127 | * provide updated file attributes |
08e0e7c8 | 128 | */ |
9b3f26c9 DH |
129 | static void afs_vnode_cache_get_attr(const void *cookie_netfs_data, |
130 | uint64_t *size) | |
08e0e7c8 | 131 | { |
9b3f26c9 | 132 | const struct afs_vnode *vnode = cookie_netfs_data; |
08e0e7c8 | 133 | |
9b3f26c9 DH |
134 | _enter("{%x,%x,%llx},", |
135 | vnode->fid.vnode, vnode->fid.unique, | |
136 | vnode->status.data_version); | |
08e0e7c8 | 137 | |
9b3f26c9 | 138 | *size = vnode->status.size; |
08e0e7c8 | 139 | } |
08e0e7c8 | 140 | |
ad6a942a DH |
141 | struct afs_vnode_cache_aux { |
142 | u64 data_version; | |
143 | u32 fid_unique; | |
144 | } __packed; | |
145 | ||
08e0e7c8 | 146 | /* |
25985edc | 147 | * provide new auxiliary cache data |
9b3f26c9 DH |
148 | */ |
149 | static uint16_t afs_vnode_cache_get_aux(const void *cookie_netfs_data, | |
150 | void *buffer, uint16_t bufmax) | |
151 | { | |
152 | const struct afs_vnode *vnode = cookie_netfs_data; | |
ad6a942a | 153 | struct afs_vnode_cache_aux aux; |
9b3f26c9 DH |
154 | |
155 | _enter("{%x,%x,%Lx},%p,%u", | |
156 | vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version, | |
157 | buffer, bufmax); | |
158 | ||
ad6a942a DH |
159 | memset(&aux, 0, sizeof(aux)); |
160 | aux.data_version = vnode->status.data_version; | |
161 | aux.fid_unique = vnode->fid.unique; | |
9b3f26c9 | 162 | |
ad6a942a DH |
163 | if (bufmax < sizeof(aux)) |
164 | return 0; | |
9b3f26c9 | 165 | |
ad6a942a DH |
166 | memcpy(buffer, &aux, sizeof(aux)); |
167 | return sizeof(aux); | |
9b3f26c9 DH |
168 | } |
169 | ||
170 | /* | |
25985edc | 171 | * check that the auxiliary data indicates that the entry is still valid |
08e0e7c8 | 172 | */ |
9b3f26c9 DH |
173 | static enum fscache_checkaux afs_vnode_cache_check_aux(void *cookie_netfs_data, |
174 | const void *buffer, | |
175 | uint16_t buflen) | |
08e0e7c8 | 176 | { |
9b3f26c9 | 177 | struct afs_vnode *vnode = cookie_netfs_data; |
ad6a942a | 178 | struct afs_vnode_cache_aux aux; |
9b3f26c9 DH |
179 | |
180 | _enter("{%x,%x,%llx},%p,%u", | |
181 | vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version, | |
182 | buffer, buflen); | |
183 | ||
ad6a942a DH |
184 | memcpy(&aux, buffer, sizeof(aux)); |
185 | ||
9b3f26c9 | 186 | /* check the size of the data is what we're expecting */ |
ad6a942a DH |
187 | if (buflen != sizeof(aux)) { |
188 | _leave(" = OBSOLETE [len %hx != %zx]", buflen, sizeof(aux)); | |
9b3f26c9 | 189 | return FSCACHE_CHECKAUX_OBSOLETE; |
08e0e7c8 DH |
190 | } |
191 | ||
ad6a942a | 192 | if (vnode->fid.unique != aux.fid_unique) { |
9b3f26c9 | 193 | _leave(" = OBSOLETE [uniq %x != %x]", |
ad6a942a | 194 | aux.fid_unique, vnode->fid.unique); |
9b3f26c9 DH |
195 | return FSCACHE_CHECKAUX_OBSOLETE; |
196 | } | |
197 | ||
ad6a942a | 198 | if (vnode->status.data_version != aux.data_version) { |
9b3f26c9 | 199 | _leave(" = OBSOLETE [vers %llx != %llx]", |
ad6a942a | 200 | aux.data_version, vnode->status.data_version); |
9b3f26c9 | 201 | return FSCACHE_CHECKAUX_OBSOLETE; |
08e0e7c8 DH |
202 | } |
203 | ||
204 | _leave(" = SUCCESS"); | |
9b3f26c9 | 205 | return FSCACHE_CHECKAUX_OKAY; |
08e0e7c8 | 206 | } |