@@ -227,3 +227,52 @@ static inline bool exceed_read_errors(struct mddev *mddev, struct md_rdev *rdev)
227
227
228
228
return false;
229
229
}
230
+
231
+ /**
232
+ * raid1_check_read_range() - check a given read range for bad blocks,
233
+ * available read length is returned;
234
+ * @rdev: the rdev to read;
235
+ * @this_sector: read position;
236
+ * @len: read length;
237
+ *
238
+ * helper function for read_balance()
239
+ *
240
+ * 1) If there are no bad blocks in the range, @len is returned;
241
+ * 2) If the range are all bad blocks, 0 is returned;
242
+ * 3) If there are partial bad blocks:
243
+ * - If the bad block range starts after @this_sector, the length of first
244
+ * good region is returned;
245
+ * - If the bad block range starts before @this_sector, 0 is returned and
246
+ * the @len is updated to the offset into the region before we get to the
247
+ * good blocks;
248
+ */
249
+ static inline int raid1_check_read_range (struct md_rdev * rdev ,
250
+ sector_t this_sector , int * len )
251
+ {
252
+ sector_t first_bad ;
253
+ int bad_sectors ;
254
+
255
+ /* no bad block overlap */
256
+ if (!is_badblock (rdev , this_sector , * len , & first_bad , & bad_sectors ))
257
+ return * len ;
258
+
259
+ /*
260
+ * bad block range starts offset into our range so we can return the
261
+ * number of sectors before the bad blocks start.
262
+ */
263
+ if (first_bad > this_sector )
264
+ return first_bad - this_sector ;
265
+
266
+ /* read range is fully consumed by bad blocks. */
267
+ if (this_sector + * len <= first_bad + bad_sectors )
268
+ return 0 ;
269
+
270
+ /*
271
+ * final case, bad block range starts before or at the start of our
272
+ * range but does not cover our entire range so we still return 0 but
273
+ * update the length with the number of sectors before we get to the
274
+ * good ones.
275
+ */
276
+ * len = first_bad + bad_sectors - this_sector ;
277
+ return 0 ;
278
+ }
0 commit comments