tr_raid5.c (234458) | tr_raid5.c (234993) |
---|---|
1/*- 2 * Copyright (c) 2012 Alexander Motin <mav@FreeBSD.org> 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 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2012 Alexander Motin <mav@FreeBSD.org> 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 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> |
28__FBSDID("$FreeBSD: head/sys/geom/raid/tr_raid5.c 234458 2012-04-19 12:30:12Z mav $"); | 28__FBSDID("$FreeBSD: head/sys/geom/raid/tr_raid5.c 234993 2012-05-04 07:32:57Z mav $"); |
29 30#include <sys/param.h> 31#include <sys/bio.h> 32#include <sys/endian.h> 33#include <sys/kernel.h> 34#include <sys/kobj.h> 35#include <sys/limits.h> 36#include <sys/lock.h> --- 64 unchanged lines hidden (view full) --- 101static int 102g_raid_tr_taste_raid5(struct g_raid_tr_object *tr, struct g_raid_volume *vol) 103{ 104 struct g_raid_tr_raid5_object *trs; 105 u_int qual; 106 107 trs = (struct g_raid_tr_raid5_object *)tr; 108 qual = tr->tro_volume->v_raid_level_qualifier; | 29 30#include <sys/param.h> 31#include <sys/bio.h> 32#include <sys/endian.h> 33#include <sys/kernel.h> 34#include <sys/kobj.h> 35#include <sys/limits.h> 36#include <sys/lock.h> --- 64 unchanged lines hidden (view full) --- 101static int 102g_raid_tr_taste_raid5(struct g_raid_tr_object *tr, struct g_raid_volume *vol) 103{ 104 struct g_raid_tr_raid5_object *trs; 105 u_int qual; 106 107 trs = (struct g_raid_tr_raid5_object *)tr; 108 qual = tr->tro_volume->v_raid_level_qualifier; |
109 if (tr->tro_volume->v_raid_level == G_RAID_VOLUME_RL_RAID5 && | 109 if (tr->tro_volume->v_raid_level == G_RAID_VOLUME_RL_RAID4 && 110 qual >= 0 && qual <= 1) { 111 /* RAID4 */ 112 } else if ((tr->tro_volume->v_raid_level == G_RAID_VOLUME_RL_RAID5 || 113 tr->tro_volume->v_raid_level == G_RAID_VOLUME_RL_RAID5E || 114 tr->tro_volume->v_raid_level == G_RAID_VOLUME_RL_RAID5EE || 115 tr->tro_volume->v_raid_level == G_RAID_VOLUME_RL_RAID6 || 116 tr->tro_volume->v_raid_level == G_RAID_VOLUME_RL_RAIDMDF) && |
110 qual >= 0 && qual <= 3) { | 117 qual >= 0 && qual <= 3) { |
111 /* RAID5 */ | 118 /* RAID5/5E/5EE/6/MDF */ |
112 } else 113 return (G_RAID_TR_TASTE_FAIL); 114 trs->trso_starting = 1; 115 return (G_RAID_TR_TASTE_SUCCEED); 116} 117 118static int 119g_raid_tr_update_state_raid5(struct g_raid_volume *vol, --- 78 unchanged lines hidden (view full) --- 198g_raid_tr_iostart_raid5_read(struct g_raid_tr_object *tr, struct bio *bp) 199{ 200 struct g_raid_volume *vol; 201 struct g_raid_subdisk *sd; 202 struct bio_queue_head queue; 203 struct bio *cbp; 204 char *addr; 205 off_t offset, start, length, nstripe, remain; | 119 } else 120 return (G_RAID_TR_TASTE_FAIL); 121 trs->trso_starting = 1; 122 return (G_RAID_TR_TASTE_SUCCEED); 123} 124 125static int 126g_raid_tr_update_state_raid5(struct g_raid_volume *vol, --- 78 unchanged lines hidden (view full) --- 205g_raid_tr_iostart_raid5_read(struct g_raid_tr_object *tr, struct bio *bp) 206{ 207 struct g_raid_volume *vol; 208 struct g_raid_subdisk *sd; 209 struct bio_queue_head queue; 210 struct bio *cbp; 211 char *addr; 212 off_t offset, start, length, nstripe, remain; |
206 int no, pno; 207 u_int strip_size, qual; | 213 int no, pno, ddisks, pdisks; 214 u_int strip_size, lvl, qual; |
208 209 vol = tr->tro_volume; 210 addr = bp->bio_data; 211 strip_size = vol->v_strip_size; | 215 216 vol = tr->tro_volume; 217 addr = bp->bio_data; 218 strip_size = vol->v_strip_size; |
219 lvl = tr->tro_volume->v_raid_level; |
|
212 qual = tr->tro_volume->v_raid_level_qualifier; 213 214 /* Stripe number. */ 215 nstripe = bp->bio_offset / strip_size; 216 /* Start position in stripe. */ 217 start = bp->bio_offset % strip_size; | 220 qual = tr->tro_volume->v_raid_level_qualifier; 221 222 /* Stripe number. */ 223 nstripe = bp->bio_offset / strip_size; 224 /* Start position in stripe. */ 225 start = bp->bio_offset % strip_size; |
226 /* Number of data and parity disks. */ 227 if (lvl == G_RAID_VOLUME_RL_RAIDMDF) 228 pdisks = 3; 229 else if (lvl == G_RAID_VOLUME_RL_RAID5EE || 230 lvl == G_RAID_VOLUME_RL_RAID6) 231 pdisks = 2; 232 else 233 pdisks = 1; 234 ddisks = vol->v_disks_count - pdisks; |
|
218 /* Parity disk number. */ | 235 /* Parity disk number. */ |
219 pno = nstripe / (vol->v_disks_count - 1) % vol->v_disks_count; 220 if (qual >= 2) 221 pno = (vol->v_disks_count - 1) - pno; 222 /* Disk number. */ 223 no = nstripe % (vol->v_disks_count - 1); 224 if (qual & 1) { 225 no = (pno + no + 1) % vol->v_disks_count; 226 } else if (no >= pno) 227 no++; | 236 if (lvl == G_RAID_VOLUME_RL_RAID4) { 237 if (qual == 0) /* P0 */ 238 pno = 0; 239 else /* PN */ 240 pno = ddisks; 241 } else { 242 pno = (nstripe / ddisks) % vol->v_disks_count; 243 if (qual >= 2) { /* PN/Left */ 244 pno = ddisks - pno; 245 if (pno < 0) 246 pno += vol->v_disks_count; 247 } 248 } 249 /* Data disk number. */ 250 no = nstripe % ddisks; 251 if (lvl == G_RAID_VOLUME_RL_RAID4) { 252 if (qual == 0) 253 no += pdisks; 254 } else if (qual & 1) { /* Continuation/Symmetric */ 255 no = (pno + pdisks + no) % vol->v_disks_count; 256 } else if (no >= pno) /* Restart/Asymmetric */ 257 no += pdisks; 258 else 259 no += imax(0, pno + pdisks - vol->v_disks_count); |
228 /* Stripe start position in disk. */ | 260 /* Stripe start position in disk. */ |
229 offset = (nstripe / (vol->v_disks_count - 1)) * strip_size; | 261 offset = (nstripe / ddisks) * strip_size; |
230 /* Length of data to operate. */ 231 remain = bp->bio_length; 232 233 bioq_init(&queue); 234 do { 235 length = MIN(strip_size - start, remain); 236 cbp = g_clone_bio(bp); 237 if (cbp == NULL) 238 goto failure; 239 cbp->bio_offset = offset + start; 240 cbp->bio_data = addr; 241 cbp->bio_length = length; 242 cbp->bio_caller1 = &vol->v_subdisks[no]; 243 bioq_insert_tail(&queue, cbp); 244 no++; | 262 /* Length of data to operate. */ 263 remain = bp->bio_length; 264 265 bioq_init(&queue); 266 do { 267 length = MIN(strip_size - start, remain); 268 cbp = g_clone_bio(bp); 269 if (cbp == NULL) 270 goto failure; 271 cbp->bio_offset = offset + start; 272 cbp->bio_data = addr; 273 cbp->bio_length = length; 274 cbp->bio_caller1 = &vol->v_subdisks[no]; 275 bioq_insert_tail(&queue, cbp); 276 no++; |
245 if (qual & 1) { | 277 if (lvl == G_RAID_VOLUME_RL_RAID4) { |
246 no %= vol->v_disks_count; | 278 no %= vol->v_disks_count; |
279 if (no == pno) 280 no = (no + pdisks) % vol->v_disks_count; 281 } else if (qual & 1) { /* Continuation/Symmetric */ 282 no %= vol->v_disks_count; |
|
247 if (no == pno) { | 283 if (no == pno) { |
248 if (qual < 2) { 249 pno = (pno + 1) % vol->v_disks_count; 250 no = (no + 2) % vol->v_disks_count; 251 } else if (pno == 0) 252 pno = vol->v_disks_count - 1; 253 else 254 pno--; | 284 if (qual < 2) /* P0/Right */ 285 pno++; 286 else /* PN/Left */ 287 pno += vol->v_disks_count - 1; 288 pno %= vol->v_disks_count; 289 no = (pno + pdisks) % vol->v_disks_count; |
255 offset += strip_size; 256 } | 290 offset += strip_size; 291 } |
257 } else { | 292 } else { /* Restart/Asymmetric */ |
258 if (no == pno) | 293 if (no == pno) |
259 no++; | 294 no += pdisks; |
260 if (no >= vol->v_disks_count) { | 295 if (no >= vol->v_disks_count) { |
261 no %= vol->v_disks_count; 262 if (qual < 2) 263 pno = (pno + 1) % vol->v_disks_count; 264 else if (pno == 0) 265 pno = vol->v_disks_count - 1; | 296 no -= vol->v_disks_count; 297 if (qual < 2) /* P0/Right */ 298 pno++; 299 else /* PN/Left */ 300 pno += vol->v_disks_count - 1; 301 pno %= vol->v_disks_count; 302 if (no == pno) 303 no += pdisks; |
266 else | 304 else |
267 pno--; | 305 no += imax(0, pno + pdisks - vol->v_disks_count); |
268 offset += strip_size; 269 } | 306 offset += strip_size; 307 } |
270 if (no == pno) 271 no++; | |
272 } 273 remain -= length; 274 addr += length; 275 start = 0; 276 } while (remain > 0); 277 for (cbp = bioq_first(&queue); cbp != NULL; 278 cbp = bioq_first(&queue)) { 279 bioq_remove(&queue, cbp); --- 97 unchanged lines hidden --- | 308 } 309 remain -= length; 310 addr += length; 311 start = 0; 312 } while (remain > 0); 313 for (cbp = bioq_first(&queue); cbp != NULL; 314 cbp = bioq_first(&queue)) { 315 bioq_remove(&queue, cbp); --- 97 unchanged lines hidden --- |