linux/fs/fscache/cache.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/* FS-Cache cache handling
   3 *
   4 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
   5 * Written by David Howells (dhowells@redhat.com)
   6 */
   7
   8#define FSCACHE_DEBUG_LEVEL CACHE
   9#include <linux/module.h>
  10#include <linux/slab.h>
  11#include "internal.h"
  12
  13LIST_HEAD(fscache_cache_list);
  14DECLARE_RWSEM(fscache_addremove_sem);
  15DECLARE_WAIT_QUEUE_HEAD(fscache_cache_cleared_wq);
  16EXPORT_SYMBOL(fscache_cache_cleared_wq);
  17
  18static LIST_HEAD(fscache_cache_tag_list);
  19
  20/*
  21 * look up a cache tag
  22 */
  23struct fscache_cache_tag *__fscache_lookup_cache_tag(const char *name)
  24{
  25        struct fscache_cache_tag *tag, *xtag;
  26
  27        /* firstly check for the existence of the tag under read lock */
  28        down_read(&fscache_addremove_sem);
  29
  30        list_for_each_entry(tag, &fscache_cache_tag_list, link) {
  31                if (strcmp(tag->name, name) == 0) {
  32                        atomic_inc(&tag->usage);
  33                        up_read(&fscache_addremove_sem);
  34                        return tag;
  35                }
  36        }
  37
  38        up_read(&fscache_addremove_sem);
  39
  40        /* the tag does not exist - create a candidate */
  41        xtag = kzalloc(sizeof(*xtag) + strlen(name) + 1, GFP_KERNEL);
  42        if (!xtag)
  43                /* return a dummy tag if out of memory */
  44                return ERR_PTR(-ENOMEM);
  45
  46        atomic_set(&xtag->usage, 1);
  47        strcpy(xtag->name, name);
  48
  49        /* write lock, search again and add if still not present */
  50        down_write(&fscache_addremove_sem);
  51
  52        list_for_each_entry(tag, &fscache_cache_tag_list, link) {
  53                if (strcmp(tag->name, name) == 0) {
  54                        atomic_inc(&tag->usage);
  55                        up_write(&fscache_addremove_sem);
  56                        kfree(xtag);
  57                        return tag;
  58                }
  59        }
  60
  61        list_add_tail(&xtag->link, &fscache_cache_tag_list);
  62        up_write(&fscache_addremove_sem);
  63        return xtag;
  64}
  65
  66/*
  67 * release a reference to a cache tag
  68 */
  69void __fscache_release_cache_tag(struct fscache_cache_tag *tag)
  70{
  71        if (tag != ERR_PTR(-ENOMEM)) {
  72                down_write(&fscache_addremove_sem);
  73
  74                if (atomic_dec_and_test(&tag->usage))
  75                        list_del_init(&tag->link);
  76                else
  77                        tag = NULL;
  78
  79                up_write(&fscache_addremove_sem);
  80
  81                kfree(tag);
  82        }
  83}
  84
  85/*
  86 * select a cache in which to store an object
  87 * - the cache addremove semaphore must be at least read-locked by the caller
  88 * - the object will never be an index
  89 */
  90struct fscache_cache *fscache_select_cache_for_object(
  91        struct fscache_cookie *cookie)
  92{
  93        struct fscache_cache_tag *tag;
  94        struct fscache_object *object;
  95        struct fscache_cache *cache;
  96
  97        _enter("");
  98
  99        if (list_empty(&fscache_cache_list)) {
 100                _leave(" = NULL [no cache]");
 101                return NULL;
 102        }
 103
 104        /* we check the parent to determine the cache to use */
 105        spin_lock(&cookie->lock);
 106
 107        /* the first in the parent's backing list should be the preferred
 108         * cache */
 109        if (!hlist_empty(&cookie->backing_objects)) {
 110                object = hlist_entry(cookie->backing_objects.first,
 111                                     struct fscache_object, cookie_link);
 112
 113                cache = object->cache;
 114                if (fscache_object_is_dying(object) ||
 115                    test_bit(FSCACHE_IOERROR, &cache->flags))
 116                        cache = NULL;
 117
 118                spin_unlock(&cookie->lock);
 119                _leave(" = %p [parent]", cache);
 120                return cache;
 121        }
 122
 123        /* the parent is unbacked */
 124        if (cookie->type != FSCACHE_COOKIE_TYPE_INDEX) {
 125                /* cookie not an index and is unbacked */
 126                spin_unlock(&cookie->lock);
 127                _leave(" = NULL [cookie ub,ni]");
 128                return NULL;
 129        }
 130
 131        spin_unlock(&cookie->lock);
 132
 133        if (!cookie->def->select_cache)
 134                goto no_preference;
 135
 136        /* ask the netfs for its preference */
 137        tag = cookie->def->select_cache(cookie->parent->netfs_data,
 138                                        cookie->netfs_data);
 139        if (!tag)
 140                goto no_preference;
 141
 142        if (tag == ERR_PTR(-ENOMEM)) {
 143                _leave(" = NULL [nomem tag]");
 144                return NULL;
 145        }
 146
 147        if (!tag->cache) {
 148                _leave(" = NULL [unbacked tag]");
 149                return NULL;
 150        }
 151
 152        if (test_bit(FSCACHE_IOERROR, &tag->cache->flags))
 153                return NULL;
 154
 155        _leave(" = %p [specific]", tag->cache);
 156        return tag->cache;
 157
 158no_preference:
 159        /* netfs has no preference - just select first cache */
 160        cache = list_entry(fscache_cache_list.next,
 161                           struct fscache_cache, link);
 162        _leave(" = %p [first]", cache);
 163        return cache;
 164}
 165
 166/**
 167 * fscache_init_cache - Initialise a cache record
 168 * @cache: The cache record to be initialised
 169 * @ops: The cache operations to be installed in that record
 170 * @idfmt: Format string to define identifier
 171 * @...: sprintf-style arguments
 172 *
 173 * Initialise a record of a cache and fill in the name.
 174 *
 175 * See Documentation/filesystems/caching/backend-api.rst for a complete
 176 * description.
 177 */
 178void fscache_init_cache(struct fscache_cache *cache,
 179                        const struct fscache_cache_ops *ops,
 180                        const char *idfmt,
 181                        ...)
 182{
 183        va_list va;
 184
 185        memset(cache, 0, sizeof(*cache));
 186
 187        cache->ops = ops;
 188
 189        va_start(va, idfmt);
 190        vsnprintf(cache->identifier, sizeof(cache->identifier), idfmt, va);
 191        va_end(va);
 192
 193        INIT_WORK(&cache->op_gc, fscache_operation_gc);
 194        INIT_LIST_HEAD(&cache->link);
 195        INIT_LIST_HEAD(&cache->object_list);
 196        INIT_LIST_HEAD(&cache->op_gc_list);
 197        spin_lock_init(&cache->object_list_lock);
 198        spin_lock_init(&cache->op_gc_list_lock);
 199}
 200EXPORT_SYMBOL(fscache_init_cache);
 201
 202/**
 203 * fscache_add_cache - Declare a cache as being open for business
 204 * @cache: The record describing the cache
 205 * @ifsdef: The record of the cache object describing the top-level index
 206 * @tagname: The tag describing this cache
 207 *
 208 * Add a cache to the system, making it available for netfs's to use.
 209 *
 210 * See Documentation/filesystems/caching/backend-api.rst for a complete
 211 * description.
 212 */
 213int fscache_add_cache(struct fscache_cache *cache,
 214                      struct fscache_object *ifsdef,
 215                      const char *tagname)
 216{
 217        struct fscache_cache_tag *tag;
 218
 219        ASSERTCMP(ifsdef->cookie, ==, &fscache_fsdef_index);
 220        BUG_ON(!cache->ops);
 221        BUG_ON(!ifsdef);
 222
 223        cache->flags = 0;
 224        ifsdef->event_mask =
 225                ((1 << NR_FSCACHE_OBJECT_EVENTS) - 1) &
 226                ~(1 << FSCACHE_OBJECT_EV_CLEARED);
 227        __set_bit(FSCACHE_OBJECT_IS_AVAILABLE, &ifsdef->flags);
 228
 229        if (!tagname)
 230                tagname = cache->identifier;
 231
 232        BUG_ON(!tagname[0]);
 233
 234        _enter("{%s.%s},,%s", cache->ops->name, cache->identifier, tagname);
 235
 236        /* we use the cache tag to uniquely identify caches */
 237        tag = __fscache_lookup_cache_tag(tagname);
 238        if (IS_ERR(tag))
 239                goto nomem;
 240
 241        if (test_and_set_bit(FSCACHE_TAG_RESERVED, &tag->flags))
 242                goto tag_in_use;
 243
 244        cache->kobj = kobject_create_and_add(tagname, fscache_root);
 245        if (!cache->kobj)
 246                goto error;
 247
 248        ifsdef->cache = cache;
 249        cache->fsdef = ifsdef;
 250
 251        down_write(&fscache_addremove_sem);
 252
 253        tag->cache = cache;
 254        cache->tag = tag;
 255
 256        /* add the cache to the list */
 257        list_add(&cache->link, &fscache_cache_list);
 258
 259        /* add the cache's netfs definition index object to the cache's
 260         * list */
 261        spin_lock(&cache->object_list_lock);
 262        list_add_tail(&ifsdef->cache_link, &cache->object_list);
 263        spin_unlock(&cache->object_list_lock);
 264        fscache_objlist_add(ifsdef);
 265
 266        /* add the cache's netfs definition index object to the top level index
 267         * cookie as a known backing object */
 268        spin_lock(&fscache_fsdef_index.lock);
 269
 270        hlist_add_head(&ifsdef->cookie_link,
 271                       &fscache_fsdef_index.backing_objects);
 272
 273        atomic_inc(&fscache_fsdef_index.usage);
 274
 275        /* done */
 276        spin_unlock(&fscache_fsdef_index.lock);
 277        up_write(&fscache_addremove_sem);
 278
 279        pr_notice("Cache \"%s\" added (type %s)\n",
 280                  cache->tag->name, cache->ops->name);
 281        kobject_uevent(cache->kobj, KOBJ_ADD);
 282
 283        _leave(" = 0 [%s]", cache->identifier);
 284        return 0;
 285
 286tag_in_use:
 287        pr_err("Cache tag '%s' already in use\n", tagname);
 288        __fscache_release_cache_tag(tag);
 289        _leave(" = -EXIST");
 290        return -EEXIST;
 291
 292error:
 293        __fscache_release_cache_tag(tag);
 294        _leave(" = -EINVAL");
 295        return -EINVAL;
 296
 297nomem:
 298        _leave(" = -ENOMEM");
 299        return -ENOMEM;
 300}
 301EXPORT_SYMBOL(fscache_add_cache);
 302
 303/**
 304 * fscache_io_error - Note a cache I/O error
 305 * @cache: The record describing the cache
 306 *
 307 * Note that an I/O error occurred in a cache and that it should no longer be
 308 * used for anything.  This also reports the error into the kernel log.
 309 *
 310 * See Documentation/filesystems/caching/backend-api.rst for a complete
 311 * description.
 312 */
 313void fscache_io_error(struct fscache_cache *cache)
 314{
 315        if (!test_and_set_bit(FSCACHE_IOERROR, &cache->flags))
 316                pr_err("Cache '%s' stopped due to I/O error\n",
 317                       cache->ops->name);
 318}
 319EXPORT_SYMBOL(fscache_io_error);
 320
 321/*
 322 * request withdrawal of all the objects in a cache
 323 * - all the objects being withdrawn are moved onto the supplied list
 324 */
 325static void fscache_withdraw_all_objects(struct fscache_cache *cache,
 326                                         struct list_head *dying_objects)
 327{
 328        struct fscache_object *object;
 329
 330        while (!list_empty(&cache->object_list)) {
 331                spin_lock(&cache->object_list_lock);
 332
 333                if (!list_empty(&cache->object_list)) {
 334                        object = list_entry(cache->object_list.next,
 335                                            struct fscache_object, cache_link);
 336                        list_move_tail(&object->cache_link, dying_objects);
 337
 338                        _debug("withdraw %p", object->cookie);
 339
 340                        /* This must be done under object_list_lock to prevent
 341                         * a race with fscache_drop_object().
 342                         */
 343                        fscache_raise_event(object, FSCACHE_OBJECT_EV_KILL);
 344                }
 345
 346                spin_unlock(&cache->object_list_lock);
 347                cond_resched();
 348        }
 349}
 350
 351/**
 352 * fscache_withdraw_cache - Withdraw a cache from the active service
 353 * @cache: The record describing the cache
 354 *
 355 * Withdraw a cache from service, unbinding all its cache objects from the
 356 * netfs cookies they're currently representing.
 357 *
 358 * See Documentation/filesystems/caching/backend-api.rst for a complete
 359 * description.
 360 */
 361void fscache_withdraw_cache(struct fscache_cache *cache)
 362{
 363        LIST_HEAD(dying_objects);
 364
 365        _enter("");
 366
 367        pr_notice("Withdrawing cache \"%s\"\n",
 368                  cache->tag->name);
 369
 370        /* make the cache unavailable for cookie acquisition */
 371        if (test_and_set_bit(FSCACHE_CACHE_WITHDRAWN, &cache->flags))
 372                BUG();
 373
 374        down_write(&fscache_addremove_sem);
 375        list_del_init(&cache->link);
 376        cache->tag->cache = NULL;
 377        up_write(&fscache_addremove_sem);
 378
 379        /* make sure all pages pinned by operations on behalf of the netfs are
 380         * written to disk */
 381        fscache_stat(&fscache_n_cop_sync_cache);
 382        cache->ops->sync_cache(cache);
 383        fscache_stat_d(&fscache_n_cop_sync_cache);
 384
 385        /* dissociate all the netfs pages backed by this cache from the block
 386         * mappings in the cache */
 387        fscache_stat(&fscache_n_cop_dissociate_pages);
 388        cache->ops->dissociate_pages(cache);
 389        fscache_stat_d(&fscache_n_cop_dissociate_pages);
 390
 391        /* we now have to destroy all the active objects pertaining to this
 392         * cache - which we do by passing them off to thread pool to be
 393         * disposed of */
 394        _debug("destroy");
 395
 396        fscache_withdraw_all_objects(cache, &dying_objects);
 397
 398        /* wait for all extant objects to finish their outstanding operations
 399         * and go away */
 400        _debug("wait for finish");
 401        wait_event(fscache_cache_cleared_wq,
 402                   atomic_read(&cache->object_count) == 0);
 403        _debug("wait for clearance");
 404        wait_event(fscache_cache_cleared_wq,
 405                   list_empty(&cache->object_list));
 406        _debug("cleared");
 407        ASSERT(list_empty(&dying_objects));
 408
 409        kobject_put(cache->kobj);
 410
 411        clear_bit(FSCACHE_TAG_RESERVED, &cache->tag->flags);
 412        fscache_release_cache_tag(cache->tag);
 413        cache->tag = NULL;
 414
 415        _leave("");
 416}
 417EXPORT_SYMBOL(fscache_withdraw_cache);
 418