Blame view
fs/cachefiles/xattr.c
7.06 KB
b4d0d230c
|
1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
9ae326a69
|
2 3 4 5 |
/* CacheFiles extended attribute management * * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) |
9ae326a69
|
6 7 8 9 10 11 12 13 14 |
*/ #include <linux/module.h> #include <linux/sched.h> #include <linux/file.h> #include <linux/fs.h> #include <linux/fsnotify.h> #include <linux/quotaops.h> #include <linux/xattr.h> |
5a0e3ad6a
|
15 |
#include <linux/slab.h> |
9ae326a69
|
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
#include "internal.h" static const char cachefiles_xattr_cache[] = XATTR_USER_PREFIX "CacheFiles.cache"; /* * check the type label on an object * - done using xattrs */ int cachefiles_check_object_type(struct cachefiles_object *object) { struct dentry *dentry = object->dentry; char type[3], xtype[3]; int ret; ASSERT(dentry); |
466b77bc9
|
32 |
ASSERT(d_backing_inode(dentry)); |
9ae326a69
|
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
if (!object->fscache.cookie) strcpy(type, "C3"); else snprintf(type, 3, "%02x", object->fscache.cookie->def->type); _enter("%p{%s}", object, type); /* attempt to install a type label directly */ ret = vfs_setxattr(dentry, cachefiles_xattr_cache, type, 2, XATTR_CREATE); if (ret == 0) { _debug("SET"); /* we succeeded */ goto error; } if (ret != -EEXIST) { |
a455589f1
|
50 51 |
pr_err("Can't set xattr on %pd [%lu] (err %d) ", |
466b77bc9
|
52 |
dentry, d_backing_inode(dentry)->i_ino, |
9ae326a69
|
53 54 55 56 57 58 59 60 61 |
-ret); goto error; } /* read the current type label */ ret = vfs_getxattr(dentry, cachefiles_xattr_cache, xtype, 3); if (ret < 0) { if (ret == -ERANGE) goto bad_type_length; |
a455589f1
|
62 63 |
pr_err("Can't read xattr on %pd [%lu] (err %d) ", |
466b77bc9
|
64 |
dentry, d_backing_inode(dentry)->i_ino, |
9ae326a69
|
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
-ret); goto error; } /* check the type is what we're expecting */ if (ret != 2) goto bad_type_length; if (xtype[0] != type[0] || xtype[1] != type[1]) goto bad_type; ret = 0; error: _leave(" = %d", ret); return ret; bad_type_length: |
6ff66ac77
|
83 84 |
pr_err("Cache object %lu type xattr length incorrect ", |
466b77bc9
|
85 |
d_backing_inode(dentry)->i_ino); |
9ae326a69
|
86 87 88 89 90 |
ret = -EIO; goto error; bad_type: xtype[2] = 0; |
a455589f1
|
91 92 |
pr_err("Cache object %pd [%lu] type %s not %s ", |
466b77bc9
|
93 |
dentry, d_backing_inode(dentry)->i_ino, |
9ae326a69
|
94 95 96 97 98 99 100 101 102 103 104 105 106 |
xtype, type); ret = -EIO; goto error; } /* * set the state xattr on a cache file */ int cachefiles_set_object_xattr(struct cachefiles_object *object, struct cachefiles_xattr *auxdata) { struct dentry *dentry = object->dentry; int ret; |
9ae326a69
|
107 108 109 110 111 |
ASSERT(dentry); _enter("%p,#%d", object, auxdata->len); /* attempt to install the cache metadata directly */ |
1362729b1
|
112 |
_debug("SET #%u", auxdata->len); |
9ae326a69
|
113 |
|
402cb8dda
|
114 |
clear_bit(FSCACHE_COOKIE_AUX_UPDATED, &object->fscache.cookie->flags); |
9ae326a69
|
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
ret = vfs_setxattr(dentry, cachefiles_xattr_cache, &auxdata->type, auxdata->len, XATTR_CREATE); if (ret < 0 && ret != -ENOMEM) cachefiles_io_error_obj( object, "Failed to set xattr with error %d", ret); _leave(" = %d", ret); return ret; } /* * update the state xattr on a cache file */ int cachefiles_update_object_xattr(struct cachefiles_object *object, struct cachefiles_xattr *auxdata) { struct dentry *dentry = object->dentry; int ret; |
e6bc06faf
|
135 136 |
if (!dentry) return -ESTALE; |
9ae326a69
|
137 138 139 140 |
_enter("%p,#%d", object, auxdata->len); /* attempt to install the cache metadata directly */ |
1362729b1
|
141 |
_debug("SET #%u", auxdata->len); |
9ae326a69
|
142 |
|
402cb8dda
|
143 |
clear_bit(FSCACHE_COOKIE_AUX_UPDATED, &object->fscache.cookie->flags); |
9ae326a69
|
144 145 146 147 148 149 150 151 152 153 154 155 156 |
ret = vfs_setxattr(dentry, cachefiles_xattr_cache, &auxdata->type, auxdata->len, XATTR_REPLACE); if (ret < 0 && ret != -ENOMEM) cachefiles_io_error_obj( object, "Failed to update xattr with error %d", ret); _leave(" = %d", ret); return ret; } /* |
5002d7bef
|
157 158 159 160 161 |
* check the consistency between the backing cache and the FS-Cache cookie */ int cachefiles_check_auxdata(struct cachefiles_object *object) { struct cachefiles_xattr *auxbuf; |
607566aec
|
162 |
enum fscache_checkaux validity; |
5002d7bef
|
163 |
struct dentry *dentry = object->dentry; |
607566aec
|
164 |
ssize_t xlen; |
5002d7bef
|
165 166 167 |
int ret; ASSERT(dentry); |
466b77bc9
|
168 |
ASSERT(d_backing_inode(dentry)); |
5002d7bef
|
169 170 171 172 173 |
ASSERT(object->fscache.cookie->def->check_aux); auxbuf = kmalloc(sizeof(struct cachefiles_xattr) + 512, GFP_KERNEL); if (!auxbuf) return -ENOMEM; |
607566aec
|
174 175 176 177 178 179 |
xlen = vfs_getxattr(dentry, cachefiles_xattr_cache, &auxbuf->type, 512 + 1); ret = -ESTALE; if (xlen < 1 || auxbuf->type != object->fscache.cookie->def->type) goto error; |
5002d7bef
|
180 |
|
607566aec
|
181 |
xlen--; |
ee1235a9a
|
182 183 |
validity = fscache_check_aux(&object->fscache, &auxbuf->data, xlen, i_size_read(d_backing_inode(dentry))); |
607566aec
|
184 185 |
if (validity != FSCACHE_CHECKAUX_OKAY) goto error; |
5002d7bef
|
186 |
|
607566aec
|
187 188 |
ret = 0; error: |
5002d7bef
|
189 |
kfree(auxbuf); |
607566aec
|
190 |
return ret; |
5002d7bef
|
191 192 193 |
} /* |
9ae326a69
|
194 195 196 197 198 199 200 201 202 203 204 205 206 |
* check the state xattr on a cache file * - return -ESTALE if the object should be deleted */ int cachefiles_check_object_xattr(struct cachefiles_object *object, struct cachefiles_xattr *auxdata) { struct cachefiles_xattr *auxbuf; struct dentry *dentry = object->dentry; int ret; _enter("%p,#%d", object, auxdata->len); ASSERT(dentry); |
466b77bc9
|
207 |
ASSERT(d_backing_inode(dentry)); |
9ae326a69
|
208 |
|
5f4f9f4af
|
209 |
auxbuf = kmalloc(sizeof(struct cachefiles_xattr) + 512, cachefiles_gfp); |
9ae326a69
|
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
if (!auxbuf) { _leave(" = -ENOMEM"); return -ENOMEM; } /* read the current type label */ ret = vfs_getxattr(dentry, cachefiles_xattr_cache, &auxbuf->type, 512 + 1); if (ret < 0) { if (ret == -ENODATA) goto stale; /* no attribute - power went off * mid-cull? */ if (ret == -ERANGE) goto bad_type_length; cachefiles_io_error_obj(object, "Can't read xattr on %lu (err %d)", |
466b77bc9
|
228 |
d_backing_inode(dentry)->i_ino, -ret); |
9ae326a69
|
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
goto error; } /* check the on-disk object */ if (ret < 1) goto bad_type_length; if (auxbuf->type != auxdata->type) goto stale; auxbuf->len = ret; /* consult the netfs */ if (object->fscache.cookie->def->check_aux) { enum fscache_checkaux result; unsigned int dlen; dlen = auxbuf->len - 1; _debug("checkaux %s #%u", object->fscache.cookie->def->name, dlen); result = fscache_check_aux(&object->fscache, |
ee1235a9a
|
252 253 |
&auxbuf->data, dlen, i_size_read(d_backing_inode(dentry))); |
9ae326a69
|
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
switch (result) { /* entry okay as is */ case FSCACHE_CHECKAUX_OKAY: goto okay; /* entry requires update */ case FSCACHE_CHECKAUX_NEEDS_UPDATE: break; /* entry requires deletion */ case FSCACHE_CHECKAUX_OBSOLETE: goto stale; default: BUG(); } /* update the current label */ ret = vfs_setxattr(dentry, cachefiles_xattr_cache, &auxdata->type, auxdata->len, XATTR_REPLACE); if (ret < 0) { cachefiles_io_error_obj(object, "Can't update xattr on %lu" " (error %d)", |
466b77bc9
|
280 |
d_backing_inode(dentry)->i_ino, -ret); |
9ae326a69
|
281 282 283 284 285 286 287 288 289 290 291 292 293 |
goto error; } } okay: ret = 0; error: kfree(auxbuf); _leave(" = %d", ret); return ret; bad_type_length: |
6ff66ac77
|
294 295 |
pr_err("Cache object %lu xattr length incorrect ", |
466b77bc9
|
296 |
d_backing_inode(dentry)->i_ino); |
9ae326a69
|
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 |
ret = -EIO; goto error; stale: ret = -ESTALE; goto error; } /* * remove the object's xattr to mark it stale */ int cachefiles_remove_object_xattr(struct cachefiles_cache *cache, struct dentry *dentry) { int ret; ret = vfs_removexattr(dentry, cachefiles_xattr_cache); if (ret < 0) { if (ret == -ENOENT || ret == -ENODATA) ret = 0; else if (ret != -ENOMEM) cachefiles_io_error(cache, "Can't remove xattr from %lu" " (error %d)", |
466b77bc9
|
321 |
d_backing_inode(dentry)->i_ino, -ret); |
9ae326a69
|
322 323 324 325 326 |
} _leave(" = %d", ret); return ret; } |