root/fs/cachefiles/interface.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cachefiles_alloc_object
  2. cachefiles_lookup_object
  3. cachefiles_lookup_complete
  4. cachefiles_grab_object
  5. cachefiles_update_object
  6. cachefiles_drop_object
  7. cachefiles_put_object
  8. cachefiles_sync_cache
  9. cachefiles_check_consistency
  10. cachefiles_attr_changed
  11. cachefiles_invalidate_object
  12. cachefiles_dissociate_pages

   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 };

/* [<][>][^][v][top][bottom][index][help] */