1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* FS-Cache interface to CacheFiles 3 * 4 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. 5 * Written by David Howells (dhowells@redhat.com) 6 */ 7 8 #include <linux/slab.h> 9 #include <linux/mount.h> 10 #include "internal.h" 11 12 struct cachefiles_lookup_data { 13 struct cachefiles_xattr *auxdata; /* auxiliary data */ 14 char *key; /* key path */ 15 }; 16 17 static int cachefiles_attr_changed(struct fscache_object *_object); 18 19 /* 20 * allocate an object record for a cookie lookup and prepare the lookup data 21 */ 22 static struct fscache_object *cachefiles_alloc_object( 23 struct fscache_cache *_cache, 24 struct fscache_cookie *cookie) 25 { 26 struct cachefiles_lookup_data *lookup_data; 27 struct cachefiles_object *object; 28 struct cachefiles_cache *cache; 29 struct cachefiles_xattr *auxdata; 30 unsigned keylen, auxlen; 31 void *buffer, *p; 32 char *key; 33 34 cache = container_of(_cache, struct cachefiles_cache, cache); 35 36 _enter("{%s},%p,", cache->cache.identifier, cookie); 37 38 lookup_data = kmalloc(sizeof(*lookup_data), cachefiles_gfp); 39 if (!lookup_data) 40 goto nomem_lookup_data; 41 42 /* create a new object record and a temporary leaf image */ 43 object = kmem_cache_alloc(cachefiles_object_jar, cachefiles_gfp); 44 if (!object) 45 goto nomem_object; 46 47 ASSERTCMP(object->backer, ==, NULL); 48 49 BUG_ON(test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags)); 50 atomic_set(&object->usage, 1); 51 52 fscache_object_init(&object->fscache, cookie, &cache->cache); 53 54 object->type = cookie->def->type; 55 56 /* get hold of the raw key 57 * - stick the length on the front and leave space on the back for the 58 * encoder 59 */ 60 buffer = kmalloc((2 + 512) + 3, cachefiles_gfp); 61 if (!buffer) 62 goto nomem_buffer; 63 64 keylen = cookie->key_len; 65 if (keylen <= sizeof(cookie->inline_key)) 66 p = cookie->inline_key; 67 else 68 p = cookie->key; 69 memcpy(buffer + 2, p, keylen); 70 71 *(uint16_t *)buffer = keylen; 72 ((char *)buffer)[keylen + 2] = 0; 73 ((char *)buffer)[keylen + 3] = 0; 74 ((char *)buffer)[keylen + 4] = 0; 75 76 /* turn the raw key into something that can work with as a filename */ 77 key = cachefiles_cook_key(buffer, keylen + 2, object->type); 78 if (!key) 79 goto nomem_key; 80 81 /* get hold of the auxiliary data and prepend the object type */ 82 auxdata = buffer; 83 auxlen = cookie->aux_len; 84 if (auxlen) { 85 if (auxlen <= sizeof(cookie->inline_aux)) 86 p = cookie->inline_aux; 87 else 88 p = cookie->aux; 89 memcpy(auxdata->data, p, auxlen); 90 } 91 92 auxdata->len = auxlen + 1; 93 auxdata->type = cookie->type; 94 95 lookup_data->auxdata = auxdata; 96 lookup_data->key = key; 97 object->lookup_data = lookup_data; 98 99 _leave(" = %p [%p]", &object->fscache, lookup_data); 100 return &object->fscache; 101 102 nomem_key: 103 kfree(buffer); 104 nomem_buffer: 105 BUG_ON(test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags)); 106 kmem_cache_free(cachefiles_object_jar, object); 107 fscache_object_destroyed(&cache->cache); 108 nomem_object: 109 kfree(lookup_data); 110 nomem_lookup_data: 111 _leave(" = -ENOMEM"); 112 return ERR_PTR(-ENOMEM); 113 } 114 115 /* 116 * attempt to look up the nominated node in this cache 117 * - return -ETIMEDOUT to be scheduled again 118 */ 119 static int cachefiles_lookup_object(struct fscache_object *_object) 120 { 121 struct cachefiles_lookup_data *lookup_data; 122 struct cachefiles_object *parent, *object; 123 struct cachefiles_cache *cache; 124 const struct cred *saved_cred; 125 int ret; 126 127 _enter("{OBJ%x}", _object->debug_id); 128 129 cache = container_of(_object->cache, struct cachefiles_cache, cache); 130 parent = container_of(_object->parent, 131 struct cachefiles_object, fscache); 132 object = container_of(_object, struct cachefiles_object, fscache); 133 lookup_data = object->lookup_data; 134 135 ASSERTCMP(lookup_data, !=, NULL); 136 137 /* look up the key, creating any missing bits */ 138 cachefiles_begin_secure(cache, &saved_cred); 139 ret = cachefiles_walk_to_object(parent, object, 140 lookup_data->key, 141 lookup_data->auxdata); 142 cachefiles_end_secure(cache, saved_cred); 143 144 /* polish off by setting the attributes of non-index files */ 145 if (ret == 0 && 146 object->fscache.cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX) 147 cachefiles_attr_changed(&object->fscache); 148 149 if (ret < 0 && ret != -ETIMEDOUT) { 150 if (ret != -ENOBUFS) 151 pr_warn("Lookup failed error %d\n", ret); 152 fscache_object_lookup_error(&object->fscache); 153 } 154 155 _leave(" [%d]", ret); 156 return ret; 157 } 158 159 /* 160 * indication of lookup completion 161 */ 162 static void cachefiles_lookup_complete(struct fscache_object *_object) 163 { 164 struct cachefiles_object *object; 165 166 object = container_of(_object, struct cachefiles_object, fscache); 167 168 _enter("{OBJ%x,%p}", object->fscache.debug_id, object->lookup_data); 169 170 if (object->lookup_data) { 171 kfree(object->lookup_data->key); 172 kfree(object->lookup_data->auxdata); 173 kfree(object->lookup_data); 174 object->lookup_data = NULL; 175 } 176 } 177 178 /* 179 * increment the usage count on an inode object (may fail if unmounting) 180 */ 181 static 182 struct fscache_object *cachefiles_grab_object(struct fscache_object *_object, 183 enum fscache_obj_ref_trace why) 184 { 185 struct cachefiles_object *object = 186 container_of(_object, struct cachefiles_object, fscache); 187 int u; 188 189 _enter("{OBJ%x,%d}", _object->debug_id, atomic_read(&object->usage)); 190 191 #ifdef CACHEFILES_DEBUG_SLAB 192 ASSERT((atomic_read(&object->usage) & 0xffff0000) != 0x6b6b0000); 193 #endif 194 195 u = atomic_inc_return(&object->usage); 196 trace_cachefiles_ref(object, _object->cookie, 197 (enum cachefiles_obj_ref_trace)why, u); 198 return &object->fscache; 199 } 200 201 /* 202 * update the auxiliary data for an object object on disk 203 */ 204 static void cachefiles_update_object(struct fscache_object *_object) 205 { 206 struct cachefiles_object *object; 207 struct cachefiles_xattr *auxdata; 208 struct cachefiles_cache *cache; 209 struct fscache_cookie *cookie; 210 const struct cred *saved_cred; 211 const void *aux; 212 unsigned auxlen; 213 214 _enter("{OBJ%x}", _object->debug_id); 215 216 object = container_of(_object, struct cachefiles_object, fscache); 217 cache = container_of(object->fscache.cache, struct cachefiles_cache, 218 cache); 219 220 if (!fscache_use_cookie(_object)) { 221 _leave(" [relinq]"); 222 return; 223 } 224 225 cookie = object->fscache.cookie; 226 auxlen = cookie->aux_len; 227 228 if (!auxlen) { 229 fscache_unuse_cookie(_object); 230 _leave(" [no aux]"); 231 return; 232 } 233 234 auxdata = kmalloc(2 + auxlen + 3, cachefiles_gfp); 235 if (!auxdata) { 236 fscache_unuse_cookie(_object); 237 _leave(" [nomem]"); 238 return; 239 } 240 241 aux = (auxlen <= sizeof(cookie->inline_aux)) ? 242 cookie->inline_aux : cookie->aux; 243 244 memcpy(auxdata->data, aux, auxlen); 245 fscache_unuse_cookie(_object); 246 247 auxdata->len = auxlen + 1; 248 auxdata->type = cookie->type; 249 250 cachefiles_begin_secure(cache, &saved_cred); 251 cachefiles_update_object_xattr(object, auxdata); 252 cachefiles_end_secure(cache, saved_cred); 253 kfree(auxdata); 254 _leave(""); 255 } 256 257 /* 258 * discard the resources pinned by an object and effect retirement if 259 * requested 260 */ 261 static void cachefiles_drop_object(struct fscache_object *_object) 262 { 263 struct cachefiles_object *object; 264 struct cachefiles_cache *cache; 265 const struct cred *saved_cred; 266 struct inode *inode; 267 blkcnt_t i_blocks = 0; 268 269 ASSERT(_object); 270 271 object = container_of(_object, struct cachefiles_object, fscache); 272 273 _enter("{OBJ%x,%d}", 274 object->fscache.debug_id, atomic_read(&object->usage)); 275 276 cache = container_of(object->fscache.cache, 277 struct cachefiles_cache, cache); 278 279 #ifdef CACHEFILES_DEBUG_SLAB 280 ASSERT((atomic_read(&object->usage) & 0xffff0000) != 0x6b6b0000); 281 #endif 282 283 /* We need to tidy the object up if we did in fact manage to open it. 284 * It's possible for us to get here before the object is fully 285 * initialised if the parent goes away or the object gets retired 286 * before we set it up. 287 */ 288 if (object->dentry) { 289 /* delete retired objects */ 290 if (test_bit(FSCACHE_OBJECT_RETIRED, &object->fscache.flags) && 291 _object != cache->cache.fsdef 292 ) { 293 _debug("- retire object OBJ%x", object->fscache.debug_id); 294 inode = d_backing_inode(object->dentry); 295 if (inode) 296 i_blocks = inode->i_blocks; 297 298 cachefiles_begin_secure(cache, &saved_cred); 299 cachefiles_delete_object(cache, object); 300 cachefiles_end_secure(cache, saved_cred); 301 } 302 303 /* close the filesystem stuff attached to the object */ 304 if (object->backer != object->dentry) 305 dput(object->backer); 306 object->backer = NULL; 307 } 308 309 /* note that the object is now inactive */ 310 if (test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags)) 311 cachefiles_mark_object_inactive(cache, object, i_blocks); 312 313 dput(object->dentry); 314 object->dentry = NULL; 315 316 _leave(""); 317 } 318 319 /* 320 * dispose of a reference to an object 321 */ 322 static void cachefiles_put_object(struct fscache_object *_object, 323 enum fscache_obj_ref_trace why) 324 { 325 struct cachefiles_object *object; 326 struct fscache_cache *cache; 327 int u; 328 329 ASSERT(_object); 330 331 object = container_of(_object, struct cachefiles_object, fscache); 332 333 _enter("{OBJ%x,%d}", 334 object->fscache.debug_id, atomic_read(&object->usage)); 335 336 #ifdef CACHEFILES_DEBUG_SLAB 337 ASSERT((atomic_read(&object->usage) & 0xffff0000) != 0x6b6b0000); 338 #endif 339 340 ASSERTIFCMP(object->fscache.parent, 341 object->fscache.parent->n_children, >, 0); 342 343 u = atomic_dec_return(&object->usage); 344 trace_cachefiles_ref(object, _object->cookie, 345 (enum cachefiles_obj_ref_trace)why, u); 346 ASSERTCMP(u, !=, -1); 347 if (u == 0) { 348 _debug("- kill object OBJ%x", object->fscache.debug_id); 349 350 ASSERT(!test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags)); 351 ASSERTCMP(object->fscache.parent, ==, NULL); 352 ASSERTCMP(object->backer, ==, NULL); 353 ASSERTCMP(object->dentry, ==, NULL); 354 ASSERTCMP(object->fscache.n_ops, ==, 0); 355 ASSERTCMP(object->fscache.n_children, ==, 0); 356 357 if (object->lookup_data) { 358 kfree(object->lookup_data->key); 359 kfree(object->lookup_data->auxdata); 360 kfree(object->lookup_data); 361 object->lookup_data = NULL; 362 } 363 364 cache = object->fscache.cache; 365 fscache_object_destroy(&object->fscache); 366 kmem_cache_free(cachefiles_object_jar, object); 367 fscache_object_destroyed(cache); 368 } 369 370 _leave(""); 371 } 372 373 /* 374 * sync a cache 375 */ 376 static void cachefiles_sync_cache(struct fscache_cache *_cache) 377 { 378 struct cachefiles_cache *cache; 379 const struct cred *saved_cred; 380 int ret; 381 382 _enter("%p", _cache); 383 384 cache = container_of(_cache, struct cachefiles_cache, cache); 385 386 /* make sure all pages pinned by operations on behalf of the netfs are 387 * written to disc */ 388 cachefiles_begin_secure(cache, &saved_cred); 389 down_read(&cache->mnt->mnt_sb->s_umount); 390 ret = sync_filesystem(cache->mnt->mnt_sb); 391 up_read(&cache->mnt->mnt_sb->s_umount); 392 cachefiles_end_secure(cache, saved_cred); 393 394 if (ret == -EIO) 395 cachefiles_io_error(cache, 396 "Attempt to sync backing fs superblock" 397 " returned error %d", 398 ret); 399 } 400 401 /* 402 * check if the backing cache is updated to FS-Cache 403 * - called by FS-Cache when evaluates if need to invalidate the cache 404 */ 405 static int cachefiles_check_consistency(struct fscache_operation *op) 406 { 407 struct cachefiles_object *object; 408 struct cachefiles_cache *cache; 409 const struct cred *saved_cred; 410 int ret; 411 412 _enter("{OBJ%x}", op->object->debug_id); 413 414 object = container_of(op->object, struct cachefiles_object, fscache); 415 cache = container_of(object->fscache.cache, 416 struct cachefiles_cache, cache); 417 418 cachefiles_begin_secure(cache, &saved_cred); 419 ret = cachefiles_check_auxdata(object); 420 cachefiles_end_secure(cache, saved_cred); 421 422 _leave(" = %d", ret); 423 return ret; 424 } 425 426 /* 427 * notification the attributes on an object have changed 428 * - called with reads/writes excluded by FS-Cache 429 */ 430 static int cachefiles_attr_changed(struct fscache_object *_object) 431 { 432 struct cachefiles_object *object; 433 struct cachefiles_cache *cache; 434 const struct cred *saved_cred; 435 struct iattr newattrs; 436 uint64_t ni_size; 437 loff_t oi_size; 438 int ret; 439 440 ni_size = _object->store_limit_l; 441 442 _enter("{OBJ%x},[%llu]", 443 _object->debug_id, (unsigned long long) ni_size); 444 445 object = container_of(_object, struct cachefiles_object, fscache); 446 cache = container_of(object->fscache.cache, 447 struct cachefiles_cache, cache); 448 449 if (ni_size == object->i_size) 450 return 0; 451 452 if (!object->backer) 453 return -ENOBUFS; 454 455 ASSERT(d_is_reg(object->backer)); 456 457 fscache_set_store_limit(&object->fscache, ni_size); 458 459 oi_size = i_size_read(d_backing_inode(object->backer)); 460 if (oi_size == ni_size) 461 return 0; 462 463 cachefiles_begin_secure(cache, &saved_cred); 464 inode_lock(d_inode(object->backer)); 465 466 /* if there's an extension to a partial page at the end of the backing 467 * file, we need to discard the partial page so that we pick up new 468 * data after it */ 469 if (oi_size & ~PAGE_MASK && ni_size > oi_size) { 470 _debug("discard tail %llx", oi_size); 471 newattrs.ia_valid = ATTR_SIZE; 472 newattrs.ia_size = oi_size & PAGE_MASK; 473 ret = notify_change(object->backer, &newattrs, NULL); 474 if (ret < 0) 475 goto truncate_failed; 476 } 477 478 newattrs.ia_valid = ATTR_SIZE; 479 newattrs.ia_size = ni_size; 480 ret = notify_change(object->backer, &newattrs, NULL); 481 482 truncate_failed: 483 inode_unlock(d_inode(object->backer)); 484 cachefiles_end_secure(cache, saved_cred); 485 486 if (ret == -EIO) { 487 fscache_set_store_limit(&object->fscache, 0); 488 cachefiles_io_error_obj(object, "Size set failed"); 489 ret = -ENOBUFS; 490 } 491 492 _leave(" = %d", ret); 493 return ret; 494 } 495 496 /* 497 * Invalidate an object 498 */ 499 static void cachefiles_invalidate_object(struct fscache_operation *op) 500 { 501 struct cachefiles_object *object; 502 struct cachefiles_cache *cache; 503 const struct cred *saved_cred; 504 struct path path; 505 uint64_t ni_size; 506 int ret; 507 508 object = container_of(op->object, struct cachefiles_object, fscache); 509 cache = container_of(object->fscache.cache, 510 struct cachefiles_cache, cache); 511 512 ni_size = op->object->store_limit_l; 513 514 _enter("{OBJ%x},[%llu]", 515 op->object->debug_id, (unsigned long long)ni_size); 516 517 if (object->backer) { 518 ASSERT(d_is_reg(object->backer)); 519 520 fscache_set_store_limit(&object->fscache, ni_size); 521 522 path.dentry = object->backer; 523 path.mnt = cache->mnt; 524 525 cachefiles_begin_secure(cache, &saved_cred); 526 ret = vfs_truncate(&path, 0); 527 if (ret == 0) 528 ret = vfs_truncate(&path, ni_size); 529 cachefiles_end_secure(cache, saved_cred); 530 531 if (ret != 0) { 532 fscache_set_store_limit(&object->fscache, 0); 533 if (ret == -EIO) 534 cachefiles_io_error_obj(object, 535 "Invalidate failed"); 536 } 537 } 538 539 fscache_op_complete(op, true); 540 _leave(""); 541 } 542 543 /* 544 * dissociate a cache from all the pages it was backing 545 */ 546 static void cachefiles_dissociate_pages(struct fscache_cache *cache) 547 { 548 _enter(""); 549 } 550 551 const struct fscache_cache_ops cachefiles_cache_ops = { 552 .name = "cachefiles", 553 .alloc_object = cachefiles_alloc_object, 554 .lookup_object = cachefiles_lookup_object, 555 .lookup_complete = cachefiles_lookup_complete, 556 .grab_object = cachefiles_grab_object, 557 .update_object = cachefiles_update_object, 558 .invalidate_object = cachefiles_invalidate_object, 559 .drop_object = cachefiles_drop_object, 560 .put_object = cachefiles_put_object, 561 .sync_cache = cachefiles_sync_cache, 562 .attr_changed = cachefiles_attr_changed, 563 .read_or_alloc_page = cachefiles_read_or_alloc_page, 564 .read_or_alloc_pages = cachefiles_read_or_alloc_pages, 565 .allocate_page = cachefiles_allocate_page, 566 .allocate_pages = cachefiles_allocate_pages, 567 .write_page = cachefiles_write_page, 568 .uncache_page = cachefiles_uncache_page, 569 .dissociate_pages = cachefiles_dissociate_pages, 570 .check_consistency = cachefiles_check_consistency, 571 }; 572