source: mainline/uspace/srv/bd/hr/io.c

Last change on this file was c1c1c41, checked in by Miroslav Cimerman <mc@…>, 6 days ago

hr: add author's email address to RAID 5 files

  • Property mode set to 100644
File size: 7.7 KB
Line 
1/*
2 * Copyright (c) 2025 Miroslav Cimerman <mc@doas.su>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup hr
30 * @{
31 */
32/**
33 * @file
34 */
35
36#include <block.h>
37#include <errno.h>
38#include <hr.h>
39#include <inttypes.h>
40#include <stdio.h>
41#include <stdlib.h>
42#include <str.h>
43#include <str_error.h>
44
45#include "io.h"
46#include "parity_stripe.h"
47#include "util.h"
48#include "var.h"
49
50/** Wrapper for block_write_direct(), never returns ENOMEM */
51errno_t hr_write_direct(service_id_t service_id, uint64_t ba, size_t cnt,
52 const void *data)
53{
54 errno_t rc;
55 while ((rc = block_write_direct(service_id, ba, cnt, data)) == ENOMEM)
56 fibril_usleep(MSEC2USEC(250)); /* sleep 250ms */
57
58 if (rc == EAGAIN)
59 rc = EIO;
60
61 return rc;
62}
63
64/** Wrapper for block_read_direct(), never returns ENOMEM */
65errno_t hr_read_direct(service_id_t service_id, uint64_t ba, size_t cnt,
66 void *data)
67{
68 errno_t rc;
69 while ((rc = block_read_direct(service_id, ba, cnt, data)) == ENOMEM)
70 fibril_usleep(MSEC2USEC(250)); /* sleep 250ms */
71
72 if (rc == EAGAIN)
73 rc = EIO;
74
75 return rc;
76}
77
78/** Wrapper for block_sync_cache(), never returns ENOMEM */
79errno_t hr_sync_cache(service_id_t service_id, uint64_t ba, size_t cnt)
80{
81 errno_t rc;
82 while ((rc = block_sync_cache(service_id, ba, cnt)) == ENOMEM)
83 fibril_usleep(MSEC2USEC(250)); /* sleep 250ms */
84
85 if (rc == EAGAIN)
86 rc = EIO;
87
88 return rc;
89}
90
91errno_t hr_io_worker(void *arg)
92{
93 hr_io_t *io = arg;
94
95 errno_t rc;
96 size_t e = io->extent;
97 hr_extent_t *extents = (hr_extent_t *)&io->vol->extents;
98
99 switch (io->type) {
100 case HR_BD_READ:
101 rc = hr_read_direct(extents[e].svc_id, io->ba, io->cnt,
102 io->data_read);
103 break;
104 case HR_BD_WRITE:
105 rc = hr_write_direct(extents[e].svc_id, io->ba, io->cnt,
106 io->data_write);
107 break;
108 default:
109 assert(0);
110 }
111
112 if (io->vol->level == HR_LVL_1) {
113 atomic_store_explicit(&io->vol->last_ext_pos_arr[e],
114 io->ba + io->cnt - 1, memory_order_relaxed);
115 }
116
117 if (rc != EOK)
118 io->vol->hr_ops.ext_state_cb(io->vol, io->extent, rc);
119
120 return rc;
121}
122
123errno_t hr_io_raid5_basic_reader(void *arg)
124{
125 errno_t rc;
126
127 hr_io_raid5_t *io = arg;
128
129 size_t ext_idx = io->extent;
130 hr_extent_t *extents = (hr_extent_t *)&io->vol->extents;
131
132 rc = hr_read_direct(extents[ext_idx].svc_id, io->ba, io->cnt,
133 io->data_read);
134 if (rc != EOK)
135 io->vol->hr_ops.ext_state_cb(io->vol, io->extent, rc);
136
137 return rc;
138}
139
140errno_t hr_io_raid5_reader(void *arg)
141{
142 errno_t rc;
143
144 hr_io_raid5_t *io = arg;
145 hr_stripe_t *stripe = io->stripe;
146
147 size_t ext_idx = io->extent;
148 hr_extent_t *extents = (hr_extent_t *)&io->vol->extents;
149
150 rc = hr_read_direct(extents[ext_idx].svc_id, io->ba, io->cnt,
151 io->data_read);
152 if (rc != EOK) {
153 hr_stripe_parity_abort(stripe);
154 io->vol->hr_ops.ext_state_cb(io->vol, io->extent, rc);
155 }
156
157 hr_stripe_commit_parity(stripe, io->strip_off, io->data_read,
158 io->cnt * io->vol->bsize);
159
160 return rc;
161}
162
163errno_t hr_io_raid5_basic_writer(void *arg)
164{
165 errno_t rc;
166
167 hr_io_raid5_t *io = arg;
168
169 size_t ext_idx = io->extent;
170 hr_extent_t *extents = (hr_extent_t *)&io->vol->extents;
171
172 rc = hr_write_direct(extents[ext_idx].svc_id, io->ba, io->cnt,
173 io->data_write);
174 if (rc != EOK)
175 io->vol->hr_ops.ext_state_cb(io->vol, io->extent, rc);
176
177 return rc;
178}
179
180errno_t hr_io_raid5_writer(void *arg)
181{
182 errno_t rc;
183
184 hr_io_raid5_t *io = arg;
185 hr_stripe_t *stripe = io->stripe;
186
187 size_t ext_idx = io->extent;
188 hr_extent_t *extents = (hr_extent_t *)&io->vol->extents;
189
190 hr_stripe_commit_parity(stripe, io->strip_off, io->data_write,
191 io->cnt * io->vol->bsize);
192
193 hr_stripe_wait_for_parity_commits(stripe);
194 if (stripe->abort)
195 return EAGAIN;
196
197 rc = hr_write_direct(extents[ext_idx].svc_id, io->ba, io->cnt,
198 io->data_write);
199 if (rc != EOK)
200 io->vol->hr_ops.ext_state_cb(io->vol, io->extent, rc);
201
202 return rc;
203}
204
205errno_t hr_io_raid5_noop_writer(void *arg)
206{
207 hr_io_raid5_t *io = arg;
208 hr_stripe_t *stripe = io->stripe;
209
210 hr_stripe_commit_parity(stripe, io->strip_off, io->data_write,
211 io->cnt * io->vol->bsize);
212
213 return EOK;
214}
215
216errno_t hr_io_raid5_parity_getter(void *arg)
217{
218 hr_io_raid5_t *io = arg;
219 hr_stripe_t *stripe = io->stripe;
220 size_t bsize = stripe->vol->bsize;
221
222 hr_stripe_wait_for_parity_commits(stripe);
223 if (stripe->abort)
224 return EAGAIN;
225
226 memcpy(io->data_read, stripe->parity + io->strip_off, io->cnt * bsize);
227
228 return EOK;
229}
230
231errno_t hr_io_raid5_subtract_writer(void *arg)
232{
233 errno_t rc;
234
235 hr_io_raid5_t *io = arg;
236 hr_stripe_t *stripe = io->stripe;
237
238 size_t ext_idx = io->extent;
239 hr_extent_t *extents = (hr_extent_t *)&io->vol->extents;
240
241 uint8_t *data = hr_malloc_waitok(io->cnt * io->vol->bsize);
242
243 rc = hr_read_direct(extents[ext_idx].svc_id, io->ba, io->cnt, data);
244 if (rc != EOK) {
245 io->vol->hr_ops.ext_state_cb(io->vol, io->extent, rc);
246 hr_stripe_parity_abort(stripe);
247 free(data);
248 return rc;
249 }
250
251 fibril_mutex_lock(&stripe->parity_lock);
252
253 hr_raid5_xor(stripe->parity + io->strip_off, data,
254 io->cnt * io->vol->bsize);
255
256 hr_raid5_xor(stripe->parity + io->strip_off, io->data_write,
257 io->cnt * io->vol->bsize);
258
259 stripe->ps_added++;
260 fibril_condvar_broadcast(&stripe->ps_added_cv);
261 fibril_mutex_unlock(&stripe->parity_lock);
262
263 hr_stripe_wait_for_parity_commits(stripe);
264 if (stripe->abort)
265 return EAGAIN;
266
267 rc = hr_write_direct(extents[ext_idx].svc_id, io->ba, io->cnt,
268 io->data_write);
269 if (rc != EOK)
270 io->vol->hr_ops.ext_state_cb(io->vol, io->extent, rc);
271
272 free(data);
273
274 return rc;
275}
276
277errno_t hr_io_raid5_reconstruct_reader(void *arg)
278{
279 errno_t rc;
280
281 hr_io_raid5_t *io = arg;
282 hr_stripe_t *stripe = io->stripe;
283
284 size_t ext_idx = io->extent;
285 hr_extent_t *extents = (hr_extent_t *)&io->vol->extents;
286
287 uint8_t *data = hr_malloc_waitok(io->cnt * io->vol->bsize);
288
289 rc = hr_read_direct(extents[ext_idx].svc_id, io->ba, io->cnt, data);
290 if (rc != EOK) {
291 hr_stripe_parity_abort(stripe);
292 io->vol->hr_ops.ext_state_cb(io->vol, io->extent, rc);
293 free(data);
294 return rc;
295 }
296
297 hr_stripe_commit_parity(stripe, io->strip_off, data,
298 io->cnt * io->vol->bsize);
299
300 free(data);
301
302 return EOK;
303}
304
305errno_t hr_io_raid5_parity_writer(void *arg)
306{
307 errno_t rc;
308
309 hr_io_raid5_t *io = arg;
310 hr_stripe_t *stripe = io->stripe;
311
312 hr_extent_t *extents = (hr_extent_t *)&io->vol->extents;
313
314 hr_stripe_wait_for_parity_commits(stripe);
315
316 if (stripe->abort)
317 return EAGAIN;
318
319 rc = hr_write_direct(extents[io->extent].svc_id, io->ba, io->cnt,
320 stripe->parity + io->strip_off);
321 if (rc != EOK)
322 io->vol->hr_ops.ext_state_cb(io->vol, io->extent, rc);
323
324 return rc;
325}
326
327/** @}
328 */
Note: See TracBrowser for help on using the repository browser.