linux/fs/cachefiles/interface.c
<<
>>
Prefs
   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
  12struct cachefiles_lookup_data {
  13        struct cachefiles_xattr *auxdata;       /* auxiliary data */
  14        char                    *key;           /* key path */
  15};
  16
  17static 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 */
  22static 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},%x,", cache->cache.identifier, cookie->debug_id);
  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(" = %x [%p]", object->fscache.debug_id, lookup_data);
 100        return &object->fscache;
 101
 102nomem_key:
 103        kfree(buffer);
 104nomem_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);
 108nomem_object:
 109        kfree(lookup_data);
 110nomem_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 */
 119static 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 */
 162static 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 */
 181static
 182struct 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 */
 204static 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 */
 261static 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 */
 322void 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 */
 376static 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("%s", _cache->tag->name);
 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 */
 405static 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 */
 430static 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(&init_user_ns, 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(&init_user_ns, object->backer, &newattrs, NULL);
 481
 482truncate_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 */
 499static 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 */
 546static void cachefiles_dissociate_pages(struct fscache_cache *cache)
 547{
 548        _enter("");
 549}
 550
 551const 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        .begin_read_operation   = cachefiles_begin_read_operation,
 572};
 573