Blame view
fs/exofs/ore.c
30.1 KB
b14f8ab28 exofs: Kbuild, He... |
1 2 |
/* * Copyright (C) 2005, 2006 |
27d2e1491 exofs: Remove IBM... |
3 |
* Avishay Traeger (avishay@gmail.com) |
b14f8ab28 exofs: Kbuild, He... |
4 |
* Copyright (C) 2008, 2009 |
aa281ac63 Boaz Harrosh - Fi... |
5 |
* Boaz Harrosh <ooo@electrozaur.com> |
b14f8ab28 exofs: Kbuild, He... |
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
* * This file is part of exofs. * * exofs is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. Since it is based on ext2, and the only * valid version of GPL for the Linux kernel is version 2, the only valid * version of GPL for exofs is version 2. * * exofs is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with exofs; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ |
5a0e3ad6a include cleanup: ... |
24 |
#include <linux/slab.h> |
143cb494c fs: add module.h ... |
25 |
#include <linux/module.h> |
5d952b839 exofs: RAID0 support |
26 |
#include <asm/div64.h> |
a1fec1dbb ore: RAID5 read |
27 |
#include <linux/lcm.h> |
b14f8ab28 exofs: Kbuild, He... |
28 |
|
a1fec1dbb ore: RAID5 read |
29 |
#include "ore_raid.h" |
8ff660ab8 exofs: Rename rai... |
30 |
|
aa281ac63 Boaz Harrosh - Fi... |
31 |
MODULE_AUTHOR("Boaz Harrosh <ooo@electrozaur.com>"); |
cf283ade0 ore: Make ore its... |
32 33 |
MODULE_DESCRIPTION("Objects Raid Engine ore.ko"); MODULE_LICENSE("GPL"); |
5a51c0c7e ore/exofs: Define... |
34 35 36 37 38 39 40 41 42 |
/* ore_verify_layout does a couple of things: * 1. Given a minimum number of needed parameters fixes up the rest of the * members to be operatonals for the ore. The needed parameters are those * that are defined by the pnfs-objects layout STD. * 2. Check to see if the current ore code actually supports these parameters * for example stripe_unit must be a multple of the system PAGE_SIZE, * and etc... * 3. Cache some havily used calculations that will be needed by users. */ |
5a51c0c7e ore/exofs: Define... |
43 44 45 46 47 48 |
enum { BIO_MAX_PAGES_KMALLOC = (PAGE_SIZE - sizeof(struct bio)) / sizeof(struct bio_vec),}; int ore_verify_layout(unsigned total_comps, struct ore_layout *layout) { u64 stripe_length; |
44231e686 ore: Enable RAID5... |
49 50 51 52 53 54 55 56 |
switch (layout->raid_algorithm) { case PNFS_OSD_RAID_0: layout->parity = 0; break; case PNFS_OSD_RAID_5: layout->parity = 1; break; case PNFS_OSD_RAID_PQ: |
ce5d36aac ore: Support for ... |
57 58 |
layout->parity = 2; break; |
44231e686 ore: Enable RAID5... |
59 60 |
case PNFS_OSD_RAID_4: default: |
ce5d36aac ore: Support for ... |
61 62 63 |
ORE_ERR("Only RAID_0/5/6 for now received-enum=%d ", layout->raid_algorithm); |
5a51c0c7e ore/exofs: Define... |
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
return -EINVAL; } if (0 != (layout->stripe_unit & ~PAGE_MASK)) { ORE_ERR("Stripe Unit(0x%llx)" " must be Multples of PAGE_SIZE(0x%lx) ", _LLU(layout->stripe_unit), PAGE_SIZE); return -EINVAL; } if (layout->group_width) { if (!layout->group_depth) { ORE_ERR("group_depth == 0 && group_width != 0 "); return -EINVAL; } if (total_comps < (layout->group_width * layout->mirrors_p1)) { ORE_ERR("Data Map wrong, " "numdevs=%d < group_width=%d * mirrors=%d ", total_comps, layout->group_width, layout->mirrors_p1); return -EINVAL; } layout->group_count = total_comps / layout->mirrors_p1 / layout->group_width; } else { if (layout->group_depth) { printk(KERN_NOTICE "Warning: group_depth ignored " "group_width == 0 && group_depth == %lld ", _LLU(layout->group_depth)); } layout->group_width = total_comps / layout->mirrors_p1; layout->group_depth = -1; layout->group_count = 1; } stripe_length = (u64)layout->group_width * layout->stripe_unit; if (stripe_length >= (1ULL << 32)) { ORE_ERR("Stripe_length(0x%llx) >= 32bit is not supported ", _LLU(stripe_length)); return -EINVAL; } layout->max_io_length = (BIO_MAX_PAGES_KMALLOC * PAGE_SIZE - layout->stripe_unit) * |
aad560b7f ore: Fix wrong ma... |
111 |
(layout->group_width - layout->parity); |
769ba8d92 ore: RAID5 Write |
112 113 114 115 116 117 118 119 |
if (layout->parity) { unsigned stripe_length = (layout->group_width - layout->parity) * layout->stripe_unit; layout->max_io_length /= stripe_length; layout->max_io_length *= stripe_length; } |
ce5d36aac ore: Support for ... |
120 121 |
ORE_DBGMSG("max_io_length=0x%lx ", layout->max_io_length); |
5a51c0c7e ore/exofs: Define... |
122 123 124 |
return 0; } EXPORT_SYMBOL(ore_verify_layout); |
8ff660ab8 exofs: Rename rai... |
125 |
static u8 *_ios_cred(struct ore_io_state *ios, unsigned index) |
9e9db4564 exofs: ios: Move ... |
126 |
{ |
5bf696dad exofs: Rename str... |
127 |
return ios->oc->comps[index & ios->oc->single_comp].cred; |
9e9db4564 exofs: ios: Move ... |
128 |
} |
8ff660ab8 exofs: Rename rai... |
129 |
static struct osd_obj_id *_ios_obj(struct ore_io_state *ios, unsigned index) |
9e9db4564 exofs: ios: Move ... |
130 |
{ |
5bf696dad exofs: Rename str... |
131 |
return &ios->oc->comps[index & ios->oc->single_comp].obj; |
9e9db4564 exofs: ios: Move ... |
132 |
} |
8ff660ab8 exofs: Rename rai... |
133 |
static struct osd_dev *_ios_od(struct ore_io_state *ios, unsigned index) |
9e9db4564 exofs: ios: Move ... |
134 |
{ |
3bd985685 ore: Support for ... |
135 136 137 138 |
ORE_DBGMSG2("oc->first_dev=%d oc->numdevs=%d i=%d oc->ods=%p ", ios->oc->first_dev, ios->oc->numdevs, index, ios->oc->ods); |
d866d875f ore/exofs: Change... |
139 |
return ore_comp_dev(ios->oc, index); |
9e9db4564 exofs: ios: Move ... |
140 |
} |
769ba8d92 ore: RAID5 Write |
141 |
int _ore_get_io_state(struct ore_layout *layout, |
a1fec1dbb ore: RAID5 read |
142 143 144 |
struct ore_components *oc, unsigned numdevs, unsigned sgs_per_dev, unsigned num_par_pages, struct ore_io_state **pios) |
b14f8ab28 exofs: Kbuild, He... |
145 |
{ |
8ff660ab8 exofs: Rename rai... |
146 |
struct ore_io_state *ios; |
a1fec1dbb ore: RAID5 read |
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
struct page **pages; struct osd_sg_entry *sgilist; struct __alloc_all_io_state { struct ore_io_state ios; struct ore_per_dev_state per_dev[numdevs]; union { struct osd_sg_entry sglist[sgs_per_dev * numdevs]; struct page *pages[num_par_pages]; }; } *_aios; if (likely(sizeof(*_aios) <= PAGE_SIZE)) { _aios = kzalloc(sizeof(*_aios), GFP_KERNEL); if (unlikely(!_aios)) { ORE_DBGMSG("Failed kzalloc bytes=%zd ", sizeof(*_aios)); *pios = NULL; return -ENOMEM; } pages = num_par_pages ? _aios->pages : NULL; sgilist = sgs_per_dev ? _aios->sglist : NULL; ios = &_aios->ios; } else { struct __alloc_small_io_state { struct ore_io_state ios; struct ore_per_dev_state per_dev[numdevs]; } *_aio_small; union __extra_part { struct osd_sg_entry sglist[sgs_per_dev * numdevs]; struct page *pages[num_par_pages]; } *extra_part; _aio_small = kzalloc(sizeof(*_aio_small), GFP_KERNEL); if (unlikely(!_aio_small)) { ORE_DBGMSG("Failed alloc first part bytes=%zd ", sizeof(*_aio_small)); *pios = NULL; return -ENOMEM; } extra_part = kzalloc(sizeof(*extra_part), GFP_KERNEL); if (unlikely(!extra_part)) { ORE_DBGMSG("Failed alloc second part bytes=%zd ", sizeof(*extra_part)); kfree(_aio_small); *pios = NULL; return -ENOMEM; } |
06886a5a3 exofs: Move all o... |
197 |
|
a1fec1dbb ore: RAID5 read |
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
pages = num_par_pages ? extra_part->pages : NULL; sgilist = sgs_per_dev ? extra_part->sglist : NULL; /* In this case the per_dev[0].sgilist holds the pointer to * be freed */ ios = &_aio_small->ios; ios->extra_part_alloc = true; } if (pages) { ios->parity_pages = pages; ios->max_par_pages = num_par_pages; } if (sgilist) { unsigned d; for (d = 0; d < numdevs; ++d) { ios->per_dev[d].sglist = sgilist; sgilist += sgs_per_dev; } ios->sgs_per_dev = sgs_per_dev; |
06886a5a3 exofs: Move all o... |
219 |
} |
45d3abcb1 exofs: Move layou... |
220 |
ios->layout = layout; |
5bf696dad exofs: Rename str... |
221 |
ios->oc = oc; |
b916c5cd4 ore: Only IO one ... |
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 |
*pios = ios; return 0; } /* Allocate an io_state for only a single group of devices * * If a user needs to call ore_read/write() this version must be used becase it * allocates extra stuff for striping and raid. * The ore might decide to only IO less then @length bytes do to alignmets * and constrains as follows: * - The IO cannot cross group boundary. * - In raid5/6 The end of the IO must align at end of a stripe eg. * (@offset + @length) % strip_size == 0. Or the complete range is within a * single stripe. * - Memory condition only permitted a shorter IO. (A user can use @length=~0 * And check the returned ios->length for max_io_size.) * * The caller must check returned ios->length (and/or ios->nr_pages) and * re-issue these pages that fall outside of ios->length */ int ore_get_rw_state(struct ore_layout *layout, struct ore_components *oc, bool is_reading, u64 offset, u64 length, struct ore_io_state **pios) { struct ore_io_state *ios; unsigned numdevs = layout->group_width * layout->mirrors_p1; |
a1fec1dbb ore: RAID5 read |
248 |
unsigned sgs_per_dev = 0, max_par_pages = 0; |
b916c5cd4 ore: Only IO one ... |
249 |
int ret; |
a1fec1dbb ore: RAID5 read |
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 |
if (layout->parity && length) { unsigned data_devs = layout->group_width - layout->parity; unsigned stripe_size = layout->stripe_unit * data_devs; unsigned pages_in_unit = layout->stripe_unit / PAGE_SIZE; u32 remainder; u64 num_stripes; u64 num_raid_units; num_stripes = div_u64_rem(length, stripe_size, &remainder); if (remainder) ++num_stripes; num_raid_units = num_stripes * layout->parity; if (is_reading) { /* For reads add per_dev sglist array */ /* TODO: Raid 6 we need twice more. Actually: * num_stripes / LCMdP(W,P); * if (W%P != 0) num_stripes *= parity; */ /* first/last seg is split */ num_raid_units += layout->group_width; |
361aba569 ore: fix BUG_ON, ... |
273 |
sgs_per_dev = div_u64(num_raid_units, data_devs) + 2; |
a1fec1dbb ore: RAID5 read |
274 275 276 277 278 279 280 281 282 |
} else { /* For Writes add parity pages array. */ max_par_pages = num_raid_units * pages_in_unit * sizeof(struct page *); } } ret = _ore_get_io_state(layout, oc, numdevs, sgs_per_dev, max_par_pages, pios); |
b916c5cd4 ore: Only IO one ... |
283 284 285 286 |
if (unlikely(ret)) return ret; ios = *pios; |
e1042ba09 exofs: Add offset... |
287 |
ios->reading = is_reading; |
b916c5cd4 ore: Only IO one ... |
288 289 290 |
ios->offset = offset; if (length) { |
a1fec1dbb ore: RAID5 read |
291 292 |
ore_calc_stripe_info(layout, offset, length, &ios->si); ios->length = ios->si.length; |
aad560b7f ore: Fix wrong ma... |
293 294 |
ios->nr_pages = ((ios->offset & (PAGE_SIZE - 1)) + ios->length + PAGE_SIZE - 1) / PAGE_SIZE; |
a1fec1dbb ore: RAID5 read |
295 296 |
if (layout->parity) _ore_post_alloc_raid_stuff(ios); |
b916c5cd4 ore: Only IO one ... |
297 |
} |
e1042ba09 exofs: Add offset... |
298 |
|
06886a5a3 exofs: Move all o... |
299 |
return 0; |
b14f8ab28 exofs: Kbuild, He... |
300 |
} |
cf283ade0 ore: Make ore its... |
301 |
EXPORT_SYMBOL(ore_get_rw_state); |
b14f8ab28 exofs: Kbuild, He... |
302 |
|
b916c5cd4 ore: Only IO one ... |
303 304 305 306 307 308 309 |
/* Allocate an io_state for all the devices in the comps array * * This version of io_state allocation is used mostly by create/remove * and trunc where we currently need all the devices. The only wastful * bit is the read/write_attributes with no IO. Those sites should * be converted to use ore_get_rw_state() with length=0 */ |
5bf696dad exofs: Rename str... |
310 |
int ore_get_io_state(struct ore_layout *layout, struct ore_components *oc, |
b916c5cd4 ore: Only IO one ... |
311 |
struct ore_io_state **pios) |
e1042ba09 exofs: Add offset... |
312 |
{ |
a1fec1dbb ore: RAID5 read |
313 |
return _ore_get_io_state(layout, oc, oc->numdevs, 0, 0, pios); |
e1042ba09 exofs: Add offset... |
314 |
} |
cf283ade0 ore: Make ore its... |
315 |
EXPORT_SYMBOL(ore_get_io_state); |
e1042ba09 exofs: Add offset... |
316 |
|
8ff660ab8 exofs: Rename rai... |
317 |
void ore_put_io_state(struct ore_io_state *ios) |
b14f8ab28 exofs: Kbuild, He... |
318 |
{ |
06886a5a3 exofs: Move all o... |
319 320 |
if (ios) { unsigned i; |
b14f8ab28 exofs: Kbuild, He... |
321 |
|
06886a5a3 exofs: Move all o... |
322 |
for (i = 0; i < ios->numdevs; i++) { |
8ff660ab8 exofs: Rename rai... |
323 |
struct ore_per_dev_state *per_dev = &ios->per_dev[i]; |
06886a5a3 exofs: Move all o... |
324 325 326 327 328 329 |
if (per_dev->or) osd_end_request(per_dev->or); if (per_dev->bio) bio_put(per_dev->bio); } |
a1fec1dbb ore: RAID5 read |
330 |
_ore_free_raid_stuff(ios); |
06886a5a3 exofs: Move all o... |
331 |
kfree(ios); |
b14f8ab28 exofs: Kbuild, He... |
332 |
} |
06886a5a3 exofs: Move all o... |
333 |
} |
cf283ade0 ore: Make ore its... |
334 |
EXPORT_SYMBOL(ore_put_io_state); |
b14f8ab28 exofs: Kbuild, He... |
335 |
|
8ff660ab8 exofs: Rename rai... |
336 |
static void _sync_done(struct ore_io_state *ios, void *p) |
06886a5a3 exofs: Move all o... |
337 338 |
{ struct completion *waiting = p; |
b14f8ab28 exofs: Kbuild, He... |
339 |
|
06886a5a3 exofs: Move all o... |
340 341 342 343 344 |
complete(waiting); } static void _last_io(struct kref *kref) { |
8ff660ab8 exofs: Rename rai... |
345 346 |
struct ore_io_state *ios = container_of( kref, struct ore_io_state, kref); |
06886a5a3 exofs: Move all o... |
347 348 349 350 351 352 |
ios->done(ios, ios->private); } static void _done_io(struct osd_request *or, void *p) { |
8ff660ab8 exofs: Rename rai... |
353 |
struct ore_io_state *ios = p; |
06886a5a3 exofs: Move all o... |
354 355 356 |
kref_put(&ios->kref, _last_io); } |
769ba8d92 ore: RAID5 Write |
357 |
int ore_io_execute(struct ore_io_state *ios) |
06886a5a3 exofs: Move all o... |
358 359 360 361 362 363 364 365 366 367 368 369 370 371 |
{ DECLARE_COMPLETION_ONSTACK(wait); bool sync = (ios->done == NULL); int i, ret; if (sync) { ios->done = _sync_done; ios->private = &wait; } for (i = 0; i < ios->numdevs; i++) { struct osd_request *or = ios->per_dev[i].or; if (unlikely(!or)) continue; |
9e9db4564 exofs: ios: Move ... |
372 |
ret = osd_finalize_request(or, 0, _ios_cred(ios, i), NULL); |
06886a5a3 exofs: Move all o... |
373 |
if (unlikely(ret)) { |
8ff660ab8 exofs: Rename rai... |
374 375 |
ORE_DBGMSG("Failed to osd_finalize_request() => %d ", |
06886a5a3 exofs: Move all o... |
376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 |
ret); return ret; } } kref_init(&ios->kref); for (i = 0; i < ios->numdevs; i++) { struct osd_request *or = ios->per_dev[i].or; if (unlikely(!or)) continue; kref_get(&ios->kref); osd_execute_request_async(or, _done_io, ios); } kref_put(&ios->kref, _last_io); ret = 0; if (sync) { wait_for_completion(&wait); |
8ff660ab8 exofs: Rename rai... |
397 |
ret = ore_check_io(ios, NULL); |
06886a5a3 exofs: Move all o... |
398 |
} |
b14f8ab28 exofs: Kbuild, He... |
399 400 |
return ret; } |
22ddc5563 exofs: Recover in... |
401 402 403 404 |
static void _clear_bio(struct bio *bio) { struct bio_vec *bv; unsigned i; |
d74c6d514 block: Add bio_fo... |
405 |
bio_for_each_segment_all(bv, bio, i) { |
22ddc5563 exofs: Recover in... |
406 407 408 409 410 411 412 413 |
unsigned this_count = bv->bv_len; if (likely(PAGE_SIZE == this_count)) clear_highpage(bv->bv_page); else zero_user(bv->bv_page, bv->bv_offset, this_count); } } |
4b46c9f5c ore/exofs: Change... |
414 |
int ore_check_io(struct ore_io_state *ios, ore_on_dev_error on_dev_error) |
b14f8ab28 exofs: Kbuild, He... |
415 |
{ |
06886a5a3 exofs: Move all o... |
416 417 418 |
enum osd_err_priority acumulated_osd_err = 0; int acumulated_lin_err = 0; int i; |
b14f8ab28 exofs: Kbuild, He... |
419 |
|
06886a5a3 exofs: Move all o... |
420 421 |
for (i = 0; i < ios->numdevs; i++) { struct osd_sense_info osi; |
4b46c9f5c ore/exofs: Change... |
422 423 |
struct ore_per_dev_state *per_dev = &ios->per_dev[i]; struct osd_request *or = per_dev->or; |
22ddc5563 exofs: Recover in... |
424 425 426 427 |
int ret; if (unlikely(!or)) continue; |
06886a5a3 exofs: Move all o... |
428 |
|
22ddc5563 exofs: Recover in... |
429 |
ret = osd_req_decode_sense(or, &osi); |
06886a5a3 exofs: Move all o... |
430 431 |
if (likely(!ret)) continue; |
2deb76db0 ore: Don't crash ... |
432 433 434 435 436 437 |
if ((OSD_ERR_PRI_CLEAR_PAGES == osi.osd_err_pri) && per_dev->bio) { /* start read offset passed endof file. * Note: if we do not have bio it means read-attributes * In this case we should return error to caller. */ |
4b46c9f5c ore/exofs: Change... |
438 |
_clear_bio(per_dev->bio); |
8ff660ab8 exofs: Rename rai... |
439 |
ORE_DBGMSG("start read offset passed end of file " |
22ddc5563 exofs: Recover in... |
440 441 |
"offset=0x%llx, length=0x%llx ", |
4b46c9f5c ore/exofs: Change... |
442 443 |
_LLU(per_dev->offset), _LLU(per_dev->length)); |
22ddc5563 exofs: Recover in... |
444 445 |
continue; /* we recovered */ |
06886a5a3 exofs: Move all o... |
446 |
} |
4b46c9f5c ore/exofs: Change... |
447 448 449 450 |
if (on_dev_error) { u64 residual = ios->reading ? or->in.residual : or->out.residual; u64 offset = (ios->offset + ios->length) - residual; |
ffefb8eaa ore: Fix crash in... |
451 452 |
unsigned dev = per_dev->dev - ios->oc->first_dev; struct ore_dev *od = ios->oc->ods[dev]; |
4b46c9f5c ore/exofs: Change... |
453 |
|
ffefb8eaa ore: Fix crash in... |
454 |
on_dev_error(ios, od, dev, osi.osd_err_pri, |
4b46c9f5c ore/exofs: Change... |
455 456 |
offset, residual); } |
06886a5a3 exofs: Move all o... |
457 458 459 460 461 |
if (osi.osd_err_pri >= acumulated_osd_err) { acumulated_osd_err = osi.osd_err_pri; acumulated_lin_err = ret; } } |
06886a5a3 exofs: Move all o... |
462 463 |
return acumulated_lin_err; } |
cf283ade0 ore: Make ore its... |
464 |
EXPORT_SYMBOL(ore_check_io); |
06886a5a3 exofs: Move all o... |
465 |
|
b367e78bd exofs: Prepare fo... |
466 467 468 |
/* * L - logical offset into the file * |
a1fec1dbb ore: RAID5 read |
469 470 |
* D - number of Data devices * D = group_width - parity |
b367e78bd exofs: Prepare fo... |
471 |
* |
a1fec1dbb ore: RAID5 read |
472 473 |
* U - The number of bytes in a stripe within a group * U = stripe_unit * D |
b367e78bd exofs: Prepare fo... |
474 |
* |
50a76fd3c exofs: groups sup... |
475 476 |
* T - The number of bytes striped within a group of component objects * (before advancing to the next group) |
a1fec1dbb ore: RAID5 read |
477 |
* T = U * group_depth |
50a76fd3c exofs: groups sup... |
478 479 480 |
* * S - The number of bytes striped across all component objects * before the pattern repeats |
a1fec1dbb ore: RAID5 read |
481 |
* S = T * group_count |
50a76fd3c exofs: groups sup... |
482 |
* |
a1fec1dbb ore: RAID5 read |
483 |
* M - The "major" (i.e., across all components) cycle number |
50a76fd3c exofs: groups sup... |
484 485 |
* M = L / S * |
a1fec1dbb ore: RAID5 read |
486 |
* G - Counts the groups from the beginning of the major cycle |
50a76fd3c exofs: groups sup... |
487 488 489 |
* G = (L - (M * S)) / T [or (L % S) / T] * * H - The byte offset within the group |
50a76fd3c exofs: groups sup... |
490 491 492 |
* H = (L - (M * S)) % T [or (L % S) % T] * * N - The "minor" (i.e., across the group) stripe number |
50a76fd3c exofs: groups sup... |
493 |
* N = H / U |
b367e78bd exofs: Prepare fo... |
494 495 496 |
* * C - The component index coresponding to L * |
a1fec1dbb ore: RAID5 read |
497 498 |
* C = (H - (N * U)) / stripe_unit + G * D * [or (L % U) / stripe_unit + G * D] |
b367e78bd exofs: Prepare fo... |
499 500 |
* * O - The component offset coresponding to L |
50a76fd3c exofs: groups sup... |
501 |
* O = L % stripe_unit + N * stripe_unit + M * group_depth * stripe_unit |
a1fec1dbb ore: RAID5 read |
502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 |
* * LCMdP – Parity cycle: Lowest Common Multiple of group_width, parity * divide by parity * LCMdP = lcm(group_width, parity) / parity * * R - The parity Rotation stripe * (Note parity cycle always starts at a group's boundary) * R = N % LCMdP * * I = the first parity device index * I = (group_width + group_width - R*parity - parity) % group_width * * Craid - The component index Rotated * Craid = (group_width + C - R*parity) % group_width * (We add the group_width to avoid negative numbers modulo math) |
b367e78bd exofs: Prepare fo... |
517 |
*/ |
611d7a5dc ore: Make ore_cal... |
518 |
void ore_calc_stripe_info(struct ore_layout *layout, u64 file_offset, |
a1fec1dbb ore: RAID5 read |
519 |
u64 length, struct ore_striping_info *si) |
5d952b839 exofs: RAID0 support |
520 |
{ |
16f75bb35 exofs: Fix trunca... |
521 522 523 |
u32 stripe_unit = layout->stripe_unit; u32 group_width = layout->group_width; u64 group_depth = layout->group_depth; |
a1fec1dbb ore: RAID5 read |
524 |
u32 parity = layout->parity; |
50a76fd3c exofs: groups sup... |
525 |
|
a1fec1dbb ore: RAID5 read |
526 527 |
u32 D = group_width - parity; u32 U = D * stripe_unit; |
50a76fd3c exofs: groups sup... |
528 |
u64 T = U * group_depth; |
16f75bb35 exofs: Fix trunca... |
529 |
u64 S = T * layout->group_count; |
50a76fd3c exofs: groups sup... |
530 531 532 533 534 535 536 537 538 539 540 |
u64 M = div64_u64(file_offset, S); /* G = (L - (M * S)) / T H = (L - (M * S)) % T */ u64 LmodS = file_offset - M * S; u32 G = div64_u64(LmodS, T); u64 H = LmodS - G * T; u32 N = div_u64(H, U); |
aad560b7f ore: Fix wrong ma... |
541 |
u32 Nlast; |
50a76fd3c exofs: groups sup... |
542 543 |
/* "H - (N * U)" is just "H % U" so it's bound to u32 */ |
a1fec1dbb ore: RAID5 read |
544 |
u32 C = (u32)(H - (N * U)) / stripe_unit + G * group_width; |
455682ce5 ore: Remove redun... |
545 |
u32 first_dev = C - C % group_width; |
b367e78bd exofs: Prepare fo... |
546 |
|
50a76fd3c exofs: groups sup... |
547 |
div_u64_rem(file_offset, stripe_unit, &si->unit_off); |
5d952b839 exofs: RAID0 support |
548 |
|
50a76fd3c exofs: groups sup... |
549 550 |
si->obj_offset = si->unit_off + (N * stripe_unit) + (M * group_depth * stripe_unit); |
455682ce5 ore: Remove redun... |
551 552 |
si->cur_comp = C - first_dev; si->cur_pg = si->unit_off / PAGE_SIZE; |
50a76fd3c exofs: groups sup... |
553 |
|
a1fec1dbb ore: RAID5 read |
554 555 556 557 |
if (parity) { u32 LCMdP = lcm(group_width, parity) / parity; /* R = N % LCMdP; */ u32 RxP = (N % LCMdP) * parity; |
a1fec1dbb ore: RAID5 read |
558 559 560 |
si->par_dev = (group_width + group_width - parity - RxP) % group_width + first_dev; |
ce5d36aac ore: Support for ... |
561 562 |
si->dev = (group_width + group_width + C - RxP) % group_width + first_dev; |
a1fec1dbb ore: RAID5 read |
563 564 565 566 567 568 569 570 571 572 573 574 575 576 |
si->bytes_in_stripe = U; si->first_stripe_start = M * S + G * T + N * U; } else { /* Make the math correct see _prepare_one_group */ si->par_dev = group_width; si->dev = C; } si->dev *= layout->mirrors_p1; si->par_dev *= layout->mirrors_p1; si->offset = file_offset; si->length = T - H; if (si->length > length) si->length = length; |
aad560b7f ore: Fix wrong ma... |
577 578 579 |
Nlast = div_u64(H + si->length + U - 1, U); si->maxdevUnits = Nlast - N; |
16f75bb35 exofs: Fix trunca... |
580 |
si->M = M; |
5d952b839 exofs: RAID0 support |
581 |
} |
611d7a5dc ore: Make ore_cal... |
582 |
EXPORT_SYMBOL(ore_calc_stripe_info); |
5d952b839 exofs: RAID0 support |
583 |
|
a1fec1dbb ore: RAID5 read |
584 585 586 |
int _ore_add_stripe_unit(struct ore_io_state *ios, unsigned *cur_pg, unsigned pgbase, struct page **pages, struct ore_per_dev_state *per_dev, int cur_len) |
5d952b839 exofs: RAID0 support |
587 |
{ |
86093aaff exofs: convert io... |
588 |
unsigned pg = *cur_pg; |
5d952b839 exofs: RAID0 support |
589 |
struct request_queue *q = |
9e9db4564 exofs: ios: Move ... |
590 |
osd_request_queue(_ios_od(ios, per_dev->dev)); |
bbf9a31bb ore: Support for ... |
591 592 |
unsigned len = cur_len; int ret; |
5d952b839 exofs: RAID0 support |
593 594 |
if (per_dev->bio == NULL) { |
aad560b7f ore: Fix wrong ma... |
595 596 597 598 599 600 601 602 603 604 |
unsigned bio_size; if (!ios->reading) { bio_size = ios->si.maxdevUnits; } else { bio_size = (ios->si.maxdevUnits + 1) * (ios->layout->group_width - ios->layout->parity) / ios->layout->group_width; } bio_size *= (ios->layout->stripe_unit / PAGE_SIZE); |
5d952b839 exofs: RAID0 support |
605 606 607 |
per_dev->bio = bio_kmalloc(GFP_KERNEL, bio_size); if (unlikely(!per_dev->bio)) { |
8ff660ab8 exofs: Rename rai... |
608 609 |
ORE_DBGMSG("Failed to allocate BIO size=%u ", |
5d952b839 exofs: RAID0 support |
610 |
bio_size); |
bbf9a31bb ore: Support for ... |
611 612 |
ret = -ENOMEM; goto out; |
5d952b839 exofs: RAID0 support |
613 614 615 616 |
} } while (cur_len > 0) { |
86093aaff exofs: convert io... |
617 618 |
unsigned pglen = min_t(unsigned, PAGE_SIZE - pgbase, cur_len); unsigned added_len; |
5d952b839 exofs: RAID0 support |
619 |
|
86093aaff exofs: convert io... |
620 |
cur_len -= pglen; |
5d952b839 exofs: RAID0 support |
621 |
|
a1fec1dbb ore: RAID5 read |
622 |
added_len = bio_add_pc_page(q, per_dev->bio, pages[pg], |
86093aaff exofs: convert io... |
623 |
pglen, pgbase); |
bbf9a31bb ore: Support for ... |
624 |
if (unlikely(pglen != added_len)) { |
aad560b7f ore: Fix wrong ma... |
625 626 627 628 629 630 631 |
/* If bi_vcnt == bi_max then this is a SW BUG */ ORE_DBGMSG("Failed bio_add_pc_page bi_vcnt=0x%x " "bi_max=0x%x BIO_MAX=0x%x cur_len=0x%x ", per_dev->bio->bi_vcnt, per_dev->bio->bi_max_vecs, BIO_MAX_PAGES_KMALLOC, cur_len); |
bbf9a31bb ore: Support for ... |
632 633 634 |
ret = -ENOMEM; goto out; } |
769ba8d92 ore: RAID5 Write |
635 |
_add_stripe_page(ios->sp2d, &ios->si, pages[pg]); |
86093aaff exofs: convert io... |
636 637 |
pgbase = 0; ++pg; |
5d952b839 exofs: RAID0 support |
638 639 |
} BUG_ON(cur_len); |
bbf9a31bb ore: Support for ... |
640 |
per_dev->length += len; |
86093aaff exofs: convert io... |
641 |
*cur_pg = pg; |
bbf9a31bb ore: Support for ... |
642 643 644 645 646 647 648 |
ret = 0; out: /* we fail the complete unit on an error eg don't advance * per_dev->length and cur_pg. This means that we might have a bigger * bio than the CDB requested length (per_dev->length). That's fine * only the oposite is fatal. */ return ret; |
5d952b839 exofs: RAID0 support |
649 |
} |
ce5d36aac ore: Support for ... |
650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 |
static int _add_parity_units(struct ore_io_state *ios, struct ore_striping_info *si, unsigned dev, unsigned first_dev, unsigned mirrors_p1, unsigned devs_in_group, unsigned cur_len) { unsigned do_parity; int ret = 0; for (do_parity = ios->layout->parity; do_parity; --do_parity) { struct ore_per_dev_state *per_dev; per_dev = &ios->per_dev[dev - first_dev]; if (!per_dev->length && !per_dev->offset) { /* Only/always the parity unit of the first * stripe will be empty. So this is a chance to * initialize the per_dev info. */ per_dev->dev = dev; per_dev->offset = si->obj_offset - si->unit_off; } ret = _ore_add_parity_unit(ios, si, per_dev, cur_len, do_parity == 1); if (unlikely(ret)) break; if (do_parity != 1) { dev = ((dev + mirrors_p1) % devs_in_group) + first_dev; si->cur_comp = (si->cur_comp + 1) % ios->layout->group_width; } } return ret; } |
982607540 ore: cleanup: Emb... |
686 |
static int _prepare_for_striping(struct ore_io_state *ios) |
5d952b839 exofs: RAID0 support |
687 |
{ |
982607540 ore: cleanup: Emb... |
688 |
struct ore_striping_info *si = &ios->si; |
5d952b839 exofs: RAID0 support |
689 |
unsigned stripe_unit = ios->layout->stripe_unit; |
b367e78bd exofs: Prepare fo... |
690 |
unsigned mirrors_p1 = ios->layout->mirrors_p1; |
a1fec1dbb ore: RAID5 read |
691 692 |
unsigned group_width = ios->layout->group_width; unsigned devs_in_group = group_width * mirrors_p1; |
b367e78bd exofs: Prepare fo... |
693 |
unsigned dev = si->dev; |
50a76fd3c exofs: groups sup... |
694 |
unsigned first_dev = dev - (dev % devs_in_group); |
50a76fd3c exofs: groups sup... |
695 |
unsigned cur_pg = ios->pages_consumed; |
982607540 ore: cleanup: Emb... |
696 |
u64 length = ios->length; |
86093aaff exofs: convert io... |
697 |
int ret = 0; |
5d952b839 exofs: RAID0 support |
698 |
|
982607540 ore: cleanup: Emb... |
699 |
if (!ios->pages) { |
982607540 ore: cleanup: Emb... |
700 701 702 |
ios->numdevs = ios->layout->mirrors_p1; return 0; } |
a1fec1dbb ore: RAID5 read |
703 |
BUG_ON(length > si->length); |
5d952b839 exofs: RAID0 support |
704 |
while (length) { |
101a64278 ore: (trivial) re... |
705 706 |
struct ore_per_dev_state *per_dev = &ios->per_dev[dev - first_dev]; |
b367e78bd exofs: Prepare fo... |
707 |
unsigned cur_len, page_off = 0; |
5d952b839 exofs: RAID0 support |
708 |
|
ce5d36aac ore: Support for ... |
709 710 |
if (!per_dev->length && !per_dev->offset) { /* First time initialize the per_dev info. */ |
b367e78bd exofs: Prepare fo... |
711 |
per_dev->dev = dev; |
a1fec1dbb ore: RAID5 read |
712 713 |
if (dev == si->dev) { WARN_ON(dev == si->par_dev); |
b367e78bd exofs: Prepare fo... |
714 715 716 717 |
per_dev->offset = si->obj_offset; cur_len = stripe_unit - si->unit_off; page_off = si->unit_off & ~PAGE_MASK; BUG_ON(page_off && (page_off != ios->pgbase)); |
a1fec1dbb ore: RAID5 read |
718 |
} else { |
ce5d36aac ore: Support for ... |
719 |
per_dev->offset = si->obj_offset - si->unit_off; |
b367e78bd exofs: Prepare fo... |
720 721 |
cur_len = stripe_unit; } |
5d952b839 exofs: RAID0 support |
722 |
} else { |
b367e78bd exofs: Prepare fo... |
723 |
cur_len = stripe_unit; |
5d952b839 exofs: RAID0 support |
724 |
} |
b367e78bd exofs: Prepare fo... |
725 726 |
if (cur_len >= length) cur_len = length; |
5d952b839 exofs: RAID0 support |
727 |
|
a1fec1dbb ore: RAID5 read |
728 729 |
ret = _ore_add_stripe_unit(ios, &cur_pg, page_off, ios->pages, per_dev, cur_len); |
5d952b839 exofs: RAID0 support |
730 731 |
if (unlikely(ret)) goto out; |
5d952b839 exofs: RAID0 support |
732 |
length -= cur_len; |
a1fec1dbb ore: RAID5 read |
733 |
|
101a64278 ore: (trivial) re... |
734 |
dev = ((dev + mirrors_p1) % devs_in_group) + first_dev; |
a1fec1dbb ore: RAID5 read |
735 |
si->cur_comp = (si->cur_comp + 1) % group_width; |
769ba8d92 ore: RAID5 Write |
736 737 |
if (unlikely((dev == si->par_dev) || (!length && ios->sp2d))) { if (!length && ios->sp2d) { |
a1fec1dbb ore: RAID5 read |
738 739 740 741 |
/* If we are writing and this is the very last * stripe. then operate on parity dev. */ dev = si->par_dev; |
455682ce5 ore: Remove redun... |
742 743 |
/* If last stripe operate on parity comp */ si->cur_comp = group_width - ios->layout->parity; |
769ba8d92 ore: RAID5 Write |
744 |
} |
a1fec1dbb ore: RAID5 read |
745 |
|
101a64278 ore: (trivial) re... |
746 747 748 |
/* In writes cur_len just means if it's the * last one. See _ore_add_parity_unit. */ |
ce5d36aac ore: Support for ... |
749 750 |
ret = _add_parity_units(ios, si, dev, first_dev, mirrors_p1, devs_in_group, |
101a64278 ore: (trivial) re... |
751 |
ios->sp2d ? length : cur_len); |
a1fec1dbb ore: RAID5 read |
752 753 754 755 756 757 758 759 760 |
if (unlikely(ret)) goto out; /* Rotate next par_dev backwards with wraping */ si->par_dev = (devs_in_group + si->par_dev - ios->layout->parity * mirrors_p1) % devs_in_group + first_dev; /* Next stripe, start fresh */ si->cur_comp = 0; |
769ba8d92 ore: RAID5 Write |
761 |
si->cur_pg = 0; |
ce5d36aac ore: Support for ... |
762 763 |
si->obj_offset += cur_len; si->unit_off = 0; |
a1fec1dbb ore: RAID5 read |
764 |
} |
5d952b839 exofs: RAID0 support |
765 766 |
} out: |
b916c5cd4 ore: Only IO one ... |
767 |
ios->numdevs = devs_in_group; |
50a76fd3c exofs: groups sup... |
768 |
ios->pages_consumed = cur_pg; |
62b62ad87 ore: Remove suppo... |
769 |
return ret; |
5d952b839 exofs: RAID0 support |
770 |
} |
8ff660ab8 exofs: Rename rai... |
771 |
int ore_create(struct ore_io_state *ios) |
06886a5a3 exofs: Move all o... |
772 773 |
{ int i, ret; |
5bf696dad exofs: Rename str... |
774 |
for (i = 0; i < ios->oc->numdevs; i++) { |
06886a5a3 exofs: Move all o... |
775 |
struct osd_request *or; |
9e9db4564 exofs: ios: Move ... |
776 |
or = osd_start_request(_ios_od(ios, i), GFP_KERNEL); |
06886a5a3 exofs: Move all o... |
777 |
if (unlikely(!or)) { |
8ff660ab8 exofs: Rename rai... |
778 779 |
ORE_ERR("%s: osd_start_request failed ", __func__); |
06886a5a3 exofs: Move all o... |
780 781 782 783 784 |
ret = -ENOMEM; goto out; } ios->per_dev[i].or = or; ios->numdevs++; |
9e9db4564 exofs: ios: Move ... |
785 |
osd_req_create_object(or, _ios_obj(ios, i)); |
06886a5a3 exofs: Move all o... |
786 |
} |
8ff660ab8 exofs: Rename rai... |
787 |
ret = ore_io_execute(ios); |
06886a5a3 exofs: Move all o... |
788 789 790 791 |
out: return ret; } |
cf283ade0 ore: Make ore its... |
792 |
EXPORT_SYMBOL(ore_create); |
06886a5a3 exofs: Move all o... |
793 |
|
8ff660ab8 exofs: Rename rai... |
794 |
int ore_remove(struct ore_io_state *ios) |
06886a5a3 exofs: Move all o... |
795 796 |
{ int i, ret; |
5bf696dad exofs: Rename str... |
797 |
for (i = 0; i < ios->oc->numdevs; i++) { |
06886a5a3 exofs: Move all o... |
798 |
struct osd_request *or; |
9e9db4564 exofs: ios: Move ... |
799 |
or = osd_start_request(_ios_od(ios, i), GFP_KERNEL); |
06886a5a3 exofs: Move all o... |
800 |
if (unlikely(!or)) { |
8ff660ab8 exofs: Rename rai... |
801 802 |
ORE_ERR("%s: osd_start_request failed ", __func__); |
06886a5a3 exofs: Move all o... |
803 804 805 806 807 |
ret = -ENOMEM; goto out; } ios->per_dev[i].or = or; ios->numdevs++; |
9e9db4564 exofs: ios: Move ... |
808 |
osd_req_remove_object(or, _ios_obj(ios, i)); |
06886a5a3 exofs: Move all o... |
809 |
} |
8ff660ab8 exofs: Rename rai... |
810 |
ret = ore_io_execute(ios); |
06886a5a3 exofs: Move all o... |
811 812 813 814 |
out: return ret; } |
cf283ade0 ore: Make ore its... |
815 |
EXPORT_SYMBOL(ore_remove); |
06886a5a3 exofs: Move all o... |
816 |
|
8ff660ab8 exofs: Rename rai... |
817 |
static int _write_mirror(struct ore_io_state *ios, int cur_comp) |
06886a5a3 exofs: Move all o... |
818 |
{ |
8ff660ab8 exofs: Rename rai... |
819 |
struct ore_per_dev_state *master_dev = &ios->per_dev[cur_comp]; |
5d952b839 exofs: RAID0 support |
820 821 822 |
unsigned dev = ios->per_dev[cur_comp].dev; unsigned last_comp = cur_comp + ios->layout->mirrors_p1; int ret = 0; |
06886a5a3 exofs: Move all o... |
823 |
|
50a76fd3c exofs: groups sup... |
824 825 |
if (ios->pages && !master_dev->length) return 0; /* Just an empty slot */ |
5d952b839 exofs: RAID0 support |
826 |
for (; cur_comp < last_comp; ++cur_comp, ++dev) { |
8ff660ab8 exofs: Rename rai... |
827 |
struct ore_per_dev_state *per_dev = &ios->per_dev[cur_comp]; |
06886a5a3 exofs: Move all o... |
828 |
struct osd_request *or; |
9e9db4564 exofs: ios: Move ... |
829 |
or = osd_start_request(_ios_od(ios, dev), GFP_KERNEL); |
06886a5a3 exofs: Move all o... |
830 |
if (unlikely(!or)) { |
8ff660ab8 exofs: Rename rai... |
831 832 |
ORE_ERR("%s: osd_start_request failed ", __func__); |
06886a5a3 exofs: Move all o... |
833 834 835 |
ret = -ENOMEM; goto out; } |
5d952b839 exofs: RAID0 support |
836 |
per_dev->or = or; |
06886a5a3 exofs: Move all o... |
837 |
|
86093aaff exofs: convert io... |
838 |
if (ios->pages) { |
06886a5a3 exofs: Move all o... |
839 |
struct bio *bio; |
5d952b839 exofs: RAID0 support |
840 |
if (per_dev != master_dev) { |
bf800ef18 block: Add bio_cl... |
841 842 |
bio = bio_clone_kmalloc(master_dev->bio, GFP_KERNEL); |
04dc1e88a exofs: Multi-devi... |
843 |
if (unlikely(!bio)) { |
8ff660ab8 exofs: Rename rai... |
844 |
ORE_DBGMSG( |
426d31071 fix printk typo '... |
845 846 |
"Failed to allocate BIO size=%u ", |
5d952b839 exofs: RAID0 support |
847 |
master_dev->bio->bi_max_vecs); |
04dc1e88a exofs: Multi-devi... |
848 849 850 |
ret = -ENOMEM; goto out; } |
74d46992e block: replace bi... |
851 |
bio->bi_disk = NULL; |
04dc1e88a exofs: Multi-devi... |
852 |
bio->bi_next = NULL; |
6851a5e5c ore: Remove check... |
853 |
per_dev->offset = master_dev->offset; |
5d952b839 exofs: RAID0 support |
854 855 856 |
per_dev->length = master_dev->length; per_dev->bio = bio; per_dev->dev = dev; |
04dc1e88a exofs: Multi-devi... |
857 |
} else { |
5d952b839 exofs: RAID0 support |
858 859 |
bio = master_dev->bio; /* FIXME: bio_set_dir() */ |
95fe6c1a2 block, fs, mm, dr... |
860 |
bio_set_op_attrs(bio, REQ_OP_WRITE, 0); |
04dc1e88a exofs: Multi-devi... |
861 |
} |
06886a5a3 exofs: Move all o... |
862 |
|
9e62bb445 ore: Fix out-of-b... |
863 864 |
osd_req_write(or, _ios_obj(ios, cur_comp), per_dev->offset, bio, per_dev->length); |
8ff660ab8 exofs: Rename rai... |
865 |
ORE_DBGMSG("write(0x%llx) offset=0x%llx " |
34ce4e7c2 exofs: debug prin... |
866 867 |
"length=0x%llx dev=%d ", |
9e62bb445 ore: Fix out-of-b... |
868 |
_LLU(_ios_obj(ios, cur_comp)->id), |
9e9db4564 exofs: ios: Move ... |
869 |
_LLU(per_dev->offset), |
5d952b839 exofs: RAID0 support |
870 |
_LLU(per_dev->length), dev); |
06886a5a3 exofs: Move all o... |
871 |
} else if (ios->kern_buff) { |
6851a5e5c ore: Remove check... |
872 873 874 875 876 877 878 |
per_dev->offset = ios->si.obj_offset; per_dev->dev = ios->si.dev + dev; /* no cross device without page array */ BUG_ON((ios->layout->group_width > 1) && (ios->si.unit_off + ios->length > ios->layout->stripe_unit)); |
9e62bb445 ore: Fix out-of-b... |
879 |
ret = osd_req_write_kern(or, _ios_obj(ios, cur_comp), |
9e9db4564 exofs: ios: Move ... |
880 881 |
per_dev->offset, ios->kern_buff, ios->length); |
5d952b839 exofs: RAID0 support |
882 883 |
if (unlikely(ret)) goto out; |
8ff660ab8 exofs: Rename rai... |
884 |
ORE_DBGMSG2("write_kern(0x%llx) offset=0x%llx " |
34ce4e7c2 exofs: debug prin... |
885 886 |
"length=0x%llx dev=%d ", |
9e62bb445 ore: Fix out-of-b... |
887 |
_LLU(_ios_obj(ios, cur_comp)->id), |
9e9db4564 exofs: ios: Move ... |
888 |
_LLU(per_dev->offset), |
6851a5e5c ore: Remove check... |
889 |
_LLU(ios->length), per_dev->dev); |
06886a5a3 exofs: Move all o... |
890 |
} else { |
9e62bb445 ore: Fix out-of-b... |
891 |
osd_req_set_attributes(or, _ios_obj(ios, cur_comp)); |
8ff660ab8 exofs: Rename rai... |
892 893 |
ORE_DBGMSG2("obj(0x%llx) set_attributes=%d dev=%d ", |
9e62bb445 ore: Fix out-of-b... |
894 |
_LLU(_ios_obj(ios, cur_comp)->id), |
9e9db4564 exofs: ios: Move ... |
895 |
ios->out_attr_len, dev); |
06886a5a3 exofs: Move all o... |
896 897 898 899 900 901 902 903 904 |
} if (ios->out_attr) osd_req_add_set_attr_list(or, ios->out_attr, ios->out_attr_len); if (ios->in_attr) osd_req_add_get_attr_list(or, ios->in_attr, ios->in_attr_len); |
b14f8ab28 exofs: Kbuild, He... |
905 |
} |
06886a5a3 exofs: Move all o... |
906 907 908 909 |
out: return ret; } |
8ff660ab8 exofs: Rename rai... |
910 |
int ore_write(struct ore_io_state *ios) |
5d952b839 exofs: RAID0 support |
911 912 913 |
{ int i; int ret; |
769ba8d92 ore: RAID5 Write |
914 915 916 917 918 919 920 |
if (unlikely(ios->sp2d && !ios->r4w)) { /* A library is attempting a RAID-write without providing * a pages lock interface. */ WARN_ON_ONCE(1); return -ENOTSUPP; } |
5d952b839 exofs: RAID0 support |
921 922 923 924 925 |
ret = _prepare_for_striping(ios); if (unlikely(ret)) return ret; for (i = 0; i < ios->numdevs; i += ios->layout->mirrors_p1) { |
8ff660ab8 exofs: Rename rai... |
926 |
ret = _write_mirror(ios, i); |
5d952b839 exofs: RAID0 support |
927 928 929 |
if (unlikely(ret)) return ret; } |
8ff660ab8 exofs: Rename rai... |
930 |
ret = ore_io_execute(ios); |
5d952b839 exofs: RAID0 support |
931 932 |
return ret; } |
cf283ade0 ore: Make ore its... |
933 |
EXPORT_SYMBOL(ore_write); |
5d952b839 exofs: RAID0 support |
934 |
|
769ba8d92 ore: RAID5 Write |
935 |
int _ore_read_mirror(struct ore_io_state *ios, unsigned cur_comp) |
06886a5a3 exofs: Move all o... |
936 |
{ |
46f4d973f exofs: unindent e... |
937 |
struct osd_request *or; |
8ff660ab8 exofs: Rename rai... |
938 |
struct ore_per_dev_state *per_dev = &ios->per_dev[cur_comp]; |
9e9db4564 exofs: ios: Move ... |
939 940 |
struct osd_obj_id *obj = _ios_obj(ios, cur_comp); unsigned first_dev = (unsigned)obj->id; |
06886a5a3 exofs: Move all o... |
941 |
|
50a76fd3c exofs: groups sup... |
942 943 |
if (ios->pages && !per_dev->length) return 0; /* Just an empty slot */ |
5d952b839 exofs: RAID0 support |
944 |
first_dev = per_dev->dev + first_dev % ios->layout->mirrors_p1; |
9e9db4564 exofs: ios: Move ... |
945 |
or = osd_start_request(_ios_od(ios, first_dev), GFP_KERNEL); |
46f4d973f exofs: unindent e... |
946 |
if (unlikely(!or)) { |
8ff660ab8 exofs: Rename rai... |
947 948 |
ORE_ERR("%s: osd_start_request failed ", __func__); |
46f4d973f exofs: unindent e... |
949 950 951 |
return -ENOMEM; } per_dev->or = or; |
46f4d973f exofs: unindent e... |
952 |
|
86093aaff exofs: convert io... |
953 |
if (ios->pages) { |
a1fec1dbb ore: RAID5 read |
954 955 956 957 958 959 960 961 962 963 964 965 966 |
if (per_dev->cur_sg) { /* finalize the last sg_entry */ _ore_add_sg_seg(per_dev, 0, false); if (unlikely(!per_dev->cur_sg)) return 0; /* Skip parity only device */ osd_req_read_sg(or, obj, per_dev->bio, per_dev->sglist, per_dev->cur_sg); } else { /* The no raid case */ osd_req_read(or, obj, per_dev->offset, per_dev->bio, per_dev->length); } |
8ff660ab8 exofs: Rename rai... |
967 |
ORE_DBGMSG("read(0x%llx) offset=0x%llx length=0x%llx" |
a1fec1dbb ore: RAID5 read |
968 969 |
" dev=%d sg_len=%d ", _LLU(obj->id), |
5d952b839 exofs: RAID0 support |
970 |
_LLU(per_dev->offset), _LLU(per_dev->length), |
a1fec1dbb ore: RAID5 read |
971 |
first_dev, per_dev->cur_sg); |
46f4d973f exofs: unindent e... |
972 |
} else { |
6851a5e5c ore: Remove check... |
973 |
BUG_ON(ios->kern_buff); |
9e9db4564 exofs: ios: Move ... |
974 |
osd_req_get_attributes(or, obj); |
8ff660ab8 exofs: Rename rai... |
975 976 |
ORE_DBGMSG2("obj(0x%llx) get_attributes=%d dev=%d ", |
9e9db4564 exofs: ios: Move ... |
977 978 |
_LLU(obj->id), ios->in_attr_len, first_dev); |
46f4d973f exofs: unindent e... |
979 |
} |
46f4d973f exofs: unindent e... |
980 981 |
if (ios->out_attr) osd_req_add_set_attr_list(or, ios->out_attr, ios->out_attr_len); |
b14f8ab28 exofs: Kbuild, He... |
982 |
|
46f4d973f exofs: unindent e... |
983 984 |
if (ios->in_attr) osd_req_add_get_attr_list(or, ios->in_attr, ios->in_attr_len); |
b14f8ab28 exofs: Kbuild, He... |
985 |
|
5d952b839 exofs: RAID0 support |
986 987 |
return 0; } |
8ff660ab8 exofs: Rename rai... |
988 |
int ore_read(struct ore_io_state *ios) |
5d952b839 exofs: RAID0 support |
989 990 991 992 993 994 995 996 997 |
{ int i; int ret; ret = _prepare_for_striping(ios); if (unlikely(ret)) return ret; for (i = 0; i < ios->numdevs; i += ios->layout->mirrors_p1) { |
769ba8d92 ore: RAID5 Write |
998 |
ret = _ore_read_mirror(ios, i); |
5d952b839 exofs: RAID0 support |
999 1000 1001 |
if (unlikely(ret)) return ret; } |
8ff660ab8 exofs: Rename rai... |
1002 |
ret = ore_io_execute(ios); |
5d952b839 exofs: RAID0 support |
1003 |
return ret; |
b14f8ab28 exofs: Kbuild, He... |
1004 |
} |
cf283ade0 ore: Make ore its... |
1005 |
EXPORT_SYMBOL(ore_read); |
b14f8ab28 exofs: Kbuild, He... |
1006 |
|
8ff660ab8 exofs: Rename rai... |
1007 |
int extract_attr_from_ios(struct ore_io_state *ios, struct osd_attr *attr) |
b14f8ab28 exofs: Kbuild, He... |
1008 1009 1010 1011 1012 1013 1014 |
{ struct osd_attr cur_attr = {.attr_page = 0}; /* start with zeros */ void *iter = NULL; int nelem; do { nelem = 1; |
06886a5a3 exofs: Move all o... |
1015 1016 |
osd_req_decode_get_attr_list(ios->per_dev[0].or, &cur_attr, &nelem, &iter); |
b14f8ab28 exofs: Kbuild, He... |
1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 |
if ((cur_attr.attr_page == attr->attr_page) && (cur_attr.attr_id == attr->attr_id)) { attr->len = cur_attr.len; attr->val_ptr = cur_attr.val_ptr; return 0; } } while (iter); return -EIO; } |
cf283ade0 ore: Make ore its... |
1027 |
EXPORT_SYMBOL(extract_attr_from_ios); |
06886a5a3 exofs: Move all o... |
1028 |
|
8ff660ab8 exofs: Rename rai... |
1029 |
static int _truncate_mirrors(struct ore_io_state *ios, unsigned cur_comp, |
5d952b839 exofs: RAID0 support |
1030 1031 1032 1033 1034 |
struct osd_attr *attr) { int last_comp = cur_comp + ios->layout->mirrors_p1; for (; cur_comp < last_comp; ++cur_comp) { |
8ff660ab8 exofs: Rename rai... |
1035 |
struct ore_per_dev_state *per_dev = &ios->per_dev[cur_comp]; |
5d952b839 exofs: RAID0 support |
1036 |
struct osd_request *or; |
9e9db4564 exofs: ios: Move ... |
1037 |
or = osd_start_request(_ios_od(ios, cur_comp), GFP_KERNEL); |
5d952b839 exofs: RAID0 support |
1038 |
if (unlikely(!or)) { |
8ff660ab8 exofs: Rename rai... |
1039 1040 |
ORE_ERR("%s: osd_start_request failed ", __func__); |
5d952b839 exofs: RAID0 support |
1041 1042 1043 |
return -ENOMEM; } per_dev->or = or; |
9e9db4564 exofs: ios: Move ... |
1044 |
osd_req_set_attributes(or, _ios_obj(ios, cur_comp)); |
5d952b839 exofs: RAID0 support |
1045 1046 1047 1048 1049 |
osd_req_add_set_attr_list(or, attr, 1); } return 0; } |
16f75bb35 exofs: Fix trunca... |
1050 |
struct _trunc_info { |
eb507bc18 ore: Make ore_str... |
1051 |
struct ore_striping_info si; |
16f75bb35 exofs: Fix trunca... |
1052 1053 1054 1055 1056 |
u64 prev_group_obj_off; u64 next_group_obj_off; unsigned first_group_dev; unsigned nex_group_dev; |
16f75bb35 exofs: Fix trunca... |
1057 |
}; |
1958c7c28 exofs/ore.c: loca... |
1058 1059 |
static void _calc_trunk_info(struct ore_layout *layout, u64 file_offset, struct _trunc_info *ti) |
16f75bb35 exofs: Fix trunca... |
1060 1061 |
{ unsigned stripe_unit = layout->stripe_unit; |
a1fec1dbb ore: RAID5 read |
1062 |
ore_calc_stripe_info(layout, file_offset, 0, &ti->si); |
16f75bb35 exofs: Fix trunca... |
1063 1064 1065 1066 1067 1068 |
ti->prev_group_obj_off = ti->si.M * stripe_unit; ti->next_group_obj_off = ti->si.M ? (ti->si.M - 1) * stripe_unit : 0; ti->first_group_dev = ti->si.dev - (ti->si.dev % layout->group_width); ti->nex_group_dev = ti->first_group_dev + layout->group_width; |
16f75bb35 exofs: Fix trunca... |
1069 |
} |
5bf696dad exofs: Rename str... |
1070 |
int ore_truncate(struct ore_layout *layout, struct ore_components *oc, |
9e9db4564 exofs: ios: Move ... |
1071 |
u64 size) |
06886a5a3 exofs: Move all o... |
1072 |
{ |
8ff660ab8 exofs: Rename rai... |
1073 |
struct ore_io_state *ios; |
5d952b839 exofs: RAID0 support |
1074 1075 1076 1077 |
struct exofs_trunc_attr { struct osd_attr attr; __be64 newsize; } *size_attrs; |
16f75bb35 exofs: Fix trunca... |
1078 |
struct _trunc_info ti; |
06886a5a3 exofs: Move all o... |
1079 |
int i, ret; |
5bf696dad exofs: Rename str... |
1080 |
ret = ore_get_io_state(layout, oc, &ios); |
5d952b839 exofs: RAID0 support |
1081 1082 |
if (unlikely(ret)) return ret; |
16f75bb35 exofs: Fix trunca... |
1083 |
_calc_trunk_info(ios->layout, size, &ti); |
b916c5cd4 ore: Only IO one ... |
1084 |
size_attrs = kcalloc(ios->oc->numdevs, sizeof(*size_attrs), |
5d952b839 exofs: RAID0 support |
1085 1086 1087 1088 1089 |
GFP_KERNEL); if (unlikely(!size_attrs)) { ret = -ENOMEM; goto out; } |
06886a5a3 exofs: Move all o... |
1090 |
|
5bf696dad exofs: Rename str... |
1091 |
ios->numdevs = ios->oc->numdevs; |
06886a5a3 exofs: Move all o... |
1092 |
|
b916c5cd4 ore: Only IO one ... |
1093 |
for (i = 0; i < ios->numdevs; ++i) { |
5d952b839 exofs: RAID0 support |
1094 1095 |
struct exofs_trunc_attr *size_attr = &size_attrs[i]; u64 obj_size; |
06886a5a3 exofs: Move all o... |
1096 |
|
16f75bb35 exofs: Fix trunca... |
1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 |
if (i < ti.first_group_dev) obj_size = ti.prev_group_obj_off; else if (i >= ti.nex_group_dev) obj_size = ti.next_group_obj_off; else if (i < ti.si.dev) /* dev within this group */ obj_size = ti.si.obj_offset + ios->layout->stripe_unit - ti.si.unit_off; else if (i == ti.si.dev) obj_size = ti.si.obj_offset; else /* i > ti.dev */ obj_size = ti.si.obj_offset - ti.si.unit_off; |
06886a5a3 exofs: Move all o... |
1108 |
|
5d952b839 exofs: RAID0 support |
1109 1110 1111 |
size_attr->newsize = cpu_to_be64(obj_size); size_attr->attr = g_attr_logical_length; size_attr->attr.val_ptr = &size_attr->newsize; |
aad560b7f ore: Fix wrong ma... |
1112 1113 |
ORE_DBGMSG2("trunc(0x%llx) obj_offset=0x%llx dev=%d ", |
5bf696dad exofs: Rename str... |
1114 |
_LLU(oc->comps->obj.id), _LLU(obj_size), i); |
5d952b839 exofs: RAID0 support |
1115 1116 1117 1118 |
ret = _truncate_mirrors(ios, i * ios->layout->mirrors_p1, &size_attr->attr); if (unlikely(ret)) goto out; |
06886a5a3 exofs: Move all o... |
1119 |
} |
8ff660ab8 exofs: Rename rai... |
1120 |
ret = ore_io_execute(ios); |
06886a5a3 exofs: Move all o... |
1121 1122 |
out: |
5d952b839 exofs: RAID0 support |
1123 |
kfree(size_attrs); |
8ff660ab8 exofs: Rename rai... |
1124 |
ore_put_io_state(ios); |
06886a5a3 exofs: Move all o... |
1125 1126 |
return ret; } |
cf283ade0 ore: Make ore its... |
1127 |
EXPORT_SYMBOL(ore_truncate); |
85e44df47 exofs: Move exofs... |
1128 1129 1130 |
const struct osd_attr g_attr_logical_length = ATTR_DEF( OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_LOGICAL_LENGTH, 8); |
cf283ade0 ore: Make ore its... |
1131 |
EXPORT_SYMBOL(g_attr_logical_length); |