aboutsummaryrefslogtreecommitdiffstats
path: root/fs/exofs/ios.c
diff options
context:
space:
mode:
authorBoaz Harrosh <bharrosh@panasas.com>2011-08-06 22:26:31 -0400
committerBoaz Harrosh <bharrosh@panasas.com>2011-08-06 22:36:18 -0400
commit8ff660ab85f524bdc7652eb5d38aaef1d66aa9c7 (patch)
treec4a29cde4fc8654ae00e65cb520e13f9fe7f4e08 /fs/exofs/ios.c
parent9e9db45649eb5d3ee5622fdad741914ecf1016a0 (diff)
exofs: Rename raid engine from exofs/ios.c => ore
ORE stands for "Objects Raid Engine" This patch is a mechanical rename of everything that was in ios.c and its API declaration to an ore.c and an osd_ore.h header. The ore engine will later be used by the pnfs objects layout driver. * File ios.c => ore.c * Declaration of types and API are moved from exofs.h to a new osd_ore.h * All used types are prefixed by ore_ from their exofs_ name. * Shift includes from exofs.h to osd_ore.h so osd_ore.h is independent, include it from exofs.h. Other than a pure rename there are no other changes. Next patch will move the ore into it's own module and will export the API to be used by exofs and later the layout driver Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Diffstat (limited to 'fs/exofs/ios.c')
-rw-r--r--fs/exofs/ios.c810
1 files changed, 0 insertions, 810 deletions
diff --git a/fs/exofs/ios.c b/fs/exofs/ios.c
deleted file mode 100644
index f9d5c5a823fb..000000000000
--- a/fs/exofs/ios.c
+++ /dev/null
@@ -1,810 +0,0 @@
1/*
2 * Copyright (C) 2005, 2006
3 * Avishay Traeger (avishay@gmail.com)
4 * Copyright (C) 2008, 2009
5 * Boaz Harrosh <bharrosh@panasas.com>
6 *
7 * This file is part of exofs.
8 *
9 * exofs is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation. Since it is based on ext2, and the only
12 * valid version of GPL for the Linux kernel is version 2, the only valid
13 * version of GPL for exofs is version 2.
14 *
15 * exofs is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with exofs; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25#include <linux/slab.h>
26#include <scsi/scsi_device.h>
27#include <asm/div64.h>
28
29#include "exofs.h"
30
31#define EXOFS_DBGMSG2(M...) do {} while (0)
32/* #define EXOFS_DBGMSG2 EXOFS_DBGMSG */
33
34static u8 *_ios_cred(struct exofs_io_state *ios, unsigned index)
35{
36 return ios->comps->comps[index & ios->comps->single_comp].cred;
37}
38
39static struct osd_obj_id *_ios_obj(struct exofs_io_state *ios, unsigned index)
40{
41 return &ios->comps->comps[index & ios->comps->single_comp].obj;
42}
43
44static struct osd_dev *_ios_od(struct exofs_io_state *ios, unsigned index)
45{
46 return ios->comps->ods[index];
47}
48
49int exofs_get_rw_state(struct exofs_layout *layout,
50 struct exofs_components *comps,
51 bool is_reading, u64 offset, u64 length,
52 struct exofs_io_state **pios)
53{
54 struct exofs_io_state *ios;
55
56 /*TODO: Maybe use kmem_cach per sbi of size
57 * exofs_io_state_size(layout->s_numdevs)
58 */
59 ios = kzalloc(exofs_io_state_size(comps->numdevs), GFP_KERNEL);
60 if (unlikely(!ios)) {
61 EXOFS_DBGMSG("Failed kzalloc bytes=%d\n",
62 exofs_io_state_size(comps->numdevs));
63 *pios = NULL;
64 return -ENOMEM;
65 }
66
67 ios->layout = layout;
68 ios->comps = comps;
69 ios->offset = offset;
70 ios->length = length;
71 ios->reading = is_reading;
72
73 *pios = ios;
74 return 0;
75}
76
77int exofs_get_io_state(struct exofs_layout *layout,
78 struct exofs_components *comps,
79 struct exofs_io_state **ios)
80{
81 return exofs_get_rw_state(layout, comps, true, 0, 0, ios);
82}
83
84void exofs_put_io_state(struct exofs_io_state *ios)
85{
86 if (ios) {
87 unsigned i;
88
89 for (i = 0; i < ios->numdevs; i++) {
90 struct exofs_per_dev_state *per_dev = &ios->per_dev[i];
91
92 if (per_dev->or)
93 osd_end_request(per_dev->or);
94 if (per_dev->bio)
95 bio_put(per_dev->bio);
96 }
97
98 kfree(ios);
99 }
100}
101
102static void _sync_done(struct exofs_io_state *ios, void *p)
103{
104 struct completion *waiting = p;
105
106 complete(waiting);
107}
108
109static void _last_io(struct kref *kref)
110{
111 struct exofs_io_state *ios = container_of(
112 kref, struct exofs_io_state, kref);
113
114 ios->done(ios, ios->private);
115}
116
117static void _done_io(struct osd_request *or, void *p)
118{
119 struct exofs_io_state *ios = p;
120
121 kref_put(&ios->kref, _last_io);
122}
123
124static int exofs_io_execute(struct exofs_io_state *ios)
125{
126 DECLARE_COMPLETION_ONSTACK(wait);
127 bool sync = (ios->done == NULL);
128 int i, ret;
129
130 if (sync) {
131 ios->done = _sync_done;
132 ios->private = &wait;
133 }
134
135 for (i = 0; i < ios->numdevs; i++) {
136 struct osd_request *or = ios->per_dev[i].or;
137 if (unlikely(!or))
138 continue;
139
140 ret = osd_finalize_request(or, 0, _ios_cred(ios, i), NULL);
141 if (unlikely(ret)) {
142 EXOFS_DBGMSG("Failed to osd_finalize_request() => %d\n",
143 ret);
144 return ret;
145 }
146 }
147
148 kref_init(&ios->kref);
149
150 for (i = 0; i < ios->numdevs; i++) {
151 struct osd_request *or = ios->per_dev[i].or;
152 if (unlikely(!or))
153 continue;
154
155 kref_get(&ios->kref);
156 osd_execute_request_async(or, _done_io, ios);
157 }
158
159 kref_put(&ios->kref, _last_io);
160 ret = 0;
161
162 if (sync) {
163 wait_for_completion(&wait);
164 ret = exofs_check_io(ios, NULL);
165 }
166 return ret;
167}
168
169static void _clear_bio(struct bio *bio)
170{
171 struct bio_vec *bv;
172 unsigned i;
173
174 __bio_for_each_segment(bv, bio, i, 0) {
175 unsigned this_count = bv->bv_len;
176
177 if (likely(PAGE_SIZE == this_count))
178 clear_highpage(bv->bv_page);
179 else
180 zero_user(bv->bv_page, bv->bv_offset, this_count);
181 }
182}
183
184int exofs_check_io(struct exofs_io_state *ios, u64 *resid)
185{
186 enum osd_err_priority acumulated_osd_err = 0;
187 int acumulated_lin_err = 0;
188 int i;
189
190 for (i = 0; i < ios->numdevs; i++) {
191 struct osd_sense_info osi;
192 struct osd_request *or = ios->per_dev[i].or;
193 int ret;
194
195 if (unlikely(!or))
196 continue;
197
198 ret = osd_req_decode_sense(or, &osi);
199 if (likely(!ret))
200 continue;
201
202 if (OSD_ERR_PRI_CLEAR_PAGES == osi.osd_err_pri) {
203 /* start read offset passed endof file */
204 _clear_bio(ios->per_dev[i].bio);
205 EXOFS_DBGMSG("start read offset passed end of file "
206 "offset=0x%llx, length=0x%llx\n",
207 _LLU(ios->per_dev[i].offset),
208 _LLU(ios->per_dev[i].length));
209
210 continue; /* we recovered */
211 }
212
213 if (osi.osd_err_pri >= acumulated_osd_err) {
214 acumulated_osd_err = osi.osd_err_pri;
215 acumulated_lin_err = ret;
216 }
217 }
218
219 /* TODO: raid specific residual calculations */
220 if (resid) {
221 if (likely(!acumulated_lin_err))
222 *resid = 0;
223 else
224 *resid = ios->length;
225 }
226
227 return acumulated_lin_err;
228}
229
230/*
231 * L - logical offset into the file
232 *
233 * U - The number of bytes in a stripe within a group
234 *
235 * U = stripe_unit * group_width
236 *
237 * T - The number of bytes striped within a group of component objects
238 * (before advancing to the next group)
239 *
240 * T = stripe_unit * group_width * group_depth
241 *
242 * S - The number of bytes striped across all component objects
243 * before the pattern repeats
244 *
245 * S = stripe_unit * group_width * group_depth * group_count
246 *
247 * M - The "major" (i.e., across all components) stripe number
248 *
249 * M = L / S
250 *
251 * G - Counts the groups from the beginning of the major stripe
252 *
253 * G = (L - (M * S)) / T [or (L % S) / T]
254 *
255 * H - The byte offset within the group
256 *
257 * H = (L - (M * S)) % T [or (L % S) % T]
258 *
259 * N - The "minor" (i.e., across the group) stripe number
260 *
261 * N = H / U
262 *
263 * C - The component index coresponding to L
264 *
265 * C = (H - (N * U)) / stripe_unit + G * group_width
266 * [or (L % U) / stripe_unit + G * group_width]
267 *
268 * O - The component offset coresponding to L
269 *
270 * O = L % stripe_unit + N * stripe_unit + M * group_depth * stripe_unit
271 */
272struct _striping_info {
273 u64 obj_offset;
274 u64 group_length;
275 u64 M; /* for truncate */
276 unsigned dev;
277 unsigned unit_off;
278};
279
280static void _calc_stripe_info(struct exofs_layout *layout, u64 file_offset,
281 struct _striping_info *si)
282{
283 u32 stripe_unit = layout->stripe_unit;
284 u32 group_width = layout->group_width;
285 u64 group_depth = layout->group_depth;
286
287 u32 U = stripe_unit * group_width;
288 u64 T = U * group_depth;
289 u64 S = T * layout->group_count;
290 u64 M = div64_u64(file_offset, S);
291
292 /*
293 G = (L - (M * S)) / T
294 H = (L - (M * S)) % T
295 */
296 u64 LmodS = file_offset - M * S;
297 u32 G = div64_u64(LmodS, T);
298 u64 H = LmodS - G * T;
299
300 u32 N = div_u64(H, U);
301
302 /* "H - (N * U)" is just "H % U" so it's bound to u32 */
303 si->dev = (u32)(H - (N * U)) / stripe_unit + G * group_width;
304 si->dev *= layout->mirrors_p1;
305
306 div_u64_rem(file_offset, stripe_unit, &si->unit_off);
307
308 si->obj_offset = si->unit_off + (N * stripe_unit) +
309 (M * group_depth * stripe_unit);
310
311 si->group_length = T - H;
312 si->M = M;
313}
314
315static int _add_stripe_unit(struct exofs_io_state *ios, unsigned *cur_pg,
316 unsigned pgbase, struct exofs_per_dev_state *per_dev,
317 int cur_len)
318{
319 unsigned pg = *cur_pg;
320 struct request_queue *q =
321 osd_request_queue(_ios_od(ios, per_dev->dev));
322
323 per_dev->length += cur_len;
324
325 if (per_dev->bio == NULL) {
326 unsigned pages_in_stripe = ios->layout->group_width *
327 (ios->layout->stripe_unit / PAGE_SIZE);
328 unsigned bio_size = (ios->nr_pages + pages_in_stripe) /
329 ios->layout->group_width;
330
331 per_dev->bio = bio_kmalloc(GFP_KERNEL, bio_size);
332 if (unlikely(!per_dev->bio)) {
333 EXOFS_DBGMSG("Failed to allocate BIO size=%u\n",
334 bio_size);
335 return -ENOMEM;
336 }
337 }
338
339 while (cur_len > 0) {
340 unsigned pglen = min_t(unsigned, PAGE_SIZE - pgbase, cur_len);
341 unsigned added_len;
342
343 BUG_ON(ios->nr_pages <= pg);
344 cur_len -= pglen;
345
346 added_len = bio_add_pc_page(q, per_dev->bio, ios->pages[pg],
347 pglen, pgbase);
348 if (unlikely(pglen != added_len))
349 return -ENOMEM;
350 pgbase = 0;
351 ++pg;
352 }
353 BUG_ON(cur_len);
354
355 *cur_pg = pg;
356 return 0;
357}
358
359static int _prepare_one_group(struct exofs_io_state *ios, u64 length,
360 struct _striping_info *si)
361{
362 unsigned stripe_unit = ios->layout->stripe_unit;
363 unsigned mirrors_p1 = ios->layout->mirrors_p1;
364 unsigned devs_in_group = ios->layout->group_width * mirrors_p1;
365 unsigned dev = si->dev;
366 unsigned first_dev = dev - (dev % devs_in_group);
367 unsigned max_comp = ios->numdevs ? ios->numdevs - mirrors_p1 : 0;
368 unsigned cur_pg = ios->pages_consumed;
369 int ret = 0;
370
371 while (length) {
372 struct exofs_per_dev_state *per_dev = &ios->per_dev[dev];
373 unsigned cur_len, page_off = 0;
374
375 if (!per_dev->length) {
376 per_dev->dev = dev;
377 if (dev < si->dev) {
378 per_dev->offset = si->obj_offset + stripe_unit -
379 si->unit_off;
380 cur_len = stripe_unit;
381 } else if (dev == si->dev) {
382 per_dev->offset = si->obj_offset;
383 cur_len = stripe_unit - si->unit_off;
384 page_off = si->unit_off & ~PAGE_MASK;
385 BUG_ON(page_off && (page_off != ios->pgbase));
386 } else { /* dev > si->dev */
387 per_dev->offset = si->obj_offset - si->unit_off;
388 cur_len = stripe_unit;
389 }
390
391 if (max_comp < dev)
392 max_comp = dev;
393 } else {
394 cur_len = stripe_unit;
395 }
396 if (cur_len >= length)
397 cur_len = length;
398
399 ret = _add_stripe_unit(ios, &cur_pg, page_off , per_dev,
400 cur_len);
401 if (unlikely(ret))
402 goto out;
403
404 dev += mirrors_p1;
405 dev = (dev % devs_in_group) + first_dev;
406
407 length -= cur_len;
408 }
409out:
410 ios->numdevs = max_comp + mirrors_p1;
411 ios->pages_consumed = cur_pg;
412 return ret;
413}
414
415static int _prepare_for_striping(struct exofs_io_state *ios)
416{
417 u64 length = ios->length;
418 u64 offset = ios->offset;
419 struct _striping_info si;
420 int ret = 0;
421
422 if (!ios->pages) {
423 if (ios->kern_buff) {
424 struct exofs_per_dev_state *per_dev = &ios->per_dev[0];
425
426 _calc_stripe_info(ios->layout, ios->offset, &si);
427 per_dev->offset = si.obj_offset;
428 per_dev->dev = si.dev;
429
430 /* no cross device without page array */
431 BUG_ON((ios->layout->group_width > 1) &&
432 (si.unit_off + ios->length >
433 ios->layout->stripe_unit));
434 }
435 ios->numdevs = ios->layout->mirrors_p1;
436 return 0;
437 }
438
439 while (length) {
440 _calc_stripe_info(ios->layout, offset, &si);
441
442 if (length < si.group_length)
443 si.group_length = length;
444
445 ret = _prepare_one_group(ios, si.group_length, &si);
446 if (unlikely(ret))
447 goto out;
448
449 offset += si.group_length;
450 length -= si.group_length;
451 }
452
453out:
454 return ret;
455}
456
457int exofs_sbi_create(struct exofs_io_state *ios)
458{
459 int i, ret;
460
461 for (i = 0; i < ios->comps->numdevs; i++) {
462 struct osd_request *or;
463
464 or = osd_start_request(_ios_od(ios, i), GFP_KERNEL);
465 if (unlikely(!or)) {
466 EXOFS_ERR("%s: osd_start_request failed\n", __func__);
467 ret = -ENOMEM;
468 goto out;
469 }
470 ios->per_dev[i].or = or;
471 ios->numdevs++;
472
473 osd_req_create_object(or, _ios_obj(ios, i));
474 }
475 ret = exofs_io_execute(ios);
476
477out:
478 return ret;
479}
480
481int exofs_sbi_remove(struct exofs_io_state *ios)
482{
483 int i, ret;
484
485 for (i = 0; i < ios->comps->numdevs; i++) {
486 struct osd_request *or;
487
488 or = osd_start_request(_ios_od(ios, i), GFP_KERNEL);
489 if (unlikely(!or)) {
490 EXOFS_ERR("%s: osd_start_request failed\n", __func__);
491 ret = -ENOMEM;
492 goto out;
493 }
494 ios->per_dev[i].or = or;
495 ios->numdevs++;
496
497 osd_req_remove_object(or, _ios_obj(ios, i));
498 }
499 ret = exofs_io_execute(ios);
500
501out:
502 return ret;
503}
504
505static int _sbi_write_mirror(struct exofs_io_state *ios, int cur_comp)
506{
507 struct exofs_per_dev_state *master_dev = &ios->per_dev[cur_comp];
508 unsigned dev = ios->per_dev[cur_comp].dev;
509 unsigned last_comp = cur_comp + ios->layout->mirrors_p1;
510 int ret = 0;
511
512 if (ios->pages && !master_dev->length)
513 return 0; /* Just an empty slot */
514
515 for (; cur_comp < last_comp; ++cur_comp, ++dev) {
516 struct exofs_per_dev_state *per_dev = &ios->per_dev[cur_comp];
517 struct osd_request *or;
518
519 or = osd_start_request(_ios_od(ios, dev), GFP_KERNEL);
520 if (unlikely(!or)) {
521 EXOFS_ERR("%s: osd_start_request failed\n", __func__);
522 ret = -ENOMEM;
523 goto out;
524 }
525 per_dev->or = or;
526 per_dev->offset = master_dev->offset;
527
528 if (ios->pages) {
529 struct bio *bio;
530
531 if (per_dev != master_dev) {
532 bio = bio_kmalloc(GFP_KERNEL,
533 master_dev->bio->bi_max_vecs);
534 if (unlikely(!bio)) {
535 EXOFS_DBGMSG(
536 "Failed to allocate BIO size=%u\n",
537 master_dev->bio->bi_max_vecs);
538 ret = -ENOMEM;
539 goto out;
540 }
541
542 __bio_clone(bio, master_dev->bio);
543 bio->bi_bdev = NULL;
544 bio->bi_next = NULL;
545 per_dev->length = master_dev->length;
546 per_dev->bio = bio;
547 per_dev->dev = dev;
548 } else {
549 bio = master_dev->bio;
550 /* FIXME: bio_set_dir() */
551 bio->bi_rw |= REQ_WRITE;
552 }
553
554 osd_req_write(or, _ios_obj(ios, dev), per_dev->offset,
555 bio, per_dev->length);
556 EXOFS_DBGMSG("write(0x%llx) offset=0x%llx "
557 "length=0x%llx dev=%d\n",
558 _LLU(_ios_obj(ios, dev)->id),
559 _LLU(per_dev->offset),
560 _LLU(per_dev->length), dev);
561 } else if (ios->kern_buff) {
562 ret = osd_req_write_kern(or, _ios_obj(ios, dev),
563 per_dev->offset,
564 ios->kern_buff, ios->length);
565 if (unlikely(ret))
566 goto out;
567 EXOFS_DBGMSG2("write_kern(0x%llx) offset=0x%llx "
568 "length=0x%llx dev=%d\n",
569 _LLU(_ios_obj(ios, dev)->id),
570 _LLU(per_dev->offset),
571 _LLU(ios->length), dev);
572 } else {
573 osd_req_set_attributes(or, _ios_obj(ios, dev));
574 EXOFS_DBGMSG2("obj(0x%llx) set_attributes=%d dev=%d\n",
575 _LLU(_ios_obj(ios, dev)->id),
576 ios->out_attr_len, dev);
577 }
578
579 if (ios->out_attr)
580 osd_req_add_set_attr_list(or, ios->out_attr,
581 ios->out_attr_len);
582
583 if (ios->in_attr)
584 osd_req_add_get_attr_list(or, ios->in_attr,
585 ios->in_attr_len);
586 }
587
588out:
589 return ret;
590}
591
592int exofs_sbi_write(struct exofs_io_state *ios)
593{
594 int i;
595 int ret;
596
597 ret = _prepare_for_striping(ios);
598 if (unlikely(ret))
599 return ret;
600
601 for (i = 0; i < ios->numdevs; i += ios->layout->mirrors_p1) {
602 ret = _sbi_write_mirror(ios, i);
603 if (unlikely(ret))
604 return ret;
605 }
606
607 ret = exofs_io_execute(ios);
608 return ret;
609}
610
611static int _sbi_read_mirror(struct exofs_io_state *ios, unsigned cur_comp)
612{
613 struct osd_request *or;
614 struct exofs_per_dev_state *per_dev = &ios->per_dev[cur_comp];
615 struct osd_obj_id *obj = _ios_obj(ios, cur_comp);
616 unsigned first_dev = (unsigned)obj->id;
617
618 if (ios->pages && !per_dev->length)
619 return 0; /* Just an empty slot */
620
621 first_dev = per_dev->dev + first_dev % ios->layout->mirrors_p1;
622 or = osd_start_request(_ios_od(ios, first_dev), GFP_KERNEL);
623 if (unlikely(!or)) {
624 EXOFS_ERR("%s: osd_start_request failed\n", __func__);
625 return -ENOMEM;
626 }
627 per_dev->or = or;
628
629 if (ios->pages) {
630 osd_req_read(or, obj, per_dev->offset,
631 per_dev->bio, per_dev->length);
632 EXOFS_DBGMSG("read(0x%llx) offset=0x%llx length=0x%llx"
633 " dev=%d\n", _LLU(obj->id),
634 _LLU(per_dev->offset), _LLU(per_dev->length),
635 first_dev);
636 } else if (ios->kern_buff) {
637 int ret = osd_req_read_kern(or, obj, per_dev->offset,
638 ios->kern_buff, ios->length);
639 EXOFS_DBGMSG2("read_kern(0x%llx) offset=0x%llx "
640 "length=0x%llx dev=%d ret=>%d\n",
641 _LLU(obj->id), _LLU(per_dev->offset),
642 _LLU(ios->length), first_dev, ret);
643 if (unlikely(ret))
644 return ret;
645 } else {
646 osd_req_get_attributes(or, obj);
647 EXOFS_DBGMSG2("obj(0x%llx) get_attributes=%d dev=%d\n",
648 _LLU(obj->id),
649 ios->in_attr_len, first_dev);
650 }
651 if (ios->out_attr)
652 osd_req_add_set_attr_list(or, ios->out_attr, ios->out_attr_len);
653
654 if (ios->in_attr)
655 osd_req_add_get_attr_list(or, ios->in_attr, ios->in_attr_len);
656
657 return 0;
658}
659
660int exofs_sbi_read(struct exofs_io_state *ios)
661{
662 int i;
663 int ret;
664
665 ret = _prepare_for_striping(ios);
666 if (unlikely(ret))
667 return ret;
668
669 for (i = 0; i < ios->numdevs; i += ios->layout->mirrors_p1) {
670 ret = _sbi_read_mirror(ios, i);
671 if (unlikely(ret))
672 return ret;
673 }
674
675 ret = exofs_io_execute(ios);
676 return ret;
677}
678
679int extract_attr_from_ios(struct exofs_io_state *ios, struct osd_attr *attr)
680{
681 struct osd_attr cur_attr = {.attr_page = 0}; /* start with zeros */
682 void *iter = NULL;
683 int nelem;
684
685 do {
686 nelem = 1;
687 osd_req_decode_get_attr_list(ios->per_dev[0].or,
688 &cur_attr, &nelem, &iter);
689 if ((cur_attr.attr_page == attr->attr_page) &&
690 (cur_attr.attr_id == attr->attr_id)) {
691 attr->len = cur_attr.len;
692 attr->val_ptr = cur_attr.val_ptr;
693 return 0;
694 }
695 } while (iter);
696
697 return -EIO;
698}
699
700static int _truncate_mirrors(struct exofs_io_state *ios, unsigned cur_comp,
701 struct osd_attr *attr)
702{
703 int last_comp = cur_comp + ios->layout->mirrors_p1;
704
705 for (; cur_comp < last_comp; ++cur_comp) {
706 struct exofs_per_dev_state *per_dev = &ios->per_dev[cur_comp];
707 struct osd_request *or;
708
709 or = osd_start_request(_ios_od(ios, cur_comp), GFP_KERNEL);
710 if (unlikely(!or)) {
711 EXOFS_ERR("%s: osd_start_request failed\n", __func__);
712 return -ENOMEM;
713 }
714 per_dev->or = or;
715
716 osd_req_set_attributes(or, _ios_obj(ios, cur_comp));
717 osd_req_add_set_attr_list(or, attr, 1);
718 }
719
720 return 0;
721}
722
723struct _trunc_info {
724 struct _striping_info si;
725 u64 prev_group_obj_off;
726 u64 next_group_obj_off;
727
728 unsigned first_group_dev;
729 unsigned nex_group_dev;
730 unsigned max_devs;
731};
732
733void _calc_trunk_info(struct exofs_layout *layout, u64 file_offset,
734 struct _trunc_info *ti)
735{
736 unsigned stripe_unit = layout->stripe_unit;
737
738 _calc_stripe_info(layout, file_offset, &ti->si);
739
740 ti->prev_group_obj_off = ti->si.M * stripe_unit;
741 ti->next_group_obj_off = ti->si.M ? (ti->si.M - 1) * stripe_unit : 0;
742
743 ti->first_group_dev = ti->si.dev - (ti->si.dev % layout->group_width);
744 ti->nex_group_dev = ti->first_group_dev + layout->group_width;
745 ti->max_devs = layout->group_width * layout->group_count;
746}
747
748int exofs_truncate(struct exofs_layout *layout, struct exofs_components *comps,
749 u64 size)
750{
751 struct exofs_io_state *ios;
752 struct exofs_trunc_attr {
753 struct osd_attr attr;
754 __be64 newsize;
755 } *size_attrs;
756 struct _trunc_info ti;
757 int i, ret;
758
759 ret = exofs_get_io_state(layout, comps, &ios);
760 if (unlikely(ret))
761 return ret;
762
763 _calc_trunk_info(ios->layout, size, &ti);
764
765 size_attrs = kcalloc(ti.max_devs, sizeof(*size_attrs),
766 GFP_KERNEL);
767 if (unlikely(!size_attrs)) {
768 ret = -ENOMEM;
769 goto out;
770 }
771
772 ios->numdevs = ios->comps->numdevs;
773
774 for (i = 0; i < ti.max_devs; ++i) {
775 struct exofs_trunc_attr *size_attr = &size_attrs[i];
776 u64 obj_size;
777
778 if (i < ti.first_group_dev)
779 obj_size = ti.prev_group_obj_off;
780 else if (i >= ti.nex_group_dev)
781 obj_size = ti.next_group_obj_off;
782 else if (i < ti.si.dev) /* dev within this group */
783 obj_size = ti.si.obj_offset +
784 ios->layout->stripe_unit - ti.si.unit_off;
785 else if (i == ti.si.dev)
786 obj_size = ti.si.obj_offset;
787 else /* i > ti.dev */
788 obj_size = ti.si.obj_offset - ti.si.unit_off;
789
790 size_attr->newsize = cpu_to_be64(obj_size);
791 size_attr->attr = g_attr_logical_length;
792 size_attr->attr.val_ptr = &size_attr->newsize;
793
794 EXOFS_DBGMSG("trunc(0x%llx) obj_offset=0x%llx dev=%d\n",
795 _LLU(comps->comps->obj.id), _LLU(obj_size), i);
796 ret = _truncate_mirrors(ios, i * ios->layout->mirrors_p1,
797 &size_attr->attr);
798 if (unlikely(ret))
799 goto out;
800 }
801 ret = exofs_io_execute(ios);
802
803out:
804 kfree(size_attrs);
805 exofs_put_io_state(ios);
806 return ret;
807}
808
809const struct osd_attr g_attr_logical_length = ATTR_DEF(
810 OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_LOGICAL_LENGTH, 8);