xref: /openbmc/linux/fs/fscache/io.c (revision 9dbbc3b9)
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);
117