Merge tag 'afs-next-20171113' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowel...
[sfrench/cifs-2.6.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_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);
29
30 struct fscache_netfs afs_cache_netfs = {
31         .name                   = "afs",
32         .version                = 1,
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,
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,
54 };
55
56 /*
57  * set the key for the index entry
58  */
59 static uint16_t afs_cell_cache_get_key(const void *cookie_netfs_data,
60                                        void *buffer, uint16_t bufmax)
61 {
62         const struct afs_cell *cell = cookie_netfs_data;
63         uint16_t klen;
64
65         _enter("%p,%p,%u", cell, buffer, bufmax);
66
67         klen = strlen(cell->name);
68         if (klen > bufmax)
69                 return 0;
70
71         memcpy(buffer, cell->name, klen);
72         return klen;
73 }
74
75 /*****************************************************************************/
76 /*
77  * set the key for the volume index entry
78  */
79 static uint16_t afs_volume_cache_get_key(const void *cookie_netfs_data,
80                                          void *buffer, uint16_t bufmax)
81 {
82         const struct afs_volume *volume = cookie_netfs_data;
83         struct {
84                 u64 volid;
85         } __packed key;
86
87         _enter("{%u},%p,%u", volume->type, buffer, bufmax);
88
89         if (bufmax < sizeof(key))
90                 return 0;
91
92         key.volid = volume->vid;
93         memcpy(buffer, &key, sizeof(key));
94         return sizeof(key);
95 }
96
97 /*****************************************************************************/
98 /*
99  * set the key for the index entry
100  */
101 static 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;
105         struct {
106                 u32 vnode_id[3];
107         } __packed key;
108
109         _enter("{%x,%x,%llx},%p,%u",
110                vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version,
111                buffer, bufmax);
112
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;
118
119         if (sizeof(key) > bufmax)
120                 return 0;
121
122         memcpy(buffer, &key, sizeof(key));
123         return sizeof(key);
124 }
125
126 /*
127  * provide updated file attributes
128  */
129 static void afs_vnode_cache_get_attr(const void *cookie_netfs_data,
130                                      uint64_t *size)
131 {
132         const struct afs_vnode *vnode = cookie_netfs_data;
133
134         _enter("{%x,%x,%llx},",
135                vnode->fid.vnode, vnode->fid.unique,
136                vnode->status.data_version);
137
138         *size = vnode->status.size;
139 }
140
141 struct afs_vnode_cache_aux {
142         u64 data_version;
143         u32 fid_unique;
144 } __packed;
145
146 /*
147  * provide new auxiliary cache data
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;
153         struct afs_vnode_cache_aux aux;
154
155         _enter("{%x,%x,%Lx},%p,%u",
156                vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version,
157                buffer, bufmax);
158
159         memset(&aux, 0, sizeof(aux));
160         aux.data_version = vnode->status.data_version;
161         aux.fid_unique = vnode->fid.unique;
162
163         if (bufmax < sizeof(aux))
164                 return 0;
165
166         memcpy(buffer, &aux, sizeof(aux));
167         return sizeof(aux);
168 }
169
170 /*
171  * check that the auxiliary data indicates that the entry is still valid
172  */
173 static 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;
178         struct afs_vnode_cache_aux aux;
179
180         _enter("{%x,%x,%llx},%p,%u",
181                vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version,
182                buffer, buflen);
183
184         memcpy(&aux, buffer, sizeof(aux));
185
186         /* check the size of the data is what we're expecting */
187         if (buflen != sizeof(aux)) {
188                 _leave(" = OBSOLETE [len %hx != %zx]", buflen, sizeof(aux));
189                 return FSCACHE_CHECKAUX_OBSOLETE;
190         }
191
192         if (vnode->fid.unique != aux.fid_unique) {
193                 _leave(" = OBSOLETE [uniq %x != %x]",
194                        aux.fid_unique, vnode->fid.unique);
195                 return FSCACHE_CHECKAUX_OBSOLETE;
196         }
197
198         if (vnode->status.data_version != aux.data_version) {
199                 _leave(" = OBSOLETE [vers %llx != %llx]",
200                        aux.data_version, vnode->status.data_version);
201                 return FSCACHE_CHECKAUX_OBSOLETE;
202         }
203
204         _leave(" = SUCCESS");
205         return FSCACHE_CHECKAUX_OKAY;
206 }