sched: Prevent balance_push() on remote runqueues
[linux-2.6-microblaze.git] / fs / fscache / io.c
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  */
27 int __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
87 error:
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
103 nobufs_unlock_dec:
104         atomic_dec(&object->n_reads);
105         wake_cookie = __fscache_unuse_cookie(cookie);
106 nobufs_unlock:
107         spin_unlock(&cookie->lock);
108         fscache_put_retrieval(op);
109         if (wake_cookie)
110                 __fscache_wake_unused_cookie(cookie);
111 nobufs:
112         fscache_stat(&fscache_n_retrievals_nobufs);
113         _leave(" = -ENOBUFS");
114         return -ENOBUFS;
115 }
116 EXPORT_SYMBOL(__fscache_begin_read_operation);