]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/ocf/src/engine/engine_wi.c
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / spdk / ocf / src / engine / engine_wi.c
1 /*
2 * Copyright(c) 2012-2018 Intel Corporation
3 * SPDX-License-Identifier: BSD-3-Clause-Clear
4 */
5
6 #include "ocf/ocf.h"
7 #include "../ocf_cache_priv.h"
8 #include "engine_wi.h"
9 #include "engine_common.h"
10 #include "../concurrency/ocf_concurrency.h"
11 #include "../ocf_request.h"
12 #include "../utils/utils_cache_line.h"
13 #include "../utils/utils_io.h"
14 #include "../metadata/metadata.h"
15
16 #define OCF_ENGINE_DEBUG_IO_NAME "wi"
17 #include "engine_debug.h"
18
19 static int ocf_write_wi_update_and_flush_metadata(struct ocf_request *req);
20
21 static const struct ocf_io_if _io_if_wi_flush_metadata = {
22 .read = ocf_write_wi_update_and_flush_metadata,
23 .write = ocf_write_wi_update_and_flush_metadata,
24 };
25
26 static void _ocf_write_wi_io_flush_metadata(struct ocf_request *req, int error)
27 {
28 if (error) {
29 ocf_core_stats_cache_error_update(req->core, OCF_WRITE);
30 req->error |= error;
31 }
32
33 if (env_atomic_dec_return(&req->req_remaining))
34 return;
35
36 if (req->error)
37 ocf_engine_error(req, true, "Failed to write data to cache");
38
39 ocf_req_unlock_wr(req);
40
41 req->complete(req, req->error);
42
43 ocf_req_put(req);
44 }
45
46 static int ocf_write_wi_update_and_flush_metadata(struct ocf_request *req)
47 {
48 struct ocf_cache *cache = req->cache;
49
50 env_atomic_set(&req->req_remaining, 1); /* One core IO */
51
52 if (ocf_engine_mapped_count(req)) {
53 /* There are mapped cache line, need to remove them */
54
55 ocf_req_hash_lock_wr(req); /*- Metadata WR access ---------------*/
56
57 /* Remove mapped cache lines from metadata */
58 ocf_purge_map_info(req);
59
60 ocf_req_hash_unlock_wr(req); /*- END Metadata WR access ---------*/
61
62 if (req->info.flush_metadata) {
63 /* Request was dirty and need to flush metadata */
64 ocf_metadata_flush_do_asynch(cache, req,
65 _ocf_write_wi_io_flush_metadata);
66 }
67
68 }
69
70 _ocf_write_wi_io_flush_metadata(req, 0);
71
72 return 0;
73 }
74
75 static void _ocf_write_wi_core_complete(struct ocf_request *req, int error)
76 {
77 if (error) {
78 req->error = error;
79 req->info.core_error = 1;
80 ocf_core_stats_core_error_update(req->core, OCF_WRITE);
81 }
82
83 if (env_atomic_dec_return(&req->req_remaining))
84 return;
85
86 OCF_DEBUG_RQ(req, "Completion");
87
88 if (req->error) {
89 ocf_req_unlock_wr(req);
90
91 req->complete(req, req->error);
92
93 ocf_req_put(req);
94 } else {
95 ocf_engine_push_req_front_if(req, &_io_if_wi_flush_metadata,
96 true);
97 }
98 }
99
100 static int _ocf_write_wi_do(struct ocf_request *req)
101 {
102 /* Get OCF request - increase reference counter */
103 ocf_req_get(req);
104
105 env_atomic_set(&req->req_remaining, 1); /* One core IO */
106
107 OCF_DEBUG_RQ(req, "Submit");
108
109 /* Submit write IO to the core */
110 ocf_submit_volume_req(&req->core->volume, req,
111 _ocf_write_wi_core_complete);
112
113 /* Update statistics */
114 ocf_engine_update_block_stats(req);
115 ocf_core_stats_request_pt_update(req->core, req->part_id, req->rw,
116 req->info.hit_no, req->core_line_count);
117
118 /* Put OCF request - decrease reference counter */
119 ocf_req_put(req);
120
121 return 0;
122 }
123
124 static void _ocf_write_wi_on_resume(struct ocf_request *req)
125 {
126 OCF_DEBUG_RQ(req, "On resume");
127 ocf_engine_push_req_front(req, true);
128 }
129
130 static const struct ocf_io_if _io_if_wi_resume = {
131 .read = _ocf_write_wi_do,
132 .write = _ocf_write_wi_do,
133 };
134
135 int ocf_write_wi(struct ocf_request *req)
136 {
137 int lock = OCF_LOCK_NOT_ACQUIRED;
138
139 OCF_DEBUG_TRACE(req->cache);
140
141 ocf_io_start(&req->ioi.io);
142
143 /* Get OCF request - increase reference counter */
144 ocf_req_get(req);
145
146 /* Set resume io_if */
147 req->io_if = &_io_if_wi_resume;
148
149 ocf_req_hash(req);
150 ocf_req_hash_lock_rd(req); /*- Metadata READ access, No eviction --------*/
151
152 /* Travers to check if request is mapped fully */
153 ocf_engine_traverse(req);
154
155 if (ocf_engine_mapped_count(req)) {
156 /* Some cache line are mapped, lock request for WRITE access */
157 lock = ocf_req_async_lock_wr(req, _ocf_write_wi_on_resume);
158 } else {
159 lock = OCF_LOCK_ACQUIRED;
160 }
161
162 ocf_req_hash_unlock_rd(req); /*- END Metadata READ access----------------*/
163
164 if (lock >= 0) {
165 if (lock == OCF_LOCK_ACQUIRED) {
166 _ocf_write_wi_do(req);
167 } else {
168 /* WR lock was not acquired, need to wait for resume */
169 OCF_DEBUG_RQ(req, "NO LOCK");
170 }
171 } else {
172 OCF_DEBUG_RQ(req, "LOCK ERROR %d", lock);
173 req->complete(req, lock);
174 ocf_req_put(req);
175 }
176
177 /* Put OCF request - decrease reference counter */
178 ocf_req_put(req);
179
180 return 0;
181 }