Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/fs/cachefiles/xattr.c
15109 views
1
/* CacheFiles extended attribute management
2
*
3
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4
* Written by David Howells ([email protected])
5
*
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public Licence
8
* as published by the Free Software Foundation; either version
9
* 2 of the Licence, or (at your option) any later version.
10
*/
11
12
#include <linux/module.h>
13
#include <linux/sched.h>
14
#include <linux/file.h>
15
#include <linux/fs.h>
16
#include <linux/fsnotify.h>
17
#include <linux/quotaops.h>
18
#include <linux/xattr.h>
19
#include <linux/slab.h>
20
#include "internal.h"
21
22
static const char cachefiles_xattr_cache[] =
23
XATTR_USER_PREFIX "CacheFiles.cache";
24
25
/*
26
* check the type label on an object
27
* - done using xattrs
28
*/
29
int cachefiles_check_object_type(struct cachefiles_object *object)
30
{
31
struct dentry *dentry = object->dentry;
32
char type[3], xtype[3];
33
int ret;
34
35
ASSERT(dentry);
36
ASSERT(dentry->d_inode);
37
38
if (!object->fscache.cookie)
39
strcpy(type, "C3");
40
else
41
snprintf(type, 3, "%02x", object->fscache.cookie->def->type);
42
43
_enter("%p{%s}", object, type);
44
45
/* attempt to install a type label directly */
46
ret = vfs_setxattr(dentry, cachefiles_xattr_cache, type, 2,
47
XATTR_CREATE);
48
if (ret == 0) {
49
_debug("SET"); /* we succeeded */
50
goto error;
51
}
52
53
if (ret != -EEXIST) {
54
kerror("Can't set xattr on %*.*s [%lu] (err %d)",
55
dentry->d_name.len, dentry->d_name.len,
56
dentry->d_name.name, dentry->d_inode->i_ino,
57
-ret);
58
goto error;
59
}
60
61
/* read the current type label */
62
ret = vfs_getxattr(dentry, cachefiles_xattr_cache, xtype, 3);
63
if (ret < 0) {
64
if (ret == -ERANGE)
65
goto bad_type_length;
66
67
kerror("Can't read xattr on %*.*s [%lu] (err %d)",
68
dentry->d_name.len, dentry->d_name.len,
69
dentry->d_name.name, dentry->d_inode->i_ino,
70
-ret);
71
goto error;
72
}
73
74
/* check the type is what we're expecting */
75
if (ret != 2)
76
goto bad_type_length;
77
78
if (xtype[0] != type[0] || xtype[1] != type[1])
79
goto bad_type;
80
81
ret = 0;
82
83
error:
84
_leave(" = %d", ret);
85
return ret;
86
87
bad_type_length:
88
kerror("Cache object %lu type xattr length incorrect",
89
dentry->d_inode->i_ino);
90
ret = -EIO;
91
goto error;
92
93
bad_type:
94
xtype[2] = 0;
95
kerror("Cache object %*.*s [%lu] type %s not %s",
96
dentry->d_name.len, dentry->d_name.len,
97
dentry->d_name.name, dentry->d_inode->i_ino,
98
xtype, type);
99
ret = -EIO;
100
goto error;
101
}
102
103
/*
104
* set the state xattr on a cache file
105
*/
106
int cachefiles_set_object_xattr(struct cachefiles_object *object,
107
struct cachefiles_xattr *auxdata)
108
{
109
struct dentry *dentry = object->dentry;
110
int ret;
111
112
ASSERT(object->fscache.cookie);
113
ASSERT(dentry);
114
115
_enter("%p,#%d", object, auxdata->len);
116
117
/* attempt to install the cache metadata directly */
118
_debug("SET %s #%u", object->fscache.cookie->def->name, auxdata->len);
119
120
ret = vfs_setxattr(dentry, cachefiles_xattr_cache,
121
&auxdata->type, auxdata->len,
122
XATTR_CREATE);
123
if (ret < 0 && ret != -ENOMEM)
124
cachefiles_io_error_obj(
125
object,
126
"Failed to set xattr with error %d", ret);
127
128
_leave(" = %d", ret);
129
return ret;
130
}
131
132
/*
133
* update the state xattr on a cache file
134
*/
135
int cachefiles_update_object_xattr(struct cachefiles_object *object,
136
struct cachefiles_xattr *auxdata)
137
{
138
struct dentry *dentry = object->dentry;
139
int ret;
140
141
ASSERT(object->fscache.cookie);
142
ASSERT(dentry);
143
144
_enter("%p,#%d", object, auxdata->len);
145
146
/* attempt to install the cache metadata directly */
147
_debug("SET %s #%u", object->fscache.cookie->def->name, auxdata->len);
148
149
ret = vfs_setxattr(dentry, cachefiles_xattr_cache,
150
&auxdata->type, auxdata->len,
151
XATTR_REPLACE);
152
if (ret < 0 && ret != -ENOMEM)
153
cachefiles_io_error_obj(
154
object,
155
"Failed to update xattr with error %d", ret);
156
157
_leave(" = %d", ret);
158
return ret;
159
}
160
161
/*
162
* check the state xattr on a cache file
163
* - return -ESTALE if the object should be deleted
164
*/
165
int cachefiles_check_object_xattr(struct cachefiles_object *object,
166
struct cachefiles_xattr *auxdata)
167
{
168
struct cachefiles_xattr *auxbuf;
169
struct dentry *dentry = object->dentry;
170
int ret;
171
172
_enter("%p,#%d", object, auxdata->len);
173
174
ASSERT(dentry);
175
ASSERT(dentry->d_inode);
176
177
auxbuf = kmalloc(sizeof(struct cachefiles_xattr) + 512, GFP_KERNEL);
178
if (!auxbuf) {
179
_leave(" = -ENOMEM");
180
return -ENOMEM;
181
}
182
183
/* read the current type label */
184
ret = vfs_getxattr(dentry, cachefiles_xattr_cache,
185
&auxbuf->type, 512 + 1);
186
if (ret < 0) {
187
if (ret == -ENODATA)
188
goto stale; /* no attribute - power went off
189
* mid-cull? */
190
191
if (ret == -ERANGE)
192
goto bad_type_length;
193
194
cachefiles_io_error_obj(object,
195
"Can't read xattr on %lu (err %d)",
196
dentry->d_inode->i_ino, -ret);
197
goto error;
198
}
199
200
/* check the on-disk object */
201
if (ret < 1)
202
goto bad_type_length;
203
204
if (auxbuf->type != auxdata->type)
205
goto stale;
206
207
auxbuf->len = ret;
208
209
/* consult the netfs */
210
if (object->fscache.cookie->def->check_aux) {
211
enum fscache_checkaux result;
212
unsigned int dlen;
213
214
dlen = auxbuf->len - 1;
215
216
_debug("checkaux %s #%u",
217
object->fscache.cookie->def->name, dlen);
218
219
result = fscache_check_aux(&object->fscache,
220
&auxbuf->data, dlen);
221
222
switch (result) {
223
/* entry okay as is */
224
case FSCACHE_CHECKAUX_OKAY:
225
goto okay;
226
227
/* entry requires update */
228
case FSCACHE_CHECKAUX_NEEDS_UPDATE:
229
break;
230
231
/* entry requires deletion */
232
case FSCACHE_CHECKAUX_OBSOLETE:
233
goto stale;
234
235
default:
236
BUG();
237
}
238
239
/* update the current label */
240
ret = vfs_setxattr(dentry, cachefiles_xattr_cache,
241
&auxdata->type, auxdata->len,
242
XATTR_REPLACE);
243
if (ret < 0) {
244
cachefiles_io_error_obj(object,
245
"Can't update xattr on %lu"
246
" (error %d)",
247
dentry->d_inode->i_ino, -ret);
248
goto error;
249
}
250
}
251
252
okay:
253
ret = 0;
254
255
error:
256
kfree(auxbuf);
257
_leave(" = %d", ret);
258
return ret;
259
260
bad_type_length:
261
kerror("Cache object %lu xattr length incorrect",
262
dentry->d_inode->i_ino);
263
ret = -EIO;
264
goto error;
265
266
stale:
267
ret = -ESTALE;
268
goto error;
269
}
270
271
/*
272
* remove the object's xattr to mark it stale
273
*/
274
int cachefiles_remove_object_xattr(struct cachefiles_cache *cache,
275
struct dentry *dentry)
276
{
277
int ret;
278
279
ret = vfs_removexattr(dentry, cachefiles_xattr_cache);
280
if (ret < 0) {
281
if (ret == -ENOENT || ret == -ENODATA)
282
ret = 0;
283
else if (ret != -ENOMEM)
284
cachefiles_io_error(cache,
285
"Can't remove xattr from %lu"
286
" (error %d)",
287
dentry->d_inode->i_ino, -ret);
288
}
289
290
_leave(" = %d", ret);
291
return ret;
292
}
293
294