]>
git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - fs/exofs/ore_raid.c
3 * Boaz Harrosh <bharrosh@panasas.com>
5 * This file is part of the objects raid engine (ore).
7 * It is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as published
9 * by the Free Software Foundation.
11 * You should have received a copy of the GNU General Public License
12 * along with "ore". If not, write to the Free Software Foundation, Inc:
13 * "Free Software Foundation <info@fsf.org>"
16 #include <linux/gfp.h>
20 struct page
*_raid_page_alloc(void)
22 return alloc_page(GFP_KERNEL
);
25 void _raid_page_free(struct page
*p
)
30 void _ore_add_sg_seg(struct ore_per_dev_state
*per_dev
, unsigned cur_len
,
33 struct osd_sg_entry
*sge
;
35 ORE_DBGMSG("dev=%d cur_len=0x%x not_last=%d cur_sg=%d "
36 "offset=0x%llx length=0x%x last_sgs_total=0x%x\n",
37 per_dev
->dev
, cur_len
, not_last
, per_dev
->cur_sg
,
38 _LLU(per_dev
->offset
), per_dev
->length
,
39 per_dev
->last_sgs_total
);
41 if (!per_dev
->cur_sg
) {
42 sge
= per_dev
->sglist
;
44 /* First time we prepare two entries */
45 if (per_dev
->length
) {
47 sge
->offset
= per_dev
->offset
;
48 sge
->len
= per_dev
->length
;
50 /* Here the parity is the first unit of this object.
51 * This happens every time we reach a parity device on
52 * the same stripe as the per_dev->offset. We need to
53 * just skip this unit.
55 per_dev
->offset
+= cur_len
;
59 /* finalize the last one */
60 sge
= &per_dev
->sglist
[per_dev
->cur_sg
- 1];
61 sge
->len
= per_dev
->length
- per_dev
->last_sgs_total
;
65 /* Partly prepare the next one */
66 struct osd_sg_entry
*next_sge
= sge
+ 1;
69 next_sge
->offset
= sge
->offset
+ sge
->len
+ cur_len
;
70 /* Save cur len so we know how mutch was added next time */
71 per_dev
->last_sgs_total
= per_dev
->length
;
73 } else if (!sge
->len
) {
74 /* Optimize for when the last unit is a parity */
79 /* In writes @cur_len means length left. .i.e cur_len==0 is the last parity U */
80 int _ore_add_parity_unit(struct ore_io_state
*ios
,
81 struct ore_striping_info
*si
,
82 struct ore_per_dev_state
*per_dev
,
86 BUG_ON(per_dev
->cur_sg
>= ios
->sgs_per_dev
);
87 _ore_add_sg_seg(per_dev
, cur_len
, true);
89 struct page
**pages
= ios
->parity_pages
+ ios
->cur_par_page
;
90 unsigned num_pages
= ios
->layout
->stripe_unit
/ PAGE_SIZE
;
91 unsigned array_start
= 0;
95 for (i
= 0; i
< num_pages
; i
++) {
96 pages
[i
] = _raid_page_alloc();
97 if (unlikely(!pages
[i
]))
100 ++(ios
->cur_par_page
);
101 /* TODO: only read support for now */
102 clear_highpage(pages
[i
]);
105 ORE_DBGMSG("writing dev=%d num_pages=%d cur_par_page=%d",
106 per_dev
->dev
, num_pages
, ios
->cur_par_page
);
108 ret
= _ore_add_stripe_unit(ios
, &array_start
, 0, pages
,
109 per_dev
, num_pages
* PAGE_SIZE
);
116 int _ore_post_alloc_raid_stuff(struct ore_io_state
*ios
)
118 /*TODO: Only raid writes has stuff to add here */
122 void _ore_free_raid_stuff(struct ore_io_state
*ios
)
124 if (ios
->parity_pages
) { /* writing and raid */
127 for (i
= 0; i
< ios
->cur_par_page
; i
++) {
128 struct page
*page
= ios
->parity_pages
[i
];
131 _raid_page_free(page
);
133 if (ios
->extra_part_alloc
)
134 kfree(ios
->parity_pages
);
136 /* Will only be set if raid reading && sglist is big */
137 if (ios
->extra_part_alloc
)
138 kfree(ios
->per_dev
[0].sglist
);