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