blob: 8ecc1141802f4e8e93146fd7ea3c9859dccacb1e [file] [log] [blame]
David Howells26aaeff2021-02-22 11:39:47 +00001// 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);