aboutsummaryrefslogtreecommitdiffstats
path: root/include/scsi
diff options
context:
space:
mode:
authorBoaz Harrosh <bharrosh@panasas.com>2011-10-14 09:33:51 -0400
committerBoaz Harrosh <bharrosh@panasas.com>2011-10-24 20:15:33 -0400
commit769ba8d92025fa390f3097e658b8ed6e032d68e9 (patch)
treeeec1a556d6b3796f702c96e7f97ce94ba7d9d410 /include/scsi
parenta1fec1dbbc8db974d2582e4040590cebe72171e4 (diff)
ore: RAID5 Write
This is finally the RAID5 Write support. The bigger part of this patch is not the XOR engine itself, But the read4write logic, which is a complete mini prepare_for_striping reading engine that can read scattered pages of a stripe into cache so it can be used for XOR calculation. That is, if the write was not stripe aligned. The main algorithm behind the XOR engine is the 2 dimensional array: struct __stripe_pages_2d. A drawing might save 1000 words --- __stripe_pages_2d | n = pages_in_stripe_unit; w = group_width - parity; | pages array presented to the XOR lib | | V | __1_page_stripe[0].pages --> [c0][c1]..[cw][c_par] <---| | | __1_page_stripe[1].pages --> [c0][c1]..[cw][c_par] <--- | ... | ... | __1_page_stripe[n].pages --> [c0][c1]..[cw][c_par] ^ | data added columns first then row --- The pages are put on this array columns first. .i.e: p0-of-c0, p1-of-c0, ... pn-of-c0, p0-of-c1, ... So we are doing a corner turn of the pages. Note that pages will zigzag down and left. but are put sequentially in growing order. So when the time comes to XOR the stripe, only the beginning and end of the array need be checked. We scan the array and any NULL spot will be field by pages-to-be-read. The FS that wants to support RAID5 needs to supply an operations-vector that searches a given page in cache, and specifies if the page is uptodate or need reading. All these pages to be read are put on a slave ore_io_state and synchronously read. All the pages of a stripe are read in one IO, using the scatter gather mechanism. In write we constrain our IO to only be incomplete on a single stripe. Meaning either the complete IO is within a single stripe so we might have pages to read from both beginning or end of the strip. Or we have some reading to do at beginning but end at strip boundary. The left over pages are pushed to the next IO by the API already established by previous work, where an IO offset/length combination presented to the ORE might get the length truncated and the user must re-submit the leftover pages. (Both exofs and NFS support this) But any ORE user should make it's best effort to align it's IO before hand and avoid complications. A cached ore_layout->stripe_size member can be used for that calculation. (NOTE: that ORE demands that stripe_size may not be bigger then 32bit) What else? Well read it and tell me. Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Diffstat (limited to 'include/scsi')
-rw-r--r--include/scsi/osd_ore.h9
1 files changed, 9 insertions, 0 deletions
diff --git a/include/scsi/osd_ore.h b/include/scsi/osd_ore.h
index 43821c18cd3f..f05fa826f89e 100644
--- a/include/scsi/osd_ore.h
+++ b/include/scsi/osd_ore.h
@@ -99,11 +99,17 @@ struct ore_striping_info {
99 unsigned dev; 99 unsigned dev;
100 unsigned par_dev; 100 unsigned par_dev;
101 unsigned unit_off; 101 unsigned unit_off;
102 unsigned cur_pg;
102 unsigned cur_comp; 103 unsigned cur_comp;
103}; 104};
104 105
105struct ore_io_state; 106struct ore_io_state;
106typedef void (*ore_io_done_fn)(struct ore_io_state *ios, void *private); 107typedef void (*ore_io_done_fn)(struct ore_io_state *ios, void *private);
108struct _ore_r4w_op {
109 /* @Priv given here is passed ios->private */
110 struct page * (*get_page)(void *priv, u64 page_index, bool *uptodate);
111 void (*put_page)(void *priv, struct page *page);
112};
107 113
108struct ore_io_state { 114struct ore_io_state {
109 struct kref kref; 115 struct kref kref;
@@ -139,6 +145,9 @@ struct ore_io_state {
139 unsigned max_par_pages; 145 unsigned max_par_pages;
140 unsigned cur_par_page; 146 unsigned cur_par_page;
141 unsigned sgs_per_dev; 147 unsigned sgs_per_dev;
148 struct __stripe_pages_2d *sp2d;
149 struct ore_io_state *ios_read_4_write;
150 const struct _ore_r4w_op *r4w;
142 151
143 /* Variable array of size numdevs */ 152 /* Variable array of size numdevs */
144 unsigned numdevs; 153 unsigned numdevs;