linux/fs/fscache/io.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/* Cache data I/O routines
   3 *
   4 * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved.
   5 * Written by David Howells (dhowells@redhat.com)
   6 */
   7
   8#define FSCACHE_DEBUG_LEVEL PAGE
   9#include <linux/module.h>
  10#define FSCACHE_USE_NEW_IO_API
  11#include <linux/fscache-cache.h>
  12#include <linux/slab.h>
  13#include <linux/netfs.h>
  14#include "internal.h"
  15
  16/*
  17 * Start a cache read operation.
  18 * - we return:
  19 *   -ENOMEM    - out of memory, some pages may be being read
  20 *   -ERESTARTSYS - interrupted, some pages may be being read
  21 *   -ENOBUFS   - no backing object or space available in which to cache any
  22 *                pages not being read
  23 *   -ENODATA   - no data available in the backing object for some or all of
  24 *                the pages
  25 *   0          - dispatched a read on all pages
  26 */
  27int __fscache_begin_read_operation(struct netfs_read_request *rreq,
  28                                   struct fscache_cookie *cookie)
  29{
  30        struct fscache_retrieval *op;
  31        struct fscache_object *object;
  32        bool wake_cookie = false;
  33        int ret;
  34
  35        _enter("rr=%08x", rreq->debug_id);
  36
  37        fscache_stat(&fscache_n_retrievals);
  38
  39        if (hlist_empty(&cookie->backing_objects))
  40                goto nobufs;
  41
  42        if (test_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags)) {
  43                _leave(" = -ENOBUFS [invalidating]");
  44                return -ENOBUFS;
  45        }
  46
  47        ASSERTCMP(cookie->def->type, !=, FSCACHE_COOKIE_TYPE_INDEX);
  48
  49        if (fscache_wait_for_deferred_lookup(cookie) < 0)
  50                return -ERESTARTSYS;
  51
  52        op = fscache_alloc_retrieval(cookie, NULL, NULL, NULL);
  53        if (!op)
  54                return -ENOMEM;
  55        trace_fscache_page_op(cookie, NULL, &op->op, fscache_page_op_retr_multi);
  56
  57        spin_lock(&cookie->lock);
  58
  59        if (!fscache_cookie_enabled(cookie) ||
  60            hlist_empty(&cookie->backing_objects))
  61                goto nobufs_unlock;
  62        object = hlist_entry(cookie->backing_objects.first,
  63                             struct fscache_object, cookie_link);
  64
  65        __fscache_use_cookie(cookie);
  66        atomic_inc(&object->n_reads);
  67        __set_bit(FSCACHE_OP_DEC_READ_CNT, &op->op.flags);
  68
  69        if (fscache_submit_op(object, &op->op) < 0)
  70                goto nobufs_unlock_dec;
  71        spin_unlock(&cookie->lock);
  72
  73        fscache_stat(&fscache_n_retrieval_ops);
  74
  75        /* we wait for the operation to become active, and then process it
  76         * *here*, in this thread, and not in the thread pool */
  77        ret = fscache_wait_for_operation_activation(
  78                object, &op->op,
  79                __fscache_stat(&fscache_n_retrieval_op_waits),
  80                __fscache_stat(&fscache_n_retrievals_object_dead));
  81        if (ret < 0)
  82                goto error;
  83
  84        /* ask the cache to honour the operation */
  85        ret = object->cache->ops->begin_read_operation(rreq, op);
  86
  87error:
  88        if (ret == -ENOMEM)
  89                fscache_stat(&fscache_n_retrievals_nomem);
  90        else if (ret == -ERESTARTSYS)
  91                fscache_stat(&fscache_n_retrievals_intr);
  92        else if (ret == -ENODATA)
  93                fscache_stat(&fscache_n_retrievals_nodata);
  94        else if (ret < 0)
  95                fscache_stat(&fscache_n_retrievals_nobufs);
  96        else
  97                fscache_stat(&fscache_n_retrievals_ok);
  98
  99        fscache_put_retrieval(op);
 100        _leave(" = %d", ret);
 101        return ret;
 102
 103nobufs_unlock_dec:
 104        atomic_dec(&object->n_reads);
 105        wake_cookie = __fscache_unuse_cookie(cookie);
 106nobufs_unlock:
 107        spin_unlock(&cookie->lock);
 108        fscache_put_retrieval(op);
 109        if (wake_cookie)
 110                __fscache_wake_unused_cookie(cookie);
 111nobufs:
 112        fscache_stat(&fscache_n_retrievals_nobufs);
 113        _leave(" = -ENOBUFS");
 114        return -ENOBUFS;
 115}
 116EXPORT_SYMBOL(__fscache_begin_read_operation);
 117